viem 2.37.13 → 2.38.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 (73) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/_cjs/actions/index.js +10 -2
  3. package/_cjs/actions/index.js.map +1 -1
  4. package/_cjs/actions/wallet/sendCallsSync.js +17 -0
  5. package/_cjs/actions/wallet/sendCallsSync.js.map +1 -0
  6. package/_cjs/actions/wallet/sendRawTransactionSync.js +17 -0
  7. package/_cjs/actions/wallet/sendRawTransactionSync.js.map +1 -0
  8. package/_cjs/actions/wallet/sendTransactionSync.js +172 -0
  9. package/_cjs/actions/wallet/sendTransactionSync.js.map +1 -0
  10. package/_cjs/actions/wallet/writeContract.js +31 -25
  11. package/_cjs/actions/wallet/writeContract.js.map +1 -1
  12. package/_cjs/actions/wallet/writeContractSync.js +9 -0
  13. package/_cjs/actions/wallet/writeContractSync.js.map +1 -0
  14. package/_cjs/clients/decorators/public.js +2 -0
  15. package/_cjs/clients/decorators/public.js.map +1 -1
  16. package/_cjs/clients/decorators/wallet.js +8 -0
  17. package/_cjs/clients/decorators/wallet.js.map +1 -1
  18. package/_cjs/errors/version.js +1 -1
  19. package/_cjs/errors/version.js.map +1 -1
  20. package/_cjs/index.js.map +1 -1
  21. package/_esm/actions/index.js +4 -0
  22. package/_esm/actions/index.js.map +1 -1
  23. package/_esm/actions/wallet/sendCallsSync.js +46 -0
  24. package/_esm/actions/wallet/sendCallsSync.js.map +1 -0
  25. package/_esm/actions/wallet/sendRawTransactionSync.js +39 -0
  26. package/_esm/actions/wallet/sendRawTransactionSync.js.map +1 -0
  27. package/_esm/actions/wallet/sendTransactionSync.js +218 -0
  28. package/_esm/actions/wallet/sendTransactionSync.js.map +1 -0
  29. package/_esm/actions/wallet/writeContract.js +31 -25
  30. package/_esm/actions/wallet/writeContract.js.map +1 -1
  31. package/_esm/actions/wallet/writeContractSync.js +38 -0
  32. package/_esm/actions/wallet/writeContractSync.js.map +1 -0
  33. package/_esm/clients/decorators/public.js +2 -0
  34. package/_esm/clients/decorators/public.js.map +1 -1
  35. package/_esm/clients/decorators/wallet.js +8 -0
  36. package/_esm/clients/decorators/wallet.js.map +1 -1
  37. package/_esm/errors/version.js +1 -1
  38. package/_esm/errors/version.js.map +1 -1
  39. package/_esm/index.js.map +1 -1
  40. package/_types/actions/index.d.ts +4 -0
  41. package/_types/actions/index.d.ts.map +1 -1
  42. package/_types/actions/wallet/sendCallsSync.d.ts +47 -0
  43. package/_types/actions/wallet/sendCallsSync.d.ts.map +1 -0
  44. package/_types/actions/wallet/sendRawTransactionSync.d.ts +42 -0
  45. package/_types/actions/wallet/sendRawTransactionSync.d.ts.map +1 -0
  46. package/_types/actions/wallet/sendTransactionSync.d.ts +73 -0
  47. package/_types/actions/wallet/sendTransactionSync.d.ts.map +1 -0
  48. package/_types/actions/wallet/writeContract.d.ts +5 -1
  49. package/_types/actions/wallet/writeContract.d.ts.map +1 -1
  50. package/_types/actions/wallet/writeContractSync.d.ts +45 -0
  51. package/_types/actions/wallet/writeContractSync.d.ts.map +1 -0
  52. package/_types/clients/decorators/public.d.ts +26 -0
  53. package/_types/clients/decorators/public.d.ts.map +1 -1
  54. package/_types/clients/decorators/wallet.d.ts +138 -0
  55. package/_types/clients/decorators/wallet.d.ts.map +1 -1
  56. package/_types/errors/version.d.ts +1 -1
  57. package/_types/errors/version.d.ts.map +1 -1
  58. package/_types/index.d.ts +4 -0
  59. package/_types/index.d.ts.map +1 -1
  60. package/_types/types/eip1193.d.ts +24 -0
  61. package/_types/types/eip1193.d.ts.map +1 -1
  62. package/actions/index.ts +24 -0
  63. package/actions/wallet/sendCallsSync.ts +85 -0
  64. package/actions/wallet/sendRawTransactionSync.ts +68 -0
  65. package/actions/wallet/sendTransactionSync.ts +390 -0
  66. package/actions/wallet/writeContract.ts +71 -36
  67. package/actions/wallet/writeContractSync.ts +108 -0
  68. package/clients/decorators/public.ts +33 -0
  69. package/clients/decorators/wallet.ts +189 -0
  70. package/errors/version.ts +1 -1
  71. package/index.ts +21 -0
  72. package/package.json +1 -1
  73. package/types/eip1193.ts +28 -0
@@ -0,0 +1,85 @@
1
+ import type { Client } from '../../clients/createClient.js'
2
+ import type { Transport } from '../../clients/transports/createTransport.js'
3
+ import type { Account } from '../../types/account.js'
4
+ import type { Chain } from '../../types/chain.js'
5
+ import type { GetCallsStatusReturnType } from './getCallsStatus.js'
6
+ import {
7
+ type SendCallsErrorType,
8
+ type SendCallsParameters,
9
+ sendCalls,
10
+ } from './sendCalls.js'
11
+ import {
12
+ type WaitForCallsStatusParameters,
13
+ waitForCallsStatus,
14
+ } from './waitForCallsStatus.js'
15
+
16
+ export type SendCallsSyncParameters<
17
+ chain extends Chain | undefined = Chain | undefined,
18
+ account extends Account | undefined = Account | undefined,
19
+ chainOverride extends Chain | undefined = Chain | undefined,
20
+ calls extends readonly unknown[] = readonly unknown[],
21
+ > = SendCallsParameters<chain, account, chainOverride, calls> &
22
+ Pick<
23
+ WaitForCallsStatusParameters,
24
+ 'pollingInterval' | 'status' | 'throwOnFailure'
25
+ > & {
26
+ /** Timeout (ms) to wait for calls to be included in a block. @default chain.blockTime * 3 */
27
+ timeout?: number | undefined
28
+ }
29
+
30
+ export type SendCallsSyncReturnType = GetCallsStatusReturnType
31
+
32
+ export type SendCallsSyncErrorType = SendCallsErrorType
33
+
34
+ /**
35
+ * Requests the connected wallet to send a batch of calls, and waits for the calls to be included in a block.
36
+ *
37
+ * - Docs: https://viem.sh/docs/actions/wallet/sendCallsSync
38
+ * - JSON-RPC Methods: [`wallet_sendCalls`](https://eips.ethereum.org/EIPS/eip-5792)
39
+ *
40
+ * @param client - Client to use
41
+ * @returns Calls status. {@link SendCallsSyncReturnType}
42
+ *
43
+ * @example
44
+ * import { createWalletClient, custom } from 'viem'
45
+ * import { mainnet } from 'viem/chains'
46
+ * import { sendCalls } from 'viem/actions'
47
+ *
48
+ * const client = createWalletClient({
49
+ * chain: mainnet,
50
+ * transport: custom(window.ethereum),
51
+ * })
52
+ * const status = await sendCallsSync(client, {
53
+ * account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
54
+ * calls: [
55
+ * {
56
+ * data: '0xdeadbeef',
57
+ * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
58
+ * },
59
+ * {
60
+ * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
61
+ * value: 69420n,
62
+ * },
63
+ * ],
64
+ * })
65
+ */
66
+ export async function sendCallsSync<
67
+ const calls extends readonly unknown[],
68
+ chain extends Chain | undefined,
69
+ account extends Account | undefined = undefined,
70
+ chainOverride extends Chain | undefined = undefined,
71
+ >(
72
+ client: Client<Transport, chain, account>,
73
+ parameters: SendCallsSyncParameters<chain, account, chainOverride, calls>,
74
+ ): Promise<SendCallsSyncReturnType> {
75
+ const { chain = client.chain } = parameters
76
+ const timeout =
77
+ parameters.timeout ?? Math.max((chain?.blockTime ?? 0) * 3, 5_000)
78
+ const result = await sendCalls(client, parameters)
79
+ const status = await waitForCallsStatus(client, {
80
+ ...parameters,
81
+ id: result.id,
82
+ timeout,
83
+ })
84
+ return status
85
+ }
@@ -0,0 +1,68 @@
1
+ import type { Client } from '../../clients/createClient.js'
2
+ import type { Transport } from '../../clients/transports/createTransport.js'
3
+ import type { ErrorType } from '../../errors/utils.js'
4
+ import type { Chain } from '../../types/chain.js'
5
+ import type { TransactionSerializedGeneric } from '../../types/transaction.js'
6
+ import type { RequestErrorType } from '../../utils/buildRequest.js'
7
+ import { formatTransactionReceipt } from '../../utils/formatters/transactionReceipt.js'
8
+ import {
9
+ type FormattedTransactionReceipt,
10
+ numberToHex,
11
+ } from '../../utils/index.js'
12
+
13
+ export type SendRawTransactionSyncParameters = {
14
+ /** The signed serialized transaction. */
15
+ serializedTransaction: TransactionSerializedGeneric
16
+ /** The timeout for the transaction. */
17
+ timeout?: number | undefined
18
+ }
19
+
20
+ export type SendRawTransactionSyncReturnType<
21
+ chain extends Chain | undefined = undefined,
22
+ > = FormattedTransactionReceipt<chain>
23
+
24
+ export type SendRawTransactionSyncErrorType = RequestErrorType | ErrorType
25
+
26
+ /**
27
+ * Sends a **signed** transaction to the network synchronously,
28
+ * and waits for the transaction to be included in a block.
29
+ *
30
+ * - Docs: https://viem.sh/docs/actions/wallet/sendRawTransactionSync
31
+ * - JSON-RPC Method: [`eth_sendRawTransactionSync`](https://eips.ethereum.org/EIPS/eip-7966)
32
+ *
33
+ * @param client - Client to use
34
+ * @param parameters - {@link SendRawTransactionParameters}
35
+ * @returns The transaction receipt. {@link SendRawTransactionSyncReturnType}
36
+ *
37
+ * @example
38
+ * import { createWalletClient, custom } from 'viem'
39
+ * import { mainnet } from 'viem/chains'
40
+ * import { sendRawTransactionSync } from 'viem/wallet'
41
+ *
42
+ * const client = createWalletClient({
43
+ * chain: mainnet,
44
+ * transport: custom(window.ethereum),
45
+ * })
46
+ *
47
+ * const receipt = await sendRawTransactionSync(client, {
48
+ * serializedTransaction: '0x02f850018203118080825208808080c080a04012522854168b27e5dc3d5839bab5e6b39e1a0ffd343901ce1622e3d64b48f1a04e00902ae0502c4728cbf12156290df99c3ed7de85b1dbfe20b5c36931733a33'
49
+ * })
50
+ */
51
+ export async function sendRawTransactionSync<chain extends Chain | undefined>(
52
+ client: Client<Transport, chain>,
53
+ { serializedTransaction, timeout }: SendRawTransactionSyncParameters,
54
+ ): Promise<SendRawTransactionSyncReturnType<chain>> {
55
+ const receipt = await client.request(
56
+ {
57
+ method: 'eth_sendRawTransactionSync',
58
+ params: timeout
59
+ ? [serializedTransaction, numberToHex(timeout)]
60
+ : [serializedTransaction],
61
+ },
62
+ { retryCount: 0 },
63
+ )
64
+ const format =
65
+ client.chain?.formatters?.transactionReceipt?.format ||
66
+ formatTransactionReceipt
67
+ return format(receipt) as SendRawTransactionSyncReturnType<chain>
68
+ }
@@ -0,0 +1,390 @@
1
+ import type { Address } from 'abitype'
2
+
3
+ import type { Account } from '../../accounts/types.js'
4
+ import {
5
+ type ParseAccountErrorType,
6
+ parseAccount,
7
+ } from '../../accounts/utils/parseAccount.js'
8
+ import type { SignTransactionErrorType } from '../../accounts/utils/signTransaction.js'
9
+ import type { Client } from '../../clients/createClient.js'
10
+ import type { Transport } from '../../clients/transports/createTransport.js'
11
+ import {
12
+ AccountNotFoundError,
13
+ type AccountNotFoundErrorType,
14
+ AccountTypeNotSupportedError,
15
+ type AccountTypeNotSupportedErrorType,
16
+ } from '../../errors/account.js'
17
+ import { BaseError } from '../../errors/base.js'
18
+ import type { ErrorType } from '../../errors/utils.js'
19
+ import type { GetAccountParameter } from '../../types/account.js'
20
+ import type {
21
+ Chain,
22
+ DeriveChain,
23
+ GetChainParameter,
24
+ } from '../../types/chain.js'
25
+ import type { GetTransactionRequestKzgParameter } from '../../types/kzg.js'
26
+ import type { Hash } from '../../types/misc.js'
27
+ import type { TransactionRequest } from '../../types/transaction.js'
28
+ import type { UnionOmit } from '../../types/utils.js'
29
+ import {
30
+ type RecoverAuthorizationAddressErrorType,
31
+ recoverAuthorizationAddress,
32
+ } from '../../utils/authorization/recoverAuthorizationAddress.js'
33
+ import type { RequestErrorType } from '../../utils/buildRequest.js'
34
+ import {
35
+ type AssertCurrentChainErrorType,
36
+ assertCurrentChain,
37
+ } from '../../utils/chain/assertCurrentChain.js'
38
+ import {
39
+ type GetTransactionErrorReturnType,
40
+ getTransactionError,
41
+ } from '../../utils/errors/getTransactionError.js'
42
+ import { extract } from '../../utils/formatters/extract.js'
43
+ import {
44
+ type FormattedTransactionRequest,
45
+ formatTransactionRequest,
46
+ } from '../../utils/formatters/transactionRequest.js'
47
+ import { getAction } from '../../utils/getAction.js'
48
+ import { LruMap } from '../../utils/lru.js'
49
+ import {
50
+ type AssertRequestErrorType,
51
+ type AssertRequestParameters,
52
+ assertRequest,
53
+ } from '../../utils/transaction/assertRequest.js'
54
+ import { type GetChainIdErrorType, getChainId } from '../public/getChainId.js'
55
+ import {
56
+ type WaitForTransactionReceiptErrorType,
57
+ waitForTransactionReceipt,
58
+ } from '../public/waitForTransactionReceipt.js'
59
+ import {
60
+ defaultParameters,
61
+ type PrepareTransactionRequestErrorType,
62
+ prepareTransactionRequest,
63
+ } from './prepareTransactionRequest.js'
64
+ import {
65
+ type SendRawTransactionSyncErrorType,
66
+ type SendRawTransactionSyncReturnType,
67
+ sendRawTransactionSync,
68
+ } from './sendRawTransactionSync.js'
69
+
70
+ const supportsWalletNamespace = new LruMap<boolean>(128)
71
+
72
+ export type SendTransactionSyncRequest<
73
+ chain extends Chain | undefined = Chain | undefined,
74
+ chainOverride extends Chain | undefined = Chain | undefined,
75
+ ///
76
+ _derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
77
+ > = UnionOmit<FormattedTransactionRequest<_derivedChain>, 'from'> &
78
+ GetTransactionRequestKzgParameter
79
+
80
+ export type SendTransactionSyncParameters<
81
+ chain extends Chain | undefined = Chain | undefined,
82
+ account extends Account | undefined = Account | undefined,
83
+ chainOverride extends Chain | undefined = Chain | undefined,
84
+ request extends SendTransactionSyncRequest<
85
+ chain,
86
+ chainOverride
87
+ > = SendTransactionSyncRequest<chain, chainOverride>,
88
+ > = request &
89
+ GetAccountParameter<account, Account | Address, true, true> &
90
+ GetChainParameter<chain, chainOverride> &
91
+ GetTransactionRequestKzgParameter<request> & {
92
+ /** Polling interval (ms) to poll for the transaction receipt. @default client.pollingInterval */
93
+ pollingInterval?: number | undefined
94
+ /** Timeout (ms) to wait for a response. @default Math.max(chain.blockTime * 3, 5_000) */
95
+ timeout?: number | undefined
96
+ }
97
+
98
+ export type SendTransactionSyncReturnType<
99
+ chain extends Chain | undefined = Chain | undefined,
100
+ > = SendRawTransactionSyncReturnType<chain>
101
+
102
+ export type SendTransactionSyncErrorType =
103
+ | ParseAccountErrorType
104
+ | GetTransactionErrorReturnType<
105
+ | AccountNotFoundErrorType
106
+ | AccountTypeNotSupportedErrorType
107
+ | AssertCurrentChainErrorType
108
+ | AssertRequestErrorType
109
+ | GetChainIdErrorType
110
+ | PrepareTransactionRequestErrorType
111
+ | SendRawTransactionSyncErrorType
112
+ | RecoverAuthorizationAddressErrorType
113
+ | SignTransactionErrorType
114
+ | RequestErrorType
115
+ >
116
+ | WaitForTransactionReceiptErrorType
117
+ | ErrorType
118
+
119
+ /**
120
+ * Creates, signs, and sends a new transaction to the network synchronously.
121
+ * Returns the transaction receipt.
122
+ *
123
+ * @param client - Client to use
124
+ * @param parameters - {@link SendTransactionSyncParameters}
125
+ * @returns The transaction receipt. {@link SendTransactionSyncReturnType}
126
+ *
127
+ * @example
128
+ * import { createWalletClient, custom } from 'viem'
129
+ * import { mainnet } from 'viem/chains'
130
+ * import { sendTransactionSync } from 'viem/wallet'
131
+ *
132
+ * const client = createWalletClient({
133
+ * chain: mainnet,
134
+ * transport: custom(window.ethereum),
135
+ * })
136
+ * const receipt = await sendTransactionSync(client, {
137
+ * account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
138
+ * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
139
+ * value: 1000000000000000000n,
140
+ * })
141
+ *
142
+ * @example
143
+ * // Account Hoisting
144
+ * import { createWalletClient, http } from 'viem'
145
+ * import { privateKeyToAccount } from 'viem/accounts'
146
+ * import { mainnet } from 'viem/chains'
147
+ * import { sendTransactionSync } from 'viem/wallet'
148
+ *
149
+ * const client = createWalletClient({
150
+ * account: privateKeyToAccount('0x…'),
151
+ * chain: mainnet,
152
+ * transport: http(),
153
+ * })
154
+ * const receipt = await sendTransactionSync(client, {
155
+ * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
156
+ * value: 1000000000000000000n,
157
+ * })
158
+ */
159
+ export async function sendTransactionSync<
160
+ chain extends Chain | undefined,
161
+ account extends Account | undefined,
162
+ const request extends SendTransactionSyncRequest<chain, chainOverride>,
163
+ chainOverride extends Chain | undefined = undefined,
164
+ >(
165
+ client: Client<Transport, chain, account>,
166
+ parameters: SendTransactionSyncParameters<
167
+ chain,
168
+ account,
169
+ chainOverride,
170
+ request
171
+ >,
172
+ ): Promise<SendTransactionSyncReturnType<chain>> {
173
+ const {
174
+ account: account_ = client.account,
175
+ chain = client.chain,
176
+ accessList,
177
+ authorizationList,
178
+ blobs,
179
+ data,
180
+ gas,
181
+ gasPrice,
182
+ maxFeePerBlobGas,
183
+ maxFeePerGas,
184
+ maxPriorityFeePerGas,
185
+ nonce,
186
+ pollingInterval,
187
+ type,
188
+ value,
189
+ ...rest
190
+ } = parameters
191
+ const timeout =
192
+ parameters.timeout ?? Math.max((chain?.blockTime ?? 0) * 3, 5_000)
193
+
194
+ if (typeof account_ === 'undefined')
195
+ throw new AccountNotFoundError({
196
+ docsPath: '/docs/actions/wallet/sendTransactionSync',
197
+ })
198
+ const account = account_ ? parseAccount(account_) : null
199
+
200
+ try {
201
+ assertRequest(parameters as AssertRequestParameters)
202
+
203
+ const to = await (async () => {
204
+ // If `to` exists on the parameters, use that.
205
+ if (parameters.to) return parameters.to
206
+
207
+ // If `to` is null, we are sending a deployment transaction.
208
+ if (parameters.to === null) return undefined
209
+
210
+ // If no `to` exists, and we are sending a EIP-7702 transaction, use the
211
+ // address of the first authorization in the list.
212
+ if (authorizationList && authorizationList.length > 0)
213
+ return await recoverAuthorizationAddress({
214
+ authorization: authorizationList[0],
215
+ }).catch(() => {
216
+ throw new BaseError(
217
+ '`to` is required. Could not infer from `authorizationList`.',
218
+ )
219
+ })
220
+
221
+ // Otherwise, we are sending a deployment transaction.
222
+ return undefined
223
+ })()
224
+
225
+ if (account?.type === 'json-rpc' || account === null) {
226
+ let chainId: number | undefined
227
+ if (chain !== null) {
228
+ chainId = await getAction(client, getChainId, 'getChainId')({})
229
+ assertCurrentChain({
230
+ currentChainId: chainId,
231
+ chain,
232
+ })
233
+ }
234
+
235
+ const chainFormat = client.chain?.formatters?.transactionRequest?.format
236
+ const format = chainFormat || formatTransactionRequest
237
+
238
+ const request = format(
239
+ {
240
+ // Pick out extra data that might exist on the chain's transaction request type.
241
+ ...extract(rest, { format: chainFormat }),
242
+ accessList,
243
+ authorizationList,
244
+ blobs,
245
+ chainId,
246
+ data,
247
+ from: account?.address,
248
+ gas,
249
+ gasPrice,
250
+ maxFeePerBlobGas,
251
+ maxFeePerGas,
252
+ maxPriorityFeePerGas,
253
+ nonce,
254
+ to,
255
+ type,
256
+ value,
257
+ } as TransactionRequest,
258
+ 'sendTransaction',
259
+ )
260
+
261
+ const isWalletNamespaceSupported = supportsWalletNamespace.get(client.uid)
262
+ const method = isWalletNamespaceSupported
263
+ ? 'wallet_sendTransaction'
264
+ : 'eth_sendTransaction'
265
+
266
+ const hash = await (async () => {
267
+ try {
268
+ return await client.request(
269
+ {
270
+ method,
271
+ params: [request],
272
+ },
273
+ { retryCount: 0 },
274
+ )
275
+ } catch (e) {
276
+ if (isWalletNamespaceSupported === false) throw e
277
+
278
+ const error = e as BaseError
279
+ // If the transport does not support the method or input, attempt to use the
280
+ // `wallet_sendTransaction` method.
281
+ if (
282
+ error.name === 'InvalidInputRpcError' ||
283
+ error.name === 'InvalidParamsRpcError' ||
284
+ error.name === 'MethodNotFoundRpcError' ||
285
+ error.name === 'MethodNotSupportedRpcError'
286
+ ) {
287
+ return (await client
288
+ .request(
289
+ {
290
+ method: 'wallet_sendTransaction',
291
+ params: [request],
292
+ },
293
+ { retryCount: 0 },
294
+ )
295
+ .then((hash) => {
296
+ supportsWalletNamespace.set(client.uid, true)
297
+ return hash
298
+ })
299
+ .catch((e) => {
300
+ const walletNamespaceError = e as BaseError
301
+ if (
302
+ walletNamespaceError.name === 'MethodNotFoundRpcError' ||
303
+ walletNamespaceError.name === 'MethodNotSupportedRpcError'
304
+ ) {
305
+ supportsWalletNamespace.set(client.uid, false)
306
+ throw error
307
+ }
308
+
309
+ throw walletNamespaceError
310
+ })) as never
311
+ }
312
+
313
+ throw error
314
+ }
315
+ })()
316
+
317
+ return getAction(
318
+ client,
319
+ waitForTransactionReceipt,
320
+ 'waitForTransactionReceipt',
321
+ )({
322
+ checkReplacement: false,
323
+ hash,
324
+ pollingInterval,
325
+ timeout,
326
+ })
327
+ }
328
+
329
+ if (account?.type === 'local') {
330
+ // Prepare the request for signing (assign appropriate fees, etc.)
331
+ const request = await getAction(
332
+ client,
333
+ prepareTransactionRequest,
334
+ 'prepareTransactionRequest',
335
+ )({
336
+ account,
337
+ accessList,
338
+ authorizationList,
339
+ blobs,
340
+ chain,
341
+ data,
342
+ gas,
343
+ gasPrice,
344
+ maxFeePerBlobGas,
345
+ maxFeePerGas,
346
+ maxPriorityFeePerGas,
347
+ nonce,
348
+ nonceManager: account.nonceManager,
349
+ parameters: [...defaultParameters, 'sidecars'],
350
+ type,
351
+ value,
352
+ ...rest,
353
+ to,
354
+ } as any)
355
+
356
+ const serializer = chain?.serializers?.transaction
357
+ const serializedTransaction = (await account.signTransaction(request, {
358
+ serializer,
359
+ })) as Hash
360
+ return (await getAction(
361
+ client,
362
+ sendRawTransactionSync,
363
+ 'sendRawTransactionSync',
364
+ )({
365
+ serializedTransaction,
366
+ })) as never
367
+ }
368
+
369
+ if (account?.type === 'smart')
370
+ throw new AccountTypeNotSupportedError({
371
+ metaMessages: [
372
+ 'Consider using the `sendUserOperation` Action instead.',
373
+ ],
374
+ docsPath: '/docs/actions/bundler/sendUserOperation',
375
+ type: 'smart',
376
+ })
377
+
378
+ throw new AccountTypeNotSupportedError({
379
+ docsPath: '/docs/actions/wallet/sendTransactionSync',
380
+ type: (account as any)?.type,
381
+ })
382
+ } catch (err) {
383
+ if (err instanceof AccountTypeNotSupportedError) throw err
384
+ throw getTransactionError(err as BaseError, {
385
+ ...parameters,
386
+ account,
387
+ chain: parameters.chain || undefined,
388
+ })
389
+ }
390
+ }
@@ -43,6 +43,7 @@ import {
43
43
  type SendTransactionReturnType,
44
44
  sendTransaction,
45
45
  } from './sendTransaction.js'
46
+ import type { sendTransactionSync } from './sendTransactionSync.js'
46
47
 
47
48
  export type WriteContractParameters<
48
49
  abi extends Abi | readonly unknown[] = Abi,
@@ -171,47 +172,81 @@ export async function writeContract<
171
172
  chainOverride
172
173
  >,
173
174
  ): Promise<WriteContractReturnType> {
174
- const {
175
- abi,
176
- account: account_ = client.account,
177
- address,
178
- args,
179
- dataSuffix,
180
- functionName,
181
- ...request
182
- } = parameters as WriteContractParameters
183
-
184
- if (typeof account_ === 'undefined')
185
- throw new AccountNotFoundError({
186
- docsPath: '/docs/contract/writeContract',
187
- })
188
- const account = account_ ? parseAccount(account_) : null
189
-
190
- const data = encodeFunctionData({
191
- abi,
192
- args,
193
- functionName,
194
- } as EncodeFunctionDataParameters)
175
+ return writeContract.internal(
176
+ client,
177
+ sendTransaction,
178
+ 'sendTransaction',
179
+ parameters,
180
+ ) as never
181
+ }
195
182
 
196
- try {
197
- return await getAction(
198
- client,
199
- sendTransaction,
200
- 'sendTransaction',
201
- )({
202
- data: `${data}${dataSuffix ? dataSuffix.replace('0x', '') : ''}`,
203
- to: address,
183
+ export namespace writeContract {
184
+ export async function internal<
185
+ chain extends Chain | undefined,
186
+ account extends Account | undefined,
187
+ const abi extends Abi | readonly unknown[],
188
+ functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
189
+ args extends ContractFunctionArgs<
190
+ abi,
191
+ 'nonpayable' | 'payable',
192
+ functionName
193
+ >,
194
+ chainOverride extends Chain | undefined,
195
+ >(
196
+ client: Client<Transport, chain, account>,
197
+ actionFn: typeof sendTransaction | typeof sendTransactionSync,
198
+ name: 'sendTransaction' | 'sendTransactionSync',
199
+ parameters: WriteContractParameters<
200
+ abi,
201
+ functionName,
202
+ args,
203
+ chain,
204
204
  account,
205
- ...request,
206
- })
207
- } catch (error) {
208
- throw getContractError(error as BaseError, {
205
+ chainOverride
206
+ >,
207
+ ) {
208
+ const {
209
209
  abi,
210
+ account: account_ = client.account,
210
211
  address,
211
212
  args,
212
- docsPath: '/docs/contract/writeContract',
213
+ dataSuffix,
214
+ functionName,
215
+ ...request
216
+ } = parameters as WriteContractParameters
217
+
218
+ if (typeof account_ === 'undefined')
219
+ throw new AccountNotFoundError({
220
+ docsPath: '/docs/contract/writeContract',
221
+ })
222
+ const account = account_ ? parseAccount(account_) : null
223
+
224
+ const data = encodeFunctionData({
225
+ abi,
226
+ args,
213
227
  functionName,
214
- sender: account?.address,
215
- })
228
+ } as EncodeFunctionDataParameters)
229
+
230
+ try {
231
+ return await getAction(
232
+ client,
233
+ actionFn as never,
234
+ name,
235
+ )({
236
+ data: `${data}${dataSuffix ? dataSuffix.replace('0x', '') : ''}`,
237
+ to: address,
238
+ account,
239
+ ...request,
240
+ })
241
+ } catch (error) {
242
+ throw getContractError(error as BaseError, {
243
+ abi,
244
+ address,
245
+ args,
246
+ docsPath: '/docs/contract/writeContract',
247
+ functionName,
248
+ sender: account?.address,
249
+ })
250
+ }
216
251
  }
217
252
  }