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.
- package/dist/{chain-32f56cfa.d.ts → chain-4b39613a.d.ts} +2 -2
- package/dist/{chain-f12cdc7f.d.ts → chain-aa4898d0.d.ts} +1 -1
- package/dist/chains.d.ts +3 -3
- package/dist/chains.js +46 -46
- package/dist/chains.mjs +1 -1
- package/dist/{chunk-ZVGTYLKU.mjs → chunk-JMFNAGCD.mjs} +4 -3
- package/dist/chunk-JMFNAGCD.mjs.map +1 -0
- package/dist/{chunk-NHAKUPTF.js → chunk-MVD4Y3AE.js} +67 -63
- package/dist/chunk-MVD4Y3AE.js.map +1 -0
- package/dist/{chunk-YODUQCHJ.mjs → chunk-OZIBQJYR.mjs} +2 -2
- package/dist/{chunk-YODUQCHJ.mjs.map → chunk-OZIBQJYR.mjs.map} +0 -0
- package/dist/{chunk-FHXXG7I6.js → chunk-PMPJGAHY.js} +14 -13
- package/dist/chunk-PMPJGAHY.js.map +1 -0
- package/dist/{chunk-YFKR74XG.js → chunk-QA3IE5DU.js} +14 -14
- package/dist/{chunk-YFKR74XG.js.map → chunk-QA3IE5DU.js.map} +0 -0
- package/dist/{chunk-T7CBAKLI.mjs → chunk-QN2NCTEN.mjs} +2 -2
- package/dist/{chunk-T7CBAKLI.mjs.map → chunk-QN2NCTEN.mjs.map} +1 -1
- package/dist/{chunk-IAQPMSGJ.js → chunk-S77NLWHO.js} +13 -13
- package/dist/{chunk-IAQPMSGJ.js.map → chunk-S77NLWHO.js.map} +1 -1
- package/dist/{chunk-SF4I2NKC.js → chunk-V5U5S7PQ.js} +411 -167
- package/dist/chunk-V5U5S7PQ.js.map +1 -0
- package/dist/{chunk-5Q6FSUU2.mjs → chunk-WWJ5YPTJ.mjs} +412 -168
- package/dist/chunk-WWJ5YPTJ.mjs.map +1 -0
- package/dist/{chunk-MYQNZSWD.mjs → chunk-ZXXEENRD.mjs} +7 -3
- package/dist/chunk-ZXXEENRD.mjs.map +1 -0
- package/dist/clients/index.d.ts +7 -7
- package/dist/clients/index.js +3 -3
- package/dist/clients/index.mjs +2 -2
- package/dist/{contract-9af4608b.d.ts → contract-74f34ac9.d.ts} +14 -3
- package/dist/{createClient-5d316c7e.d.ts → createClient-55a04188.d.ts} +2 -2
- package/dist/{createPublicClient-9d2b42e1.d.ts → createPublicClient-3b27b282.d.ts} +3 -3
- package/dist/{createTestClient-79498dab.d.ts → createTestClient-93f9eac6.d.ts} +3 -3
- package/dist/{createWalletClient-f69a5230.d.ts → createWalletClient-c10df94d.d.ts} +3 -3
- package/dist/{eip1193-6c485d63.d.ts → eip1193-4c24765a.d.ts} +1 -1
- package/dist/ens.d.ts +1 -0
- package/dist/ens.js +11 -0
- package/dist/ens.js.map +1 -0
- package/dist/ens.mjs +11 -0
- package/dist/ens.mjs.map +1 -0
- package/dist/index.d.ts +125 -113
- package/dist/index.js +14 -6
- package/dist/index.mjs +13 -5
- package/dist/normalize-ef9240c0.d.ts +33 -0
- package/dist/{parseGwei-4308ad80.d.ts → parseGwei-b323fb0a.d.ts} +101 -37
- package/dist/public.d.ts +9 -9
- package/dist/public.js +4 -4
- package/dist/public.mjs +3 -3
- package/dist/{sendTransaction-1c8290a9.d.ts → sendTransaction-f17a2389.d.ts} +3 -3
- package/dist/{stopImpersonatingAccount-7781842a.d.ts → stopImpersonatingAccount-afb26486.d.ts} +2 -2
- package/dist/test.d.ts +5 -5
- package/dist/test.js +3 -3
- package/dist/test.mjs +2 -2
- package/dist/{transactionRequest-341b6ed2.d.ts → transactionRequest-93e9f001.d.ts} +2 -2
- package/dist/utils/index.d.ts +14 -16
- package/dist/utils/index.js +8 -2
- package/dist/utils/index.mjs +7 -1
- package/dist/wallet.d.ts +7 -7
- package/dist/wallet.js +3 -3
- package/dist/wallet.mjs +2 -2
- package/dist/{watchAsset-afaad3c7.d.ts → watchAsset-efd3dd05.d.ts} +3 -3
- package/dist/{watchPendingTransactions-3b722547.d.ts → watchPendingTransactions-a8688b26.d.ts} +17 -27
- package/dist/{webSocket-b180e679.d.ts → webSocket-d2e7bd0e.d.ts} +2 -2
- package/dist/window.d.ts +2 -2
- package/package.json +8 -2
- package/src/_test/abis.ts +7 -0
- package/src/_test/bench.ts +4 -4
- package/src/_test/index.ts +3 -1
- package/src/_test/utils.ts +39 -1
- package/src/actions/public/call.bench.ts +5 -5
- package/src/actions/public/deployContract.ts +4 -4
- package/src/actions/public/estimateGas.bench.ts +6 -6
- package/src/actions/public/getBlock.bench.ts +5 -5
- package/src/actions/public/getBlockNumber.bench.ts +5 -5
- package/src/actions/public/getGasPrice.bench.ts +1 -10
- package/src/actions/public/getTransaction.bench.ts +5 -5
- package/src/actions/public/getTransactionReceipt.bench.ts +5 -5
- package/src/actions/public/multicall.test.ts +452 -0
- package/src/actions/public/multicall.ts +103 -0
- package/src/actions/public/readContract.test.ts +226 -26
- package/src/actions/public/readContract.ts +13 -27
- package/src/actions/public/simulateContract.bench.ts +10 -0
- package/src/actions/public/simulateContract.test.ts +209 -37
- package/src/actions/public/simulateContract.ts +17 -21
- package/src/actions/public/watchContractEvent.test.ts +36 -32
- package/src/actions/public/watchEvent.test.ts +34 -29
- package/src/actions/wallet/signMessage.test.ts +0 -1
- package/src/actions/wallet/switchChain.test.ts +1 -2
- package/src/actions/wallet/watchAsset.test.ts +1 -2
- package/src/actions/wallet/writeContract.test.ts +37 -7
- package/src/actions/wallet/writeContract.ts +5 -14
- package/src/clients/transports/fallback.test.ts +34 -0
- package/src/clients/transports/fallback.ts +3 -1
- package/src/clients/transports/http.test.ts +0 -1
- package/src/clients/transports/webSocket.test.ts +0 -1
- package/src/constants/abis.test.ts +53 -0
- package/src/constants/abis.ts +44 -0
- package/src/constants/index.test.ts +14 -0
- package/src/constants/index.ts +3 -0
- package/src/constants/solidity.test.ts +41 -0
- package/src/constants/solidity.ts +35 -0
- package/src/ens.ts +5 -0
- package/src/errors/abi.test.ts +0 -2
- package/src/errors/base.test.ts +44 -2
- package/src/errors/base.ts +12 -12
- package/src/errors/block.test.ts +6 -6
- package/src/errors/contract.test.ts +233 -0
- package/src/errors/contract.ts +133 -80
- package/src/errors/index.ts +4 -2
- package/src/errors/request.test.ts +3 -4
- package/src/errors/request.ts +17 -17
- package/src/errors/rpc.test.ts +1 -2
- package/src/errors/transaction.test.ts +12 -12
- package/src/errors/transport.test.ts +0 -1
- package/src/index.test.ts +46 -0
- package/src/index.ts +8 -0
- package/src/types/contract.ts +55 -4
- package/src/types/index.ts +5 -0
- package/src/types/multicall.ts +82 -0
- package/src/utils/abi/decodeAbi.test.ts +1 -2
- package/src/utils/abi/decodeAbi.ts +11 -7
- package/src/utils/abi/decodeDeployData.test.ts +7 -15
- package/src/utils/abi/decodeDeployData.ts +10 -7
- package/src/utils/abi/decodeErrorResult.test.ts +103 -3
- package/src/utils/abi/decodeErrorResult.ts +30 -13
- package/src/utils/abi/decodeFunctionData.test.ts +0 -1
- package/src/utils/abi/decodeFunctionResult.test.ts +80 -9
- package/src/utils/abi/decodeFunctionResult.ts +15 -11
- package/src/utils/abi/encodeAbi.test.ts +40 -7
- package/src/utils/abi/encodeAbi.ts +28 -13
- package/src/utils/abi/encodeDeployData.test.ts +6 -13
- package/src/utils/abi/encodeDeployData.ts +10 -7
- package/src/utils/abi/encodeErrorResult.test.ts +2 -7
- package/src/utils/abi/encodeErrorResult.ts +18 -11
- package/src/utils/abi/encodeEventTopics.test.ts +11 -14
- package/src/utils/abi/encodeEventTopics.ts +15 -9
- package/src/utils/abi/encodeFunctionData.test.ts +5 -7
- package/src/utils/abi/encodeFunctionData.ts +16 -9
- package/src/utils/abi/encodeFunctionResult.test.ts +10 -15
- package/src/utils/abi/encodeFunctionResult.ts +9 -7
- package/src/utils/abi/getAbiItem.test.ts +547 -0
- package/src/utils/abi/getAbiItem.ts +93 -3
- package/src/utils/abi/index.ts +5 -1
- package/src/utils/address/getAddress.test.ts +6 -6
- package/src/utils/contract/getContractError.test.ts +247 -62
- package/src/utils/contract/getContractError.ts +30 -38
- package/src/utils/data/pad.bench.ts +0 -9
- package/src/utils/data/trim.bench.ts +0 -16
- package/src/utils/encoding/encodeBytes.bench.ts +0 -12
- package/src/utils/encoding/encodeHex.bench.ts +0 -11
- package/src/utils/ens/index.test.ts +13 -0
- package/src/utils/ens/index.ts +5 -0
- package/src/utils/ens/labelhash.test.ts +55 -0
- package/src/utils/ens/labelhash.ts +16 -0
- package/src/utils/ens/namehash.test.ts +65 -0
- package/src/utils/ens/namehash.ts +28 -0
- package/src/utils/ens/normalize.bench.ts +14 -0
- package/src/utils/ens/normalize.test.ts +35 -0
- package/src/utils/ens/normalize.ts +14 -0
- package/src/utils/hash/keccak256.ts +3 -5
- package/src/utils/index.test.ts +3 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/rpc.test.ts +3 -6
- package/src/utils/unit/formatUnit.bench.ts +0 -5
- package/src/utils/unit/parseUnit.bench.ts +0 -5
- package/dist/chunk-5Q6FSUU2.mjs.map +0 -1
- package/dist/chunk-FHXXG7I6.js.map +0 -1
- package/dist/chunk-MYQNZSWD.mjs.map +0 -1
- package/dist/chunk-NHAKUPTF.js.map +0 -1
- package/dist/chunk-SF4I2NKC.js.map +0 -1
- 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({
|
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({
|
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 {
|
3
|
-
import {
|
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
|
13
|
+
export type DecodeErrorResultArgs = { abi?: Abi; data: Hex }
|
10
14
|
|
11
|
-
export
|
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
|
-
|
14
|
-
|
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 (!
|
34
|
+
if (!abiItem)
|
17
35
|
throw new AbiErrorSignatureNotFoundError(signature, {
|
18
36
|
docsPath: '/docs/contract/decodeErrorResult',
|
19
37
|
})
|
20
38
|
return {
|
21
|
-
|
22
|
-
args: ('inputs' in
|
23
|
-
|
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
|
}
|
@@ -13,7 +13,7 @@ test('returns ()', () => {
|
|
13
13
|
stateMutability: 'pure',
|
14
14
|
type: 'function',
|
15
15
|
},
|
16
|
-
]
|
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
|
-
]
|
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
|
-
]
|
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
|
-
]
|
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
|
-
]
|
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
|
-
]
|
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
|
-
]
|
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,
|
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 =
|
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 =
|
28
|
+
TFunctionName extends string = string,
|
28
29
|
> = ExtractResultFromAbi<TAbi, TFunctionName>
|
29
30
|
|
30
31
|
export function decodeFunctionResult<
|
31
|
-
TAbi extends Abi | readonly unknown[]
|
32
|
-
TFunctionName extends string
|
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 = (
|
42
|
-
|
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
|
-
]
|
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
|
-
]
|
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)" "
|
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: [
|
941
|
+
values: [
|
942
|
+
'0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604570a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045',
|
943
|
+
],
|
910
944
|
}),
|
911
945
|
).toMatchInlineSnapshot(
|
912
|
-
'"
|
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
|
-
]
|
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<
|
18
|
-
|
19
|
-
|
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<
|
26
|
-
|
27
|
-
|
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({
|
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
|
-
|
205
|
+
...parts,
|
192
206
|
]),
|
193
207
|
}
|
208
|
+
}
|
194
209
|
return { dynamic: false, encoded: padHex(value, { dir: 'right' }) }
|
195
210
|
}
|
196
211
|
|