viem 0.0.1-alpha.20 → 0.0.1-alpha.22

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 (170) hide show
  1. package/dist/{chain-32f56cfa.d.ts → chain-4b39613a.d.ts} +2 -2
  2. package/dist/{chain-f12cdc7f.d.ts → chain-aa4898d0.d.ts} +1 -1
  3. package/dist/chains.d.ts +3 -3
  4. package/dist/chains.js +46 -46
  5. package/dist/chains.mjs +1 -1
  6. package/dist/{chunk-ZVGTYLKU.mjs → chunk-JMFNAGCD.mjs} +4 -3
  7. package/dist/chunk-JMFNAGCD.mjs.map +1 -0
  8. package/dist/{chunk-NHAKUPTF.js → chunk-MVD4Y3AE.js} +67 -63
  9. package/dist/chunk-MVD4Y3AE.js.map +1 -0
  10. package/dist/{chunk-YODUQCHJ.mjs → chunk-OZIBQJYR.mjs} +2 -2
  11. package/dist/{chunk-YODUQCHJ.mjs.map → chunk-OZIBQJYR.mjs.map} +0 -0
  12. package/dist/{chunk-FHXXG7I6.js → chunk-PMPJGAHY.js} +14 -13
  13. package/dist/chunk-PMPJGAHY.js.map +1 -0
  14. package/dist/{chunk-YFKR74XG.js → chunk-QA3IE5DU.js} +14 -14
  15. package/dist/{chunk-YFKR74XG.js.map → chunk-QA3IE5DU.js.map} +0 -0
  16. package/dist/{chunk-T7CBAKLI.mjs → chunk-QN2NCTEN.mjs} +2 -2
  17. package/dist/{chunk-T7CBAKLI.mjs.map → chunk-QN2NCTEN.mjs.map} +1 -1
  18. package/dist/{chunk-IAQPMSGJ.js → chunk-S77NLWHO.js} +13 -13
  19. package/dist/{chunk-IAQPMSGJ.js.map → chunk-S77NLWHO.js.map} +1 -1
  20. package/dist/{chunk-SF4I2NKC.js → chunk-V5U5S7PQ.js} +411 -167
  21. package/dist/chunk-V5U5S7PQ.js.map +1 -0
  22. package/dist/{chunk-5Q6FSUU2.mjs → chunk-WWJ5YPTJ.mjs} +412 -168
  23. package/dist/chunk-WWJ5YPTJ.mjs.map +1 -0
  24. package/dist/{chunk-MYQNZSWD.mjs → chunk-ZXXEENRD.mjs} +7 -3
  25. package/dist/chunk-ZXXEENRD.mjs.map +1 -0
  26. package/dist/clients/index.d.ts +7 -7
  27. package/dist/clients/index.js +3 -3
  28. package/dist/clients/index.mjs +2 -2
  29. package/dist/{contract-9af4608b.d.ts → contract-74f34ac9.d.ts} +14 -3
  30. package/dist/{createClient-5d316c7e.d.ts → createClient-55a04188.d.ts} +2 -2
  31. package/dist/{createPublicClient-9d2b42e1.d.ts → createPublicClient-3b27b282.d.ts} +3 -3
  32. package/dist/{createTestClient-79498dab.d.ts → createTestClient-93f9eac6.d.ts} +3 -3
  33. package/dist/{createWalletClient-f69a5230.d.ts → createWalletClient-c10df94d.d.ts} +3 -3
  34. package/dist/{eip1193-6c485d63.d.ts → eip1193-4c24765a.d.ts} +1 -1
  35. package/dist/ens.d.ts +1 -0
  36. package/dist/ens.js +11 -0
  37. package/dist/ens.js.map +1 -0
  38. package/dist/ens.mjs +11 -0
  39. package/dist/ens.mjs.map +1 -0
  40. package/dist/index.d.ts +125 -113
  41. package/dist/index.js +14 -6
  42. package/dist/index.mjs +13 -5
  43. package/dist/normalize-ef9240c0.d.ts +33 -0
  44. package/dist/{parseGwei-4308ad80.d.ts → parseGwei-b323fb0a.d.ts} +101 -37
  45. package/dist/public.d.ts +9 -9
  46. package/dist/public.js +4 -4
  47. package/dist/public.mjs +3 -3
  48. package/dist/{sendTransaction-1c8290a9.d.ts → sendTransaction-f17a2389.d.ts} +3 -3
  49. package/dist/{stopImpersonatingAccount-7781842a.d.ts → stopImpersonatingAccount-afb26486.d.ts} +2 -2
  50. package/dist/test.d.ts +5 -5
  51. package/dist/test.js +3 -3
  52. package/dist/test.mjs +2 -2
  53. package/dist/{transactionRequest-341b6ed2.d.ts → transactionRequest-93e9f001.d.ts} +2 -2
  54. package/dist/utils/index.d.ts +14 -16
  55. package/dist/utils/index.js +8 -2
  56. package/dist/utils/index.mjs +7 -1
  57. package/dist/wallet.d.ts +7 -7
  58. package/dist/wallet.js +3 -3
  59. package/dist/wallet.mjs +2 -2
  60. package/dist/{watchAsset-afaad3c7.d.ts → watchAsset-efd3dd05.d.ts} +3 -3
  61. package/dist/{watchPendingTransactions-3b722547.d.ts → watchPendingTransactions-a8688b26.d.ts} +17 -27
  62. package/dist/{webSocket-b180e679.d.ts → webSocket-d2e7bd0e.d.ts} +2 -2
  63. package/dist/window.d.ts +2 -2
  64. package/package.json +8 -2
  65. package/src/_test/abis.ts +7 -0
  66. package/src/_test/bench.ts +4 -4
  67. package/src/_test/index.ts +3 -1
  68. package/src/_test/utils.ts +39 -1
  69. package/src/actions/public/call.bench.ts +5 -5
  70. package/src/actions/public/deployContract.ts +4 -4
  71. package/src/actions/public/estimateGas.bench.ts +6 -6
  72. package/src/actions/public/getBlock.bench.ts +5 -5
  73. package/src/actions/public/getBlockNumber.bench.ts +5 -5
  74. package/src/actions/public/getGasPrice.bench.ts +1 -10
  75. package/src/actions/public/getTransaction.bench.ts +5 -5
  76. package/src/actions/public/getTransactionReceipt.bench.ts +5 -5
  77. package/src/actions/public/multicall.test.ts +452 -0
  78. package/src/actions/public/multicall.ts +103 -0
  79. package/src/actions/public/readContract.test.ts +226 -26
  80. package/src/actions/public/readContract.ts +13 -27
  81. package/src/actions/public/simulateContract.bench.ts +10 -0
  82. package/src/actions/public/simulateContract.test.ts +209 -37
  83. package/src/actions/public/simulateContract.ts +17 -21
  84. package/src/actions/public/watchContractEvent.test.ts +36 -32
  85. package/src/actions/public/watchEvent.test.ts +34 -29
  86. package/src/actions/wallet/signMessage.test.ts +0 -1
  87. package/src/actions/wallet/switchChain.test.ts +1 -2
  88. package/src/actions/wallet/watchAsset.test.ts +1 -2
  89. package/src/actions/wallet/writeContract.test.ts +37 -7
  90. package/src/actions/wallet/writeContract.ts +5 -14
  91. package/src/clients/transports/fallback.test.ts +34 -0
  92. package/src/clients/transports/fallback.ts +3 -1
  93. package/src/clients/transports/http.test.ts +0 -1
  94. package/src/clients/transports/webSocket.test.ts +0 -1
  95. package/src/constants/abis.test.ts +53 -0
  96. package/src/constants/abis.ts +44 -0
  97. package/src/constants/index.test.ts +14 -0
  98. package/src/constants/index.ts +3 -0
  99. package/src/constants/solidity.test.ts +41 -0
  100. package/src/constants/solidity.ts +35 -0
  101. package/src/ens.ts +5 -0
  102. package/src/errors/abi.test.ts +0 -2
  103. package/src/errors/base.test.ts +44 -2
  104. package/src/errors/base.ts +12 -12
  105. package/src/errors/block.test.ts +6 -6
  106. package/src/errors/contract.test.ts +233 -0
  107. package/src/errors/contract.ts +133 -80
  108. package/src/errors/index.ts +4 -2
  109. package/src/errors/request.test.ts +3 -4
  110. package/src/errors/request.ts +17 -17
  111. package/src/errors/rpc.test.ts +1 -2
  112. package/src/errors/transaction.test.ts +12 -12
  113. package/src/errors/transport.test.ts +0 -1
  114. package/src/index.test.ts +46 -0
  115. package/src/index.ts +8 -0
  116. package/src/types/contract.ts +55 -4
  117. package/src/types/index.ts +5 -0
  118. package/src/types/multicall.ts +82 -0
  119. package/src/utils/abi/decodeAbi.test.ts +1 -2
  120. package/src/utils/abi/decodeAbi.ts +11 -7
  121. package/src/utils/abi/decodeDeployData.test.ts +7 -15
  122. package/src/utils/abi/decodeDeployData.ts +10 -7
  123. package/src/utils/abi/decodeErrorResult.test.ts +103 -3
  124. package/src/utils/abi/decodeErrorResult.ts +30 -13
  125. package/src/utils/abi/decodeFunctionData.test.ts +0 -1
  126. package/src/utils/abi/decodeFunctionResult.test.ts +80 -9
  127. package/src/utils/abi/decodeFunctionResult.ts +15 -11
  128. package/src/utils/abi/encodeAbi.test.ts +40 -7
  129. package/src/utils/abi/encodeAbi.ts +28 -13
  130. package/src/utils/abi/encodeDeployData.test.ts +6 -13
  131. package/src/utils/abi/encodeDeployData.ts +10 -7
  132. package/src/utils/abi/encodeErrorResult.test.ts +2 -7
  133. package/src/utils/abi/encodeErrorResult.ts +18 -11
  134. package/src/utils/abi/encodeEventTopics.test.ts +11 -14
  135. package/src/utils/abi/encodeEventTopics.ts +15 -9
  136. package/src/utils/abi/encodeFunctionData.test.ts +5 -7
  137. package/src/utils/abi/encodeFunctionData.ts +16 -9
  138. package/src/utils/abi/encodeFunctionResult.test.ts +10 -15
  139. package/src/utils/abi/encodeFunctionResult.ts +9 -7
  140. package/src/utils/abi/getAbiItem.test.ts +547 -0
  141. package/src/utils/abi/getAbiItem.ts +93 -3
  142. package/src/utils/abi/index.ts +5 -1
  143. package/src/utils/address/getAddress.test.ts +6 -6
  144. package/src/utils/contract/getContractError.test.ts +247 -62
  145. package/src/utils/contract/getContractError.ts +30 -38
  146. package/src/utils/data/pad.bench.ts +0 -9
  147. package/src/utils/data/trim.bench.ts +0 -16
  148. package/src/utils/encoding/encodeBytes.bench.ts +0 -12
  149. package/src/utils/encoding/encodeHex.bench.ts +0 -11
  150. package/src/utils/ens/index.test.ts +13 -0
  151. package/src/utils/ens/index.ts +5 -0
  152. package/src/utils/ens/labelhash.test.ts +55 -0
  153. package/src/utils/ens/labelhash.ts +16 -0
  154. package/src/utils/ens/namehash.test.ts +65 -0
  155. package/src/utils/ens/namehash.ts +28 -0
  156. package/src/utils/ens/normalize.bench.ts +14 -0
  157. package/src/utils/ens/normalize.test.ts +35 -0
  158. package/src/utils/ens/normalize.ts +14 -0
  159. package/src/utils/hash/keccak256.ts +3 -5
  160. package/src/utils/index.test.ts +3 -0
  161. package/src/utils/index.ts +4 -0
  162. package/src/utils/rpc.test.ts +3 -6
  163. package/src/utils/unit/formatUnit.bench.ts +0 -5
  164. package/src/utils/unit/parseUnit.bench.ts +0 -5
  165. package/dist/chunk-5Q6FSUU2.mjs.map +0 -1
  166. package/dist/chunk-FHXXG7I6.js.map +0 -1
  167. package/dist/chunk-MYQNZSWD.mjs.map +0 -1
  168. package/dist/chunk-NHAKUPTF.js.map +0 -1
  169. package/dist/chunk-SF4I2NKC.js.map +0 -1
  170. package/dist/chunk-ZVGTYLKU.mjs.map +0 -1
@@ -0,0 +1,233 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { baycContractConfig } from '../_test/abis'
3
+ import { errorsExampleABI } from '../_test/generated'
4
+ import { BaseError } from './base'
5
+ import {
6
+ ContractFunctionExecutionError,
7
+ ContractFunctionRevertedError,
8
+ RawContractError,
9
+ } from './contract'
10
+
11
+ describe('ContractFunctionExecutionError', () => {
12
+ test('default', () => {
13
+ expect(
14
+ new ContractFunctionExecutionError(new BaseError('Internal error.'), {
15
+ abi: baycContractConfig.abi,
16
+ functionName: 'totalSupply',
17
+ }),
18
+ ).toMatchInlineSnapshot(`
19
+ [ContractFunctionExecutionError: Internal error.
20
+
21
+ Function: totalSupply()
22
+
23
+ Version: viem@1.0.2]
24
+ `)
25
+ })
26
+
27
+ test('args: contractAddress', () => {
28
+ expect(
29
+ new ContractFunctionExecutionError(new BaseError('Internal error.'), {
30
+ abi: baycContractConfig.abi,
31
+ functionName: 'totalSupply',
32
+ contractAddress: '0x0000000000000000000000000000000000000000',
33
+ }),
34
+ ).toMatchInlineSnapshot(`
35
+ [ContractFunctionExecutionError: Internal error.
36
+
37
+ Contract: 0x0000000000000000000000000000000000000000
38
+ Function: totalSupply()
39
+
40
+ Version: viem@1.0.2]
41
+ `)
42
+ })
43
+
44
+ test('args: args', () => {
45
+ expect(
46
+ new ContractFunctionExecutionError(new BaseError('Internal error.'), {
47
+ abi: baycContractConfig.abi,
48
+ functionName: 'mintApe',
49
+ args: [1n],
50
+ contractAddress: '0x0000000000000000000000000000000000000000',
51
+ }),
52
+ ).toMatchInlineSnapshot(`
53
+ [ContractFunctionExecutionError: Internal error.
54
+
55
+ Contract: 0x0000000000000000000000000000000000000000
56
+ Function: mintApe(uint256 numberOfTokens)
57
+ Arguments: (1)
58
+
59
+ Version: viem@1.0.2]
60
+ `)
61
+ })
62
+
63
+ test('args: docsPath', () => {
64
+ expect(
65
+ new ContractFunctionExecutionError(new BaseError('Internal error.'), {
66
+ abi: baycContractConfig.abi,
67
+ functionName: 'mintApe',
68
+ args: [1n],
69
+ contractAddress: '0x0000000000000000000000000000000000000000',
70
+ docsPath: '/docs',
71
+ }),
72
+ ).toMatchInlineSnapshot(`
73
+ [ContractFunctionExecutionError: Internal error.
74
+
75
+ Contract: 0x0000000000000000000000000000000000000000
76
+ Function: mintApe(uint256 numberOfTokens)
77
+ Arguments: (1)
78
+
79
+ Docs: https://viem.sh/docs
80
+ Version: viem@1.0.2]
81
+ `)
82
+ })
83
+
84
+ test('args: sender', () => {
85
+ expect(
86
+ new ContractFunctionExecutionError(new BaseError('Internal error.'), {
87
+ abi: baycContractConfig.abi,
88
+ functionName: 'mintApe',
89
+ args: [1n],
90
+ contractAddress: '0x0000000000000000000000000000000000000000',
91
+ sender: '0x0000000000000000000000000000000000000000',
92
+ }),
93
+ ).toMatchInlineSnapshot(`
94
+ [ContractFunctionExecutionError: Internal error.
95
+
96
+ Contract: 0x0000000000000000000000000000000000000000
97
+ Function: mintApe(uint256 numberOfTokens)
98
+ Arguments: (1)
99
+ Sender: 0x0000000000000000000000000000000000000000
100
+
101
+ Version: viem@1.0.2]
102
+ `)
103
+ })
104
+
105
+ test('cause: metaMessages', () => {
106
+ expect(
107
+ new ContractFunctionExecutionError(
108
+ new BaseError('Internal error.', { metaMessages: ['foo', 'bar'] }),
109
+ {
110
+ abi: baycContractConfig.abi,
111
+ functionName: 'totalSupply',
112
+ contractAddress: '0x0000000000000000000000000000000000000000',
113
+ },
114
+ ),
115
+ ).toMatchInlineSnapshot(`
116
+ [ContractFunctionExecutionError: Internal error.
117
+
118
+ foo
119
+ bar
120
+
121
+ Contract: 0x0000000000000000000000000000000000000000
122
+ Function: totalSupply()
123
+
124
+ Version: viem@1.0.2]
125
+ `)
126
+ })
127
+
128
+ test('no message', () => {
129
+ expect(
130
+ new ContractFunctionExecutionError(new BaseError(''), {
131
+ abi: baycContractConfig.abi,
132
+ functionName: 'foo',
133
+ }),
134
+ ).toMatchInlineSnapshot(`
135
+ [ContractFunctionExecutionError: An unknown error occurred while executing the contract function "foo".
136
+
137
+
138
+ Version: viem@1.0.2]
139
+ `)
140
+ })
141
+
142
+ test('function does not exist', () => {
143
+ expect(
144
+ new ContractFunctionExecutionError(new BaseError('Internal error.'), {
145
+ abi: baycContractConfig.abi,
146
+ functionName: 'foo',
147
+ }),
148
+ ).toMatchInlineSnapshot(`
149
+ [ContractFunctionExecutionError: Internal error.
150
+
151
+
152
+ Version: viem@1.0.2]
153
+ `)
154
+ })
155
+ })
156
+
157
+ describe('ContractFunctionRevertedError', () => {
158
+ test('default', () => {
159
+ expect(
160
+ new ContractFunctionRevertedError({
161
+ abi: errorsExampleABI,
162
+ message: 'oh no',
163
+ functionName: 'totalSupply',
164
+ }),
165
+ ).toMatchInlineSnapshot(`
166
+ [ContractFunctionRevertedError: The contract function "totalSupply" reverted with the following reason:
167
+ oh no
168
+
169
+ Version: viem@1.0.2]
170
+ `)
171
+ })
172
+
173
+ test('data: Error(string)', () => {
174
+ expect(
175
+ new ContractFunctionRevertedError({
176
+ abi: errorsExampleABI,
177
+ data: '0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000022456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473000000000000000000000000000000000000000000000000000000000000',
178
+ functionName: 'totalSupply',
179
+ }),
180
+ ).toMatchInlineSnapshot(`
181
+ [ContractFunctionRevertedError: The contract function "totalSupply" reverted with the following reason:
182
+ EnumerableSet: index out of bounds
183
+
184
+ Version: viem@1.0.2]
185
+ `)
186
+ })
187
+
188
+ test('data: Panic(uint256)', () => {
189
+ expect(
190
+ new ContractFunctionRevertedError({
191
+ abi: errorsExampleABI,
192
+ data: '0x4e487b710000000000000000000000000000000000000000000000000000000000000001',
193
+ functionName: 'totalSupply',
194
+ }),
195
+ ).toMatchInlineSnapshot(`
196
+ [ContractFunctionRevertedError: The contract function "totalSupply" reverted with the following reason:
197
+ An \`assert\` condition failed.
198
+
199
+ Version: viem@1.0.2]
200
+ `)
201
+ })
202
+
203
+ test('data: custom error', () => {
204
+ expect(
205
+ new ContractFunctionRevertedError({
206
+ abi: errorsExampleABI,
207
+ data: '0xdb731cf4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000066275676765720000000000000000000000000000000000000000000000000000',
208
+ functionName: 'customComplexError',
209
+ }),
210
+ ).toMatchInlineSnapshot(`
211
+ [ContractFunctionRevertedError: The contract function "customComplexError" reverted.
212
+
213
+ Error: ComplexError((address sender, uint256 bar), string message, uint256 number)
214
+ Arguments: ({"sender":"0x0000000000000000000000000000000000000000","bar":"69"}, bugger, 69)
215
+
216
+ Version: viem@1.0.2]
217
+ `)
218
+ })
219
+
220
+ test('data: zero data', () => {
221
+ expect(
222
+ new ContractFunctionRevertedError({
223
+ abi: errorsExampleABI,
224
+ data: '0x',
225
+ functionName: 'customComplexError',
226
+ }),
227
+ ).toMatchInlineSnapshot(`
228
+ [ContractFunctionRevertedError: The contract function "customComplexError" reverted.
229
+
230
+ Version: viem@1.0.2]
231
+ `)
232
+ })
233
+ })
@@ -1,125 +1,178 @@
1
1
  import { Abi } from 'abitype'
2
- import { Address } from '../types'
2
+ import { panicReasons } from '../constants'
3
+ import { Address, Hex } from '../types'
4
+ import {
5
+ DecodeErrorResultResponse,
6
+ decodeErrorResult,
7
+ getAbiItem,
8
+ formatAbiItemWithArgs,
9
+ formatAbiItem,
10
+ } from '../utils'
3
11
  import { BaseError } from './base'
4
12
 
5
- export class ContractMethodExecutionError extends BaseError {
6
- abi?: Abi
13
+ export class ContractFunctionExecutionError extends BaseError {
14
+ abi: Abi
7
15
  args?: unknown[]
16
+ cause: BaseError
8
17
  contractAddress?: Address
9
18
  formattedArgs?: string
10
- functionName?: string
11
- reason?: string
19
+ functionName: string
12
20
  sender?: Address
13
21
 
14
- name = 'ContractMethodExecutionError'
22
+ name = 'ContractFunctionExecutionError'
15
23
 
16
24
  constructor(
17
- message?: string,
25
+ cause: BaseError,
18
26
  {
19
27
  abi,
20
28
  args,
21
- cause,
22
29
  contractAddress,
23
- formattedArgs,
30
+ docsPath,
24
31
  functionName,
25
- functionWithParams,
26
32
  sender,
27
33
  }: {
28
- abi?: Abi
34
+ abi: Abi
29
35
  args?: any
30
- cause?: Error
31
36
  contractAddress?: Address
32
- formattedArgs?: string
33
- functionName?: string
34
- functionWithParams?: string
37
+ docsPath?: string
38
+ functionName: string
35
39
  sender?: Address
36
- } = {},
40
+ },
37
41
  ) {
42
+ const abiItem = getAbiItem({ abi, args, name: functionName })
43
+ const formattedArgs = abiItem
44
+ ? formatAbiItemWithArgs({
45
+ abiItem,
46
+ args,
47
+ includeFunctionName: false,
48
+ includeName: false,
49
+ })
50
+ : undefined
51
+ const functionWithParams = abiItem
52
+ ? formatAbiItem(abiItem, { includeName: true })
53
+ : undefined
54
+
38
55
  super(
39
- [
40
- message,
41
- ' ',
42
- sender && `Sender: ${sender}`,
43
- contractAddress &&
44
- `Contract: ${
45
- /* c8 ignore start */
46
- process.env.TEST
47
- ? '0x0000000000000000000000000000000000000000'
48
- : contractAddress
49
- /* c8 ignore end */
50
- }`,
51
- functionWithParams && `Function: ${functionWithParams}`,
52
- formattedArgs &&
53
- `Arguments: ${[...Array(functionName?.length ?? 0).keys()]
54
- .map(() => ' ')
55
- .join('')}${formattedArgs}`,
56
- ]
57
- .filter(Boolean)
58
- .join('\n'),
56
+ cause.shortMessage ||
57
+ `An unknown error occurred while executing the contract function "${functionName}".`,
59
58
  {
60
59
  cause,
60
+ docsPath,
61
+ metaMessages: [
62
+ ...(cause.metaMessages ? [...cause.metaMessages, ' '] : []),
63
+ contractAddress &&
64
+ `Contract: ${
65
+ /* c8 ignore start */
66
+ process.env.TEST
67
+ ? '0x0000000000000000000000000000000000000000'
68
+ : contractAddress
69
+ /* c8 ignore end */
70
+ }`,
71
+ functionWithParams && `Function: ${functionWithParams}`,
72
+ formattedArgs &&
73
+ formattedArgs !== '()' &&
74
+ `Arguments: ${[...Array(functionName?.length ?? 0).keys()]
75
+ .map(() => ' ')
76
+ .join('')}${formattedArgs}`,
77
+ sender && `Sender: ${sender}`,
78
+ ].filter(Boolean) as string[],
61
79
  },
62
80
  )
63
- if (message) this.reason = message
64
81
  this.abi = abi
65
82
  this.args = args
83
+ this.cause = cause
66
84
  this.contractAddress = contractAddress
67
85
  this.functionName = functionName
68
86
  this.sender = sender
69
87
  }
70
88
  }
71
89
 
72
- export class ContractMethodZeroDataError extends BaseError {
73
- abi?: Abi
74
- args?: unknown[]
75
- contractAddress?: Address
76
- functionName?: string
77
- functionWithParams?: string
90
+ export class ContractFunctionRevertedError extends BaseError {
91
+ name = 'ContractFunctionRevertedError'
78
92
 
79
- name = 'ContractMethodZeroDataError'
93
+ data?: DecodeErrorResultResponse
94
+ reason?: string
80
95
 
81
96
  constructor({
82
97
  abi,
83
- args,
84
- cause,
85
- contractAddress,
98
+ data,
86
99
  functionName,
87
- functionWithParams,
88
- }: {
89
- abi?: Abi
90
- args?: any
91
- cause?: Error
92
- contractAddress?: Address
93
- functionName?: string
94
- functionWithParams?: string
95
- } = {}) {
100
+ message,
101
+ }: { abi: Abi; data?: Hex; functionName: string; message?: string }) {
102
+ let decodedData: DecodeErrorResultResponse | undefined = undefined
103
+ let metaMessages
104
+ let reason
105
+ if (data && data !== '0x') {
106
+ decodedData = decodeErrorResult({ abi, data })
107
+ const { abiItem, errorName, args: errorArgs } = decodedData
108
+ if (errorName === 'Error') {
109
+ reason = (errorArgs as [string])[0]
110
+ } else if (errorName === 'Panic') {
111
+ const [firstArg] = errorArgs as [number]
112
+ reason = panicReasons[firstArg as keyof typeof panicReasons]
113
+ } else if (errorArgs) {
114
+ const errorWithParams = abiItem
115
+ ? formatAbiItem(abiItem, { includeName: true })
116
+ : undefined
117
+ const formattedArgs = abiItem
118
+ ? formatAbiItemWithArgs({
119
+ abiItem,
120
+ args: errorArgs,
121
+ includeFunctionName: false,
122
+ includeName: false,
123
+ })
124
+ : undefined
125
+
126
+ metaMessages = [
127
+ errorWithParams ? `Error: ${errorWithParams}` : '',
128
+ formattedArgs && formattedArgs !== '()'
129
+ ? `Arguments: ${[...Array(errorName?.length ?? 0).keys()]
130
+ .map(() => ' ')
131
+ .join('')}${formattedArgs}`
132
+ : '',
133
+ ]
134
+ }
135
+ } else if (message) reason = message
136
+
96
137
  super(
97
- [
98
- `The contract method "${functionName}" returned no data ("0x"). This could be due to any of the following:`,
99
- `- The contract does not have the function "${functionName}",`,
100
- '- The parameters passed to the contract function may be invalid, or',
101
- '- The address is not a contract.',
102
- ' ',
103
- contractAddress &&
104
- `Contract: ${
105
- /* c8 ignore start */
106
- process.env.TEST
107
- ? '0x0000000000000000000000000000000000000000'
108
- : contractAddress
109
- /* c8 ignore end */
110
- }`,
111
- functionWithParams && `Function: ${functionWithParams}`,
112
- functionWithParams && ` > "0x"`,
113
- ]
114
- .filter(Boolean)
115
- .join('\n'),
138
+ reason
139
+ ? [
140
+ `The contract function "${functionName}" reverted with the following reason:`,
141
+ reason,
142
+ ].join('\n')
143
+ : `The contract function "${functionName}" reverted.`,
116
144
  {
117
- cause,
145
+ metaMessages,
118
146
  },
119
147
  )
120
- this.abi = abi
121
- this.args = args
122
- this.contractAddress = contractAddress
123
- this.functionName = functionName
148
+
149
+ this.reason = reason
150
+ this.data = decodedData
151
+ }
152
+ }
153
+
154
+ export class ContractFunctionZeroDataError extends BaseError {
155
+ name = 'ContractFunctionZeroDataError'
156
+ constructor({ functionName }: { functionName: string }) {
157
+ super(`The contract function "${functionName}" returned no data ("0x").`, {
158
+ metaMessages: [
159
+ 'This could be due to any of the following:',
160
+ `- The contract does not have the function "${functionName}",`,
161
+ '- The parameters passed to the contract function may be invalid, or',
162
+ '- The address is not a contract.',
163
+ ],
164
+ })
165
+ }
166
+ }
167
+
168
+ export class RawContractError extends BaseError {
169
+ code = 3
170
+ name = 'RawContractError'
171
+
172
+ data?: Hex
173
+
174
+ constructor({ data, message }: { data?: Hex; message?: string }) {
175
+ super(message || '')
176
+ this.data = data
124
177
  }
125
178
  }
@@ -25,8 +25,10 @@ export { BaseError } from './base'
25
25
  export { BlockNotFoundError } from './block'
26
26
 
27
27
  export {
28
- ContractMethodExecutionError,
29
- ContractMethodZeroDataError,
28
+ ContractFunctionExecutionError,
29
+ ContractFunctionRevertedError,
30
+ ContractFunctionZeroDataError,
31
+ RawContractError,
30
32
  } from './contract'
31
33
 
32
34
  export { SizeExceedsPaddingSizeError } from './data'
@@ -27,7 +27,7 @@ test('RequestError', () => {
27
27
  error: { code: 1337, message: 'error details' },
28
28
  }),
29
29
  {
30
- humanMessage: 'An internal error was received.',
30
+ shortMessage: 'An internal error was received.',
31
31
  },
32
32
  ),
33
33
  ).toMatchInlineSnapshot(`
@@ -46,7 +46,7 @@ test('RpcRequestError', () => {
46
46
  url: 'https://viem.sh',
47
47
  error: { code: 1337, message: 'error details' },
48
48
  }),
49
- { humanMessage: 'An internal error was received.' },
49
+ { shortMessage: 'An internal error was received.' },
50
50
  ),
51
51
  ).toMatchInlineSnapshot(`
52
52
  [RpcError: An internal error was received.
@@ -65,7 +65,7 @@ test('RpcRequestError', () => {
65
65
  error: { code: 1337, message: 'error details' },
66
66
  }),
67
67
  {
68
- humanMessage: 'An internal error was received.',
68
+ shortMessage: 'An internal error was received.',
69
69
  docsPath: '/lol',
70
70
  },
71
71
  ),
@@ -73,7 +73,6 @@ test('RpcRequestError', () => {
73
73
  [RpcError: An internal error was received.
74
74
 
75
75
  Docs: https://viem.sh/lol
76
-
77
76
  Details: error details
78
77
  Version: viem@1.0.2]
79
78
  `)
@@ -4,9 +4,9 @@ import { RpcError } from './rpc'
4
4
  export class RequestError extends BaseError {
5
5
  constructor(
6
6
  err: Error,
7
- { docsPath, humanMessage }: { docsPath?: string; humanMessage: string },
7
+ { docsPath, shortMessage }: { docsPath?: string; shortMessage: string },
8
8
  ) {
9
- super(humanMessage, {
9
+ super(shortMessage, {
10
10
  cause: err,
11
11
  docsPath,
12
12
  })
@@ -19,9 +19,9 @@ export class RpcRequestError extends RequestError {
19
19
 
20
20
  constructor(
21
21
  err: RpcError,
22
- { docsPath, humanMessage }: { docsPath?: string; humanMessage: string },
22
+ { docsPath, shortMessage }: { docsPath?: string; shortMessage: string },
23
23
  ) {
24
- super(err, { docsPath, humanMessage })
24
+ super(err, { docsPath, shortMessage })
25
25
  this.code = err.code
26
26
  this.name = err.name
27
27
  }
@@ -33,7 +33,7 @@ export class ParseRpcError extends RpcRequestError {
33
33
 
34
34
  constructor(err: RpcError) {
35
35
  super(err, {
36
- humanMessage:
36
+ shortMessage:
37
37
  'Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.',
38
38
  })
39
39
  }
@@ -44,7 +44,7 @@ export class InvalidRequestRpcError extends RpcRequestError {
44
44
  code = -32600
45
45
 
46
46
  constructor(err: RpcError) {
47
- super(err, { humanMessage: 'JSON is not a valid request object.' })
47
+ super(err, { shortMessage: 'JSON is not a valid request object.' })
48
48
  }
49
49
  }
50
50
 
@@ -54,7 +54,7 @@ export class MethodNotFoundRpcError extends RpcRequestError {
54
54
 
55
55
  constructor(err: RpcError) {
56
56
  super(err, {
57
- humanMessage: 'The method does not exist / is not available.',
57
+ shortMessage: 'The method does not exist / is not available.',
58
58
  })
59
59
  }
60
60
  }
@@ -65,7 +65,7 @@ export class InvalidParamsRpcError extends RpcRequestError {
65
65
 
66
66
  constructor(err: RpcError) {
67
67
  super(err, {
68
- humanMessage: [
68
+ shortMessage: [
69
69
  'Invalid parameters were provided to the RPC method.',
70
70
  'Double check you have provided the correct parameters.',
71
71
  ].join('\n'),
@@ -78,7 +78,7 @@ export class InternalRpcError extends RpcRequestError {
78
78
  code = -32603
79
79
 
80
80
  constructor(err: RpcError) {
81
- super(err, { humanMessage: 'An internal error was received.' })
81
+ super(err, { shortMessage: 'An internal error was received.' })
82
82
  }
83
83
  }
84
84
 
@@ -88,7 +88,7 @@ export class InvalidInputRpcError extends RpcRequestError {
88
88
 
89
89
  constructor(err: RpcError) {
90
90
  super(err, {
91
- humanMessage: [
91
+ shortMessage: [
92
92
  'Missing or invalid parameters.',
93
93
  'Double check you have provided the correct parameters.',
94
94
  ].join('\n'),
@@ -101,7 +101,7 @@ export class ResourceNotFoundRpcError extends RpcRequestError {
101
101
  code = -32001
102
102
 
103
103
  constructor(err: RpcError) {
104
- super(err, { humanMessage: 'Requested resource not found.' })
104
+ super(err, { shortMessage: 'Requested resource not found.' })
105
105
  }
106
106
  }
107
107
 
@@ -110,7 +110,7 @@ export class ResourceUnavailableRpcError extends RpcRequestError {
110
110
  code = -32002
111
111
 
112
112
  constructor(err: RpcError) {
113
- super(err, { humanMessage: 'Requested resource not available.' })
113
+ super(err, { shortMessage: 'Requested resource not available.' })
114
114
  }
115
115
  }
116
116
 
@@ -119,7 +119,7 @@ export class TransactionRejectedRpcError extends RpcRequestError {
119
119
  code = -32003
120
120
 
121
121
  constructor(err: RpcError) {
122
- super(err, { humanMessage: 'Transaction creation failed.' })
122
+ super(err, { shortMessage: 'Transaction creation failed.' })
123
123
  }
124
124
  }
125
125
 
@@ -128,7 +128,7 @@ export class MethodNotSupportedRpcError extends RpcRequestError {
128
128
  code = -32004
129
129
 
130
130
  constructor(err: RpcError) {
131
- super(err, { humanMessage: 'Method is not implemented.' })
131
+ super(err, { shortMessage: 'Method is not implemented.' })
132
132
  }
133
133
  }
134
134
 
@@ -137,7 +137,7 @@ export class LimitExceededRpcError extends RpcRequestError {
137
137
  code = -32005
138
138
 
139
139
  constructor(err: RpcError) {
140
- super(err, { humanMessage: 'Request exceeds defined limit.' })
140
+ super(err, { shortMessage: 'Request exceeds defined limit.' })
141
141
  }
142
142
  }
143
143
 
@@ -147,7 +147,7 @@ export class JsonRpcVersionUnsupportedError extends RpcRequestError {
147
147
 
148
148
  constructor(err: RpcError) {
149
149
  super(err, {
150
- humanMessage: 'Version of JSON-RPC protocol is not supported.',
150
+ shortMessage: 'Version of JSON-RPC protocol is not supported.',
151
151
  })
152
152
  }
153
153
  }
@@ -157,7 +157,7 @@ export class UnknownRpcError extends RequestError {
157
157
 
158
158
  constructor(err: Error) {
159
159
  super(err, {
160
- humanMessage: 'An unknown RPC error occurred.',
160
+ shortMessage: 'An unknown RPC error occurred.',
161
161
  })
162
162
  }
163
163
  }
@@ -21,8 +21,7 @@ test('RpcError', () => {
21
21
  Request body: {"foo":"bar"}
22
22
 
23
23
  Details: Error
24
- Version: viem@1.0.2
25
- Internal Error: {"code":420,"message":"Error"}]
24
+ Version: viem@1.0.2]
26
25
  `)
27
26
  })
28
27