@valve-tech/wallet-adapter 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -0
- package/README.md +70 -34
- package/dist/hooks.d.ts +122 -58
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +8 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/receipt.d.ts +47 -11
- package/dist/receipt.d.ts.map +1 -1
- package/dist/receipt.js +46 -15
- package/dist/receipt.js.map +1 -1
- package/dist/send.d.ts +22 -17
- package/dist/send.d.ts.map +1 -1
- package/dist/send.js +26 -18
- package/dist/send.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,85 @@ this file.
|
|
|
6
6
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
7
7
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
8
8
|
|
|
9
|
+
## [0.5.0] — 2026-05-05
|
|
10
|
+
|
|
11
|
+
### Changed — BREAKING
|
|
12
|
+
|
|
13
|
+
- **All lifecycle event payloads are now rich info bags carrying full
|
|
14
|
+
`TxContext` (`chainId` + original `request`) plus phase-specific
|
|
15
|
+
fields.** The previous shapes forced consumers (especially the
|
|
16
|
+
upcoming `@valve-tech/tx-tracker`) to maintain a side-channel
|
|
17
|
+
`hash → request` map and re-fetch chainId / block timestamp / block
|
|
18
|
+
baseFeePerGas from the public client. The lib already has all of
|
|
19
|
+
that in scope when it fires events, so the consumer should never
|
|
20
|
+
have to re-gather it.
|
|
21
|
+
|
|
22
|
+
Old / new signatures:
|
|
23
|
+
|
|
24
|
+
| Hook | Old | New |
|
|
25
|
+
| ---- | --- | --- |
|
|
26
|
+
| `onAwaitingSignature` | `() => void` | `(info: TxContext) => void` |
|
|
27
|
+
| `onTransactionHash` (per-call & global) | `(hash: Hex) => void` | `(info: TxContext<{ hash }>) => void` |
|
|
28
|
+
| `onConfirmed` | `(receipt: TransactionReceipt) => void` | `(info: TxContext<{ hash, receipt, block? }>) => void` |
|
|
29
|
+
| `onFailed` | `(error: Error) => void` | `(info: TxContext<{ error, hash?, receipt?, block? }>) => void` |
|
|
30
|
+
| `onDropped` | `(info: { hash }) => void` | `(info: TxContext<{ hash }>) => void` |
|
|
31
|
+
| `onReplaced` | `(info: { original, replacement, receipt? }) => void` | `(info: TxContext<{ original, replacement, receipt?, block? }>) => void` |
|
|
32
|
+
|
|
33
|
+
The `onPhase` discriminated-union event gains the same enrichment;
|
|
34
|
+
`WritePhaseEvent` is now derived mechanically from a `WritePhaseSteps`
|
|
35
|
+
map intersected with `TxContext<Steps[K]>`, so adding a phase or a
|
|
36
|
+
shared field is a one-line edit instead of seven.
|
|
37
|
+
|
|
38
|
+
- **`awaitReceiptWithHooks` now requires `request` in its options and
|
|
39
|
+
fetches the containing `Block` by default.** Signature gained
|
|
40
|
+
`request: WalletSendTransactionRequest` (used to populate `TxContext`
|
|
41
|
+
in event payloads) and `includeBlock?: boolean = true`. When
|
|
42
|
+
`includeBlock` is left at its default, the helper calls
|
|
43
|
+
`publicClient.getBlock({ blockHash })` once after a successful
|
|
44
|
+
receipt-await; the resulting `Block` is attached to `confirmed` /
|
|
45
|
+
receipt-bearing `failed` event payloads. Pass `includeBlock: false`
|
|
46
|
+
to skip the extra RPC round trip in environments that don't need
|
|
47
|
+
block-level data.
|
|
48
|
+
|
|
49
|
+
- **`ReceiptAwaiter` interface gained `getBlock`.** Mocks need to add
|
|
50
|
+
a `getBlock(args: { blockHash: Hex }): Promise<Block>` field. Real
|
|
51
|
+
viem `PublicClient` instances satisfy the new shape unchanged.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- `WritePhaseSteps` interface — phase-name → per-phase delta map.
|
|
56
|
+
Declared as `interface` (not `type`) so consumers can extend the
|
|
57
|
+
lifecycle via declaration merging without forking the union.
|
|
58
|
+
- `TxContext<Extra extends object = object>` — generic always-present
|
|
59
|
+
context (`chainId`, `request`) intersected with `Extra` to derive
|
|
60
|
+
per-phase event shapes. Defaulting `Extra` keeps `TxContext` usable
|
|
61
|
+
bare.
|
|
62
|
+
- `WritePhaseEvent` is now derived mechanically as
|
|
63
|
+
`{ [K in keyof WritePhaseSteps]: { phase: K } & TxContext<WritePhaseSteps[K]> }[keyof WritePhaseSteps]`.
|
|
64
|
+
- `confirmed` and `replaced` events carry an optional `block: Block`.
|
|
65
|
+
`failed` events carry the receipt-bearing context (hash, receipt,
|
|
66
|
+
block) when the failure has one (revert), and just the error +
|
|
67
|
+
context otherwise (wallet rejection, network timeout).
|
|
68
|
+
|
|
69
|
+
### Migration
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
// before — v0.4.x
|
|
73
|
+
hooks: {
|
|
74
|
+
onConfirmed: (receipt) => recordTx({ hash: receipt.transactionHash, receipt }),
|
|
75
|
+
onFailed: (error) => logFailure(error),
|
|
76
|
+
}
|
|
77
|
+
await awaitReceiptWithHooks({ publicClient, hash, hooks })
|
|
78
|
+
|
|
79
|
+
// after — v0.5.x
|
|
80
|
+
hooks: {
|
|
81
|
+
onConfirmed: (info) => recordTx(info), // info.chainId, info.request, info.hash, info.receipt, info.block
|
|
82
|
+
onFailed: (info) => logFailure(info.error, info.chainId, info.request),
|
|
83
|
+
}
|
|
84
|
+
await awaitReceiptWithHooks({ publicClient, hash, request, hooks })
|
|
85
|
+
// ^^^^^^^ new required field
|
|
86
|
+
```
|
|
87
|
+
|
|
9
88
|
## [0.4.1] — 2026-05-04
|
|
10
89
|
|
|
11
90
|
### Fixed
|
package/README.md
CHANGED
|
@@ -13,21 +13,27 @@ all agree on the same surface:
|
|
|
13
13
|
named hooks (`onAwaitingSignature`, `onTransactionHash`,
|
|
14
14
|
`onConfirmed`, `onFailed`, `onDropped`, `onReplaced`) plus a
|
|
15
15
|
complementary single-callback shape (`onPhase(event)`) with a
|
|
16
|
-
discriminated-union payload.
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
discriminated-union payload. Every payload is a `TxContext` info
|
|
17
|
+
bag — `{ chainId, request, ...phase-specific }` — so consumers
|
|
18
|
+
never have to side-channel the originating chain or the original
|
|
19
|
+
send request. Fire-ers fire BOTH shapes for every transition —
|
|
20
|
+
exactly once each — so wiring named hooks doesn't preclude
|
|
21
|
+
`onPhase` and vice versa.
|
|
19
22
|
3. **`sendTransactionWithHooks(options)`** — wallet-side helper. Fires
|
|
20
23
|
the pre-wallet (`onAwaitingSignature`, `onPhase('awaiting-signature')`)
|
|
21
|
-
and post-hash (`onTransactionHash`, `onPhase('pending', { hash })`)
|
|
24
|
+
and post-hash (`onTransactionHash`, `onPhase('pending', { ..., hash })`)
|
|
22
25
|
transitions. Converts wallet rejections to a typed
|
|
23
|
-
`WalletRejectedError`, fires `onFailed` + `onPhase('failed', { error })`,
|
|
26
|
+
`WalletRejectedError`, fires `onFailed` + `onPhase('failed', { ..., error })`,
|
|
24
27
|
then throws.
|
|
25
28
|
4. **`awaitReceiptWithHooks(options)`** — chain-side helper. Awaits
|
|
26
|
-
`waitForTransactionReceipt`,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`
|
|
30
|
-
|
|
29
|
+
`waitForTransactionReceipt`, fetches the containing block (so
|
|
30
|
+
downstream consumers don't re-fetch it for `timestamp` /
|
|
31
|
+
`baseFeePerGas`), then fires `onConfirmed` +
|
|
32
|
+
`onPhase('confirmed', { ..., hash, receipt, block })` on success,
|
|
33
|
+
or `onFailed` + `onPhase('failed', ...)` with a typed
|
|
34
|
+
`ContractRevertedError` on `status: 'reverted'`. Other receipt-await
|
|
35
|
+
errors re-thrown unchanged after firing the failure hooks. Pass
|
|
36
|
+
`includeBlock: false` to skip the block fetch.
|
|
31
37
|
5. **`TX_STATUS` / `TrackedTx`** — vocabulary for "this transaction is
|
|
32
38
|
in flight" UIs (toast strips, inline indicators, history panes) so
|
|
33
39
|
they can sit on top of any tracker without redefining state names.
|
|
@@ -93,28 +99,35 @@ export class MyClient {
|
|
|
93
99
|
private wallet: WalletAdapter,
|
|
94
100
|
private chainId: number,
|
|
95
101
|
private escrow: `0x${string}`,
|
|
96
|
-
/**
|
|
97
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Optional global / analytics channel — fires alongside the per-call hook.
|
|
104
|
+
* Receives the rich `{ chainId, request, hash }` info bag, so analytics
|
|
105
|
+
* observers see the originating chain and request without a side channel.
|
|
106
|
+
*/
|
|
107
|
+
private onTransactionHash?: WriteHookParams['onTransactionHash'],
|
|
98
108
|
) {}
|
|
99
109
|
|
|
100
110
|
async deposit(params: MyWriteParams & WriteHookParams) {
|
|
111
|
+
const request = {
|
|
112
|
+
to: this.escrow,
|
|
113
|
+
data: this.encodeDeposit(params),
|
|
114
|
+
chainId: this.chainId,
|
|
115
|
+
}
|
|
101
116
|
try {
|
|
102
117
|
const hash = await sendTransactionWithHooks({
|
|
103
118
|
wallet: this.wallet,
|
|
104
|
-
request
|
|
105
|
-
to: this.escrow,
|
|
106
|
-
data: this.encodeDeposit(params),
|
|
107
|
-
chainId: this.chainId,
|
|
108
|
-
},
|
|
119
|
+
request,
|
|
109
120
|
hooks: params,
|
|
110
121
|
onTransactionHash: this.onTransactionHash,
|
|
111
122
|
})
|
|
112
123
|
const receipt = await awaitReceiptWithHooks({
|
|
113
124
|
publicClient: this.publicClient,
|
|
114
125
|
hash,
|
|
126
|
+
request, // carried into every phase event as part of TxContext
|
|
115
127
|
hooks: params,
|
|
116
128
|
})
|
|
117
129
|
// protocol-specific work here (decode logs, etc.) — onConfirmed already fired
|
|
130
|
+
// with { chainId, request, hash, receipt, block } in scope
|
|
118
131
|
return { hash, receipt }
|
|
119
132
|
} catch (err) {
|
|
120
133
|
if (err instanceof WalletRejectedError) {
|
|
@@ -131,28 +144,33 @@ export class MyClient {
|
|
|
131
144
|
|
|
132
145
|
`sendTransactionWithHooks` guarantees:
|
|
133
146
|
|
|
134
|
-
- `onAwaitingSignature` fires **once
|
|
135
|
-
`wallet.sendTransaction`.
|
|
136
|
-
- `onTransactionHash` (per-call **and** global) fires **once each
|
|
137
|
-
|
|
147
|
+
- `onAwaitingSignature` fires **once** with `{ chainId, request }`,
|
|
148
|
+
**immediately before** `wallet.sendTransaction`.
|
|
149
|
+
- `onTransactionHash` (per-call **and** global) fires **once each**
|
|
150
|
+
with `{ chainId, request, hash }`, **after** `sendTransaction`
|
|
151
|
+
resolves and **before** any receipt-await.
|
|
138
152
|
- Wallet rejections — detected via the three-signal check in
|
|
139
153
|
`@valve-tech/viem-errors` (EIP-1193 `code === 4001`, viem class name,
|
|
140
154
|
message regex, anywhere in the cause chain) — are thrown as
|
|
141
|
-
`WalletRejectedError`. `onFailed` fires with
|
|
142
|
-
before the throw.
|
|
143
|
-
- Any other thrown error fires `onFailed`
|
|
144
|
-
the SDK keeps control of its error mapping.
|
|
155
|
+
`WalletRejectedError`. `onFailed` fires with
|
|
156
|
+
`{ chainId, request, error: <WalletRejectedError> }` before the throw.
|
|
157
|
+
- Any other thrown error fires `onFailed` (with `error: <thrown>`) and
|
|
158
|
+
re-throws unchanged so the SDK keeps control of its error mapping.
|
|
145
159
|
|
|
146
160
|
`awaitReceiptWithHooks` guarantees:
|
|
147
161
|
|
|
148
|
-
- On `receipt.status === 'success'`:
|
|
162
|
+
- On `receipt.status === 'success'`: fetches the containing block
|
|
163
|
+
(unless `includeBlock: false`), then fires
|
|
164
|
+
`onConfirmed({ chainId, request, hash, receipt, block? })` and
|
|
149
165
|
resolves with the receipt.
|
|
150
|
-
- On `receipt.status === 'reverted'`:
|
|
151
|
-
`
|
|
152
|
-
|
|
166
|
+
- On `receipt.status === 'reverted'`: fetches the block, then fires
|
|
167
|
+
`onFailed({ chainId, request, hash, receipt, block?, error: <ContractRevertedError> })`
|
|
168
|
+
and throws the error. `ContractRevertedError` carries `hash` + the
|
|
169
|
+
full `receipt` for log inspection.
|
|
153
170
|
- On any thrown error during the receipt-await (network / RPC /
|
|
154
|
-
abort): fires `onFailed
|
|
155
|
-
unchanged.
|
|
171
|
+
abort): fires `onFailed({ chainId, request, error })` (no
|
|
172
|
+
`hash`/`receipt`/`block`) and re-throws unchanged. The block fetch
|
|
173
|
+
is skipped when the receipt itself fails to arrive.
|
|
156
174
|
|
|
157
175
|
A `WriteHookParams` consumer (toast strip, inline indicator, etc.)
|
|
158
176
|
that wires all four hooks can drive its full state machine — pre-wallet
|
|
@@ -184,11 +202,13 @@ function subtitle(tx: TrackedTx): string {
|
|
|
184
202
|
| `WalletAdapter` | type | `{ address?, sendTransaction(req), readContract?(req) }` |
|
|
185
203
|
| `WalletSendTransactionRequest` | type | EIP-1559 send shape — `{ to, data, value?, chainId, maxFeePerGas?, maxPriorityFeePerGas? }` |
|
|
186
204
|
| `WalletReadContractRequest` | type | `{ address, abi, functionName, args?, chainId? }` |
|
|
187
|
-
| `WriteHookParams` | type | six named hooks (`onAwaitingSignature`, `onTransactionHash`, `onConfirmed`, `onFailed`, `onDropped`, `onReplaced`) + `onPhase(event)` |
|
|
205
|
+
| `WriteHookParams` | type | six named hooks (`onAwaitingSignature`, `onTransactionHash`, `onConfirmed`, `onFailed`, `onDropped`, `onReplaced`) + `onPhase(event)`. Every callback receives a `TxContext<Steps[K]>` info bag. |
|
|
188
206
|
| `WritePhase` | type | `'preparing' \| 'awaiting-signature' \| 'pending' \| 'confirmed' \| 'failed' \| 'dropped' \| 'replaced'` |
|
|
189
|
-
| `
|
|
207
|
+
| `WritePhaseSteps` | interface | per-phase data delta map. `pending: { hash }`, `confirmed: { hash, receipt, block? }`, etc. Open to declaration merging. |
|
|
208
|
+
| `TxContext<Extra>` | type | `{ chainId, request } & Extra`. The always-present context intersected with the per-phase delta. Defaults `Extra` to `object`. |
|
|
209
|
+
| `WritePhaseEvent` | type | derived `{ [K in keyof WritePhaseSteps]: { phase: K } & TxContext<WritePhaseSteps[K]> }[keyof WritePhaseSteps]`. |
|
|
190
210
|
| `sendTransactionWithHooks(opts)` | function | `{ wallet, request, hooks?, onTransactionHash? } → Promise<Hex>`. Wallet-side helper. |
|
|
191
|
-
| `awaitReceiptWithHooks(opts)` | function | `{ publicClient, hash, hooks? } → Promise<TransactionReceipt>`. Chain-side helper. |
|
|
211
|
+
| `awaitReceiptWithHooks(opts)` | function | `{ publicClient, hash, request, includeBlock?, hooks? } → Promise<TransactionReceipt>`. Chain-side helper; fetches the containing block by default. |
|
|
192
212
|
| `WalletRejectedError` | class | `Error` subclass with `cause: Error`. Thrown by `sendTransactionWithHooks` on user rejection. |
|
|
193
213
|
| `ContractRevertedError` | class | `Error` subclass with `hash` + `receipt`. Thrown by `awaitReceiptWithHooks` on `status: reverted`. |
|
|
194
214
|
| `SendTransactionWithHooksOptions` / `AwaitReceiptWithHooksOptions` / `ReceiptAwaiter` | type | options + minimal client shape |
|
|
@@ -206,6 +226,22 @@ function subtitle(tx: TrackedTx): string {
|
|
|
206
226
|
state-machine consumers. Fire-ers fire BOTH shapes for every
|
|
207
227
|
transition — exactly once each. Wiring named hooks doesn't preclude
|
|
208
228
|
`onPhase` and vice versa.
|
|
229
|
+
- **Rich payloads, not bare arguments.** Every event carries
|
|
230
|
+
`TxContext` (`chainId` + the original `request`) on top of its
|
|
231
|
+
phase-specific fields. The lib already has all of that in scope
|
|
232
|
+
when it fires events; the alternative — `(receipt) => void` and
|
|
233
|
+
`(hash) => void` — forces every consumer to maintain a side-channel
|
|
234
|
+
`hash → request` map and call `client.chain.id` from inside their
|
|
235
|
+
callbacks. `awaitReceiptWithHooks` also fetches the containing
|
|
236
|
+
block once and includes it on `confirmed` / receipt-bearing
|
|
237
|
+
`failed` events, so downstream consumers (notably
|
|
238
|
+
`@valve-tech/tx-tracker`) skip the round trip.
|
|
239
|
+
- **`WritePhaseSteps` is the single source of truth for phase
|
|
240
|
+
shapes.** `WritePhaseEvent` is derived mechanically as
|
|
241
|
+
`{ [K in keyof WritePhaseSteps]: { phase: K } & TxContext<WritePhaseSteps[K]> }`,
|
|
242
|
+
so adding a phase is one entry in the map plus a fire-er. Adding a
|
|
243
|
+
shared field is one entry in `TxContext`. Both stay in lockstep
|
|
244
|
+
with the named hook signatures.
|
|
209
245
|
- **`onFailed` is the unified failure callback for revert / rejection /
|
|
210
246
|
network errors.** Wallet rejection, on-chain revert, and network
|
|
211
247
|
errors all flow through it. `instanceof` against
|
package/dist/hooks.d.ts
CHANGED
|
@@ -29,8 +29,17 @@
|
|
|
29
29
|
*
|
|
30
30
|
* Fire-ers fire BOTH shapes for every transition — exactly once each —
|
|
31
31
|
* so consumers can choose which to wire without affecting the other.
|
|
32
|
+
*
|
|
33
|
+
* Every payload carries a `TxContext` (`chainId` + `request`) so
|
|
34
|
+
* consumers never have to side-channel the originating chain or the
|
|
35
|
+
* original send request to use the events. `confirmed` and
|
|
36
|
+
* receipt-bearing `failed` events also carry the containing `Block` so
|
|
37
|
+
* downstream trackers don't have to re-fetch it for timestamp / fee
|
|
38
|
+
* analytics — that's the "don't make consumers re-gather what we
|
|
39
|
+
* already have" rule the events are designed around.
|
|
32
40
|
*/
|
|
33
|
-
import type { Hex, TransactionReceipt } from 'viem';
|
|
41
|
+
import type { Block, Hex, TransactionReceipt } from 'viem';
|
|
42
|
+
import type { WalletSendTransactionRequest } from './wallet.js';
|
|
34
43
|
/**
|
|
35
44
|
* Every lifecycle phase a tracked transaction can be in, from intent
|
|
36
45
|
* through terminal observation. Carriers (helpers, trackers, SDKs)
|
|
@@ -39,45 +48,98 @@ import type { Hex, TransactionReceipt } from 'viem';
|
|
|
39
48
|
*/
|
|
40
49
|
export type WritePhase = 'preparing' | 'awaiting-signature' | 'pending' | 'confirmed' | 'failed' | 'dropped' | 'replaced';
|
|
41
50
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
51
|
+
* Per-phase data delta. Each entry is exactly the fields available at
|
|
52
|
+
* that phase BEYOND the always-present `TxContext` (`chainId`,
|
|
53
|
+
* `request`).
|
|
54
|
+
*
|
|
55
|
+
* Adding a new phase is one entry here plus a fire-er; adding a new
|
|
56
|
+
* shared field is one entry in `TxContext`. The `WritePhaseEvent`
|
|
57
|
+
* union is derived from this map, so variants stay in lockstep
|
|
58
|
+
* mechanically.
|
|
59
|
+
*
|
|
60
|
+
* Declared as an `interface` (not a `type`) so consumers can use
|
|
61
|
+
* declaration merging to extend the map with their own phases — useful
|
|
62
|
+
* for trackers that surface implementation-specific transitions
|
|
63
|
+
* without forking the union.
|
|
64
|
+
*
|
|
65
|
+
* `block` is optional on `confirmed` / `failed` / `replaced` because
|
|
66
|
+
* `awaitReceiptWithHooks` allows opting out of the block fetch via
|
|
67
|
+
* `includeBlock: false`. Trackers that observe `replaced` from the
|
|
68
|
+
* mempool may also fire it without a receipt.
|
|
69
|
+
*/
|
|
70
|
+
export interface WritePhaseSteps {
|
|
71
|
+
preparing: object;
|
|
72
|
+
'awaiting-signature': object;
|
|
73
|
+
pending: {
|
|
74
|
+
hash: Hex;
|
|
75
|
+
};
|
|
76
|
+
confirmed: {
|
|
77
|
+
hash: Hex;
|
|
78
|
+
receipt: TransactionReceipt;
|
|
79
|
+
block?: Block;
|
|
80
|
+
};
|
|
81
|
+
failed: {
|
|
82
|
+
error: Error;
|
|
83
|
+
hash?: Hex;
|
|
84
|
+
receipt?: TransactionReceipt;
|
|
85
|
+
block?: Block;
|
|
86
|
+
};
|
|
87
|
+
dropped: {
|
|
88
|
+
hash: Hex;
|
|
89
|
+
};
|
|
90
|
+
replaced: {
|
|
91
|
+
original: Hex;
|
|
92
|
+
replacement: Hex;
|
|
93
|
+
receipt?: TransactionReceipt;
|
|
94
|
+
block?: Block;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Always-present transaction context surrounding every phase event.
|
|
99
|
+
* Carries the chain identity and the original send request so
|
|
100
|
+
* consumers don't have to maintain a side-channel `hash → request` map
|
|
101
|
+
* or call `client.chain.id` from inside their callbacks.
|
|
102
|
+
*
|
|
103
|
+
* `Extra` is the per-phase delta from `WritePhaseSteps[K]`. Defaulting
|
|
104
|
+
* `Extra` to `object` lets the bare `TxContext` describe phases with
|
|
105
|
+
* no extra fields (`preparing`, `awaiting-signature`).
|
|
106
|
+
*/
|
|
107
|
+
export type TxContext<Extra extends object = object> = {
|
|
108
|
+
/** Chain id this transaction targets. Pulled off `request.chainId`. */
|
|
109
|
+
chainId: number;
|
|
110
|
+
/**
|
|
111
|
+
* The fully-formed wallet send request as passed into the SDK
|
|
112
|
+
* (`to`, `data`, `value`, `chainId`, gas inputs). Carried verbatim
|
|
113
|
+
* so consumers can construct a tracked-tx record or replay the
|
|
114
|
+
* input without extra plumbing.
|
|
115
|
+
*/
|
|
116
|
+
request: WalletSendTransactionRequest;
|
|
117
|
+
} & Extra;
|
|
118
|
+
/**
|
|
119
|
+
* Discriminated-union event payload for the `onPhase` callback.
|
|
120
|
+
* Switch on `event.phase` and TypeScript narrows the rest of the
|
|
121
|
+
* fields automatically — no `event.context?.receipt` indirection.
|
|
122
|
+
*
|
|
123
|
+
* Derived mechanically from `WritePhaseSteps` × `TxContext` so adding
|
|
124
|
+
* a phase to the map is the only edit needed to extend the union.
|
|
45
125
|
*/
|
|
46
126
|
export type WritePhaseEvent = {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
phase: 'pending';
|
|
52
|
-
hash: Hex;
|
|
53
|
-
} | {
|
|
54
|
-
phase: 'confirmed';
|
|
55
|
-
hash: Hex;
|
|
56
|
-
receipt: TransactionReceipt;
|
|
57
|
-
} | {
|
|
58
|
-
phase: 'failed';
|
|
59
|
-
error: Error;
|
|
60
|
-
hash?: Hex;
|
|
61
|
-
receipt?: TransactionReceipt;
|
|
62
|
-
} | {
|
|
63
|
-
phase: 'dropped';
|
|
64
|
-
hash: Hex;
|
|
65
|
-
} | {
|
|
66
|
-
phase: 'replaced';
|
|
67
|
-
original: Hex;
|
|
68
|
-
replacement: Hex;
|
|
69
|
-
receipt?: TransactionReceipt;
|
|
70
|
-
};
|
|
127
|
+
[K in keyof WritePhaseSteps]: {
|
|
128
|
+
phase: K;
|
|
129
|
+
} & TxContext<WritePhaseSteps[K]>;
|
|
130
|
+
}[keyof WritePhaseSteps];
|
|
71
131
|
/**
|
|
72
132
|
* Per-call hooks fired at real boundaries during a tracked tx's
|
|
73
133
|
* lifecycle. Every field is optional. SDKs and trackers fire whichever
|
|
74
134
|
* subset corresponds to phases they actually observe; consumers wire
|
|
75
135
|
* only the ones their UI needs.
|
|
76
136
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
137
|
+
* Each named hook receives a `TxContext<WritePhaseSteps[K]>` info bag
|
|
138
|
+
* matching the phase. The `onPhase` complement receives the full
|
|
139
|
+
* discriminated union. Fire-ers fire both for every transition — the
|
|
140
|
+
* named hook (if a consumer wired it) and `onPhase` (if a consumer
|
|
141
|
+
* wired it) — so no transition is observable from one shape but not
|
|
142
|
+
* the other.
|
|
81
143
|
*/
|
|
82
144
|
export interface WriteHookParams {
|
|
83
145
|
/**
|
|
@@ -85,34 +147,42 @@ export interface WriteHookParams {
|
|
|
85
147
|
* from "preparing" to "awaiting wallet signature" at the precise
|
|
86
148
|
* boundary, regardless of how much pre-wallet work the SDK did.
|
|
87
149
|
*/
|
|
88
|
-
onAwaitingSignature?: () => void;
|
|
150
|
+
onAwaitingSignature?: (info: TxContext<WritePhaseSteps['awaiting-signature']>) => void;
|
|
89
151
|
/**
|
|
90
|
-
* Called once with the on-chain tx hash
|
|
91
|
-
* `sendTransaction` resolves and *before* any
|
|
92
|
-
* from "awaiting" to "pending" the moment
|
|
152
|
+
* Called once with the on-chain tx hash plus full context,
|
|
153
|
+
* immediately after `sendTransaction` resolves and *before* any
|
|
154
|
+
* receipt-await. UI flips from "awaiting" to "pending" the moment
|
|
155
|
+
* the hash exists.
|
|
93
156
|
*
|
|
94
157
|
* Per-call vs constructor-level: SDKs may also expose a separate
|
|
95
158
|
* constructor-level `onTransactionHash` channel for analytics /
|
|
96
|
-
* global observers — they're complementary, fire on the same line
|
|
159
|
+
* global observers — they're complementary, fire on the same line
|
|
160
|
+
* with the same payload.
|
|
97
161
|
*/
|
|
98
|
-
onTransactionHash?: (
|
|
162
|
+
onTransactionHash?: (info: TxContext<WritePhaseSteps['pending']>) => void;
|
|
99
163
|
/**
|
|
100
|
-
* Called once
|
|
101
|
-
*
|
|
102
|
-
*
|
|
164
|
+
* Called once when `receipt.status === 'success'`. Receives the full
|
|
165
|
+
* info bag — `hash`, `receipt`, optional `block` (present unless
|
|
166
|
+
* `includeBlock: false` was passed), plus `chainId` and `request` —
|
|
167
|
+
* so consumers don't re-fetch the block for timestamp / baseFee
|
|
168
|
+
* UI.
|
|
103
169
|
*/
|
|
104
|
-
onConfirmed?: (
|
|
170
|
+
onConfirmed?: (info: TxContext<WritePhaseSteps['confirmed']>) => void;
|
|
105
171
|
/**
|
|
106
|
-
* Called once with the underlying error
|
|
107
|
-
*
|
|
172
|
+
* Called once with the underlying error (and any context available
|
|
173
|
+
* at the failure point) on any terminal failure that is NOT a
|
|
174
|
+
* replacement or a drop:
|
|
108
175
|
* - wallet rejection (`WalletRejectedError`)
|
|
109
176
|
* - on-chain revert (`ContractRevertedError`)
|
|
110
177
|
* - any other thrown error from the wallet or RPC.
|
|
111
178
|
*
|
|
112
|
-
* Use `instanceof` against `WalletRejectedError` /
|
|
113
|
-
* to discriminate; everything else is a
|
|
179
|
+
* Use `instanceof` against `WalletRejectedError` /
|
|
180
|
+
* `ContractRevertedError` to discriminate; everything else is a
|
|
181
|
+
* plain `Error`. Wallet-side failures carry no `hash` / `receipt`;
|
|
182
|
+
* receipt-bearing failures (revert) carry both, plus the block
|
|
183
|
+
* (unless `includeBlock: false`).
|
|
114
184
|
*/
|
|
115
|
-
onFailed?: (
|
|
185
|
+
onFailed?: (info: TxContext<WritePhaseSteps['failed']>) => void;
|
|
116
186
|
/**
|
|
117
187
|
* Called once when a tracker has determined the tx will not be
|
|
118
188
|
* included — typically: not seen in mempool for N consecutive blocks
|
|
@@ -124,24 +194,18 @@ export interface WriteHookParams {
|
|
|
124
194
|
* observation. Wire this against a `tx-tracker` instance, not against
|
|
125
195
|
* `awaitReceiptWithHooks`.
|
|
126
196
|
*/
|
|
127
|
-
onDropped?: (info:
|
|
128
|
-
hash: Hex;
|
|
129
|
-
}) => void;
|
|
197
|
+
onDropped?: (info: TxContext<WritePhaseSteps['dropped']>) => void;
|
|
130
198
|
/**
|
|
131
199
|
* Called once when a tracker observes that a *different* tx with the
|
|
132
200
|
* same nonce mined in place of the one we were watching — typically
|
|
133
201
|
* the user's own speed-up / cancel from their wallet, or a
|
|
134
202
|
* fee-replacement broadcast separately.
|
|
135
203
|
*
|
|
136
|
-
* `
|
|
137
|
-
* mined; trackers may emit `replaced`
|
|
138
|
-
* saw the replacement in the mempool.
|
|
204
|
+
* `info.receipt` and `info.block` are populated when the replacement
|
|
205
|
+
* has been mined; trackers may emit `replaced` without them if they
|
|
206
|
+
* only saw the replacement in the mempool.
|
|
139
207
|
*/
|
|
140
|
-
onReplaced?: (info:
|
|
141
|
-
original: Hex;
|
|
142
|
-
replacement: Hex;
|
|
143
|
-
receipt?: TransactionReceipt;
|
|
144
|
-
}) => void;
|
|
208
|
+
onReplaced?: (info: TxContext<WritePhaseSteps['replaced']>) => void;
|
|
145
209
|
/**
|
|
146
210
|
* Single-callback complement to the named hooks. Fires for every
|
|
147
211
|
* lifecycle transition with a discriminated-union payload. Useful
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAA;AAC1D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAClB,WAAW,GACX,oBAAoB,GACpB,SAAS,GACT,WAAW,GACX,QAAQ,GACR,SAAS,GACT,UAAU,CAAA;AAEd;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,OAAO,EAAE;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,CAAA;IACtB,SAAS,EAAE;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,kBAAkB,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,CAAA;IACpE,MAAM,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,CAAA;IACjF,OAAO,EAAE;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,CAAA;IACtB,QAAQ,EAAE;QAAE,QAAQ,EAAE,GAAG,CAAC;QAAC,WAAW,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,CAAA;CAC3F;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI;IACrD,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,OAAO,EAAE,4BAA4B,CAAA;CACtC,GAAG,KAAK,CAAA;AAET;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG;KAC3B,CAAC,IAAI,MAAM,eAAe,GAAG;QAAE,KAAK,EAAE,CAAC,CAAA;KAAE,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CAC3E,CAAC,MAAM,eAAe,CAAC,CAAA;AAExB;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC,KAAK,IAAI,CAAA;IACtF;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,CAAA;IACzE;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAA;IACrE;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAA;IAC/D;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,CAAA;IACjE;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,IAAI,CAAA;IACnE;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;CAC3C"}
|
package/dist/hooks.js
CHANGED
|
@@ -29,6 +29,14 @@
|
|
|
29
29
|
*
|
|
30
30
|
* Fire-ers fire BOTH shapes for every transition — exactly once each —
|
|
31
31
|
* so consumers can choose which to wire without affecting the other.
|
|
32
|
+
*
|
|
33
|
+
* Every payload carries a `TxContext` (`chainId` + `request`) so
|
|
34
|
+
* consumers never have to side-channel the originating chain or the
|
|
35
|
+
* original send request to use the events. `confirmed` and
|
|
36
|
+
* receipt-bearing `failed` events also carry the containing `Block` so
|
|
37
|
+
* downstream trackers don't have to re-fetch it for timestamp / fee
|
|
38
|
+
* analytics — that's the "don't make consumers re-gather what we
|
|
39
|
+
* already have" rule the events are designed around.
|
|
32
40
|
*/
|
|
33
41
|
export {};
|
|
34
42
|
//# sourceMappingURL=hooks.js.map
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @fileoverview Public API of `@valve-tech/wallet-adapter`.
|
|
3
3
|
*/
|
|
4
4
|
export type { WalletAdapter, WalletSendTransactionRequest, WalletReadContractRequest, } from './wallet.js';
|
|
5
|
-
export type { WriteHookParams, WritePhase, WritePhaseEvent, } from './hooks.js';
|
|
5
|
+
export type { TxContext, WriteHookParams, WritePhase, WritePhaseEvent, WritePhaseSteps, } from './hooks.js';
|
|
6
6
|
export { TX_STATUS, TX_FLOW, STALE_TX_AGE_MS, CONFIRMED_DISPLAY_MS, FAILED_DISPLAY_MS, } from './tx-status.js';
|
|
7
7
|
export type { TrackedTx, TrackedTxGas, TrackedTxStatus, TxFlow, TxConfirmedCallback, } from './tx-status.js';
|
|
8
8
|
export { sendTransactionWithHooks, WalletRejectedError, type SendTransactionWithHooksOptions, } from './send.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,aAAa,EACb,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,aAAa,CAAA;AAEpB,YAAY,EACV,eAAe,EACf,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,SAAS,EACT,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,SAAS,EACT,YAAY,EACZ,eAAe,EACf,MAAM,EACN,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,+BAA+B,GACrC,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,aAAa,EACb,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,aAAa,CAAA;AAEpB,YAAY,EACV,SAAS,EACT,eAAe,EACf,UAAU,EACV,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,SAAS,EACT,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,SAAS,EACT,YAAY,EACZ,eAAe,EACf,MAAM,EACN,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,+BAA+B,GACrC,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgBH,OAAO,EACL,SAAS,EACT,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AAUvB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GAEpB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GAGtB,MAAM,cAAc,CAAA"}
|
package/dist/receipt.d.ts
CHANGED
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* After the wallet returns a hash, an SDK has to:
|
|
5
5
|
* 1. Await the receipt.
|
|
6
|
-
* 2.
|
|
7
|
-
*
|
|
6
|
+
* 2. Pull the containing block (so consumers don't re-fetch it just
|
|
7
|
+
* for `timestamp` / `baseFeePerGas`).
|
|
8
|
+
* 3. Distinguish `success` from `reverted`.
|
|
9
|
+
* 4. Fire `onConfirmed` (success) or `onFailed` with a typed revert
|
|
8
10
|
* error (reverted), plus `onPhase` for the same transition, so any
|
|
9
11
|
* UI wired against `WriteHookParams` flips to a terminal state.
|
|
10
12
|
*
|
|
11
|
-
* Without a helper for this, every SDK re-implements the receipt-await
|
|
12
|
-
* status-check + typed-error-throw block —
|
|
13
|
-
*
|
|
13
|
+
* Without a helper for this, every SDK re-implements: the receipt-await
|
|
14
|
+
* + block-fetch + status-check + typed-error-throw block — and worse,
|
|
15
|
+
* every SDK either re-fetches the block in its own callbacks or skips
|
|
16
|
+
* it and forces every consumer to fetch it. The amortization here is
|
|
17
|
+
* the whole point: one `getBlock` call inside this helper, every
|
|
18
|
+
* downstream consumer skips it.
|
|
14
19
|
*
|
|
15
20
|
* Drop detection (tx vanished from mempool without inclusion) and
|
|
16
21
|
* replacement detection are deliberately NOT in this helper. They
|
|
@@ -20,8 +25,9 @@
|
|
|
20
25
|
* defines `onDropped` / `onReplaced` so consumers can wire them once;
|
|
21
26
|
* this helper just doesn't fire them.
|
|
22
27
|
*/
|
|
23
|
-
import type { Hex, TransactionReceipt } from 'viem';
|
|
28
|
+
import type { Block, Hex, TransactionReceipt } from 'viem';
|
|
24
29
|
import type { WriteHookParams } from './hooks.js';
|
|
30
|
+
import type { WalletSendTransactionRequest } from './wallet.js';
|
|
25
31
|
/**
|
|
26
32
|
* Thrown by `awaitReceiptWithHooks` when the receipt arrives with
|
|
27
33
|
* `status === 'reverted'`. The full receipt is preserved so consumers
|
|
@@ -42,30 +48,60 @@ export declare class ContractRevertedError extends Error {
|
|
|
42
48
|
* Minimal viem `PublicClient` slice the helper needs. Defining it
|
|
43
49
|
* locally lets consumers pass a viem client OR a hand-rolled mock
|
|
44
50
|
* without depending on the full `PublicClient` surface.
|
|
51
|
+
*
|
|
52
|
+
* `getBlock` is invoked once on receipt success / revert (when
|
|
53
|
+
* `includeBlock` is left at its default of `true`) so the resulting
|
|
54
|
+
* `confirmed` / `failed` event payload carries the block timestamp,
|
|
55
|
+
* baseFeePerGas, etc. without forcing every consumer to fetch it.
|
|
45
56
|
*/
|
|
46
57
|
export interface ReceiptAwaiter {
|
|
47
58
|
waitForTransactionReceipt(args: {
|
|
48
59
|
hash: Hex;
|
|
49
60
|
}): Promise<TransactionReceipt>;
|
|
61
|
+
getBlock(args: {
|
|
62
|
+
blockHash: Hex;
|
|
63
|
+
}): Promise<Block>;
|
|
50
64
|
}
|
|
51
65
|
export interface AwaitReceiptWithHooksOptions {
|
|
52
|
-
/** A viem `PublicClient` (or anything with the same
|
|
66
|
+
/** A viem `PublicClient` (or anything with the same shape). */
|
|
53
67
|
publicClient: ReceiptAwaiter;
|
|
54
68
|
/** The hash returned by `sendTransactionWithHooks` (or any other broadcast path). */
|
|
55
69
|
hash: Hex;
|
|
56
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* The original send request. Carried into all phase events as part
|
|
72
|
+
* of the always-present `TxContext` so consumers don't have to
|
|
73
|
+
* maintain a side-channel `hash → request` map.
|
|
74
|
+
*/
|
|
75
|
+
request: WalletSendTransactionRequest;
|
|
76
|
+
/**
|
|
77
|
+
* Whether to fetch and attach the containing `Block` to `confirmed`
|
|
78
|
+
* and revert-`failed` event payloads. Defaults to `true` — the
|
|
79
|
+
* helper is the right place to amortize the block fetch on behalf of
|
|
80
|
+
* every downstream consumer. Pass `false` to skip the extra RPC
|
|
81
|
+
* round trip when no consumer needs block-level data.
|
|
82
|
+
*/
|
|
83
|
+
includeBlock?: boolean;
|
|
84
|
+
/** Per-call hooks. `onConfirmed` and `onFailed` fire from this helper. */
|
|
57
85
|
hooks?: WriteHookParams;
|
|
58
86
|
}
|
|
59
87
|
/**
|
|
60
|
-
* Await a transaction receipt and fire the post-hash lifecycle hooks
|
|
88
|
+
* Await a transaction receipt and fire the post-hash lifecycle hooks
|
|
89
|
+
* with rich payloads (chainId, request, hash, receipt, block).
|
|
90
|
+
*
|
|
61
91
|
* Throws `ContractRevertedError` on revert. Other errors during the
|
|
62
92
|
* receipt-await are re-thrown unchanged after `onFailed` fires.
|
|
63
93
|
*
|
|
64
94
|
* @example
|
|
65
95
|
* ```ts
|
|
66
96
|
* const hash = await sendTransactionWithHooks({ wallet, request, hooks })
|
|
67
|
-
* const receipt = await awaitReceiptWithHooks({
|
|
68
|
-
*
|
|
97
|
+
* const receipt = await awaitReceiptWithHooks({
|
|
98
|
+
* publicClient,
|
|
99
|
+
* hash,
|
|
100
|
+
* request, // same shape passed to sendTransactionWithHooks
|
|
101
|
+
* hooks,
|
|
102
|
+
* })
|
|
103
|
+
* // onConfirmed / onFailed have fired by the time we get here, with
|
|
104
|
+
* // chainId + request + hash + receipt + block in scope.
|
|
69
105
|
* ```
|
|
70
106
|
*/
|
|
71
107
|
export declare function awaitReceiptWithHooks(options: AwaitReceiptWithHooksOptions): Promise<TransactionReceipt>;
|
package/dist/receipt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAA;AAC1D,OAAO,KAAK,EAAa,eAAe,EAAmB,MAAM,YAAY,CAAA;AAC7E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAE/D;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;IAClB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;gBAExB,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,kBAAkB;CAMnD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,yBAAyB,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC3E,QAAQ,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;CACnD;AAED,MAAM,WAAW,4BAA4B;IAC3C,+DAA+D;IAC/D,YAAY,EAAE,cAAc,CAAA;IAC5B,qFAAqF;IACrF,IAAI,EAAE,GAAG,CAAA;IACT;;;;OAIG;IACH,OAAO,EAAE,4BAA4B,CAAA;IACrC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,eAAe,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,kBAAkB,CAAC,CA0C7B"}
|
package/dist/receipt.js
CHANGED
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* After the wallet returns a hash, an SDK has to:
|
|
5
5
|
* 1. Await the receipt.
|
|
6
|
-
* 2.
|
|
7
|
-
*
|
|
6
|
+
* 2. Pull the containing block (so consumers don't re-fetch it just
|
|
7
|
+
* for `timestamp` / `baseFeePerGas`).
|
|
8
|
+
* 3. Distinguish `success` from `reverted`.
|
|
9
|
+
* 4. Fire `onConfirmed` (success) or `onFailed` with a typed revert
|
|
8
10
|
* error (reverted), plus `onPhase` for the same transition, so any
|
|
9
11
|
* UI wired against `WriteHookParams` flips to a terminal state.
|
|
10
12
|
*
|
|
11
|
-
* Without a helper for this, every SDK re-implements the receipt-await
|
|
12
|
-
* status-check + typed-error-throw block —
|
|
13
|
-
*
|
|
13
|
+
* Without a helper for this, every SDK re-implements: the receipt-await
|
|
14
|
+
* + block-fetch + status-check + typed-error-throw block — and worse,
|
|
15
|
+
* every SDK either re-fetches the block in its own callbacks or skips
|
|
16
|
+
* it and forces every consumer to fetch it. The amortization here is
|
|
17
|
+
* the whole point: one `getBlock` call inside this helper, every
|
|
18
|
+
* downstream consumer skips it.
|
|
14
19
|
*
|
|
15
20
|
* Drop detection (tx vanished from mempool without inclusion) and
|
|
16
21
|
* replacement detection are deliberately NOT in this helper. They
|
|
@@ -38,37 +43,63 @@ export class ContractRevertedError extends Error {
|
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
45
|
/**
|
|
41
|
-
* Await a transaction receipt and fire the post-hash lifecycle hooks
|
|
46
|
+
* Await a transaction receipt and fire the post-hash lifecycle hooks
|
|
47
|
+
* with rich payloads (chainId, request, hash, receipt, block).
|
|
48
|
+
*
|
|
42
49
|
* Throws `ContractRevertedError` on revert. Other errors during the
|
|
43
50
|
* receipt-await are re-thrown unchanged after `onFailed` fires.
|
|
44
51
|
*
|
|
45
52
|
* @example
|
|
46
53
|
* ```ts
|
|
47
54
|
* const hash = await sendTransactionWithHooks({ wallet, request, hooks })
|
|
48
|
-
* const receipt = await awaitReceiptWithHooks({
|
|
49
|
-
*
|
|
55
|
+
* const receipt = await awaitReceiptWithHooks({
|
|
56
|
+
* publicClient,
|
|
57
|
+
* hash,
|
|
58
|
+
* request, // same shape passed to sendTransactionWithHooks
|
|
59
|
+
* hooks,
|
|
60
|
+
* })
|
|
61
|
+
* // onConfirmed / onFailed have fired by the time we get here, with
|
|
62
|
+
* // chainId + request + hash + receipt + block in scope.
|
|
50
63
|
* ```
|
|
51
64
|
*/
|
|
52
65
|
export async function awaitReceiptWithHooks(options) {
|
|
53
|
-
const { publicClient, hash, hooks } = options;
|
|
66
|
+
const { publicClient, hash, request, includeBlock = true, hooks } = options;
|
|
67
|
+
const ctx = { chainId: request.chainId, request };
|
|
54
68
|
let receipt;
|
|
55
69
|
try {
|
|
56
70
|
receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
57
71
|
}
|
|
58
72
|
catch (err) {
|
|
59
73
|
const failure = err instanceof Error ? err : new Error(String(err));
|
|
60
|
-
|
|
61
|
-
hooks?.
|
|
74
|
+
const failedInfo = { ...ctx, error: failure };
|
|
75
|
+
hooks?.onFailed?.(failedInfo);
|
|
76
|
+
hooks?.onPhase?.({ phase: 'failed', ...failedInfo });
|
|
62
77
|
throw failure;
|
|
63
78
|
}
|
|
79
|
+
const block = includeBlock
|
|
80
|
+
? await publicClient.getBlock({ blockHash: receipt.blockHash })
|
|
81
|
+
: undefined;
|
|
64
82
|
if (receipt.status === 'reverted') {
|
|
65
83
|
const revert = new ContractRevertedError(hash, receipt);
|
|
66
|
-
|
|
67
|
-
|
|
84
|
+
const failedInfo = {
|
|
85
|
+
...ctx,
|
|
86
|
+
error: revert,
|
|
87
|
+
hash,
|
|
88
|
+
receipt,
|
|
89
|
+
...(block ? { block } : {}),
|
|
90
|
+
};
|
|
91
|
+
hooks?.onFailed?.(failedInfo);
|
|
92
|
+
hooks?.onPhase?.({ phase: 'failed', ...failedInfo });
|
|
68
93
|
throw revert;
|
|
69
94
|
}
|
|
70
|
-
|
|
71
|
-
|
|
95
|
+
const confirmedInfo = {
|
|
96
|
+
...ctx,
|
|
97
|
+
hash,
|
|
98
|
+
receipt,
|
|
99
|
+
...(block ? { block } : {}),
|
|
100
|
+
};
|
|
101
|
+
hooks?.onConfirmed?.(confirmedInfo);
|
|
102
|
+
hooks?.onPhase?.({ phase: 'confirmed', ...confirmedInfo });
|
|
72
103
|
return receipt;
|
|
73
104
|
}
|
|
74
105
|
//# sourceMappingURL=receipt.js.map
|
package/dist/receipt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receipt.js","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"receipt.js","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH;;;;;;;;GAQG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAM9C,YAAY,IAAS,EAAE,OAA2B;QAChD,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACvC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;CACF;AAwCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAA;IAC3E,MAAM,GAAG,GAAc,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,CAAA;IAE5D,IAAI,OAA2B,CAAA;IAC/B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,YAAY,CAAC,yBAAyB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IAClE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QACnE,MAAM,UAAU,GAAyC,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;QACnF,KAAK,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAA;QAC7B,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,CAAC,CAAA;QACpD,MAAM,OAAO,CAAA;IACf,CAAC;IAED,MAAM,KAAK,GAAG,YAAY;QACxB,CAAC,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAC/D,CAAC,CAAC,SAAS,CAAA;IAEb,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACvD,MAAM,UAAU,GAAyC;YACvD,GAAG,GAAG;YACN,KAAK,EAAE,MAAM;YACb,IAAI;YACJ,OAAO;YACP,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5B,CAAA;QACD,KAAK,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAA;QAC7B,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,CAAC,CAAA;QACpD,MAAM,MAAM,CAAA;IACd,CAAC;IAED,MAAM,aAAa,GAA4C;QAC7D,GAAG,GAAG;QACN,IAAI;QACJ,OAAO;QACP,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5B,CAAA;IACD,KAAK,EAAE,WAAW,EAAE,CAAC,aAAa,CAAC,CAAA;IACnC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,aAAa,EAAE,CAAC,CAAA;IAC1D,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
package/dist/send.d.ts
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* This is the runtime piece of the lifecycle contract. SDK authors call
|
|
6
6
|
* this from inside any write method that opens a wallet popup; it
|
|
7
7
|
* guarantees:
|
|
8
|
-
* - `onAwaitingSignature` fires exactly once
|
|
9
|
-
* `wallet.sendTransaction(...)`.
|
|
8
|
+
* - `onAwaitingSignature` fires exactly once with `TxContext` (chainId
|
|
9
|
+
* + request), immediately before `wallet.sendTransaction(...)`.
|
|
10
10
|
* - `onTransactionHash` (per-call) and the global `onTransactionHash`
|
|
11
|
-
* channel fire exactly once each
|
|
12
|
-
* and BEFORE the SDK awaits any receipt
|
|
13
|
-
* UI from `awaiting-signature` to
|
|
14
|
-
* instead of stalling for the
|
|
11
|
+
* channel fire exactly once each with `TxContext + hash`, after
|
|
12
|
+
* `sendTransaction` resolves and BEFORE the SDK awaits any receipt
|
|
13
|
+
* — so callers can flip their UI from `awaiting-signature` to
|
|
14
|
+
* `pending` the moment a hash exists instead of stalling for the
|
|
15
|
+
* full inclusion window.
|
|
15
16
|
* - Wallet rejections (EIP-1193 `code === 4001`, viem's
|
|
16
17
|
* `UserRejectedRequestError`, or matching message text — see
|
|
17
18
|
* `@valve-tech/viem-errors` for the detection signals) are converted
|
|
@@ -19,14 +20,13 @@
|
|
|
19
20
|
* them. Non-rejection errors are re-thrown unchanged so the SDK
|
|
20
21
|
* can map them to its own typed error vocabulary.
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* fan-out, and the precise ordering relative to `sendTransaction`.
|
|
23
|
+
* Every payload carries `chainId` and the original `request`, so
|
|
24
|
+
* analytics observers and tx-tracker consumers don't need to keep a
|
|
25
|
+
* side-channel `hash → request` map or read chainId off the client.
|
|
26
26
|
*/
|
|
27
27
|
import type { Hex } from 'viem';
|
|
28
28
|
import type { WalletAdapter, WalletSendTransactionRequest } from './wallet.js';
|
|
29
|
-
import type { WriteHookParams } from './hooks.js';
|
|
29
|
+
import type { TxContext, WriteHookParams, WritePhaseSteps } from './hooks.js';
|
|
30
30
|
/**
|
|
31
31
|
* Thrown by `sendTransactionWithHooks` when the wallet rejection is
|
|
32
32
|
* detected at any level of the cause chain. The original error is
|
|
@@ -47,16 +47,16 @@ export interface SendTransactionWithHooksOptions {
|
|
|
47
47
|
wallet: WalletAdapter;
|
|
48
48
|
/** The fully-formed send request (calldata, gas inputs, chainId). */
|
|
49
49
|
request: WalletSendTransactionRequest;
|
|
50
|
-
/** Per-call lifecycle hooks.
|
|
50
|
+
/** Per-call lifecycle hooks. All fields are optional. */
|
|
51
51
|
hooks?: WriteHookParams;
|
|
52
52
|
/**
|
|
53
53
|
* Optional global / constructor-level `onTransactionHash` channel.
|
|
54
54
|
* Fires alongside `hooks.onTransactionHash` on the same line —
|
|
55
|
-
* complementary, not alternatives.
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* complementary, not alternatives. Receives the same rich
|
|
56
|
+
* `TxContext + hash` payload so analytics observers don't have to
|
|
57
|
+
* resolve chainId / request from a side channel.
|
|
58
58
|
*/
|
|
59
|
-
onTransactionHash?: (
|
|
59
|
+
onTransactionHash?: (info: TxContext<WritePhaseSteps['pending']>) => void;
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
62
|
* Submit a transaction through the wallet adapter, firing lifecycle
|
|
@@ -72,7 +72,12 @@ export interface SendTransactionWithHooksOptions {
|
|
|
72
72
|
* hooks: params, // user-supplied per-call hooks
|
|
73
73
|
* onTransactionHash: this.onHash, // constructor-level / analytics
|
|
74
74
|
* })
|
|
75
|
-
* const receipt = await
|
|
75
|
+
* const receipt = await awaitReceiptWithHooks({
|
|
76
|
+
* publicClient,
|
|
77
|
+
* hash,
|
|
78
|
+
* request: { ...prepared, ...gasInputs },
|
|
79
|
+
* hooks: params,
|
|
80
|
+
* })
|
|
76
81
|
* return { hash, receipt }
|
|
77
82
|
* } catch (err) {
|
|
78
83
|
* if (err instanceof WalletRejectedError) {
|
package/dist/send.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../src/send.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../src/send.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE7E;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;gBAET,KAAK,EAAE,KAAK;CAKzB;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,iEAAiE;IACjE,MAAM,EAAE,aAAa,CAAA;IACrB,qEAAqE;IACrE,OAAO,EAAE,4BAA4B,CAAA;IACrC,yDAAyD;IACzD,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,CAAA;CAC1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,GAAG,CAAC,CA0Bd"}
|
package/dist/send.js
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* This is the runtime piece of the lifecycle contract. SDK authors call
|
|
6
6
|
* this from inside any write method that opens a wallet popup; it
|
|
7
7
|
* guarantees:
|
|
8
|
-
* - `onAwaitingSignature` fires exactly once
|
|
9
|
-
* `wallet.sendTransaction(...)`.
|
|
8
|
+
* - `onAwaitingSignature` fires exactly once with `TxContext` (chainId
|
|
9
|
+
* + request), immediately before `wallet.sendTransaction(...)`.
|
|
10
10
|
* - `onTransactionHash` (per-call) and the global `onTransactionHash`
|
|
11
|
-
* channel fire exactly once each
|
|
12
|
-
* and BEFORE the SDK awaits any receipt
|
|
13
|
-
* UI from `awaiting-signature` to
|
|
14
|
-
* instead of stalling for the
|
|
11
|
+
* channel fire exactly once each with `TxContext + hash`, after
|
|
12
|
+
* `sendTransaction` resolves and BEFORE the SDK awaits any receipt
|
|
13
|
+
* — so callers can flip their UI from `awaiting-signature` to
|
|
14
|
+
* `pending` the moment a hash exists instead of stalling for the
|
|
15
|
+
* full inclusion window.
|
|
15
16
|
* - Wallet rejections (EIP-1193 `code === 4001`, viem's
|
|
16
17
|
* `UserRejectedRequestError`, or matching message text — see
|
|
17
18
|
* `@valve-tech/viem-errors` for the detection signals) are converted
|
|
@@ -19,10 +20,9 @@
|
|
|
19
20
|
* them. Non-rejection errors are re-thrown unchanged so the SDK
|
|
20
21
|
* can map them to its own typed error vocabulary.
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* fan-out, and the precise ordering relative to `sendTransaction`.
|
|
23
|
+
* Every payload carries `chainId` and the original `request`, so
|
|
24
|
+
* analytics observers and tx-tracker consumers don't need to keep a
|
|
25
|
+
* side-channel `hash → request` map or read chainId off the client.
|
|
26
26
|
*/
|
|
27
27
|
import { isUserRejectionError } from '@valve-tech/viem-errors';
|
|
28
28
|
/**
|
|
@@ -53,7 +53,12 @@ export class WalletRejectedError extends Error {
|
|
|
53
53
|
* hooks: params, // user-supplied per-call hooks
|
|
54
54
|
* onTransactionHash: this.onHash, // constructor-level / analytics
|
|
55
55
|
* })
|
|
56
|
-
* const receipt = await
|
|
56
|
+
* const receipt = await awaitReceiptWithHooks({
|
|
57
|
+
* publicClient,
|
|
58
|
+
* hash,
|
|
59
|
+
* request: { ...prepared, ...gasInputs },
|
|
60
|
+
* hooks: params,
|
|
61
|
+
* })
|
|
57
62
|
* return { hash, receipt }
|
|
58
63
|
* } catch (err) {
|
|
59
64
|
* if (err instanceof WalletRejectedError) {
|
|
@@ -65,10 +70,11 @@ export class WalletRejectedError extends Error {
|
|
|
65
70
|
*/
|
|
66
71
|
export async function sendTransactionWithHooks(options) {
|
|
67
72
|
const { wallet, request, hooks, onTransactionHash } = options;
|
|
73
|
+
const ctx = { chainId: request.chainId, request };
|
|
68
74
|
let hash;
|
|
69
75
|
try {
|
|
70
|
-
hooks?.onAwaitingSignature?.();
|
|
71
|
-
hooks?.onPhase?.({ phase: 'awaiting-signature' });
|
|
76
|
+
hooks?.onAwaitingSignature?.(ctx);
|
|
77
|
+
hooks?.onPhase?.({ phase: 'awaiting-signature', ...ctx });
|
|
72
78
|
hash = await wallet.sendTransaction(request);
|
|
73
79
|
}
|
|
74
80
|
catch (err) {
|
|
@@ -77,13 +83,15 @@ export async function sendTransactionWithHooks(options) {
|
|
|
77
83
|
: err instanceof Error
|
|
78
84
|
? err
|
|
79
85
|
: new Error(String(err));
|
|
80
|
-
|
|
81
|
-
hooks?.
|
|
86
|
+
const failedInfo = { ...ctx, error: failure };
|
|
87
|
+
hooks?.onFailed?.(failedInfo);
|
|
88
|
+
hooks?.onPhase?.({ phase: 'failed', ...failedInfo });
|
|
82
89
|
throw failure;
|
|
83
90
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
hooks?.
|
|
91
|
+
const pendingInfo = { ...ctx, hash };
|
|
92
|
+
onTransactionHash?.(pendingInfo);
|
|
93
|
+
hooks?.onTransactionHash?.(pendingInfo);
|
|
94
|
+
hooks?.onPhase?.({ phase: 'pending', ...pendingInfo });
|
|
87
95
|
return hash;
|
|
88
96
|
}
|
|
89
97
|
//# sourceMappingURL=send.js.map
|
package/dist/send.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send.js","sourceRoot":"","sources":["../src/send.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAI9D;;;;;;GAMG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAI5C,YAAY,KAAY;QACtB,KAAK,CAAC,qCAAqC,CAAC,CAAA;QAC5C,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF;AAsBD
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../src/send.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAI9D;;;;;;GAMG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAI5C,YAAY,KAAY;QACtB,KAAK,CAAC,qCAAqC,CAAC,CAAA;QAC5C,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF;AAsBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAwC;IAExC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAA;IAC7D,MAAM,GAAG,GAAc,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,CAAA;IAE5D,IAAI,IAAS,CAAA;IACb,IAAI,CAAC;QACH,KAAK,EAAE,mBAAmB,EAAE,CAAC,GAAG,CAAC,CAAA;QACjC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,GAAG,GAAG,EAAE,CAAC,CAAA;QACzD,IAAI,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,oBAAoB,CAAC,GAAG,CAAC;YACvC,CAAC,CAAC,IAAI,mBAAmB,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9E,CAAC,CAAC,GAAG,YAAY,KAAK;gBACpB,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QAC5B,MAAM,UAAU,GAAyC,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;QACnF,KAAK,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAA;QAC7B,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,CAAC,CAAA;QACpD,MAAM,OAAO,CAAA;IACf,CAAC;IAED,MAAM,WAAW,GAA0C,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,CAAA;IAC3E,iBAAiB,EAAE,CAAC,WAAW,CAAC,CAAA;IAChC,KAAK,EAAE,iBAAiB,EAAE,CAAC,WAAW,CAAC,CAAA;IACvC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,WAAW,EAAE,CAAC,CAAA;IACtD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valve-tech/wallet-adapter",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Framework-agnostic vocabulary + runtime helpers for EVM dapp wallet integration. WalletAdapter interface (sign + send), WriteHookParams full lifecycle (onAwaitingSignature, onTransactionHash, onConfirmed, onFailed, onDropped, onReplaced) plus complementary onPhase(event) discriminated-union shape
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Framework-agnostic vocabulary + runtime helpers for EVM dapp wallet integration. WalletAdapter interface (sign + send), WriteHookParams full lifecycle with rich TxContext payloads (chainId + original request) on every event so consumers don't side-channel; six named hooks (onAwaitingSignature, onTransactionHash, onConfirmed, onFailed, onDropped, onReplaced) plus complementary onPhase(event) discriminated-union shape derived from the WritePhaseSteps phase-map; sendTransactionWithHooks + awaitReceiptWithHooks helpers that fire the hooks at real boundaries (with awaitReceiptWithHooks fetching the containing block once on behalf of all downstream consumers); typed WalletRejectedError + ContractRevertedError for instanceof-discriminated catch; plus TX_STATUS / TX_FLOW / TrackedTx for tx-state UI. Lets SDKs and dapps share one contract instead of each redefining it. Part of the valve-tech/evm-toolkit synchronized release line.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/valve-tech/evm-toolkit/tree/main/packages/wallet-adapter#readme",
|
|
7
7
|
"repository": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"prepare": "yarn build"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@valve-tech/viem-errors": "^0.
|
|
49
|
+
"@valve-tech/viem-errors": "^0.5.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"viem": "^2.0.0"
|