Skip to content

Commit

Permalink
fix: parse Abi with zod as readonly array (#200)
Browse files Browse the repository at this point in the history
* fix: parse Abi with zod as readonly array

* chore: update .changeset/hungry-pets-switch.md

Co-authored-by: awkweb <tom@meagher.co>

---------

Co-authored-by: awkweb <tom@meagher.co>
  • Loading branch information
Mathieu Bour and tmm committed Oct 12, 2023
1 parent 7c5b8e0 commit 56f8201
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 82 deletions.
5 changes: 5 additions & 0 deletions .changeset/hungry-pets-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"abitype": patch
---

Marked `Abi` Zod schema as `readonly`.
170 changes: 88 additions & 82 deletions packages/abitype/src/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,92 +207,98 @@ export const AbiItemType = z.union([
* @example
* const parsedAbi = Abi.parse([…])
*/
export const Abi = z.array(
z.union([
AbiError,
AbiEvent,
// TODO: Replace code below to `z.switch` (https://github.com/colinhacks/zod/issues/2106)
// Need to redefine `AbiFunction | AbiConstructor | AbiFallback | AbiReceive` since `z.discriminate` doesn't support `z.preprocess` on `options`
// https://github.com/colinhacks/zod/issues/1490
z.preprocess(
(val) => {
const abiItem = val as
| AbiConstructorType
| AbiFallbackType
| AbiFunctionType
| AbiReceiveType
if (abiItem.type === 'receive') return abiItem
// Calculate `stateMutability` for deprecated fields: `constant` and `payable`
if (
(val as { stateMutability: AbiFunctionType['stateMutability'] })
.stateMutability === undefined
) {
export const Abi = z
.array(
z.union([
AbiError,
AbiEvent,
// TODO: Replace code below to `z.switch` (https://github.com/colinhacks/zod/issues/2106)
// Need to redefine `AbiFunction | AbiConstructor | AbiFallback | AbiReceive` since `z.discriminate` doesn't support `z.preprocess` on `options`
// https://github.com/colinhacks/zod/issues/1490
z.preprocess(
(val) => {
const abiItem = val as
| AbiConstructorType
| AbiFallbackType
| AbiFunctionType
| AbiReceiveType
if (abiItem.type === 'receive') return abiItem
// Calculate `stateMutability` for deprecated fields: `constant` and `payable`
if (
abiItem.type === 'function' &&
(abiItem as AbiFunctionType).constant
)
abiItem.stateMutability = 'view'
else if (
(abiItem as AbiConstructorType | AbiFallbackType | AbiFunctionType)
.payable
)
abiItem.stateMutability = 'payable'
else abiItem.stateMutability = 'nonpayable'
}

return val
},
z.intersection(
z.object({
/**
* @deprecated use `pure` or `view` from {@link AbiStateMutability} instead
* https://github.com/ethereum/solidity/issues/992
*/
constant: z.boolean().optional(),
/**
* @deprecated Vyper used to provide gas estimates
* https://github.com/vyperlang/vyper/issues/2151
*/
gas: z.number().optional(),
/**
* @deprecated use `payable` or `nonpayable` from {@link AbiStateMutability} instead
* https://github.com/ethereum/solidity/issues/992
*/
payable: z.boolean().optional(),
}),
z.discriminatedUnion('type', [
z.object({
type: z.literal('function'),
inputs: z.array(AbiParameter).readonly(),
name: z.string().regex(/[a-zA-Z$_][a-zA-Z0-9$_]*/),
outputs: z.array(AbiParameter).readonly(),
stateMutability: AbiStateMutability,
}),
(val as { stateMutability: AbiFunctionType['stateMutability'] })
.stateMutability === undefined
) {
if (
abiItem.type === 'function' &&
(abiItem as AbiFunctionType).constant
)
abiItem.stateMutability = 'view'
else if (
(
abiItem as
| AbiConstructorType
| AbiFallbackType
| AbiFunctionType
).payable
)
abiItem.stateMutability = 'payable'
else abiItem.stateMutability = 'nonpayable'
}

return val
},
z.intersection(
z.object({
type: z.literal('constructor'),
inputs: z.array(AbiParameter).readonly(),
stateMutability: z.union([
z.literal('payable'),
z.literal('nonpayable'),
]),
/**
* @deprecated use `pure` or `view` from {@link AbiStateMutability} instead
* https://github.com/ethereum/solidity/issues/992
*/
constant: z.boolean().optional(),
/**
* @deprecated Vyper used to provide gas estimates
* https://github.com/vyperlang/vyper/issues/2151
*/
gas: z.number().optional(),
/**
* @deprecated use `payable` or `nonpayable` from {@link AbiStateMutability} instead
* https://github.com/ethereum/solidity/issues/992
*/
payable: z.boolean().optional(),
}),
z.object({
type: z.literal('fallback'),
inputs: z.tuple([]).optional(),
stateMutability: z.union([
z.literal('payable'),
z.literal('nonpayable'),
]),
}),
z.object({
type: z.literal('receive'),
stateMutability: z.literal('payable'),
}),
]),
z.discriminatedUnion('type', [
z.object({
type: z.literal('function'),
inputs: z.array(AbiParameter).readonly(),
name: z.string().regex(/[a-zA-Z$_][a-zA-Z0-9$_]*/),
outputs: z.array(AbiParameter).readonly(),
stateMutability: AbiStateMutability,
}),
z.object({
type: z.literal('constructor'),
inputs: z.array(AbiParameter).readonly(),
stateMutability: z.union([
z.literal('payable'),
z.literal('nonpayable'),
]),
}),
z.object({
type: z.literal('fallback'),
inputs: z.tuple([]).optional(),
stateMutability: z.union([
z.literal('payable'),
z.literal('nonpayable'),
]),
}),
z.object({
type: z.literal('receive'),
stateMutability: z.literal('payable'),
}),
]),
),
),
),
]),
)
]),
)
.readonly()

////////////////////////////////////////////////////////////////////////////////////////////////////
// Typed Data Types
Expand Down

1 comment on commit 56f8201

@vercel
Copy link

@vercel vercel bot commented on 56f8201 Oct 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

abitype – ./

abitype-git-main-wagmi-dev.vercel.app
abitype-wagmi-dev.vercel.app
abitype.dev
abitype.vercel.app

Please sign in to comment.