viem 1.5.4 → 1.6.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.
Files changed (204) hide show
  1. package/chains/utils/package.json +5 -0
  2. package/dist/cjs/accounts/index.js +5 -1
  3. package/dist/cjs/accounts/index.js.map +1 -1
  4. package/dist/cjs/accounts/utils/privateKeyToAddress.js +12 -0
  5. package/dist/cjs/accounts/utils/privateKeyToAddress.js.map +1 -0
  6. package/dist/cjs/accounts/utils/signTransaction.js.map +1 -1
  7. package/dist/cjs/actions/public/estimateGas.js +3 -1
  8. package/dist/cjs/actions/public/estimateGas.js.map +1 -1
  9. package/dist/cjs/actions/public/watchContractEvent.js +134 -67
  10. package/dist/cjs/actions/public/watchContractEvent.js.map +1 -1
  11. package/dist/cjs/actions/public/watchEvent.js +136 -62
  12. package/dist/cjs/actions/public/watchEvent.js.map +1 -1
  13. package/dist/cjs/actions/wallet/sendTransaction.js.map +1 -1
  14. package/dist/cjs/actions/wallet/writeContract.js.map +1 -1
  15. package/dist/cjs/chains/{formatters/celo.js → celo/formatters.js} +1 -1
  16. package/dist/cjs/chains/celo/formatters.js.map +1 -0
  17. package/dist/cjs/chains/{serializers/celo.js → celo/serializers.js} +1 -1
  18. package/dist/cjs/chains/celo/serializers.js.map +1 -0
  19. package/dist/cjs/{types/formatter.js → chains/celo/types.js} +1 -1
  20. package/dist/cjs/chains/celo/types.js.map +1 -0
  21. package/dist/cjs/chains/index.js +30 -15
  22. package/dist/cjs/chains/index.js.map +1 -1
  23. package/dist/cjs/chains/optimism/fees.js +7 -0
  24. package/dist/cjs/chains/optimism/fees.js.map +1 -0
  25. package/dist/cjs/chains/{formatters/optimism.js → optimism/formatters.js} +13 -1
  26. package/dist/cjs/chains/optimism/formatters.js.map +1 -0
  27. package/dist/cjs/{types/serializer.js → chains/optimism/types.js} +1 -1
  28. package/dist/cjs/chains/optimism/types.js.map +1 -0
  29. package/dist/cjs/chains/utils.js +11 -0
  30. package/dist/cjs/chains/utils.js.map +1 -0
  31. package/dist/cjs/errors/node.js +1 -1
  32. package/dist/cjs/errors/node.js.map +1 -1
  33. package/dist/cjs/index.js.map +1 -1
  34. package/dist/cjs/utils/chain.js +5 -3
  35. package/dist/cjs/utils/chain.js.map +1 -1
  36. package/dist/cjs/utils/formatters/block.js.map +1 -1
  37. package/dist/cjs/utils/formatters/extract.js.map +1 -1
  38. package/dist/cjs/utils/formatters/formatter.js.map +1 -1
  39. package/dist/cjs/utils/formatters/transaction.js.map +1 -1
  40. package/dist/cjs/utils/formatters/transactionReceipt.js.map +1 -1
  41. package/dist/cjs/utils/formatters/transactionRequest.js.map +1 -1
  42. package/dist/cjs/utils/transaction/prepareRequest.js +15 -6
  43. package/dist/cjs/utils/transaction/prepareRequest.js.map +1 -1
  44. package/dist/esm/accounts/index.js +2 -0
  45. package/dist/esm/accounts/index.js.map +1 -1
  46. package/dist/esm/accounts/utils/privateKeyToAddress.js +15 -0
  47. package/dist/esm/accounts/utils/privateKeyToAddress.js.map +1 -0
  48. package/dist/esm/accounts/utils/signTransaction.js.map +1 -1
  49. package/dist/esm/actions/public/estimateGas.js +4 -2
  50. package/dist/esm/actions/public/estimateGas.js.map +1 -1
  51. package/dist/esm/actions/public/watchContractEvent.js +145 -76
  52. package/dist/esm/actions/public/watchContractEvent.js.map +1 -1
  53. package/dist/esm/actions/public/watchEvent.js +146 -70
  54. package/dist/esm/actions/public/watchEvent.js.map +1 -1
  55. package/dist/esm/actions/wallet/sendTransaction.js +1 -1
  56. package/dist/esm/actions/wallet/sendTransaction.js.map +1 -1
  57. package/dist/esm/actions/wallet/writeContract.js.map +1 -1
  58. package/dist/esm/chains/{formatters/celo.js → celo/formatters.js} +2 -2
  59. package/dist/esm/chains/celo/formatters.js.map +1 -0
  60. package/dist/esm/chains/{serializers/celo.js → celo/serializers.js} +1 -1
  61. package/dist/esm/chains/celo/serializers.js.map +1 -0
  62. package/dist/esm/chains/celo/types.js +2 -0
  63. package/dist/esm/chains/celo/types.js.map +1 -0
  64. package/dist/esm/chains/index.js +22 -7
  65. package/dist/esm/chains/index.js.map +1 -1
  66. package/dist/esm/chains/optimism/fees.js +4 -0
  67. package/dist/esm/chains/optimism/fees.js.map +1 -0
  68. package/dist/esm/chains/{formatters/optimism.js → optimism/formatters.js} +15 -2
  69. package/dist/esm/chains/optimism/formatters.js.map +1 -0
  70. package/dist/esm/chains/optimism/types.js +2 -0
  71. package/dist/esm/chains/optimism/types.js.map +1 -0
  72. package/dist/esm/chains/utils.js +4 -0
  73. package/dist/esm/chains/utils.js.map +1 -0
  74. package/dist/esm/errors/node.js +1 -1
  75. package/dist/esm/errors/node.js.map +1 -1
  76. package/dist/esm/index.js.map +1 -1
  77. package/dist/esm/utils/chain.js +5 -3
  78. package/dist/esm/utils/chain.js.map +1 -1
  79. package/dist/esm/utils/formatters/block.js.map +1 -1
  80. package/dist/esm/utils/formatters/extract.js.map +1 -1
  81. package/dist/esm/utils/formatters/formatter.js.map +1 -1
  82. package/dist/esm/utils/formatters/transaction.js.map +1 -1
  83. package/dist/esm/utils/formatters/transactionReceipt.js.map +1 -1
  84. package/dist/esm/utils/formatters/transactionRequest.js.map +1 -1
  85. package/dist/esm/utils/transaction/prepareRequest.js +14 -5
  86. package/dist/esm/utils/transaction/prepareRequest.js.map +1 -1
  87. package/dist/types/accounts/index.d.ts +2 -0
  88. package/dist/types/accounts/index.d.ts.map +1 -1
  89. package/dist/types/accounts/utils/privateKeyToAddress.d.ts +11 -0
  90. package/dist/types/accounts/utils/privateKeyToAddress.d.ts.map +1 -0
  91. package/dist/types/accounts/utils/signTransaction.d.ts +2 -2
  92. package/dist/types/accounts/utils/signTransaction.d.ts.map +1 -1
  93. package/dist/types/actions/public/estimateGas.d.ts.map +1 -1
  94. package/dist/types/actions/public/getTransactionReceipt.d.ts +1 -1
  95. package/dist/types/actions/public/getTransactionReceipt.d.ts.map +1 -1
  96. package/dist/types/actions/public/simulateContract.d.ts +2 -2
  97. package/dist/types/actions/public/simulateContract.d.ts.map +1 -1
  98. package/dist/types/actions/public/watchContractEvent.d.ts +32 -6
  99. package/dist/types/actions/public/watchContractEvent.d.ts.map +1 -1
  100. package/dist/types/actions/public/watchEvent.d.ts +32 -9
  101. package/dist/types/actions/public/watchEvent.d.ts.map +1 -1
  102. package/dist/types/actions/wallet/deployContract.d.ts +1 -1
  103. package/dist/types/actions/wallet/deployContract.d.ts.map +1 -1
  104. package/dist/types/actions/wallet/sendTransaction.d.ts +2 -2
  105. package/dist/types/actions/wallet/sendTransaction.d.ts.map +1 -1
  106. package/dist/types/actions/wallet/writeContract.d.ts +4 -2
  107. package/dist/types/actions/wallet/writeContract.d.ts.map +1 -1
  108. package/dist/types/chains/{formatters/celo.d.ts → celo/formatters.d.ts} +26 -85
  109. package/dist/types/chains/celo/formatters.d.ts.map +1 -0
  110. package/dist/types/chains/{serializers/celo.d.ts → celo/serializers.d.ts} +4 -4
  111. package/dist/types/chains/celo/serializers.d.ts.map +1 -0
  112. package/dist/types/chains/celo/types.d.ts +60 -0
  113. package/dist/types/chains/celo/types.d.ts.map +1 -0
  114. package/dist/types/chains/index.d.ts +2527 -2754
  115. package/dist/types/chains/index.d.ts.map +1 -1
  116. package/dist/types/chains/optimism/fees.d.ts +4 -0
  117. package/dist/types/chains/optimism/fees.d.ts.map +1 -0
  118. package/dist/types/chains/{formatters/optimism.d.ts → optimism/formatters.d.ts} +77 -54
  119. package/dist/types/chains/optimism/formatters.d.ts.map +1 -0
  120. package/dist/types/chains/optimism/types.d.ts +53 -0
  121. package/dist/types/chains/optimism/types.d.ts.map +1 -0
  122. package/dist/types/chains/utils.d.ts +6 -0
  123. package/dist/types/chains/utils.d.ts.map +1 -0
  124. package/dist/types/clients/decorators/public.d.ts +1 -1
  125. package/dist/types/clients/decorators/public.d.ts.map +1 -1
  126. package/dist/types/errors/node.d.ts.map +1 -1
  127. package/dist/types/index.d.ts +13 -3
  128. package/dist/types/index.d.ts.map +1 -1
  129. package/dist/types/types/chain.d.ts +52 -8
  130. package/dist/types/types/chain.d.ts.map +1 -1
  131. package/dist/types/types/rpc.d.ts +1 -1
  132. package/dist/types/types/rpc.d.ts.map +1 -1
  133. package/dist/types/types/utils.d.ts +10 -0
  134. package/dist/types/types/utils.d.ts.map +1 -1
  135. package/dist/types/utils/chain.d.ts +3 -6
  136. package/dist/types/utils/chain.d.ts.map +1 -1
  137. package/dist/types/utils/formatters/block.d.ts +7 -3
  138. package/dist/types/utils/formatters/block.d.ts.map +1 -1
  139. package/dist/types/utils/formatters/extract.d.ts +2 -2
  140. package/dist/types/utils/formatters/extract.d.ts.map +1 -1
  141. package/dist/types/utils/formatters/formatter.d.ts +1 -1
  142. package/dist/types/utils/formatters/transaction.d.ts +8 -4
  143. package/dist/types/utils/formatters/transaction.d.ts.map +1 -1
  144. package/dist/types/utils/formatters/transactionReceipt.d.ts +3 -4
  145. package/dist/types/utils/formatters/transactionReceipt.d.ts.map +1 -1
  146. package/dist/types/utils/formatters/transactionRequest.d.ts +4 -5
  147. package/dist/types/utils/formatters/transactionRequest.d.ts.map +1 -1
  148. package/dist/types/utils/transaction/prepareRequest.d.ts +6 -11
  149. package/dist/types/utils/transaction/prepareRequest.d.ts.map +1 -1
  150. package/package.json +8 -2
  151. package/src/accounts/index.ts +6 -0
  152. package/src/accounts/utils/privateKeyToAddress.ts +20 -0
  153. package/src/accounts/utils/signTransaction.ts +2 -2
  154. package/src/actions/public/estimateGas.ts +11 -2
  155. package/src/actions/public/simulateContract.ts +2 -2
  156. package/src/actions/public/watchContractEvent.ts +201 -87
  157. package/src/actions/public/watchEvent.ts +230 -109
  158. package/src/actions/wallet/deployContract.ts +1 -1
  159. package/src/actions/wallet/sendTransaction.ts +9 -6
  160. package/src/actions/wallet/writeContract.ts +11 -7
  161. package/src/chains/{formatters/celo.ts → celo/formatters.ts} +29 -48
  162. package/src/chains/{serializers/celo.ts → celo/serializers.ts} +5 -5
  163. package/src/chains/celo/types.ts +111 -0
  164. package/src/chains/index.ts +22 -7
  165. package/src/chains/optimism/fees.ts +5 -0
  166. package/src/chains/optimism/formatters.ts +74 -0
  167. package/src/chains/optimism/types.ts +102 -0
  168. package/src/chains/utils.ts +41 -0
  169. package/src/clients/decorators/public.ts +3 -3
  170. package/src/errors/node.ts +2 -1
  171. package/src/index.ts +24 -8
  172. package/src/types/chain.ts +91 -14
  173. package/src/types/rpc.ts +2 -6
  174. package/src/types/utils.ts +11 -0
  175. package/src/utils/chain.ts +21 -10
  176. package/src/utils/formatters/block.ts +8 -6
  177. package/src/utils/formatters/extract.ts +2 -2
  178. package/src/utils/formatters/formatter.ts +2 -2
  179. package/src/utils/formatters/transaction.ts +8 -6
  180. package/src/utils/formatters/transactionReceipt.ts +9 -3
  181. package/src/utils/formatters/transactionRequest.ts +9 -3
  182. package/src/utils/transaction/prepareRequest.ts +48 -22
  183. package/dist/cjs/chains/formatters/celo.js.map +0 -1
  184. package/dist/cjs/chains/formatters/optimism.js.map +0 -1
  185. package/dist/cjs/chains/serializers/celo.js.map +0 -1
  186. package/dist/cjs/types/formatter.js.map +0 -1
  187. package/dist/cjs/types/serializer.js.map +0 -1
  188. package/dist/esm/chains/formatters/celo.js.map +0 -1
  189. package/dist/esm/chains/formatters/optimism.js.map +0 -1
  190. package/dist/esm/chains/serializers/celo.js.map +0 -1
  191. package/dist/esm/types/formatter.js +0 -2
  192. package/dist/esm/types/formatter.js.map +0 -1
  193. package/dist/esm/types/serializer.js +0 -2
  194. package/dist/esm/types/serializer.js.map +0 -1
  195. package/dist/types/chains/formatters/celo.d.ts.map +0 -1
  196. package/dist/types/chains/formatters/optimism.d.ts.map +0 -1
  197. package/dist/types/chains/serializers/celo.d.ts.map +0 -1
  198. package/dist/types/types/formatter.d.ts +0 -17
  199. package/dist/types/types/formatter.d.ts.map +0 -1
  200. package/dist/types/types/serializer.d.ts +0 -7
  201. package/dist/types/types/serializer.d.ts.map +0 -1
  202. package/src/chains/formatters/optimism.ts +0 -91
  203. package/src/types/formatter.ts +0 -42
  204. package/src/types/serializer.ts +0 -19
@@ -2,10 +2,13 @@ import type { Abi, AbiEvent, Address, ExtractAbiEvent, Narrow } from 'abitype'
2
2
 
3
3
  import type { Client } from '../../clients/createClient.js'
4
4
  import type { Transport } from '../../clients/transports/createTransport.js'
5
+ import type { EncodeEventTopicsParameters, LogTopic } from '../../index.js'
5
6
  import type { Chain } from '../../types/chain.js'
6
7
  import type { GetEventArgs, InferEventName } from '../../types/contract.js'
7
8
  import type { Filter } from '../../types/filter.js'
8
9
  import type { Log } from '../../types/log.js'
10
+ import type { GetTransportConfig } from '../../types/transport.js'
11
+
9
12
  import {
10
13
  type GetAbiItemParameters,
11
14
  getAbiItem,
@@ -14,7 +17,14 @@ import { observe } from '../../utils/observe.js'
14
17
  import { poll } from '../../utils/poll.js'
15
18
  import { stringify } from '../../utils/stringify.js'
16
19
 
17
- import { InvalidInputRpcError } from '../../index.js'
20
+ import { DecodeLogDataMismatch } from '../../errors/abi.js'
21
+ import {
22
+ DecodeLogTopicsMismatch,
23
+ InvalidInputRpcError,
24
+ decodeEventLog,
25
+ encodeEventTopics,
26
+ formatLog,
27
+ } from '../../index.js'
18
28
  import {
19
29
  type CreateContractEventFilterParameters,
20
30
  createContractEventFilter,
@@ -24,6 +34,19 @@ import { getFilterChanges } from './getFilterChanges.js'
24
34
  import { getLogs } from './getLogs.js'
25
35
  import { uninstallFilter } from './uninstallFilter.js'
26
36
 
37
+ type PollOptions = {
38
+ /**
39
+ * Whether or not the transaction hashes should be batched on each invocation.
40
+ * @default true
41
+ */
42
+ batch?: boolean
43
+ /**
44
+ * Polling frequency (in ms). Defaults to Client's pollingInterval config.
45
+ * @default client.pollingInterval
46
+ */
47
+ pollingInterval?: number
48
+ }
49
+
27
50
  export type WatchContractEventOnLogsParameter<
28
51
  TAbi extends Abi | readonly unknown[] = readonly unknown[],
29
52
  TEventName extends string = string,
@@ -47,22 +70,38 @@ export type WatchContractEventParameters<
47
70
  /** Contract ABI. */
48
71
  abi: Narrow<TAbi>
49
72
  args?: GetEventArgs<TAbi, TEventName>
50
- /** Whether or not the event logs should be batched on each invocation. */
51
- batch?: boolean
52
73
  /** Contract event. */
53
74
  eventName?: InferEventName<TAbi, TEventName>
54
75
  /** The callback to call when an error occurred when trying to get for a new block. */
55
76
  onError?: (error: Error) => void
56
77
  /** The callback to call when new event logs are received. */
57
78
  onLogs: WatchContractEventOnLogsFn<TAbi, TEventName, TStrict>
58
- /** Polling frequency (in ms). Defaults to Client's pollingInterval config. */
59
- pollingInterval?: number
60
79
  /**
61
80
  * Whether or not the logs must match the indexed/non-indexed arguments on `event`.
62
81
  * @default false
63
82
  */
64
83
  strict?: TStrict
65
- }
84
+ } & (GetTransportConfig<Transport>['type'] extends 'webSocket'
85
+ ?
86
+ | {
87
+ batch?: never
88
+ /**
89
+ * Whether or not the WebSocket Transport should poll the JSON-RPC, rather than using `eth_subscribe`.
90
+ * @default false
91
+ */
92
+ poll?: false
93
+ pollingInterval?: never
94
+ }
95
+ | (PollOptions & {
96
+ /**
97
+ * Whether or not the WebSocket Transport should poll the JSON-RPC, rather than using `eth_subscribe`.
98
+ * @default true
99
+ */
100
+ poll?: true
101
+ })
102
+ : PollOptions & {
103
+ poll?: true
104
+ })
66
105
 
67
106
  export type WatchContractEventReturnType = () => void
68
107
 
@@ -111,96 +150,171 @@ export function watchContractEvent<
111
150
  eventName,
112
151
  onError,
113
152
  onLogs,
153
+ poll: poll_,
114
154
  pollingInterval = client.pollingInterval,
115
155
  strict: strict_,
116
156
  }: WatchContractEventParameters<TAbi, TEventName, TStrict>,
117
157
  ): WatchContractEventReturnType {
118
- const observerId = stringify([
119
- 'watchContractEvent',
120
- address,
121
- args,
122
- batch,
123
- client.uid,
124
- eventName,
125
- pollingInterval,
126
- ])
127
- const strict = strict_ ?? false
128
-
129
- return observe(observerId, { onLogs, onError }, (emit) => {
130
- let previousBlockNumber: bigint
131
- let filter: Filter<'event', TAbi, TEventName> | undefined
132
- let initialized = false
133
-
134
- const unwatch = poll(
135
- async () => {
136
- if (!initialized) {
137
- try {
138
- filter = (await createContractEventFilter(client, {
139
- abi,
140
- address,
141
- args,
142
- eventName,
143
- strict,
144
- } as unknown as CreateContractEventFilterParameters)) as Filter<
145
- 'event',
146
- TAbi,
147
- TEventName
148
- >
149
- } catch {}
150
- initialized = true
151
- return
152
- }
158
+ const enablePolling =
159
+ typeof poll_ !== 'undefined' ? poll_ : client.transport.type !== 'webSocket'
153
160
 
154
- try {
155
- let logs: Log[]
156
- if (filter) {
157
- logs = await getFilterChanges(client, { filter })
158
- } else {
159
- // If the filter doesn't exist, we will fall back to use `getLogs`.
160
- // The fall back exists because some RPC Providers do not support filters.
161
-
162
- // Fetch the block number to use for `getLogs`.
163
- const blockNumber = await getBlockNumber(client)
164
-
165
- // If the block number has changed, we will need to fetch the logs.
166
- // If the block number doesn't exist, we are yet to reach the first poll interval,
167
- // so do not emit any logs.
168
- if (previousBlockNumber && previousBlockNumber !== blockNumber) {
169
- logs = await getLogs(client, {
161
+ const pollContractEvent = () => {
162
+ const observerId = stringify([
163
+ 'watchContractEvent',
164
+ address,
165
+ args,
166
+ batch,
167
+ client.uid,
168
+ eventName,
169
+ pollingInterval,
170
+ ])
171
+ const strict = strict_ ?? false
172
+
173
+ return observe(observerId, { onLogs, onError }, (emit) => {
174
+ let previousBlockNumber: bigint
175
+ let filter: Filter<'event', TAbi, TEventName> | undefined
176
+ let initialized = false
177
+
178
+ const unwatch = poll(
179
+ async () => {
180
+ if (!initialized) {
181
+ try {
182
+ filter = (await createContractEventFilter(client, {
183
+ abi,
170
184
  address,
171
185
  args,
172
- fromBlock: previousBlockNumber + 1n,
173
- toBlock: blockNumber,
174
- event: getAbiItem({
175
- abi,
176
- name: eventName,
177
- } as unknown as GetAbiItemParameters) as AbiEvent,
178
- })
186
+ eventName,
187
+ strict,
188
+ } as unknown as CreateContractEventFilterParameters)) as Filter<
189
+ 'event',
190
+ TAbi,
191
+ TEventName
192
+ >
193
+ } catch {}
194
+ initialized = true
195
+ return
196
+ }
197
+
198
+ try {
199
+ let logs: Log[]
200
+ if (filter) {
201
+ logs = await getFilterChanges(client, { filter })
179
202
  } else {
180
- logs = []
203
+ // If the filter doesn't exist, we will fall back to use `getLogs`.
204
+ // The fall back exists because some RPC Providers do not support filters.
205
+
206
+ // Fetch the block number to use for `getLogs`.
207
+ const blockNumber = await getBlockNumber(client)
208
+
209
+ // If the block number has changed, we will need to fetch the logs.
210
+ // If the block number doesn't exist, we are yet to reach the first poll interval,
211
+ // so do not emit any logs.
212
+ if (previousBlockNumber && previousBlockNumber !== blockNumber) {
213
+ logs = await getLogs(client, {
214
+ address,
215
+ args,
216
+ fromBlock: previousBlockNumber + 1n,
217
+ toBlock: blockNumber,
218
+ event: getAbiItem({
219
+ abi,
220
+ name: eventName,
221
+ } as unknown as GetAbiItemParameters) as AbiEvent,
222
+ })
223
+ } else {
224
+ logs = []
225
+ }
226
+ previousBlockNumber = blockNumber
181
227
  }
182
- previousBlockNumber = blockNumber
228
+
229
+ if (logs.length === 0) return
230
+ if (batch) emit.onLogs(logs as any)
231
+ else logs.forEach((log) => emit.onLogs([log] as any))
232
+ } catch (err) {
233
+ // If a filter has been set and gets uninstalled, providers will throw an InvalidInput error.
234
+ // Reinitalize the filter when this occurs
235
+ if (filter && err instanceof InvalidInputRpcError)
236
+ initialized = false
237
+ emit.onError?.(err as Error)
183
238
  }
239
+ },
240
+ {
241
+ emitOnBegin: true,
242
+ interval: pollingInterval,
243
+ },
244
+ )
184
245
 
185
- if (logs.length === 0) return
186
- if (batch) emit.onLogs(logs as any)
187
- else logs.forEach((log) => emit.onLogs([log] as any))
188
- } catch (err) {
189
- // If a filter has been set and gets uninstalled, providers will throw an InvalidInput error.
190
- // Reinitalize the filter when this occurs
191
- if (filter && err instanceof InvalidInputRpcError) initialized = false
192
- emit.onError?.(err as Error)
193
- }
194
- },
195
- {
196
- emitOnBegin: true,
197
- interval: pollingInterval,
198
- },
199
- )
200
-
201
- return async () => {
202
- if (filter) await uninstallFilter(client, { filter })
203
- unwatch()
204
- }
205
- })
246
+ return async () => {
247
+ if (filter) await uninstallFilter(client, { filter })
248
+ unwatch()
249
+ }
250
+ })
251
+ }
252
+
253
+ const subscribeContractEvent = () => {
254
+ let active = true
255
+ let unsubscribe = () => (active = false)
256
+ ;(async () => {
257
+ try {
258
+ const topics: LogTopic[] = eventName
259
+ ? encodeEventTopics({
260
+ abi: abi,
261
+ eventName: eventName,
262
+ args,
263
+ } as EncodeEventTopicsParameters)
264
+ : []
265
+
266
+ const { unsubscribe: unsubscribe_ } = await client.transport.subscribe({
267
+ params: ['logs', { address, topics }],
268
+ onData(data: any) {
269
+ if (!active) return
270
+ const log = data.result
271
+ try {
272
+ const { eventName, args } = decodeEventLog({
273
+ abi: abi,
274
+ data: log.data,
275
+ topics: log.topics as any,
276
+ strict: strict_,
277
+ })
278
+ const formatted = formatLog(log, {
279
+ args,
280
+ eventName: eventName as string,
281
+ })
282
+ onLogs([formatted] as any)
283
+ } catch (err) {
284
+ let eventName
285
+ let isUnnamed
286
+ if (
287
+ err instanceof DecodeLogDataMismatch ||
288
+ err instanceof DecodeLogTopicsMismatch
289
+ ) {
290
+ // If strict mode is on, and log data/topics do not match event definition, skip.
291
+ if (strict_) return
292
+ eventName = err.abiItem.name
293
+ isUnnamed = err.abiItem.inputs?.some(
294
+ (x) => !('name' in x && x.name),
295
+ )
296
+ }
297
+
298
+ // Set args to empty if there is an error decoding (e.g. indexed/non-indexed params mismatch).
299
+ const formatted = formatLog(log, {
300
+ args: isUnnamed ? [] : {},
301
+ eventName,
302
+ })
303
+ onLogs([formatted] as any)
304
+ }
305
+ },
306
+ onError(error: Error) {
307
+ onError?.(error)
308
+ },
309
+ })
310
+ unsubscribe = unsubscribe_
311
+ if (!active) unsubscribe()
312
+ } catch (err) {
313
+ onError?.(err as Error)
314
+ }
315
+ })()
316
+ return unsubscribe
317
+ }
318
+
319
+ return enablePolling ? pollContractEvent() : subscribeContractEvent()
206
320
  }