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
@@ -14,7 +14,15 @@ test('revert SoldOutError()', () => {
14
14
  ],
15
15
  data: '0x7f6df6bb',
16
16
  }),
17
- ).toEqual({ errorName: 'SoldOutError', args: undefined })
17
+ ).toEqual({
18
+ abiItem: {
19
+ inputs: [],
20
+ name: 'SoldOutError',
21
+ type: 'error',
22
+ },
23
+ errorName: 'SoldOutError',
24
+ args: undefined,
25
+ })
18
26
  expect(
19
27
  decodeErrorResult({
20
28
  abi: [
@@ -26,7 +34,14 @@ test('revert SoldOutError()', () => {
26
34
  ],
27
35
  data: '0x7f6df6bb',
28
36
  }),
29
- ).toEqual({ errorName: 'SoldOutError', args: undefined })
37
+ ).toEqual({
38
+ abiItem: {
39
+ name: 'SoldOutError',
40
+ type: 'error',
41
+ },
42
+ errorName: 'SoldOutError',
43
+ args: undefined,
44
+ })
30
45
  })
31
46
 
32
47
  test('revert AccessDeniedError(string)', () => {
@@ -48,6 +63,17 @@ test('revert AccessDeniedError(string)', () => {
48
63
  data: '0x83aa206e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a796f7520646f206e6f7420686176652061636365737320736572000000000000',
49
64
  }),
50
65
  ).toEqual({
66
+ abiItem: {
67
+ inputs: [
68
+ {
69
+ internalType: 'string',
70
+ name: 'a',
71
+ type: 'string',
72
+ },
73
+ ],
74
+ name: 'AccessDeniedError',
75
+ type: 'error',
76
+ },
51
77
  errorName: 'AccessDeniedError',
52
78
  args: ['you do not have access ser'],
53
79
  })
@@ -94,6 +120,39 @@ test('revert AccessDeniedError((uint256,bool,address,uint256))', () => {
94
120
  data: '0x0a1895610000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac0000000000000000000000000000000000000000000000000000000000000029',
95
121
  }),
96
122
  ).toEqual({
123
+ abiItem: {
124
+ inputs: [
125
+ {
126
+ components: [
127
+ {
128
+ internalType: 'uint256',
129
+ name: 'weight',
130
+ type: 'uint256',
131
+ },
132
+ {
133
+ internalType: 'bool',
134
+ name: 'voted',
135
+ type: 'bool',
136
+ },
137
+ {
138
+ internalType: 'address',
139
+ name: 'delegate',
140
+ type: 'address',
141
+ },
142
+ {
143
+ internalType: 'uint256',
144
+ name: 'vote',
145
+ type: 'uint256',
146
+ },
147
+ ],
148
+ internalType: 'struct Ballot.Voter',
149
+ name: 'voter',
150
+ type: 'tuple',
151
+ },
152
+ ],
153
+ name: 'AccessDeniedError',
154
+ type: 'error',
155
+ },
97
156
  errorName: 'AccessDeniedError',
98
157
  args: [
99
158
  {
@@ -106,6 +165,48 @@ test('revert AccessDeniedError((uint256,bool,address,uint256))', () => {
106
165
  })
107
166
  })
108
167
 
168
+ test('Error(string)', () => {
169
+ expect(
170
+ decodeErrorResult({
171
+ data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000',
172
+ }),
173
+ ).toEqual({
174
+ abiItem: {
175
+ inputs: [
176
+ {
177
+ name: 'message',
178
+ type: 'string',
179
+ },
180
+ ],
181
+ name: 'Error',
182
+ type: 'error',
183
+ },
184
+ errorName: 'Error',
185
+ args: ['test'],
186
+ })
187
+ })
188
+
189
+ test.todo('Panic(uint256)')
190
+
191
+ test('zero data', () => {
192
+ expect(() =>
193
+ decodeErrorResult({
194
+ abi: [
195
+ {
196
+ inputs: [],
197
+ name: 'SoldOutError',
198
+ type: 'error',
199
+ },
200
+ ],
201
+ data: '0x',
202
+ }),
203
+ ).toThrowErrorMatchingInlineSnapshot(`
204
+ "Cannot decode zero data (\\"0x\\") with ABI parameters.
205
+
206
+ Version: viem@1.0.2"
207
+ `)
208
+ })
209
+
109
210
  test("errors: error doesn't exist", () => {
110
211
  expect(() =>
111
212
  decodeErrorResult({
@@ -124,7 +225,6 @@ test("errors: error doesn't exist", () => {
124
225
  You can look up the signature \\"0xa3741467\\" here: https://sig.eth.samczsun.com/.
125
226
 
126
227
  Docs: https://viem.sh/docs/contract/decodeErrorResult
127
-
128
228
  Version: viem@1.0.2"
129
229
  `)
130
230
  })
@@ -1,28 +1,45 @@
1
- import { Abi } from 'abitype'
2
- import { AbiErrorSignatureNotFoundError } from '../../errors'
3
- import { Hex } from '../../types'
1
+ import { Abi, AbiError } from 'abitype'
2
+ import { solidityError, solidityPanic } from '../../constants'
3
+ import {
4
+ AbiDecodingZeroDataError,
5
+ AbiErrorSignatureNotFoundError,
6
+ } from '../../errors'
7
+ import { AbiItem, Hex } from '../../types'
4
8
  import { slice } from '../data'
5
9
  import { getFunctionSignature } from '../hash'
6
10
  import { decodeAbi } from './decodeAbi'
7
11
  import { formatAbiItem } from './formatAbiItem'
8
12
 
9
- export type DecodeErrorResultArgs = { abi: Abi; data: Hex }
13
+ export type DecodeErrorResultArgs = { abi?: Abi; data: Hex }
10
14
 
11
- export function decodeErrorResult({ abi, data }: DecodeErrorResultArgs) {
15
+ export type DecodeErrorResultResponse = {
16
+ abiItem: AbiItem
17
+ errorName: string
18
+ args?: readonly unknown[]
19
+ }
20
+
21
+ export function decodeErrorResult({
22
+ abi,
23
+ data,
24
+ }: DecodeErrorResultArgs): DecodeErrorResultResponse {
12
25
  const signature = slice(data, 0, 4)
13
- const description = abi.find(
14
- (x) => signature === getFunctionSignature(formatAbiItem(x)),
26
+ if (signature === '0x') throw new AbiDecodingZeroDataError()
27
+
28
+ const abi_ = [...(abi || []), solidityError, solidityPanic]
29
+ const abiItem = abi_.find(
30
+ (x) =>
31
+ x.type === 'error' &&
32
+ signature === getFunctionSignature(formatAbiItem(x)),
15
33
  )
16
- if (!description)
34
+ if (!abiItem)
17
35
  throw new AbiErrorSignatureNotFoundError(signature, {
18
36
  docsPath: '/docs/contract/decodeErrorResult',
19
37
  })
20
38
  return {
21
- errorName: (description as { name: string }).name,
22
- args: ('inputs' in description &&
23
- description.inputs &&
24
- description.inputs.length > 0
25
- ? decodeAbi({ data: slice(data, 4), params: description.inputs })
39
+ abiItem,
40
+ args: ('inputs' in abiItem && abiItem.inputs && abiItem.inputs.length > 0
41
+ ? decodeAbi({ data: slice(data, 4), params: abiItem.inputs })
26
42
  : undefined) as readonly unknown[] | undefined,
43
+ errorName: (abiItem as { name: string }).name,
27
44
  }
28
45
  }
@@ -134,7 +134,6 @@ test("errors: function doesn't exist", () => {
134
134
  You can look up the signature \\"0xa3741467\\" here: https://sig.eth.samczsun.com/.
135
135
 
136
136
  Docs: https://viem.sh/docs/contract/decodeFunctionData
137
-
138
137
  Version: viem@1.0.2"
139
138
  `)
140
139
  })
@@ -13,7 +13,7 @@ test('returns ()', () => {
13
13
  stateMutability: 'pure',
14
14
  type: 'function',
15
15
  },
16
- ] as const,
16
+ ],
17
17
  functionName: 'foo',
18
18
  data: '0x',
19
19
  }),
@@ -28,7 +28,7 @@ test('returns ()', () => {
28
28
  stateMutability: 'pure',
29
29
  type: 'function',
30
30
  },
31
- ] as const,
31
+ ],
32
32
  functionName: 'foo',
33
33
  // @ts-expect-error
34
34
  data: '',
@@ -53,7 +53,7 @@ test('returns (address)', () => {
53
53
  stateMutability: 'pure',
54
54
  type: 'function',
55
55
  },
56
- ] as const,
56
+ ],
57
57
  functionName: 'foo',
58
58
  data: '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
59
59
  }),
@@ -111,7 +111,7 @@ test('returns (Bar)', () => {
111
111
  stateMutability: 'pure',
112
112
  type: 'function',
113
113
  },
114
- ] as const,
114
+ ],
115
115
  functionName: 'bar',
116
116
  data: '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac0000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac0000000000000000000000000000000000000000000000000000000000000045',
117
117
  }),
@@ -182,7 +182,7 @@ test('returns (Bar, string)', () => {
182
182
  stateMutability: 'pure',
183
183
  type: 'function',
184
184
  },
185
- ] as const,
185
+ ],
186
186
  functionName: 'baz',
187
187
  data: '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac0000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000',
188
188
  }),
@@ -200,6 +200,79 @@ test('returns (Bar, string)', () => {
200
200
  ])
201
201
  })
202
202
 
203
+ test('overloads', () => {
204
+ expect(
205
+ decodeFunctionResult({
206
+ abi: [
207
+ {
208
+ inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }],
209
+ name: 'foo',
210
+ outputs: [
211
+ {
212
+ internalType: 'uint256',
213
+ name: 'x',
214
+ type: 'uint256',
215
+ },
216
+ ],
217
+ stateMutability: 'pure',
218
+ type: 'function',
219
+ },
220
+ {
221
+ inputs: [],
222
+ name: 'foo',
223
+ outputs: [
224
+ {
225
+ internalType: 'address',
226
+ name: 'sender',
227
+ type: 'address',
228
+ },
229
+ ],
230
+ stateMutability: 'pure',
231
+ type: 'function',
232
+ },
233
+ ],
234
+ functionName: 'foo',
235
+ data: '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
236
+ }),
237
+ ).toEqual('0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC')
238
+
239
+ expect(
240
+ decodeFunctionResult({
241
+ abi: [
242
+ {
243
+ inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }],
244
+ name: 'foo',
245
+ outputs: [
246
+ {
247
+ internalType: 'uint256',
248
+ name: 'x',
249
+ type: 'uint256',
250
+ },
251
+ ],
252
+ stateMutability: 'pure',
253
+ type: 'function',
254
+ },
255
+ {
256
+ inputs: [],
257
+ name: 'foo',
258
+ outputs: [
259
+ {
260
+ internalType: 'address',
261
+ name: 'sender',
262
+ type: 'address',
263
+ },
264
+ ],
265
+ stateMutability: 'pure',
266
+ type: 'function',
267
+ },
268
+ ],
269
+ functionName: 'foo',
270
+ data: '0x0000000000000000000000000000000000000000000000000000000000000069',
271
+ args: [10n],
272
+ }),
273
+ ).toEqual(105n)
274
+ })
275
+
203
276
  test("error: function doesn't exist", () => {
204
277
  expect(() =>
205
278
  decodeFunctionResult({
@@ -217,7 +290,7 @@ test("error: function doesn't exist", () => {
217
290
  stateMutability: 'pure',
218
291
  type: 'function',
219
292
  },
220
- ] as const,
293
+ ],
221
294
  // @ts-expect-error
222
295
  functionName: 'baz',
223
296
  data: '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
@@ -228,7 +301,6 @@ test("error: function doesn't exist", () => {
228
301
  Make sure you are using the correct ABI and that the function exists on it.
229
302
 
230
303
  Docs: https://viem.sh/docs/contract/decodeFunctionResult
231
-
232
304
  Version: viem@1.0.2"
233
305
  `,
234
306
  )
@@ -244,7 +316,7 @@ test("error: function doesn't exist", () => {
244
316
  stateMutability: 'pure',
245
317
  type: 'function',
246
318
  },
247
- ] as const,
319
+ ],
248
320
  functionName: 'foo',
249
321
  data: '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
250
322
  }),
@@ -255,7 +327,6 @@ test("error: function doesn't exist", () => {
255
327
  Make sure you are using the correct ABI and that the function exists on it.
256
328
 
257
329
  Docs: https://viem.sh/docs/contract/decodeFunctionResult
258
-
259
330
  Version: viem@1.0.2"
260
331
  `,
261
332
  )
@@ -1,46 +1,50 @@
1
- import { Abi, ExtractAbiFunctionNames } from 'abitype'
1
+ import { Abi, Narrow } from 'abitype'
2
2
  import {
3
3
  AbiFunctionNotFoundError,
4
4
  AbiFunctionOutputsNotFoundError,
5
5
  } from '../../errors'
6
-
7
6
  import {
7
+ ExtractArgsFromAbi,
8
8
  ExtractFunctionNameFromAbi,
9
9
  ExtractResultFromAbi,
10
10
  Hex,
11
11
  } from '../../types'
12
12
  import { decodeAbi } from './decodeAbi'
13
+ import { getAbiItem, GetAbiItemArgs } from './getAbiItem'
13
14
 
14
15
  const docsPath = '/docs/contract/decodeFunctionResult'
15
16
 
16
17
  export type DecodeFunctionResultArgs<
17
18
  TAbi extends Abi | readonly unknown[] = Abi,
18
- TFunctionName extends string = any,
19
+ TFunctionName extends string = string,
19
20
  > = {
20
- abi: TAbi
21
+ abi: Narrow<TAbi>
21
22
  functionName: ExtractFunctionNameFromAbi<TAbi, TFunctionName>
22
23
  data: Hex
23
- }
24
+ } & Partial<ExtractArgsFromAbi<TAbi, TFunctionName>>
24
25
 
25
26
  export type DecodeFunctionResultResponse<
26
27
  TAbi extends Abi | readonly unknown[] = Abi,
27
- TFunctionName extends string = any,
28
+ TFunctionName extends string = string,
28
29
  > = ExtractResultFromAbi<TAbi, TFunctionName>
29
30
 
30
31
  export function decodeFunctionResult<
31
- TAbi extends Abi | readonly unknown[] = Abi,
32
- TFunctionName extends string = any,
32
+ TAbi extends Abi | readonly unknown[],
33
+ TFunctionName extends string,
33
34
  >({
34
35
  abi,
36
+ args,
35
37
  functionName,
36
38
  data,
37
39
  }: DecodeFunctionResultArgs<TAbi, TFunctionName>): DecodeFunctionResultResponse<
38
40
  TAbi,
39
41
  TFunctionName
40
42
  > {
41
- const description = (abi as Abi).find(
42
- (x) => 'name' in x && x.name === functionName,
43
- )
43
+ const description = getAbiItem({
44
+ abi,
45
+ args,
46
+ name: functionName,
47
+ } as GetAbiItemArgs)
44
48
  if (!description)
45
49
  throw new AbiFunctionNotFoundError(functionName, { docsPath })
46
50
  if (!('outputs' in description))
@@ -745,7 +745,7 @@ describe('static', () => {
745
745
  { internalType: 'uint256[2]', name: 'xOut', type: 'uint256[2]' },
746
746
  { internalType: 'bool', name: 'yOut', type: 'bool' },
747
747
  { internalType: 'string[3]', name: 'zOut', type: 'string[3]' },
748
- ] as any,
748
+ ],
749
749
  values: [[420n, 69n], true, ['wagmi', 'viem', 'lol']],
750
750
  }),
751
751
  ).toMatchInlineSnapshot(
@@ -885,7 +885,7 @@ describe('dynamic', () => {
885
885
  name: 'zIn',
886
886
  type: 'string',
887
887
  },
888
- ] as const,
888
+ ],
889
889
  values: [[420n, 69n], true, 'wagmi'],
890
890
  }),
891
891
  ).toMatchInlineSnapshot(
@@ -897,7 +897,39 @@ describe('dynamic', () => {
897
897
  describe('(bytes)', () => {
898
898
  test('default', () => {
899
899
  expect(
900
- // cast abi-encode "a(bytes)" "0x042069"
900
+ // cast abi-encode "a(bytes)" "0x42069"
901
+ encodeAbi({
902
+ params: [
903
+ {
904
+ internalType: 'bytes',
905
+ name: 'xIn',
906
+ type: 'bytes',
907
+ },
908
+ ],
909
+ values: ['0x42069'],
910
+ }),
911
+ ).toMatchInlineSnapshot(
912
+ '"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034206900000000000000000000000000000000000000000000000000000000000"',
913
+ )
914
+ expect(
915
+ // cast abi-encode "a(bytes)" "0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"
916
+ encodeAbi({
917
+ params: [
918
+ {
919
+ internalType: 'bytes',
920
+ name: 'xIn',
921
+ type: 'bytes',
922
+ },
923
+ ],
924
+ values: [
925
+ '0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045',
926
+ ],
927
+ }),
928
+ ).toMatchInlineSnapshot(
929
+ '"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000"',
930
+ )
931
+ expect(
932
+ // cast abi-encode "a(bytes)" "0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604570a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"
901
933
  encodeAbi({
902
934
  params: [
903
935
  {
@@ -906,10 +938,12 @@ describe('dynamic', () => {
906
938
  type: 'bytes',
907
939
  },
908
940
  ],
909
- values: ['0x042069'],
941
+ values: [
942
+ '0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604570a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045',
943
+ ],
910
944
  }),
911
945
  ).toMatchInlineSnapshot(
912
- '"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030420690000000000000000000000000000000000000000000000000000000000"',
946
+ '"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004870a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604570a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000"',
913
947
  )
914
948
  })
915
949
  })
@@ -1168,7 +1202,7 @@ describe('dynamic', () => {
1168
1202
  name: 'wagmiIn',
1169
1203
  type: 'tuple',
1170
1204
  },
1171
- ] as const,
1205
+ ],
1172
1206
  values: [
1173
1207
  {
1174
1208
  foo: {
@@ -1356,7 +1390,6 @@ test('invalid type', () => {
1356
1390
  Please provide a valid ABI type.
1357
1391
 
1358
1392
  Docs: https://viem.sh/docs/contract/encodeAbi
1359
-
1360
1393
  Version: viem@1.0.2"
1361
1394
  `)
1362
1395
  })
@@ -2,6 +2,7 @@ import {
2
2
  AbiParameter,
3
3
  AbiParametersToPrimitiveTypes,
4
4
  AbiParameterToPrimitiveType,
5
+ Narrow,
5
6
  } from 'abitype'
6
7
 
7
8
  import {
@@ -11,28 +12,36 @@ import {
11
12
  InvalidArrayError,
12
13
  } from '../../errors'
13
14
  import { Hex } from '../../types'
14
- import { concat, padHex, size } from '../data'
15
+ import { concat, padHex, size, slice } from '../data'
15
16
  import { boolToHex, numberToHex, stringToHex } from '../encoding'
16
17
 
17
- export type EncodeAbiArgs<TParams extends readonly AbiParameter[]> = {
18
- params: TParams
19
- values: AbiParametersToPrimitiveTypes<TParams>
18
+ export type EncodeAbiArgs<
19
+ TParams extends
20
+ | readonly AbiParameter[]
21
+ | readonly unknown[] = readonly AbiParameter[],
22
+ > = {
23
+ params: Narrow<TParams>
24
+ values: TParams extends readonly AbiParameter[]
25
+ ? AbiParametersToPrimitiveTypes<TParams>
26
+ : never
20
27
  }
21
28
 
22
29
  /**
23
30
  * @description Encodes a list of primitive values into an ABI-encoded hex value.
24
31
  */
25
- export function encodeAbi<TParams extends readonly AbiParameter[]>({
26
- params,
27
- values,
28
- }: EncodeAbiArgs<TParams>) {
32
+ export function encodeAbi<
33
+ TParams extends readonly AbiParameter[] | readonly unknown[],
34
+ >({ params, values }: EncodeAbiArgs<TParams>) {
29
35
  if (params.length !== values.length)
30
36
  throw new AbiEncodingLengthMismatchError({
31
- expectedLength: params.length,
37
+ expectedLength: params.length as number,
32
38
  givenLength: values.length,
33
39
  })
34
40
  // Prepare the parameters to determine dynamic types to encode.
35
- const preparedParams = prepareParams({ params, values })
41
+ const preparedParams = prepareParams({
42
+ params: params as readonly AbiParameter[],
43
+ values,
44
+ })
36
45
  const data = encodeParams(preparedParams)
37
46
  if (data.length === 0) return '0x'
38
47
  return data
@@ -49,7 +58,7 @@ function prepareParams<TParams extends readonly AbiParameter[]>({
49
58
  params,
50
59
  values,
51
60
  }: {
52
- params: TParams
61
+ params: Narrow<TParams>
53
62
  values: AbiParametersToPrimitiveTypes<TParams>
54
63
  }) {
55
64
  let preparedParams: PreparedParam[] = []
@@ -183,14 +192,20 @@ function encodeBytes<TParam extends AbiParameter>(
183
192
  { param }: { param: TParam },
184
193
  ): PreparedParam {
185
194
  const [_, size_] = param.type.split('bytes')
186
- if (!size_)
195
+ if (!size_) {
196
+ const partsLength = Math.floor(size(value) / 32)
197
+ const parts: Hex[] = []
198
+ for (let i = 0; i < partsLength + 1; i++) {
199
+ parts.push(padHex(slice(value, i * 32, (i + 1) * 32), { dir: 'right' }))
200
+ }
187
201
  return {
188
202
  dynamic: true,
189
203
  encoded: concat([
190
204
  padHex(numberToHex(size(value), { size: 32 })),
191
- padHex(value, { dir: 'right' }),
205
+ ...parts,
192
206
  ]),
193
207
  }
208
+ }
194
209
  return { dynamic: false, encoded: padHex(value, { dir: 'right' }) }
195
210
  }
196
211