Skip to content

Commit ee4d256

Browse files
committed
feat: encodeFunctionResult
1 parent b4c1771 commit ee4d256

File tree

13 files changed

+545
-3
lines changed

13 files changed

+545
-3
lines changed

.changeset/violet-humans-press.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Added `encodeFunctionResult`.

site/.vitepress/sidebar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,8 @@ export const sidebar: DefaultTheme.Sidebar = {
474474
link: '/docs/contract/encodeFunctionData',
475475
},
476476
{
477-
text: 'encodeFunctionResult 🚧',
478-
link: '/docs/contract/encodeFunctionData',
477+
text: 'encodeFunctionResult',
478+
link: '/docs/contract/encodeFunctionResult',
479479
},
480480
],
481481
},
Lines changed: 189 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,191 @@
11
# encodeFunctionResult
22

3-
TODO
3+
Encodes structured return data into ABI encoded data. It is the opposite of [`decodeFunctionResult`](/docs/contract/decodeFunctionResult).
4+
5+
## Install
6+
7+
```ts
8+
import { encodeFunctionResult } from 'viem';
9+
```
10+
11+
## Usage
12+
13+
Given an ABI (`abi`) and a function (`functionName`), pass through the values (`values`) to encode:
14+
15+
::: code-group
16+
17+
```ts [example.ts]
18+
import { encodeFunctionResult } from 'viem';
19+
20+
const data = encodeFunctionResult({
21+
abi: wagmiAbi,
22+
functionName: 'ownerOf',
23+
value: ['0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'],
24+
});
25+
// '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
26+
```
27+
28+
```ts [abi.ts]
29+
export const wagmiAbi = [
30+
...
31+
{
32+
inputs: [{ name: 'tokenId', type: 'uint256' }],
33+
name: 'ownerOf',
34+
outputs: [{ name: '', type: 'address' }],
35+
stateMutability: 'view',
36+
type: 'function',
37+
},
38+
...
39+
] as const;
40+
```
41+
42+
```ts [client.ts]
43+
import { createPublicClient, http } from 'viem';
44+
import { mainnet } from 'viem/chains';
45+
46+
export const publicClient = createPublicClient({
47+
chain: mainnet,
48+
transport: http(),
49+
});
50+
```
51+
52+
:::
53+
54+
### A more complex example
55+
56+
::: code-group
57+
58+
```ts [example.ts]
59+
import { decodeFunctionResult } from 'viem'
60+
61+
const data = decodeFunctionResult({
62+
abi: wagmiAbi,
63+
functionName: 'getInfo',
64+
value: [
65+
{
66+
foo: {
67+
sender: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
68+
x: 69420n,
69+
y: true
70+
},
71+
sender: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
72+
z: 69
73+
}
74+
]
75+
})
76+
// 0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac0000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac0000000000000000000000000000000000000000000000000000000000000045
77+
```
78+
79+
```ts [abi.ts]
80+
export const wagmiAbi = [
81+
...
82+
{
83+
inputs: [],
84+
name: 'getInfo',
85+
outputs: [
86+
{
87+
components: [
88+
{
89+
components: [
90+
{
91+
internalType: 'address',
92+
name: 'sender',
93+
type: 'address',
94+
},
95+
{
96+
internalType: 'uint256',
97+
name: 'x',
98+
type: 'uint256',
99+
},
100+
{
101+
internalType: 'bool',
102+
name: 'y',
103+
type: 'bool',
104+
},
105+
],
106+
internalType: 'struct Example.Foo',
107+
name: 'foo',
108+
type: 'tuple',
109+
},
110+
{
111+
internalType: 'address',
112+
name: 'sender',
113+
type: 'address',
114+
},
115+
{
116+
internalType: 'uint32',
117+
name: 'z',
118+
type: 'uint32',
119+
},
120+
],
121+
internalType: 'struct Example.Bar',
122+
name: 'res',
123+
type: 'tuple',
124+
},
125+
],
126+
stateMutability: 'pure',
127+
type: 'function',
128+
},
129+
...
130+
] as const;
131+
```
132+
133+
```ts [client.ts]
134+
import { createPublicClient, http } from 'viem';
135+
import { mainnet } from 'viem/chains';
136+
137+
export const publicClient = createPublicClient({
138+
chain: mainnet,
139+
transport: http(),
140+
});
141+
```
142+
143+
:::
144+
145+
## Return Value
146+
147+
The decoded data. Type is inferred from the ABI.
148+
149+
## Parameters
150+
151+
### abi
152+
153+
- **Type:** [`Abi`](/docs/glossary/types#TODO)
154+
155+
The contract's ABI.
156+
157+
```ts
158+
const data = encodeFunctionResult({
159+
abi: wagmiAbi, // [!code focus]
160+
functionName: 'ownerOf',
161+
value: ['0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'],
162+
});
163+
```
164+
165+
### functionName
166+
167+
- **Type:** `string`
168+
169+
The function to encode from the ABI.
170+
171+
```ts
172+
const data = encodeFunctionResult({
173+
abi: wagmiAbi,
174+
functionName: 'ownerOf', // [!code focus]
175+
value: ['0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'],
176+
});
177+
```
178+
179+
### values
180+
181+
- **Type**: `Hex`
182+
183+
Return values to encode.
184+
185+
```ts
186+
const data = encodeFunctionResult({
187+
abi: wagmiAbi,
188+
functionName: 'ownerOf',
189+
value: ['0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'], // [!code focus]
190+
});
191+
```

src/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ test('exports actions', () => {
7474
"encodeAbi": [Function],
7575
"encodeBytes": [Function],
7676
"encodeFunctionData": [Function],
77+
"encodeFunctionResult": [Function],
7778
"encodeHex": [Function],
7879
"encodeRlp": [Function],
7980
"estimateGas": [Function],

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ export {
276276
encodeAbi,
277277
encodeBytes,
278278
encodeFunctionData,
279+
encodeFunctionResult,
279280
encodeHex,
280281
encodeRlp,
281282
getAddress,

src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export type {
4040
ExtractArgsFromAbi,
4141
ExtractArgsFromEventDefinition,
4242
ExtractArgsFromFunctionDefinition,
43+
ExtractResultFromAbi,
4344
} from './solidity'
4445

4546
export type {

src/types/solidity.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,31 @@ export type ExtractArgsFromAbi<
3737
/** Arguments to pass contract method */ args: TArgs
3838
}
3939

40+
export type ExtractResultFromAbi<
41+
TAbi extends Abi | readonly unknown[],
42+
TFunctionName extends string,
43+
TAbiFunction extends AbiFunction & { type: 'function' } = TAbi extends Abi
44+
? ExtractAbiFunction<TAbi, TFunctionName>
45+
: AbiFunction & { type: 'function' },
46+
TArgs = AbiParametersToPrimitiveTypes<TAbiFunction['outputs']>,
47+
FailedToParseArgs =
48+
| ([TArgs] extends [never] ? true : false)
49+
| (readonly unknown[] extends TArgs ? true : false),
50+
> = true extends FailedToParseArgs
51+
? {
52+
/**
53+
* Arguments to pass contract method
54+
*
55+
* Use a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) on {@link abi} for type inference.
56+
*/
57+
result?: readonly unknown[]
58+
}
59+
: TArgs extends readonly []
60+
? { result?: never }
61+
: {
62+
/** Arguments to pass contract method */ result: TArgs
63+
}
64+
4065
//////////////////////////////////////////////////////////////////////
4166
// Event/Function Definitions
4267

0 commit comments

Comments
 (0)