diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index 2c66715cd9bd..a62c68bd8378 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -81,7 +81,7 @@ "lodash.omit": "^4.5.0", "tslib": "^2.5.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/aztec.js/package.json b/yarn-project/aztec.js/package.json index 2c1cdffddb32..79b901b4db76 100644 --- a/yarn-project/aztec.js/package.json +++ b/yarn-project/aztec.js/package.json @@ -104,7 +104,7 @@ "axios": "^1.15.1", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@aztec/builder": "workspace:^", diff --git a/yarn-project/aztec.js/src/wallet/wallet.ts b/yarn-project/aztec.js/src/wallet/wallet.ts index 5000c09787d4..6ae8bddebdde 100644 --- a/yarn-project/aztec.js/src/wallet/wallet.ts +++ b/yarn-project/aztec.js/src/wallet/wallet.ts @@ -14,7 +14,15 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import { type ContractInstanceWithAddress, ContractInstanceWithAddressSchema } from '@aztec/stdlib/contract'; import { Gas, ManaUsageEstimate } from '@aztec/stdlib/gas'; import { LogId } from '@aztec/stdlib/logs'; -import { AbiDecodedSchema, type ApiSchemaFor, optional, schemas, zodFor } from '@aztec/stdlib/schemas'; +import { + AbiDecodedSchema, + type ApiSchemaFor, + getSchemaParameters, + getSchemaReturnType, + optional, + schemas, + zodFor, +} from '@aztec/stdlib/schemas'; import type { ExecutionPayload, InTx } from '@aztec/stdlib/tx'; import { Capsule, @@ -545,56 +553,60 @@ const OffchainOutputSchema = z.object({ * This is the single source of truth for method schemas - batch schemas are derived from this. */ const WalletMethodSchemas = { - getChainInfo: z - .function() - .args() - .returns(z.object({ chainId: schemas.Fr, version: schemas.Fr })), - getContractMetadata: z.function().args(schemas.AztecAddress).returns(ContractMetadataSchema), - getContractClassMetadata: z.function().args(schemas.Fr).returns(ContractClassMetadataSchema), - getPrivateEvents: z - .function() - .args(EventMetadataDefinitionSchema, PrivateEventFilterSchema) - .returns(z.array(PrivateEventSchema)), - registerSender: z.function().args(schemas.AztecAddress, optional(z.string())).returns(schemas.AztecAddress), - getAddressBook: z - .function() - .args() - .returns(z.array(z.object({ alias: z.string(), item: schemas.AztecAddress }))), - getAccounts: z - .function() - .args() - .returns(z.array(z.object({ alias: z.string(), item: schemas.AztecAddress }))), - registerContract: z - .function() - .args(ContractInstanceWithAddressSchema, optional(ContractArtifactSchema), optional(schemas.Fr)) - .returns(ContractInstanceWithAddressSchema), - registerContractClass: z.function().args(ContractArtifactSchema).returns(z.void()), - simulateTx: z - .function() - .args(ExecutionPayloadSchema, SimulateOptionsSchema) - .returns(TxSimulationResultWithAppOffset.schema), - executeUtility: z - .function() - .args( + getChainInfo: z.function({ input: z.tuple([]), output: z.object({ chainId: schemas.Fr, version: schemas.Fr }) }), + getContractMetadata: z.function({ input: z.tuple([schemas.AztecAddress]), output: ContractMetadataSchema }), + getContractClassMetadata: z.function({ input: z.tuple([schemas.Fr]), output: ContractClassMetadataSchema }), + getPrivateEvents: z.function({ + input: z.tuple([EventMetadataDefinitionSchema, PrivateEventFilterSchema]), + output: z.array(PrivateEventSchema), + }), + registerSender: z.function({ + input: z.tuple([schemas.AztecAddress, optional(z.string())]), + output: schemas.AztecAddress, + }), + getAddressBook: z.function({ + input: z.tuple([]), + output: z.array(z.object({ alias: z.string(), item: schemas.AztecAddress })), + }), + getAccounts: z.function({ + input: z.tuple([]), + output: z.array(z.object({ alias: z.string(), item: schemas.AztecAddress })), + }), + registerContract: z.function({ + input: z.tuple([ContractInstanceWithAddressSchema, optional(ContractArtifactSchema), optional(schemas.Fr)]), + output: ContractInstanceWithAddressSchema, + }), + registerContractClass: z.function({ input: z.tuple([ContractArtifactSchema]), output: z.void() }), + simulateTx: z.function({ + input: z.tuple([ExecutionPayloadSchema, SimulateOptionsSchema]), + output: TxSimulationResultWithAppOffset.schema, + }), + executeUtility: z.function({ + input: z.tuple([ FunctionCall.schema, z.object({ scopes: z.array(schemas.AztecAddress), authWitnesses: optional(z.array(AuthWitness.schema)), }), - ) - .returns(UtilityExecutionResult.schema), - profileTx: z.function().args(ExecutionPayloadSchema, ProfileOptionsSchema).returns(TxProfileResult.schema), - sendTx: z - .function() - .args(ExecutionPayloadSchema, SendOptionsSchema) - .returns( - z.union([ - z.object({ txHash: TxHash.schema }).merge(OffchainOutputSchema), - z.object({ receipt: TxReceipt.schema }).merge(OffchainOutputSchema), - ]), - ), - createAuthWit: z.function().args(schemas.AztecAddress, MessageHashOrIntentSchema).returns(AuthWitness.schema), - requestCapabilities: z.function().args(AppCapabilitiesSchema).returns(WalletCapabilitiesSchema), + ]), + output: UtilityExecutionResult.schema, + }), + profileTx: z.function({ + input: z.tuple([ExecutionPayloadSchema, ProfileOptionsSchema]), + output: TxProfileResult.schema, + }), + sendTx: z.function({ + input: z.tuple([ExecutionPayloadSchema, SendOptionsSchema]), + output: z.union([ + z.object({ txHash: TxHash.schema }).merge(OffchainOutputSchema), + z.object({ receipt: TxReceipt.schema }).merge(OffchainOutputSchema), + ]), + }), + createAuthWit: z.function({ + input: z.tuple([schemas.AztecAddress, MessageHashOrIntentSchema]), + output: AuthWitness.schema, + }), + requestCapabilities: z.function({ input: z.tuple([AppCapabilitiesSchema]), output: WalletCapabilitiesSchema }), }; /** @@ -605,19 +617,19 @@ const WalletMethodSchemas = { function createBatchSchemas, z.ZodTypeAny>>>( methodSchemas: T, ) { - const names = Object.keys(methodSchemas) as (keyof T)[]; + const names = Object.keys(methodSchemas) as Extract[]; const namesAndArgs = names.map(name => z.object({ name: z.literal(name), - args: methodSchemas[name].parameters(), + args: getSchemaParameters(methodSchemas[name]), }), ); const namesAndReturns = names.map(name => z.object({ name: z.literal(name), - result: methodSchemas[name].returnType(), + result: getSchemaReturnType(methodSchemas[name]), }), ); @@ -636,5 +648,5 @@ export { BatchedMethodSchema, BatchedResultSchema }; export const WalletSchema: ApiSchemaFor = { ...WalletMethodSchemas, // @ts-expect-error - ApiSchemaFor cannot properly type generic methods with readonly arrays - batch: z.function().args(z.array(BatchedMethodSchema)).returns(z.array(BatchedResultSchema)), + batch: z.function({ input: z.tuple([z.array(BatchedMethodSchema)]), output: z.array(BatchedResultSchema) }), }; diff --git a/yarn-project/blob-client/package.json b/yarn-project/blob-client/package.json index 11f77b5d302d..1e54e668eda6 100644 --- a/yarn-project/blob-client/package.json +++ b/yarn-project/blob-client/package.json @@ -67,7 +67,7 @@ "source-map-support": "^0.5.21", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/bot/package.json b/yarn-project/bot/package.json index e655415db67d..6cdf8c8285dc 100644 --- a/yarn-project/bot/package.json +++ b/yarn-project/bot/package.json @@ -71,7 +71,7 @@ "source-map-support": "^0.5.21", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/bot/src/interface.ts b/yarn-project/bot/src/interface.ts index de91ca8ae10d..ed763949e54c 100644 --- a/yarn-project/bot/src/interface.ts +++ b/yarn-project/bot/src/interface.ts @@ -22,11 +22,11 @@ export interface BotRunnerApi { } export const BotRunnerApiSchema: ApiSchemaFor = { - start: z.function().args().returns(z.void()), - stop: z.function().args().returns(z.void()), - run: z.function().args().returns(z.void()), - setup: z.function().args().returns(z.void()), - getInfo: z.function().args().returns(BotInfoSchema), - getConfig: z.function().args().returns(BotConfigSchema), - update: z.function().args(BotConfigSchema).returns(z.void()), + start: z.function({ input: z.tuple([]), output: z.void() }), + stop: z.function({ input: z.tuple([]), output: z.void() }), + run: z.function({ input: z.tuple([]), output: z.void() }), + setup: z.function({ input: z.tuple([]), output: z.void() }), + getInfo: z.function({ input: z.tuple([]), output: BotInfoSchema }), + getConfig: z.function({ input: z.tuple([]), output: BotConfigSchema }), + update: z.function({ input: z.tuple([BotConfigSchema]), output: z.void() }), }; diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index e6b854ef3f3f..4275ad5a2962 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -104,7 +104,7 @@ "typescript": "^5.3.3", "util": "^0.12.5", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "0x": "^5.7.0", diff --git a/yarn-project/end-to-end/src/test-wallet/wallet_worker_script.ts b/yarn-project/end-to-end/src/test-wallet/wallet_worker_script.ts index a532bbabdbd1..f4727bd7fb5b 100644 --- a/yarn-project/end-to-end/src/test-wallet/wallet_worker_script.ts +++ b/yarn-project/end-to-end/src/test-wallet/wallet_worker_script.ts @@ -3,7 +3,7 @@ import type { SendOptions } from '@aztec/aztec.js/wallet'; import { jsonStringify } from '@aztec/foundation/json-rpc'; import { createLogger } from '@aztec/foundation/log'; import type { ApiSchema, Fr } from '@aztec/foundation/schemas'; -import { parseWithOptionals, schemaHasMethod } from '@aztec/foundation/schemas'; +import { getSchemaParameters, parseWithOptionals, schemaHasMethod } from '@aztec/foundation/schemas'; import { NodeListener, TransportServer } from '@aztec/foundation/transport'; import { ExecutionPayload, Tx } from '@aztec/stdlib/tx'; @@ -46,7 +46,7 @@ try { throw new Error(`Unknown method: ${msg.fn}`); } const jsonParams = JSON.parse(msg.args) as unknown[]; - const args: any[] = await parseWithOptionals(jsonParams, schema[msg.fn].parameters()); + const args: any[] = await parseWithOptionals(jsonParams, getSchemaParameters(schema[msg.fn])); // we have to erase the fn type in order to be able to spread ...args const handler: ((...args: any[]) => Promise) | undefined = msg.fn in customMethods ? customMethods[msg.fn as keyof typeof customMethods] : undefined; diff --git a/yarn-project/end-to-end/src/test-wallet/worker_wallet.ts b/yarn-project/end-to-end/src/test-wallet/worker_wallet.ts index dea79c32e477..7ea5528c180c 100644 --- a/yarn-project/end-to-end/src/test-wallet/worker_wallet.ts +++ b/yarn-project/end-to-end/src/test-wallet/worker_wallet.ts @@ -22,7 +22,7 @@ import type { Fr } from '@aztec/foundation/curves/bn254'; import { jsonStringify } from '@aztec/foundation/json-rpc'; import { createLogger } from '@aztec/foundation/log'; import { promiseWithResolvers } from '@aztec/foundation/promise'; -import type { ApiSchema } from '@aztec/foundation/schemas'; +import { type ApiSchema, getSchemaReturnType } from '@aztec/foundation/schemas'; import { sleep } from '@aztec/foundation/sleep'; import { NodeConnector, TransportClient } from '@aztec/foundation/transport'; import type { PXEConfig } from '@aztec/pxe/config'; @@ -124,7 +124,7 @@ export class WorkerWallet implements Wallet { private async call(fn: string, ...args: any[]): Promise { const resultJson = await this.callRaw(fn, ...args); const methodSchema = (WorkerWalletSchema as ApiSchema)[fn]; - return methodSchema.returnType().parseAsync(JSON.parse(resultJson)); + return getSchemaReturnType(methodSchema).parseAsync(JSON.parse(resultJson)); } getChainInfo(): Promise { diff --git a/yarn-project/end-to-end/src/test-wallet/worker_wallet_schema.ts b/yarn-project/end-to-end/src/test-wallet/worker_wallet_schema.ts index 7e2a47c4d8bf..c8c9b394d0b2 100644 --- a/yarn-project/end-to-end/src/test-wallet/worker_wallet_schema.ts +++ b/yarn-project/end-to-end/src/test-wallet/worker_wallet_schema.ts @@ -8,6 +8,6 @@ import { z } from 'zod'; /** Schema for the WorkerWallet API — extends WalletSchema with proveTx and registerAccount. */ export const WorkerWalletSchema = { ...WalletSchema, - proveTx: z.function().args(ExecutionPayloadSchema, SendOptionsSchema).returns(Tx.schema), - registerAccount: z.function().args(schemas.Fr, schemas.Fr).returns(AztecAddress.schema), + proveTx: z.function({ input: z.tuple([ExecutionPayloadSchema, SendOptionsSchema]), output: Tx.schema }), + registerAccount: z.function({ input: z.tuple([schemas.Fr, schemas.Fr]), output: AztecAddress.schema }), }; diff --git a/yarn-project/entrypoints/package.json b/yarn-project/entrypoints/package.json index d6f4c051ddc2..f2254b0e34cc 100644 --- a/yarn-project/entrypoints/package.json +++ b/yarn-project/entrypoints/package.json @@ -72,7 +72,7 @@ "@aztec/protocol-contracts": "workspace:^", "@aztec/stdlib": "workspace:^", "tslib": "^2.4.0", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/epoch-cache/package.json b/yarn-project/epoch-cache/package.json index 844a7c5c1a34..5387b7ff6a04 100644 --- a/yarn-project/epoch-cache/package.json +++ b/yarn-project/epoch-cache/package.json @@ -35,7 +35,7 @@ "jest-mock-extended": "^4.0.0", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/ethereum/package.json b/yarn-project/ethereum/package.json index 14d029d693da..eaa7b6aad708 100644 --- a/yarn-project/ethereum/package.json +++ b/yarn-project/ethereum/package.json @@ -59,7 +59,7 @@ "lodash.pickby": "^4.5.0", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/foundation/package.json b/yarn-project/foundation/package.json index 5e61ce266e19..3b798a313bff 100644 --- a/yarn-project/foundation/package.json +++ b/yarn-project/foundation/package.json @@ -166,7 +166,7 @@ "pino-pretty": "^13.0.0", "sha3": "^2.1.4", "undici": "^5.28.5", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/foundation/src/branded-types/checkpoint_number.ts b/yarn-project/foundation/src/branded-types/checkpoint_number.ts index 1d864b78e03c..97c1f1f14b95 100644 --- a/yarn-project/foundation/src/branded-types/checkpoint_number.ts +++ b/yarn-project/foundation/src/branded-types/checkpoint_number.ts @@ -103,7 +103,7 @@ CheckpointNumber.INITIAL = CheckpointNumber(1); function makeCheckpointNumberSchema(minValue: number) { return z .union([z.number(), z.bigint(), z.string()]) - .pipe(z.coerce.number().int().min(minValue)) + .pipe(z.coerce.number().int().min(minValue)) .transform(value => CheckpointNumber(value)); } diff --git a/yarn-project/foundation/src/branded-types/epoch.ts b/yarn-project/foundation/src/branded-types/epoch.ts index 7fb02501cee0..df32a833d2fc 100644 --- a/yarn-project/foundation/src/branded-types/epoch.ts +++ b/yarn-project/foundation/src/branded-types/epoch.ts @@ -84,5 +84,5 @@ EpochNumber.ZERO = EpochNumber(0); */ export const EpochNumberSchema = z .union([z.number(), z.bigint(), z.string()]) - .pipe(z.coerce.number().int().min(0)) + .pipe(z.coerce.number().int().min(0)) .transform(value => EpochNumber(value)); diff --git a/yarn-project/foundation/src/branded-types/index_within_checkpoint.ts b/yarn-project/foundation/src/branded-types/index_within_checkpoint.ts index 131cfb8e9b3f..58c32bd53fed 100644 --- a/yarn-project/foundation/src/branded-types/index_within_checkpoint.ts +++ b/yarn-project/foundation/src/branded-types/index_within_checkpoint.ts @@ -84,5 +84,5 @@ IndexWithinCheckpoint.ZERO = IndexWithinCheckpoint(0); */ export const IndexWithinCheckpointSchema = z .union([z.number(), z.bigint(), z.string()]) - .pipe(z.coerce.number().int().min(0)) + .pipe(z.coerce.number().int().min(0)) .transform(value => IndexWithinCheckpoint(value)); diff --git a/yarn-project/foundation/src/branded-types/slot.ts b/yarn-project/foundation/src/branded-types/slot.ts index 2657cd622036..040808e0e3a1 100644 --- a/yarn-project/foundation/src/branded-types/slot.ts +++ b/yarn-project/foundation/src/branded-types/slot.ts @@ -89,5 +89,5 @@ SlotNumber.ZERO = SlotNumber(0); */ export const SlotNumberSchema = z .union([z.number(), z.bigint(), z.string()]) - .pipe(z.coerce.number().int().min(0)) + .pipe(z.coerce.number().int().min(0)) .transform(value => SlotNumber(value)); diff --git a/yarn-project/foundation/src/config/secret_value.ts b/yarn-project/foundation/src/config/secret_value.ts index 546306fb4c58..6ef806f38c6a 100644 --- a/yarn-project/foundation/src/config/secret_value.ts +++ b/yarn-project/foundation/src/config/secret_value.ts @@ -43,7 +43,7 @@ export class SecretValue { /** * Returns a Zod schema */ - static schema(valueSchema: ZodType): ZodType, any, any> { + static schema(valueSchema: ZodType): ZodType, any> { return valueSchema.transform(value => new SecretValue(value)); } } diff --git a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.test.ts b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.test.ts index db40fa9143e6..52f0d7f8eae1 100644 --- a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.test.ts +++ b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.test.ts @@ -16,9 +16,9 @@ interface TestService { } const schema: ApiSchemaFor = { - setValue: z.function().args(z.string()).returns(z.string()), - getValue: z.function().args().returns(z.string().optional()), - badReturn: z.function().args().returns(z.number()), + setValue: z.function({ input: z.tuple([z.string()]), output: z.string() }), + getValue: z.function({ input: z.tuple([]), output: z.string().optional() }), + badReturn: z.function({ input: z.tuple([]), output: z.number() }), }; describe('SafeJsonRpcClient', () => { diff --git a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts index b10c6535f8ed..2ad514ccbeed 100644 --- a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts +++ b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts @@ -2,7 +2,7 @@ import { format } from 'util'; import { type Logger, createLogger } from '../../log/pino-logger.js'; import { type PromiseWithResolvers, promiseWithResolvers } from '../../promise/utils.js'; -import { type ApiSchema, type ApiSchemaFor, schemaHasMethod } from '../../schemas/api.js'; +import { type ApiSchema, type ApiSchemaFor, getSchemaReturnType, schemaHasMethod } from '../../schemas/api.js'; import { jsonStringify } from '../convert.js'; import { type JsonRpcFetch, defaultFetch } from './fetch.js'; @@ -236,7 +236,7 @@ export function createSafeJsonRpcClient( if ([null, undefined, 'null', 'undefined'].includes(response.result)) { return; } - return (schema as ApiSchema)[methodName].returnType().parseAsync(response.result); + return getSchemaReturnType((schema as ApiSchema)[methodName]).parseAsync(response.result); }; const clientId = nextClientId++; diff --git a/yarn-project/foundation/src/json-rpc/fixtures/test_state.ts b/yarn-project/foundation/src/json-rpc/fixtures/test_state.ts index 04ff2fac2591..a469d263591b 100644 --- a/yarn-project/foundation/src/json-rpc/fixtures/test_state.ts +++ b/yarn-project/foundation/src/json-rpc/fixtures/test_state.ts @@ -130,14 +130,14 @@ export class TestState implements TestStateApi { } export const TestStateSchema: ApiSchemaFor = { - getNote: z.function().args(z.number()).returns(TestNote.schema.optional()), - getNotes: z.function().args(optional(schemas.Integer)).returns(z.array(TestNote.schema)), - getNotes2: z.function().args(optional(schemas.BigInt)).returns(z.array(TestNote.schema)), - getNotes3: z.function().args(optional(schemas.Integer)).returns(z.array(TestNote.schema)), - clear: z.function().returns(z.void()), - addNotes: z.function().args(z.array(TestNote.schema)).returns(z.array(TestNote.schema)), - fail: z.function().returns(z.void()), - count: z.function().returns(z.number()), - getStatus: z.function().returns(z.object({ status: z.string(), count: schemas.BigInt })), - getTuple: z.function().returns(z.tuple([z.string(), optional(z.string()), z.number()])), + getNote: z.function({ input: z.tuple([z.number()]), output: TestNote.schema.optional() }), + getNotes: z.function({ input: z.tuple([optional(schemas.Integer)]), output: z.array(TestNote.schema) }), + getNotes2: z.function({ input: z.tuple([optional(schemas.BigInt)]), output: z.array(TestNote.schema) }), + getNotes3: z.function({ input: z.tuple([optional(schemas.Integer)]), output: z.array(TestNote.schema) }), + clear: z.function({ input: z.tuple([]), output: z.void() }), + addNotes: z.function({ input: z.tuple([z.array(TestNote.schema)]), output: z.array(TestNote.schema) }), + fail: z.function({ input: z.tuple([]), output: z.void() }), + count: z.function({ input: z.tuple([]), output: z.number() }), + getStatus: z.function({ input: z.tuple([]), output: z.object({ status: z.string(), count: schemas.BigInt }) }), + getTuple: z.function({ input: z.tuple([]), output: z.tuple([z.string(), optional(z.string()), z.number()]) }), }; diff --git a/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.test.ts b/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.test.ts index a86408b52633..faf3af004d14 100644 --- a/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.test.ts +++ b/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.test.ts @@ -56,7 +56,7 @@ describe('SafeJsonRpcServer', () => { it('calls an RPC function with incorrect parameter type', async () => { const response = await send({ method: 'getNote', params: [{ index: 1 }] }); - expectError(response, 400, expect.stringContaining('Expected number, received object')); + expectError(response, 400, expect.stringContaining('Invalid input: expected number, received object')); }); it('calls an RPC function with a primitive return type', async () => { diff --git a/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.ts b/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.ts index d8cdeb5cced8..f1b0a6fa1105 100644 --- a/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.ts +++ b/yarn-project/foundation/src/json-rpc/server/safe_json_rpc_server.ts @@ -10,7 +10,13 @@ import { ZodError } from 'zod'; import { type Logger, createLogger } from '../../log/index.js'; import { promiseWithResolvers } from '../../promise/utils.js'; -import { type ApiSchema, type ApiSchemaFor, parseWithOptionals, schemaHasMethod } from '../../schemas/index.js'; +import { + type ApiSchema, + type ApiSchemaFor, + getSchemaParameters, + parseWithOptionals, + schemaHasMethod, +} from '../../schemas/index.js'; import { jsonStringify } from '../convert.js'; import { assert } from '../js_utils.js'; @@ -309,7 +315,7 @@ export class SafeJsonProxy implements Proxy { assert(schemaHasMethod(this.schema, methodName), `Method ${methodName} not found in schema`); const method = this.handler[methodName as keyof T]; assert(typeof method === 'function', `Method ${methodName} is not a function`); - const args = await parseWithOptionals(jsonParams, this.schema[methodName].parameters()); + const args = await parseWithOptionals(jsonParams, getSchemaParameters(this.schema[methodName])); const ret = await method.apply(this.handler, args); this.log.debug(format('response', methodName, ret)); return ret; diff --git a/yarn-project/foundation/src/json-rpc/test/integration.test.ts b/yarn-project/foundation/src/json-rpc/test/integration.test.ts index 91aee21bf63f..1109bda365ec 100644 --- a/yarn-project/foundation/src/json-rpc/test/integration.test.ts +++ b/yarn-project/foundation/src/json-rpc/test/integration.test.ts @@ -80,7 +80,9 @@ describe('JsonRpc integration', () => { }); it('calls an RPC function with incorrect parameter type', async () => { - await expect(() => client.getNote('foo' as any)).rejects.toThrow('Expected number, received string'); + await expect(() => client.getNote('foo' as any)).rejects.toThrow( + 'Invalid input: expected number, received string', + ); }); it('calls an RPC function with a primitive return type', async () => { diff --git a/yarn-project/foundation/src/noir/noir_package_config.ts b/yarn-project/foundation/src/noir/noir_package_config.ts index af2345e20fb3..d0e1a411b59e 100644 --- a/yarn-project/foundation/src/noir/noir_package_config.ts +++ b/yarn-project/foundation/src/noir/noir_package_config.ts @@ -10,26 +10,6 @@ const noirLocalDependencySchema = z.object({ path: z.string(), }); -const noirPackageConfigSchema = z.object({ - package: z.object({ - name: z.string().default(''), - type: z.enum(['lib', 'contract', 'bin']).default('bin'), - entry: z.string().optional(), - description: z.string().optional(), - authors: z.array(z.string()).optional(), - // eslint-disable-next-line camelcase - compiler_version: z.string().optional(), - backend: z.string().optional(), - license: z.string().optional(), - }), - dependencies: z.record(z.union([noirGitDependencySchema, noirLocalDependencySchema])).default({}), -}); - -/** - * Noir package configuration. - */ -export type NoirPackageConfig = z.infer; - /** * A remote package dependency. */ @@ -45,6 +25,38 @@ export type NoirLocalDependencyConfig = z.infer; +}; + +const noirPackageConfigSchema: z.ZodType = z.object({ + package: z.object({ + name: z.string().default(''), + type: z.enum(['lib', 'contract', 'bin']).default('bin'), + entry: z.string().optional(), + description: z.string().optional(), + authors: z.array(z.string()).optional(), + // eslint-disable-next-line camelcase + compiler_version: z.string().optional(), + backend: z.string().optional(), + license: z.string().optional(), + }), + dependencies: z.record(z.string(), z.union([noirGitDependencySchema, noirLocalDependencySchema])).default({}), +}); + /** * Checks that an object is a package configuration. * @param config - Config to check diff --git a/yarn-project/foundation/src/schemas/api.test.ts b/yarn-project/foundation/src/schemas/api.test.ts new file mode 100644 index 000000000000..b10fbbc5035b --- /dev/null +++ b/yarn-project/foundation/src/schemas/api.test.ts @@ -0,0 +1,55 @@ +import { z } from 'zod'; + +import type { ApiSchemaFor } from './api.js'; +import { optional } from './utils.js'; + +describe('ApiSchemaFor', () => { + it('typechecks matching schemas', () => { + interface TestApi { + getCount(): Promise; + setName(name: string): Promise; + find(limit?: number): Promise; + } + + const schema: ApiSchemaFor = { + getCount: z.function({ input: z.tuple([]), output: z.number() }), + setName: z.function({ input: z.tuple([z.string()]), output: z.void() }), + find: z.function({ input: z.tuple([optional(z.number())]), output: z.array(z.string()) }), + }; + + expect(Object.keys(schema)).toEqual(['getCount', 'setName', 'find']); + }); + + it('rejects schemas that do not match the interface', () => { + interface TestApi { + getCount(): Promise; + setName(name: string): Promise; + find(limit?: number): Promise; + } + + const _schemaWithWrongReturn: ApiSchemaFor = { + // @ts-expect-error getCount must return a number. + getCount: z.function({ input: z.tuple([]), output: z.string() }), + setName: z.function({ input: z.tuple([z.string()]), output: z.void() }), + find: z.function({ input: z.tuple([optional(z.number())]), output: z.array(z.string()) }), + }; + + const _schemaWithWrongParameter: ApiSchemaFor = { + getCount: z.function({ input: z.tuple([]), output: z.number() }), + // @ts-expect-error setName must accept a string. + setName: z.function({ input: z.tuple([z.number()]), output: z.void() }), + find: z.function({ input: z.tuple([optional(z.number())]), output: z.array(z.string()) }), + }; + + const _schemaWithRequiredOptionalParameter: ApiSchemaFor = { + getCount: z.function({ input: z.tuple([]), output: z.number() }), + setName: z.function({ input: z.tuple([z.string()]), output: z.void() }), + // @ts-expect-error find's optional argument must accept nulls from JSON-RPC and output undefined. + find: z.function({ input: z.tuple([z.number()]), output: z.array(z.string()) }), + }; + + expect(_schemaWithWrongReturn).toBeDefined(); + expect(_schemaWithWrongParameter).toBeDefined(); + expect(_schemaWithRequiredOptionalParameter).toBeDefined(); + }); +}); diff --git a/yarn-project/foundation/src/schemas/api.ts b/yarn-project/foundation/src/schemas/api.ts index 2090999e363d..0651125b5c73 100644 --- a/yarn-project/foundation/src/schemas/api.ts +++ b/yarn-project/foundation/src/schemas/api.ts @@ -2,32 +2,19 @@ import type { z } from 'zod'; import type { ZodNullableOptional } from './utils.js'; -// Forces usage of ZodNullableOptional in parameters schemas so we properly accept nulls for optional parameters. -type ZodParameterTypeFor = undefined extends T - ? ZodNullableOptional> - : z.ZodType; - -type ZodReturnTypeFor = z.ZodType; - -// This monstruosity is used for mapping function arguments to their schema representation. -// The complexity is required to satisfy ZodTuple which requires a fixed length tuple and -// has a very annoying type of [] | [ZodTypeAny, ...ZodTypeAny], and most types fail to match -// the second option. While a purely recursive approach works, it fails when trying to deal -// with optional arguments (ie optional items in the tuple), and ts does not really like them -// during a recursion and fails with infinite stack depth. -// This type appears to satisfy everyone. Everyone but me. -type ZodMapParameterTypes = T extends [] - ? [] - : T extends [item: infer Head, ...infer Rest] - ? [ZodParameterTypeFor, ...{ [K in keyof Rest]: ZodParameterTypeFor }] - : T extends [item?: infer Head, ...infer Rest] - ? [ZodNullableOptional>, ...{ [K in keyof Rest]: ZodParameterTypeFor }] - : never; +// Forces usage of schemas that accept nulls for optional parameters. +type ZodParameterTypeFor = undefined extends T ? ZodNullableOptional> : z.ZodType; + +type ZodReturnTypeFor = z.ZodType; + +type ZodMapParameterTypes = { + [K in keyof T]-?: ZodParameterTypeFor; +}; /** Maps all functions in an interface to their schema representation. */ export type ApiSchemaFor = { [K in keyof T]: T[K] extends (...args: infer Args) => Promise - ? z.ZodFunction, z.ZodUnknown>, ZodReturnTypeFor> + ? z.ZodFunction, null>, ZodReturnTypeFor> : never; }; @@ -44,7 +31,17 @@ export function schemaHasMethod( return ( typeof methodName === 'string' && Object.hasOwn(schema, methodName) && - typeof schema[methodName].parameters === 'function' && - typeof schema[methodName].returnType === 'function' + schema[methodName].def.input !== undefined && + schema[methodName].def.output !== undefined ); } + +/** Returns the parameter tuple schema for an API method schema. */ +export function getSchemaParameters, z.ZodTypeAny>>(schema: T) { + return schema.def.input; +} + +/** Returns the return value schema for an API method schema. */ +export function getSchemaReturnType, z.ZodTypeAny>>(schema: T) { + return schema.def.output; +} diff --git a/yarn-project/foundation/src/schemas/parse.ts b/yarn-project/foundation/src/schemas/parse.ts index f36c6b2f3021..b3c4ea359218 100644 --- a/yarn-project/foundation/src/schemas/parse.ts +++ b/yarn-project/foundation/src/schemas/parse.ts @@ -4,16 +4,19 @@ import { times } from '../collection/array.js'; /** Parses the given arguments using a tuple from the provided schemas. */ export function parse(args: IArguments, ...schemas: T) { - return z.tuple(schemas).parse(args); + return schemas.length === 0 + ? z.tuple([]).parse(args) + : z.tuple(schemas as [z.ZodTypeAny, ...z.ZodTypeAny[]]).parse(args); } /** * Parses the given arguments against a tuple, allowing empty for optional items. - * @dev Zod doesn't like tuplues with optional items. See https://github.com/colinhacks/zod/discussions/949. + * @dev Zod doesn't like tuples with optional items. See https://github.com/colinhacks/zod/discussions/949. */ -export function parseWithOptionals(args: any[], schema: T): Promise { - const missingCount = schema.items.length - args.length; - const optionalCount = schema.items.filter(isOptional).length; +export function parseWithOptionals>(args: any[], schema: T): Promise> { + const items = schema.def.items; + const missingCount = items.length - args.length; + const optionalCount = items.filter(isOptional).length; const toParse = missingCount > 0 && missingCount <= optionalCount ? args.concat(times(missingCount, () => undefined)) : args; return schema.parseAsync(toParse); @@ -24,6 +27,6 @@ function isOptional(schema: z.ZodTypeAny) { return schema.isOptional(); } catch { // See https://github.com/colinhacks/zod/issues/1911 - return schema._def.typeName === 'ZodOptional'; + return schema.def.type === 'optional'; } } diff --git a/yarn-project/foundation/src/schemas/schemas.ts b/yarn-project/foundation/src/schemas/schemas.ts index fb9a759cba0d..993235eb2c26 100644 --- a/yarn-project/foundation/src/schemas/schemas.ts +++ b/yarn-project/foundation/src/schemas/schemas.ts @@ -44,15 +44,15 @@ export const schemas = { ]), /** Coerces any input to bigint. */ - BigInt: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.bigint()), + BigInt: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.bigint()), /** Coerces any input to integer number. */ - Integer: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.number().int()), + Integer: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.number().int()), /** Coerces input to UInt32. */ UInt32: z.union([z.bigint(), z.number(), z.string()]).pipe( z.coerce - .number() + .number() .int() .min(0) .max(2 ** 32 - 1), @@ -61,7 +61,7 @@ export const schemas = { /** Coerces input to UInt64. */ UInt64: z.union([z.bigint(), z.number(), z.string()]).pipe( z.coerce - .bigint() + .bigint() .min(0n) .max(2n ** 64n - 1n), ), diff --git a/yarn-project/foundation/src/schemas/types.ts b/yarn-project/foundation/src/schemas/types.ts index 163a4c38bb50..8a7e72bb041b 100644 --- a/yarn-project/foundation/src/schemas/types.ts +++ b/yarn-project/foundation/src/schemas/types.ts @@ -1,6 +1,6 @@ import type { ZodType } from 'zod'; -export type ZodFor = ZodType; +export type ZodFor = ZodType; /** * Creates a schema validator that enforces all properties of type T are present in the schema. @@ -26,7 +26,7 @@ export type ZodFor = ZodType; * ``` */ export function zodFor() { - return (schema => schema) as >( + return (schema => schema) as >( schema: keyof T extends keyof S['_output'] ? keyof S['_output'] extends keyof T ? S diff --git a/yarn-project/foundation/src/schemas/utils.ts b/yarn-project/foundation/src/schemas/utils.ts index ef5835f13285..0ba2fa4f72bd 100644 --- a/yarn-project/foundation/src/schemas/utils.ts +++ b/yarn-project/foundation/src/schemas/utils.ts @@ -1,16 +1,4 @@ -import { - OK, - type ParseInput, - type ParseReturnType, - ZodFirstPartyTypeKind, - type ZodObject, - ZodOptional, - ZodParsedType, - type ZodRawShape, - type ZodType, - type ZodTypeAny, - z, -} from 'zod'; +import { type ZodObject, type ZodRawShape, type ZodType, type ZodTypeAny, z } from 'zod'; import { pick } from '../collection/object.js'; import { isHex, withoutHexPrefix } from '../string/index.js'; @@ -41,24 +29,7 @@ export const bufferSchema: ZodFor = z.union([ z.instanceof(Buffer), ]); -export class ZodNullableOptional extends ZodOptional { - _isNullableOptional = true; - - override _parse(input: ParseInput): ParseReturnType { - const parsedType = this._getType(input); - if (parsedType === ZodParsedType.undefined || parsedType === ZodParsedType.null) { - return OK(undefined); - } - return this._def.innerType._parse(input); - } - - static override create(type: T): ZodNullableOptional { - return new ZodNullableOptional({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodOptional, - }) as any; - } -} +export type ZodNullableOptional = ZodType | undefined, z.input | null | undefined>; /** * Declares a parameter as optional. Use this over z.optional in order to accept nulls as undefineds. @@ -66,7 +37,7 @@ export class ZodNullableOptional extends ZodOptional { * need to convert nulls to undefineds as we parse. */ export function optional(schema: T) { - return ZodNullableOptional.create(schema); + return schema.nullish().transform(value => value ?? undefined); } type ToJsonIs = T extends { toJSON(): TRet } ? T : never; @@ -83,7 +54,6 @@ export function hexSchemaFor : never, - any, string > { const stringSchema = refinement ? z.string().refine(refinement, `Not a valid instance`) : z.string(); @@ -101,11 +71,7 @@ export function hexSchemaFor( klazz: TClass, refinement?: (buf: Buffer) => boolean, -): ZodType< - TClass extends { fromBuffer(buf: Buffer): infer TInstance } ? ToJsonIs : never, - any, - string -> { +): ZodType : never, string> { return bufferSchema.refine(refinement ?? (() => true), 'Not a valid buffer').transform(klazz.fromBuffer.bind(klazz)); } diff --git a/yarn-project/foundation/src/trees/sibling_path.ts b/yarn-project/foundation/src/trees/sibling_path.ts index d05d0463782e..b7d58e5510c4 100644 --- a/yarn-project/foundation/src/trees/sibling_path.ts +++ b/yarn-project/foundation/src/trees/sibling_path.ts @@ -1,3 +1,5 @@ +import { z } from 'zod'; + import { makeTuple } from '../array/array.js'; import { Fr } from '../curves/bn254/index.js'; import { schemas } from '../schemas/index.js'; @@ -42,10 +44,14 @@ export class SiblingPath { } static schemaFor(size: N) { - return schemas.Buffer.transform(b => SiblingPath.fromBuffer(b) as SiblingPath).refine( - path => path.pathSize === size, - path => ({ message: `Expected sibling path size ${size} but got ${path.pathSize}` }), - ); + return schemas.Buffer.transform(b => SiblingPath.fromBuffer(b) as SiblingPath).superRefine((path, ctx) => { + if (path.pathSize !== size) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Expected sibling path size ${size} but got ${path.pathSize}`, + }); + } + }); } toJSON() { diff --git a/yarn-project/node-keystore/package.json b/yarn-project/node-keystore/package.json index b290fcf34d57..786d62dbab2f 100644 --- a/yarn-project/node-keystore/package.json +++ b/yarn-project/node-keystore/package.json @@ -70,7 +70,7 @@ "@ethersproject/wallet": "^5.7.0", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/prover-client/package.json b/yarn-project/prover-client/package.json index daedd2c6f705..1340a4433c20 100644 --- a/yarn-project/prover-client/package.json +++ b/yarn-project/prover-client/package.json @@ -86,7 +86,7 @@ "lodash.chunk": "^4.2.0", "source-map-support": "^0.5.21", "tslib": "^2.4.0", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@aztec/noir-contracts.js": "workspace:^", diff --git a/yarn-project/prover-client/src/proving_broker/rpc.ts b/yarn-project/prover-client/src/proving_broker/rpc.ts index c1da60eb1da1..3bbd89d50ca3 100644 --- a/yarn-project/prover-client/src/proving_broker/rpc.ts +++ b/yarn-project/prover-client/src/proving_broker/rpc.ts @@ -37,26 +37,29 @@ const GetProvingJobResponse = z.object({ }); export const ProvingJobProducerSchema: ApiSchemaFor = { - enqueueProvingJob: z.function().args(ProvingJob).returns(ProvingJobStatus), - getProvingJobStatus: z.function().args(ProvingJobId).returns(ProvingJobStatus), - cancelProvingJob: z.function().args(ProvingJobId).returns(z.void()), - getCompletedJobs: z.function().args(z.array(ProvingJobId)).returns(z.array(ProvingJobId)), + enqueueProvingJob: z.function({ input: z.tuple([ProvingJob]), output: ProvingJobStatus }), + getProvingJobStatus: z.function({ input: z.tuple([ProvingJobId]), output: ProvingJobStatus }), + cancelProvingJob: z.function({ input: z.tuple([ProvingJobId]), output: z.void() }), + getCompletedJobs: z.function({ input: z.tuple([z.array(ProvingJobId)]), output: z.array(ProvingJobId) }), }; export const ProvingJobConsumerSchema: ApiSchemaFor = { - getProvingJob: z.function().args(optional(ProvingJobFilterSchema)).returns(GetProvingJobResponse.optional()), - reportProvingJobError: z - .function() - .args(ProvingJobId, z.string(), optional(z.boolean()), optional(ProvingJobFilterSchema)) - .returns(GetProvingJobResponse.optional()), - reportProvingJobProgress: z - .function() - .args(ProvingJobId, z.number(), optional(ProvingJobFilterSchema)) - .returns(GetProvingJobResponse.optional()), - reportProvingJobSuccess: z - .function() - .args(ProvingJobId, ProofUri, optional(ProvingJobFilterSchema)) - .returns(GetProvingJobResponse.optional()), + getProvingJob: z.function({ + input: z.tuple([optional(ProvingJobFilterSchema)]), + output: GetProvingJobResponse.optional(), + }), + reportProvingJobError: z.function({ + input: z.tuple([ProvingJobId, z.string(), optional(z.boolean()), optional(ProvingJobFilterSchema)]), + output: GetProvingJobResponse.optional(), + }), + reportProvingJobProgress: z.function({ + input: z.tuple([ProvingJobId, z.number(), optional(ProvingJobFilterSchema)]), + output: GetProvingJobResponse.optional(), + }), + reportProvingJobSuccess: z.function({ + input: z.tuple([ProvingJobId, ProofUri, optional(ProvingJobFilterSchema)]), + output: GetProvingJobResponse.optional(), + }), }; export const ProvingJobBrokerSchema: ApiSchemaFor = { @@ -65,10 +68,10 @@ export const ProvingJobBrokerSchema: ApiSchemaFor = { }; export const ProvingJobBrokerDebugSchema: ApiSchemaFor = { - replayProvingJob: z - .function() - .args(ProvingJobId, z.nativeEnum(ProvingRequestType), EpochNumberSchema, ProofUri) - .returns(ProvingJobStatus), + replayProvingJob: z.function({ + input: z.tuple([ProvingJobId, z.nativeEnum(ProvingRequestType), EpochNumberSchema, ProofUri]), + output: ProvingJobStatus, + }), }; export const ProvingJobBrokerSchemaWithDebug: ApiSchemaFor = { diff --git a/yarn-project/slasher/package.json b/yarn-project/slasher/package.json index ede89aea698f..a36013fc3076 100644 --- a/yarn-project/slasher/package.json +++ b/yarn-project/slasher/package.json @@ -66,7 +66,7 @@ "source-map-support": "^0.5.21", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@aztec/aztec.js": "workspace:^", diff --git a/yarn-project/stdlib/package.json b/yarn-project/stdlib/package.json index e1630eba71f4..d8f872a45910 100644 --- a/yarn-project/stdlib/package.json +++ b/yarn-project/stdlib/package.json @@ -110,7 +110,7 @@ "pako": "^2.1.0", "tslib": "^2.4.0", "viem": "npm:@aztec/viem@2.38.2", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/expect": "^30.0.0", diff --git a/yarn-project/stdlib/src/abi/abi.ts b/yarn-project/stdlib/src/abi/abi.ts index c2328d262ebf..ff92bc344e7d 100644 --- a/yarn-project/stdlib/src/abi/abi.ts +++ b/yarn-project/stdlib/src/abi/abi.ts @@ -222,10 +222,11 @@ export const FunctionDebugMetadataSchema = z.object({ }), ), }), - acir_locations: z.record(z.number()), - brillig_locations: z.record(z.record(z.number())), + acir_locations: z.record(z.string(), z.number()), + brillig_locations: z.record(z.string(), z.record(z.string(), z.number())), }), files: z.record( + z.string(), z.object({ source: z.string(), path: z.string(), @@ -376,7 +377,7 @@ export const ContractArtifactSchema = zodFor()( functions: z.array(FunctionArtifactSchema), nonDispatchPublicFunctions: z.array(FunctionAbiSchema), outputs: z.object({ - structs: z.record(z.array(AbiTypeSchema)).transform(structs => { + structs: z.record(z.string(), z.array(AbiTypeSchema)).transform(structs => { for (const [key, value] of Object.entries(structs)) { // We are manually ordering events and functions in the abi by path. // The path ordering is arbitrary, and only needed to ensure deterministic order. @@ -388,9 +389,9 @@ export const ContractArtifactSchema = zodFor()( } return structs; }), - globals: z.record(z.array(AbiValueSchema)), + globals: z.record(z.string(), z.array(AbiValueSchema)), }), - storageLayout: z.record(z.object({ slot: schemas.Fr })), + storageLayout: z.record(z.string(), z.object({ slot: schemas.Fr })), fileMap: z.record( z.coerce.number(), z.object({ diff --git a/yarn-project/stdlib/src/block/block_parameter.ts b/yarn-project/stdlib/src/block/block_parameter.ts index da4940895137..18642e97015d 100644 --- a/yarn-project/stdlib/src/block/block_parameter.ts +++ b/yarn-project/stdlib/src/block/block_parameter.ts @@ -36,7 +36,7 @@ export type NormalizedBlockParameter = | { archive: Fr } | { tag: Exclude }; -export const NormalizedBlockParameterSchema: z.ZodType = z.union([ +export const NormalizedBlockParameterSchema: z.ZodType = z.union([ z.object({ number: BlockNumberSchema }).strict(), z.object({ hash: BlockHash.schema }).strict(), z.object({ archive: schemas.Fr }).strict(), @@ -52,7 +52,7 @@ export const NormalizedBlockParameterSchema: z.ZodType = z.union([ +export const BlockParameterSchema: z.ZodType = z.union([ NormalizedBlockParameterSchema, BlockHash.schema, BlockTagSchema, diff --git a/yarn-project/stdlib/src/block/l2_block_source.ts b/yarn-project/stdlib/src/block/l2_block_source.ts index 63745280802f..c8ac9b303b33 100644 --- a/yarn-project/stdlib/src/block/l2_block_source.ts +++ b/yarn-project/stdlib/src/block/l2_block_source.ts @@ -42,14 +42,14 @@ export type BlocksQuery = | { from: BlockNumber; limit: number; onlyCheckpointed?: boolean } | { epoch: EpochNumber; onlyCheckpointed: true }; -export const BlockQuerySchema: z.ZodType = z.union([ +export const BlockQuerySchema: z.ZodType = z.union([ z.object({ number: BlockNumberSchema }).strict(), z.object({ hash: BlockHash.schema }).strict(), z.object({ archive: schemas.Fr }).strict(), z.object({ tag: BlockTagWithoutLatestSchema }).strict(), ]); -export const BlocksQuerySchema: z.ZodType = z.union([ +export const BlocksQuerySchema: z.ZodType = z.union([ z .object({ from: BlockNumberSchema, limit: z.number().int().min(1), onlyCheckpointed: z.boolean().optional() }) .strict(), @@ -72,18 +72,18 @@ export type CheckpointsQuery = { from: CheckpointNumber; limit: number } | { epo */ export type ProposedCheckpointQuery = { number: CheckpointNumber } | { slot: SlotNumber } | { tag: 'proposed' }; -export const CheckpointQuerySchema: z.ZodType = z.union([ +export const CheckpointQuerySchema: z.ZodType = z.union([ z.object({ number: CheckpointNumberSchema }).strict(), z.object({ slot: SlotNumberSchema }).strict(), z.object({ tag: z.union([z.literal('checkpointed'), z.literal('proven'), z.literal('finalized')]) }).strict(), ]); -export const CheckpointsQuerySchema: z.ZodType = z.union([ +export const CheckpointsQuerySchema: z.ZodType = z.union([ z.object({ from: CheckpointNumberSchema, limit: z.number().int().min(1) }).strict(), z.object({ epoch: EpochNumberSchema }).strict(), ]); -export const ProposedCheckpointQuerySchema: z.ZodType = z.union([ +export const ProposedCheckpointQuerySchema: z.ZodType = z.union([ z.object({ number: CheckpointNumberSchema }).strict(), z.object({ slot: SlotNumberSchema }).strict(), z.object({ tag: z.literal('proposed') }).strict(), diff --git a/yarn-project/stdlib/src/interfaces/archiver.test.ts b/yarn-project/stdlib/src/interfaces/archiver.test.ts index 3ee0d7305a5b..ef6efa854b5b 100644 --- a/yarn-project/stdlib/src/interfaces/archiver.test.ts +++ b/yarn-project/stdlib/src/interfaces/archiver.test.ts @@ -167,12 +167,23 @@ describe('ArchiverApiSchema', () => { it('getPrivateLogsByTags', async () => { const result = await context.client.getPrivateLogsByTags([SiloedTag.random()]); expect(result).toEqual([[expect.any(TxScopedL2Log)]]); + + const resultWithOptionals = await context.client.getPrivateLogsByTags([SiloedTag.random()], 3, BlockNumber(4)); + expect(resultWithOptionals).toEqual([[expect.any(TxScopedL2Log)]]); }); it('getPublicLogsByTagsFromContract', async () => { const contractAddress = await AztecAddress.random(); const result = await context.client.getPublicLogsByTagsFromContract(contractAddress, [Tag.random()]); expect(result).toEqual([[expect.any(TxScopedL2Log)]]); + + const resultWithOptionals = await context.client.getPublicLogsByTagsFromContract( + contractAddress, + [Tag.random()], + 3, + BlockNumber(4), + ); + expect(resultWithOptionals).toEqual([[expect.any(TxScopedL2Log)]]); }); it('getPublicLogs', async () => { @@ -502,17 +513,30 @@ class MockArchiver implements ArchiverApi { expect(blockNumber).toEqual(BlockNumber(1)); return Promise.resolve(`0x01`); } - getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { + getPrivateLogsByTags(tags: SiloedTag[], page?: number, upToBlockNumber?: BlockNumber): Promise { expect(tags[0]).toBeInstanceOf(SiloedTag); + if (page !== undefined) { + expect(page).toBe(3); + } + if (upToBlockNumber !== undefined) { + expect(upToBlockNumber).toBe(BlockNumber(4)); + } return Promise.resolve([tags.map(() => randomTxScopedPrivateL2Log())]); } getPublicLogsByTagsFromContract( contractAddress: AztecAddress, tags: Tag[], - _logsPerTag?: number, + page?: number, + upToBlockNumber?: BlockNumber, ): Promise { expect(contractAddress).toBeInstanceOf(AztecAddress); expect(tags[0]).toBeInstanceOf(Tag); + if (page !== undefined) { + expect(page).toBe(3); + } + if (upToBlockNumber !== undefined) { + expect(upToBlockNumber).toBe(BlockNumber(4)); + } return Promise.resolve([tags.map(() => randomTxScopedPrivateL2Log())]); } async getPublicLogs(filter: LogFilter): Promise { diff --git a/yarn-project/stdlib/src/interfaces/archiver.ts b/yarn-project/stdlib/src/interfaces/archiver.ts index 39b3f1a906d8..b8abf1c873b8 100644 --- a/yarn-project/stdlib/src/interfaces/archiver.ts +++ b/yarn-project/stdlib/src/interfaces/archiver.ts @@ -89,58 +89,63 @@ export type ArchiverApi = Omit< >; export const ArchiverApiSchema: ApiSchemaFor = { - getRollupAddress: z.function().args().returns(schemas.EthAddress), - getRegistryAddress: z.function().args().returns(schemas.EthAddress), - getBlockNumber: z.function().args(optional(BlockQuerySchema)).returns(BlockNumberSchema.optional()), - getCheckpointNumber: z.function().args().returns(CheckpointNumberSchema), - getCheckpoint: z.function().args(CheckpointQuerySchema).returns(PublishedCheckpoint.schema.optional()), - getCheckpoints: z.function().args(CheckpointsQuerySchema).returns(z.array(PublishedCheckpoint.schema)), - getCheckpointData: z.function().args(CheckpointQuerySchema).returns(CheckpointDataSchema.optional()), - getCheckpointsData: z.function().args(CheckpointsQuerySchema).returns(z.array(CheckpointDataSchema)), - getTxEffect: z.function().args(TxHash.schema).returns(indexedTxSchema().optional()), - getSettledTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema.optional()), - getSyncedL2SlotNumber: z.function().args().returns(schemas.SlotNumber.optional()), - getSyncedL2EpochNumber: z.function().args().returns(EpochNumberSchema.optional()), - getBlocksForSlot: z.function().args(schemas.SlotNumber).returns(z.array(L2Block.schema)), - isEpochComplete: z.function().args(EpochNumberSchema).returns(z.boolean()), - getL2Tips: z.function().args().returns(L2TipsSchema), - getPrivateLogsByTags: z - .function() - .args(z.array(SiloedTag.schema), optional(z.number().gte(0))) - .returns(z.array(z.array(TxScopedL2Log.schema))), - getPublicLogsByTagsFromContract: z - .function() - .args(schemas.AztecAddress, z.array(Tag.schema), optional(z.number().gte(0))) - .returns(z.array(z.array(TxScopedL2Log.schema))), - getPublicLogs: z.function().args(LogFilterSchema).returns(GetPublicLogsResponseSchema), - getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), - getContractClass: z.function().args(schemas.Fr).returns(ContractClassPublicSchema.optional()), - getBytecodeCommitment: z.function().args(schemas.Fr).returns(schemas.Fr), - getContract: z - .function() - .args(schemas.AztecAddress, optional(schemas.BigInt)) - .returns(ContractInstanceWithAddressSchema.optional()), - getContractClassIds: z.function().args().returns(z.array(schemas.Fr)), - registerContractFunctionSignatures: z.function().args(z.array(z.string())).returns(z.void()), - getL1ToL2Messages: z.function().args(CheckpointNumberSchema).returns(z.array(schemas.Fr)), - getL1ToL2MessageIndex: z.function().args(schemas.Fr).returns(schemas.BigInt.optional()), - getDebugFunctionName: z.function().args(schemas.AztecAddress, schemas.FunctionSelector).returns(optional(z.string())), - getL1Constants: z.function().args().returns(L1RollupConstantsSchema), - isPruneDueAtSlot: z.function().args(schemas.SlotNumber).returns(z.boolean()), - getGenesisValues: z - .function() - .args() - .returns(z.object({ genesisArchiveRoot: schemas.Fr })), - getL1Timestamp: z.function().args().returns(schemas.BigInt.optional()), - getProposedCheckpointData: z - .function() - .args(optional(ProposedCheckpointQuerySchema)) - .returns(ProposedCheckpointDataSchema.optional()), - syncImmediate: z.function().args().returns(z.void()), - isPendingChainInvalid: z.function().args().returns(z.boolean()), - getPendingChainValidationStatus: z.function().args().returns(ValidateCheckpointResultSchema), - getBlock: z.function().args(BlockQuerySchema).returns(L2Block.schema.optional()), - getBlocks: z.function().args(BlocksQuerySchema).returns(z.array(L2Block.schema)), - getBlockData: z.function().args(BlockQuerySchema).returns(BlockDataSchema.optional()), - getBlocksData: z.function().args(BlocksQuerySchema).returns(z.array(BlockDataSchema)), + getRollupAddress: z.function({ input: z.tuple([]), output: schemas.EthAddress }), + getRegistryAddress: z.function({ input: z.tuple([]), output: schemas.EthAddress }), + getBlockNumber: z.function({ input: z.tuple([optional(BlockQuerySchema)]), output: BlockNumberSchema.optional() }), + getCheckpointNumber: z.function({ input: z.tuple([]), output: CheckpointNumberSchema }), + getCheckpoint: z.function({ input: z.tuple([CheckpointQuerySchema]), output: PublishedCheckpoint.schema.optional() }), + getCheckpoints: z.function({ input: z.tuple([CheckpointsQuerySchema]), output: z.array(PublishedCheckpoint.schema) }), + getCheckpointData: z.function({ input: z.tuple([CheckpointQuerySchema]), output: CheckpointDataSchema.optional() }), + getCheckpointsData: z.function({ input: z.tuple([CheckpointsQuerySchema]), output: z.array(CheckpointDataSchema) }), + getTxEffect: z.function({ input: z.tuple([TxHash.schema]), output: indexedTxSchema().optional() }), + getSettledTxReceipt: z.function({ input: z.tuple([TxHash.schema]), output: TxReceipt.schema.optional() }), + getSyncedL2SlotNumber: z.function({ input: z.tuple([]), output: schemas.SlotNumber.optional() }), + getSyncedL2EpochNumber: z.function({ input: z.tuple([]), output: EpochNumberSchema.optional() }), + getBlocksForSlot: z.function({ input: z.tuple([schemas.SlotNumber]), output: z.array(L2Block.schema) }), + isEpochComplete: z.function({ input: z.tuple([EpochNumberSchema]), output: z.boolean() }), + getL2Tips: z.function({ input: z.tuple([]), output: L2TipsSchema }), + getPrivateLogsByTags: z.function({ + input: z.tuple([z.array(SiloedTag.schema), optional(z.number().gte(0)), optional(BlockNumberSchema)]), + output: z.array(z.array(TxScopedL2Log.schema)), + }), + getPublicLogsByTagsFromContract: z.function({ + input: z.tuple([ + schemas.AztecAddress, + z.array(Tag.schema), + optional(z.number().gte(0)), + optional(BlockNumberSchema), + ]), + output: z.array(z.array(TxScopedL2Log.schema)), + }), + getPublicLogs: z.function({ input: z.tuple([LogFilterSchema]), output: GetPublicLogsResponseSchema }), + getContractClassLogs: z.function({ input: z.tuple([LogFilterSchema]), output: GetContractClassLogsResponseSchema }), + getContractClass: z.function({ input: z.tuple([schemas.Fr]), output: ContractClassPublicSchema.optional() }), + getBytecodeCommitment: z.function({ input: z.tuple([schemas.Fr]), output: schemas.Fr }), + getContract: z.function({ + input: z.tuple([schemas.AztecAddress, optional(schemas.BigInt)]), + output: ContractInstanceWithAddressSchema.optional(), + }), + getContractClassIds: z.function({ input: z.tuple([]), output: z.array(schemas.Fr) }), + registerContractFunctionSignatures: z.function({ input: z.tuple([z.array(z.string())]), output: z.void() }), + getL1ToL2Messages: z.function({ input: z.tuple([CheckpointNumberSchema]), output: z.array(schemas.Fr) }), + getL1ToL2MessageIndex: z.function({ input: z.tuple([schemas.Fr]), output: schemas.BigInt.optional() }), + getDebugFunctionName: z.function({ + input: z.tuple([schemas.AztecAddress, schemas.FunctionSelector]), + output: optional(z.string()), + }), + getL1Constants: z.function({ input: z.tuple([]), output: L1RollupConstantsSchema }), + isPruneDueAtSlot: z.function({ input: z.tuple([schemas.SlotNumber]), output: z.boolean() }), + getGenesisValues: z.function({ input: z.tuple([]), output: z.object({ genesisArchiveRoot: schemas.Fr }) }), + getL1Timestamp: z.function({ input: z.tuple([]), output: schemas.BigInt.optional() }), + getProposedCheckpointData: z.function({ + input: z.tuple([optional(ProposedCheckpointQuerySchema)]), + output: ProposedCheckpointDataSchema.optional(), + }), + syncImmediate: z.function({ input: z.tuple([]), output: z.void() }), + isPendingChainInvalid: z.function({ input: z.tuple([]), output: z.boolean() }), + getPendingChainValidationStatus: z.function({ input: z.tuple([]), output: ValidateCheckpointResultSchema }), + getBlock: z.function({ input: z.tuple([BlockQuerySchema]), output: L2Block.schema.optional() }), + getBlocks: z.function({ input: z.tuple([BlocksQuerySchema]), output: z.array(L2Block.schema) }), + getBlockData: z.function({ input: z.tuple([BlockQuerySchema]), output: BlockDataSchema.optional() }), + getBlocksData: z.function({ input: z.tuple([BlocksQuerySchema]), output: z.array(BlockDataSchema) }), }; diff --git a/yarn-project/stdlib/src/interfaces/aztec-node-admin.ts b/yarn-project/stdlib/src/interfaces/aztec-node-admin.ts index 309b7ea6f94b..409acb28e569 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node-admin.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node-admin.ts @@ -99,17 +99,20 @@ export const AztecNodeAdminConfigSchema = SequencerConfigSchema.merge(ProverConf .merge(z.object({ maxPendingTxCount: z.number(), skipIncomingProposals: z.boolean().optional() })); export const AztecNodeAdminApiSchema: ApiSchemaFor = { - getConfig: z.function().returns(AztecNodeAdminConfigSchema), - setConfig: z.function().args(AztecNodeAdminConfigSchema.partial()).returns(z.void()), - startSnapshotUpload: z.function().args(z.string()).returns(z.void()), - rollbackTo: z.function().args(z.number(), optional(z.boolean()), optional(z.boolean())).returns(z.void()), - pauseSync: z.function().returns(z.void()), - resumeSync: z.function().returns(z.void()), - getSlashOffenses: z - .function() - .args(z.union([z.bigint(), z.literal('all'), z.literal('current')])) - .returns(z.array(OffenseSchema)), - reloadKeystore: z.function().returns(z.void()), + getConfig: z.function({ input: z.tuple([]), output: AztecNodeAdminConfigSchema }), + setConfig: z.function({ input: z.tuple([AztecNodeAdminConfigSchema.partial()]), output: z.void() }), + startSnapshotUpload: z.function({ input: z.tuple([z.string()]), output: z.void() }), + rollbackTo: z.function({ + input: z.tuple([z.number(), optional(z.boolean()), optional(z.boolean())]), + output: z.void(), + }), + pauseSync: z.function({ input: z.tuple([]), output: z.void() }), + resumeSync: z.function({ input: z.tuple([]), output: z.void() }), + getSlashOffenses: z.function({ + input: z.tuple([z.union([z.bigint(), z.literal('all'), z.literal('current')])]), + output: z.array(OffenseSchema), + }), + reloadKeystore: z.function({ input: z.tuple([]), output: z.void() }), }; export function createAztecNodeAdminClient( diff --git a/yarn-project/stdlib/src/interfaces/aztec-node-debug.ts b/yarn-project/stdlib/src/interfaces/aztec-node-debug.ts index 8d2a2e703483..77b06c29a5b7 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node-debug.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node-debug.ts @@ -22,7 +22,7 @@ export interface AztecNodeDebug { } export const AztecNodeDebugApiSchema: ApiSchemaFor = { - mineBlock: z.function().returns(z.void()), + mineBlock: z.function({ input: z.tuple([]), output: z.void() }), }; export function createAztecNodeDebugClient( diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index d007587d1790..f7ba90236a4b 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -281,12 +281,27 @@ describe('AztecNodeApiSchema', () => { it('getPrivateLogsByTags', async () => { const response = await context.client.getPrivateLogsByTags([SiloedTag.random()]); expect(response).toEqual([[expect.any(TxScopedL2Log)]]); + + const responseWithOptionals = await context.client.getPrivateLogsByTags( + [SiloedTag.random()], + 3, + BlockHash.random(), + ); + expect(responseWithOptionals).toEqual([[expect.any(TxScopedL2Log)]]); }); it('getPublicLogsByTagsFromContract', async () => { const contractAddress = await AztecAddress.random(); const response = await context.client.getPublicLogsByTagsFromContract(contractAddress, [Tag.random()]); expect(response).toEqual([[expect.any(TxScopedL2Log)]]); + + const responseWithOptionals = await context.client.getPublicLogsByTagsFromContract( + contractAddress, + [Tag.random()], + 3, + BlockHash.random(), + ); + expect(responseWithOptionals).toEqual([[expect.any(TxScopedL2Log)]]); }); it('sendTx', async () => { @@ -722,19 +737,32 @@ class MockAztecNode implements AztecNode { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); return Promise.resolve({ logs: [await ExtendedContractClassLog.random()], maxLogsHit: true }); } - getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { + getPrivateLogsByTags(tags: SiloedTag[], page?: number, referenceBlock?: BlockHash): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(SiloedTag); + if (page !== undefined) { + expect(page).toBe(3); + } + if (referenceBlock !== undefined) { + expect(referenceBlock).toBeInstanceOf(BlockHash); + } return Promise.resolve([[randomTxScopedPrivateL2Log()]]); } getPublicLogsByTagsFromContract( contractAddress: AztecAddress, tags: Tag[], - _logsPerTag?: number, + page?: number, + referenceBlock?: BlockHash, ): Promise { expect(contractAddress).toBeInstanceOf(AztecAddress); expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Tag); + if (page !== undefined) { + expect(page).toBe(3); + } + if (referenceBlock !== undefined) { + expect(referenceBlock).toBeInstanceOf(BlockHash); + } return Promise.resolve([[randomTxScopedPrivateL2Log()]]); } sendTx(tx: Tx): Promise { diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index 3b06ec6bc1e0..9ca1e204be9f 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -507,177 +507,202 @@ const MAX_SIGNATURES_PER_REGISTER_CALL = 100; const MAX_SIGNATURE_LEN = 10000; export const AztecNodeApiSchema: ApiSchemaFor = { - getWorldStateSyncStatus: z.function().args().returns(WorldStateSyncStatusSchema), + getWorldStateSyncStatus: z.function({ input: z.tuple([]), output: WorldStateSyncStatusSchema }), - findLeavesIndexes: z - .function() - .args(BlockParameterSchema, z.nativeEnum(MerkleTreeId), z.array(schemas.Fr).max(MAX_RPC_LEN)) - .returns(z.array(optional(dataInBlockSchemaFor(schemas.BigInt)))), + findLeavesIndexes: z.function({ + input: z.tuple([BlockParameterSchema, z.nativeEnum(MerkleTreeId), z.array(schemas.Fr).max(MAX_RPC_LEN)]), + output: z.array(optional(dataInBlockSchemaFor(schemas.BigInt))), + }), - getNullifierMembershipWitness: z - .function() - .args(BlockParameterSchema, schemas.Fr) - .returns(NullifierMembershipWitness.schema.optional()), + getNullifierMembershipWitness: z.function({ + input: z.tuple([BlockParameterSchema, schemas.Fr]), + output: NullifierMembershipWitness.schema.optional(), + }), - getLowNullifierMembershipWitness: z - .function() - .args(BlockParameterSchema, schemas.Fr) - .returns(NullifierMembershipWitness.schema.optional()), + getLowNullifierMembershipWitness: z.function({ + input: z.tuple([BlockParameterSchema, schemas.Fr]), + output: NullifierMembershipWitness.schema.optional(), + }), - getPublicDataWitness: z - .function() - .args(BlockParameterSchema, schemas.Fr) - .returns(PublicDataWitness.schema.optional()), + getPublicDataWitness: z.function({ + input: z.tuple([BlockParameterSchema, schemas.Fr]), + output: PublicDataWitness.schema.optional(), + }), - getBlockHashMembershipWitness: z - .function() - .args(BlockParameterSchema, BlockHash.schema) - .returns(MembershipWitness.schemaFor(ARCHIVE_HEIGHT).optional()), + getBlockHashMembershipWitness: z.function({ + input: z.tuple([BlockParameterSchema, BlockHash.schema]), + output: MembershipWitness.schemaFor(ARCHIVE_HEIGHT).optional(), + }), - getNoteHashMembershipWitness: z - .function() - .args(BlockParameterSchema, schemas.Fr) - .returns(MembershipWitness.schemaFor(NOTE_HASH_TREE_HEIGHT).optional()), + getNoteHashMembershipWitness: z.function({ + input: z.tuple([BlockParameterSchema, schemas.Fr]), + output: MembershipWitness.schemaFor(NOTE_HASH_TREE_HEIGHT).optional(), + }), - getL1ToL2MessageMembershipWitness: z - .function() - .args(BlockParameterSchema, schemas.Fr) - .returns(z.tuple([schemas.BigInt, SiblingPath.schemaFor(L1_TO_L2_MSG_TREE_HEIGHT)]).optional()), + getL1ToL2MessageMembershipWitness: z.function({ + input: z.tuple([BlockParameterSchema, schemas.Fr]), + output: z.tuple([schemas.BigInt, SiblingPath.schemaFor(L1_TO_L2_MSG_TREE_HEIGHT)]).optional(), + }), - getL1ToL2MessageCheckpoint: z.function().args(schemas.Fr).returns(CheckpointNumberSchema.optional()), + getL1ToL2MessageCheckpoint: z.function({ input: z.tuple([schemas.Fr]), output: CheckpointNumberSchema.optional() }), - getL2ToL1Messages: z - .function() - .args(EpochNumberSchema) - .returns(z.array(z.array(z.array(z.array(schemas.Fr))))), + getL2ToL1Messages: z.function({ + input: z.tuple([EpochNumberSchema]), + output: z.array(z.array(z.array(z.array(schemas.Fr)))), + }), - getBlockNumber: z.function().args(optional(ChainTipSchema)).returns(BlockNumberSchema), + getBlockNumber: z.function({ input: z.tuple([optional(ChainTipSchema)]), output: BlockNumberSchema }), - getCheckpointNumber: z.function().args(optional(ChainTipSchema)).returns(CheckpointNumberSchema), + getCheckpointNumber: z.function({ input: z.tuple([optional(ChainTipSchema)]), output: CheckpointNumberSchema }), - getChainTips: z.function().args().returns(ChainTipsSchema), + getChainTips: z.function({ input: z.tuple([]), output: ChainTipsSchema }), - getCheckpointsData: z.function().args(CheckpointsQuerySchema).returns(z.array(CheckpointDataSchema)), + getCheckpointsData: z.function({ input: z.tuple([CheckpointsQuerySchema]), output: z.array(CheckpointDataSchema) }), - getBlock: z - .function() - .args(BlockParameterSchema, optional(BlockIncludeOptionsSchema)) - .returns(BlockResponseSchema.optional()), + getBlock: z.function({ + input: z.tuple([BlockParameterSchema, optional(BlockIncludeOptionsSchema)]), + output: BlockResponseSchema.optional(), + }), - getBlockData: z.function().args(BlockParameterSchema).returns(BlockDataSchema.optional()), + getBlockData: z.function({ input: z.tuple([BlockParameterSchema]), output: BlockDataSchema.optional() }), - getBlocks: z - .function() - .args(BlockNumberPositiveSchema, z.number().gt(0).lte(MAX_RPC_BLOCKS_LEN), optional(BlocksIncludeOptionsSchema)) - .returns(z.array(BlockResponseSchema)), + getBlocks: z.function({ + input: z.tuple([ + BlockNumberPositiveSchema, + z.number().gt(0).lte(MAX_RPC_BLOCKS_LEN), + optional(BlocksIncludeOptionsSchema), + ]), + output: z.array(BlockResponseSchema), + }), - getCheckpoint: z - .function() - .args(CheckpointParameterSchema, optional(CheckpointIncludeOptionsSchema)) - .returns(CheckpointResponseSchema.optional()), + getCheckpoint: z.function({ + input: z.tuple([CheckpointParameterSchema, optional(CheckpointIncludeOptionsSchema)]), + output: CheckpointResponseSchema.optional(), + }), - getCheckpoints: z - .function() - .args( + getCheckpoints: z.function({ + input: z.tuple([ CheckpointNumberPositiveSchema, z.number().gt(0).lte(MAX_RPC_CHECKPOINTS_LEN), optional(CheckpointIncludeOptionsSchema), - ) - .returns(z.array(CheckpointResponseSchema)), + ]), + output: z.array(CheckpointResponseSchema), + }), - isReady: z.function().returns(z.boolean()), + isReady: z.function({ input: z.tuple([]), output: z.boolean() }), - getNodeInfo: z.function().returns(NodeInfoSchema), + getNodeInfo: z.function({ input: z.tuple([]), output: NodeInfoSchema }), - getCurrentMinFees: z.function().returns(GasFees.schema), + getCurrentMinFees: z.function({ input: z.tuple([]), output: GasFees.schema }), - getPredictedMinFees: z - .function() - .args(optional(z.nativeEnum(ManaUsageEstimate))) - .returns(z.array(GasFees.schema)), + getPredictedMinFees: z.function({ + input: z.tuple([optional(z.nativeEnum(ManaUsageEstimate))]), + output: z.array(GasFees.schema), + }), - getMaxPriorityFees: z.function().returns(GasFees.schema), + getMaxPriorityFees: z.function({ input: z.tuple([]), output: GasFees.schema }), - getNodeVersion: z.function().returns(z.string()), + getNodeVersion: z.function({ input: z.tuple([]), output: z.string() }), - getVersion: z.function().returns(z.number()), + getVersion: z.function({ input: z.tuple([]), output: z.number() }), - getChainId: z.function().returns(z.number()), + getChainId: z.function({ input: z.tuple([]), output: z.number() }), - getL1ContractAddresses: z.function().returns(L1ContractAddressesSchema), + getL1ContractAddresses: z.function({ input: z.tuple([]), output: L1ContractAddressesSchema }), - getProtocolContractAddresses: z.function().returns(ProtocolContractAddressesSchema), + getProtocolContractAddresses: z.function({ input: z.tuple([]), output: ProtocolContractAddressesSchema }), - registerContractFunctionSignatures: z - .function() - .args(z.array(z.string().max(MAX_SIGNATURE_LEN)).max(MAX_SIGNATURES_PER_REGISTER_CALL)) - .returns(z.void()), + registerContractFunctionSignatures: z.function({ + input: z.tuple([z.array(z.string().max(MAX_SIGNATURE_LEN)).max(MAX_SIGNATURES_PER_REGISTER_CALL)]), + output: z.void(), + }), - getPublicLogs: z.function().args(LogFilterSchema).returns(GetPublicLogsResponseSchema), + getPublicLogs: z.function({ input: z.tuple([LogFilterSchema]), output: GetPublicLogsResponseSchema }), - getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), + getContractClassLogs: z.function({ input: z.tuple([LogFilterSchema]), output: GetContractClassLogsResponseSchema }), - getPrivateLogsByTags: z - .function() - .args(z.array(SiloedTag.schema).max(MAX_RPC_LEN), optional(z.number().gte(0)), optional(BlockHash.schema)) - .returns(z.array(z.array(TxScopedL2Log.schema))), + getPrivateLogsByTags: z.function({ + input: z.tuple([ + z.array(SiloedTag.schema).max(MAX_RPC_LEN), + optional(z.number().gte(0)), + optional(BlockHash.schema), + ]), + output: z.array(z.array(TxScopedL2Log.schema)), + }), - getPublicLogsByTagsFromContract: z - .function() - .args( + getPublicLogsByTagsFromContract: z.function({ + input: z.tuple([ schemas.AztecAddress, z.array(Tag.schema).max(MAX_RPC_LEN), optional(z.number().gte(0)), optional(BlockHash.schema), - ) - .returns(z.array(z.array(TxScopedL2Log.schema))), + ]), + output: z.array(z.array(TxScopedL2Log.schema)), + }), - sendTx: z.function().args(Tx.schema).returns(z.void()), + sendTx: z.function({ input: z.tuple([Tx.schema]), output: z.void() }), - getTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema), + getTxReceipt: z.function({ input: z.tuple([TxHash.schema]), output: TxReceipt.schema }), - getTxEffect: z.function().args(TxHash.schema).returns(indexedTxSchema().optional()), + getTxEffect: z.function({ input: z.tuple([TxHash.schema]), output: indexedTxSchema().optional() }), - getPendingTxs: z - .function() - .args(optional(z.number().gte(1).lte(MAX_RPC_TXS_LEN).default(MAX_RPC_TXS_LEN)), optional(TxHash.schema)) - .returns(z.array(Tx.schema)), + getPendingTxs: z.function({ + input: z.tuple([ + optional(z.number().gte(1).lte(MAX_RPC_TXS_LEN).default(MAX_RPC_TXS_LEN)), + optional(TxHash.schema), + ]), + output: z.array(Tx.schema), + }), - getPendingTxCount: z.function().returns(z.number()), + getPendingTxCount: z.function({ input: z.tuple([]), output: z.number() }), - getTxByHash: z.function().args(TxHash.schema).returns(Tx.schema.optional()), + getTxByHash: z.function({ input: z.tuple([TxHash.schema]), output: Tx.schema.optional() }), - getTxsByHash: z.function().args(z.array(TxHash.schema).max(MAX_RPC_TXS_LEN)).returns(z.array(Tx.schema)), + getTxsByHash: z.function({ + input: z.tuple([z.array(TxHash.schema).max(MAX_RPC_TXS_LEN)]), + output: z.array(Tx.schema), + }), - getPublicStorageAt: z.function().args(BlockParameterSchema, schemas.AztecAddress, schemas.Fr).returns(schemas.Fr), + getPublicStorageAt: z.function({ + input: z.tuple([BlockParameterSchema, schemas.AztecAddress, schemas.Fr]), + output: schemas.Fr, + }), - getValidatorsStats: z.function().returns(ValidatorsStatsSchema), + getValidatorsStats: z.function({ input: z.tuple([]), output: ValidatorsStatsSchema }), - getValidatorStats: z - .function() - .args(schemas.EthAddress, optional(schemas.SlotNumber), optional(schemas.SlotNumber)) - .returns(SingleValidatorStatsSchema.optional()), + getValidatorStats: z.function({ + input: z.tuple([schemas.EthAddress, optional(schemas.SlotNumber), optional(schemas.SlotNumber)]), + output: SingleValidatorStatsSchema.optional(), + }), - simulatePublicCalls: z - .function() - .args(Tx.schema, optional(z.boolean()), optional(SimulationOverrides.schema)) - .returns(PublicSimulationOutput.schema), + simulatePublicCalls: z.function({ + input: z.tuple([Tx.schema, optional(z.boolean()), optional(SimulationOverrides.schema)]), + output: PublicSimulationOutput.schema, + }), - isValidTx: z - .function() - .args( + isValidTx: z.function({ + input: z.tuple([ Tx.schema, - optional(z.object({ isSimulation: optional(z.boolean()), skipFeeEnforcement: optional(z.boolean()) })), - ) - .returns(TxValidationResultSchema), - - getContractClass: z.function().args(schemas.Fr).returns(ContractClassPublicSchema.optional()), - - getContract: z.function().args(schemas.AztecAddress).returns(ContractInstanceWithAddressSchema.optional()), - - getEncodedEnr: z.function().returns(z.string().optional()), - - getAllowedPublicSetup: z.function().args().returns(z.array(AllowedElementSchema)), + optional( + z.object({ + isSimulation: optional(z.boolean()).optional(), + skipFeeEnforcement: optional(z.boolean()).optional(), + }), + ), + ]), + output: TxValidationResultSchema, + }), + + getContractClass: z.function({ input: z.tuple([schemas.Fr]), output: ContractClassPublicSchema.optional() }), + + getContract: z.function({ + input: z.tuple([schemas.AztecAddress]), + output: ContractInstanceWithAddressSchema.optional(), + }), + + getEncodedEnr: z.function({ input: z.tuple([]), output: z.string().optional() }), + + getAllowedPublicSetup: z.function({ input: z.tuple([]), output: z.array(AllowedElementSchema) }), }; export function createAztecNodeClient( diff --git a/yarn-project/stdlib/src/interfaces/p2p-bootstrap.ts b/yarn-project/stdlib/src/interfaces/p2p-bootstrap.ts index 6a039e6e0bd5..1a5e450f83e1 100644 --- a/yarn-project/stdlib/src/interfaces/p2p-bootstrap.ts +++ b/yarn-project/stdlib/src/interfaces/p2p-bootstrap.ts @@ -16,6 +16,6 @@ export interface P2PBootstrapApi { } export const P2PBootstrapApiSchema: ApiSchemaFor = { - getEncodedEnr: z.function().returns(z.string()), - getRoutingTable: z.function().returns(z.array(z.string())), + getEncodedEnr: z.function({ input: z.tuple([]), output: z.string() }), + getRoutingTable: z.function({ input: z.tuple([]), output: z.array(z.string()) }), }; diff --git a/yarn-project/stdlib/src/interfaces/p2p.ts b/yarn-project/stdlib/src/interfaces/p2p.ts index a729ecf22938..111a3b9becb7 100644 --- a/yarn-project/stdlib/src/interfaces/p2p.ts +++ b/yarn-project/stdlib/src/interfaces/p2p.ts @@ -70,19 +70,22 @@ export interface P2PClient extends P2PApi { } export const P2PApiSchema: ApiSchemaFor = { - getCheckpointAttestationsForSlot: z - .function() - .args( + getCheckpointAttestationsForSlot: z.function({ + input: z.tuple([ schemas.SlotNumber, optional(z.string().regex(/^0x[0-9a-fA-F]+$/) as unknown as z.ZodType), - ) - .returns(z.array(CheckpointAttestation.schema)), - getPendingTxs: z - .function() - .args(optional(z.number().gte(1).lte(MAX_RPC_TXS_LEN).default(MAX_RPC_TXS_LEN)), optional(TxHash.schema)) - .returns(z.array(Tx.schema)), + ]), + output: z.array(CheckpointAttestation.schema), + }), + getPendingTxs: z.function({ + input: z.tuple([ + optional(z.number().gte(1).lte(MAX_RPC_TXS_LEN).default(MAX_RPC_TXS_LEN)), + optional(TxHash.schema), + ]), + output: z.array(Tx.schema), + }), - getPendingTxCount: z.function().returns(schemas.Integer), - getEncodedEnr: z.function().returns(z.string().optional()), - getPeers: z.function().args(optional(z.boolean())).returns(z.array(PeerInfoSchema)), + getPendingTxCount: z.function({ input: z.tuple([]), output: schemas.Integer }), + getEncodedEnr: z.function({ input: z.tuple([]), output: z.string().optional() }), + getPeers: z.function({ input: z.tuple([optional(z.boolean())]), output: z.array(PeerInfoSchema) }), }; diff --git a/yarn-project/stdlib/src/interfaces/prover-agent.ts b/yarn-project/stdlib/src/interfaces/prover-agent.ts index 78654da2a23c..93d465a61e36 100644 --- a/yarn-project/stdlib/src/interfaces/prover-agent.ts +++ b/yarn-project/stdlib/src/interfaces/prover-agent.ts @@ -15,5 +15,5 @@ export interface ProverAgentApi { } export const ProverAgentApiSchema: ApiSchemaFor = { - getStatus: z.function().args().returns(ProverAgentStatusSchema), + getStatus: z.function({ input: z.tuple([]), output: ProverAgentStatusSchema }), }; diff --git a/yarn-project/stdlib/src/interfaces/prover-node.ts b/yarn-project/stdlib/src/interfaces/prover-node.ts index b28438708136..f5c98d0a28aa 100644 --- a/yarn-project/stdlib/src/interfaces/prover-node.ts +++ b/yarn-project/stdlib/src/interfaces/prover-node.ts @@ -41,14 +41,14 @@ export interface ProverNodeApi { /** Schemas for prover node API functions. */ export const ProverNodeApiSchema: ApiSchemaFor = { - getJobs: z - .function() - .args() - .returns(z.array(z.object({ uuid: z.string(), status: z.enum(EpochProvingJobState), epochNumber: z.number() }))), + getJobs: z.function({ + input: z.tuple([]), + output: z.array(z.object({ uuid: z.string(), status: z.enum(EpochProvingJobState), epochNumber: z.number() })), + }), - startProof: z.function().args(schemas.Integer).returns(z.void()), + startProof: z.function({ input: z.tuple([schemas.Integer]), output: z.void() }), - getL2Tips: z.function().args().returns(L2TipsSchema), + getL2Tips: z.function({ input: z.tuple([]), output: L2TipsSchema }), - getWorldStateSyncStatus: z.function().args().returns(WorldStateSyncStatusSchema), + getWorldStateSyncStatus: z.function({ input: z.tuple([]), output: WorldStateSyncStatusSchema }), }; diff --git a/yarn-project/stdlib/src/interfaces/proving-job-source.ts b/yarn-project/stdlib/src/interfaces/proving-job-source.ts index a05573791b20..0af2f09a0932 100644 --- a/yarn-project/stdlib/src/interfaces/proving-job-source.ts +++ b/yarn-project/stdlib/src/interfaces/proving-job-source.ts @@ -33,8 +33,8 @@ export interface ProvingJobSource { } export const ProvingJobSourceSchema: ApiSchemaFor = { - getProvingJob: z.function().args().returns(ProvingJob.optional()), - heartbeat: z.function().args(ProvingJobId).returns(z.void()), - resolveProvingJob: z.function().args(ProvingJobId, ProvingJobResult).returns(z.void()), - rejectProvingJob: z.function().args(ProvingJobId, z.string()).returns(z.void()), + getProvingJob: z.function({ input: z.tuple([]), output: ProvingJob.optional() }), + heartbeat: z.function({ input: z.tuple([ProvingJobId]), output: z.void() }), + resolveProvingJob: z.function({ input: z.tuple([ProvingJobId, ProvingJobResult]), output: z.void() }), + rejectProvingJob: z.function({ input: z.tuple([ProvingJobId, z.string()]), output: z.void() }), }; diff --git a/yarn-project/stdlib/src/interfaces/proving-job.ts b/yarn-project/stdlib/src/interfaces/proving-job.ts index 1a242da7974e..514770b3d8da 100644 --- a/yarn-project/stdlib/src/interfaces/proving-job.ts +++ b/yarn-project/stdlib/src/interfaces/proving-job.ts @@ -388,8 +388,8 @@ export type ProvingRequestResultFor = { type: T; r export const ProvingJobId = z.string(); -export const ProofUri = z.string().brand('ProvingJobUri'); -export type ProofUri = z.infer; +export type ProofUri = string & z.$brand<'ProvingJobUri'>; +export const ProofUri: ZodFor = z.string().transform(value => value as ProofUri); export type ProvingJobId = z.infer; @@ -400,7 +400,7 @@ type ProvingJobShape = { inputsUri: ProofUri; }; -export const ProvingJob: z.ZodType = z.object({ +export const ProvingJob: z.ZodType = z.object({ id: ProvingJobId, type: z.nativeEnum(ProvingRequestType), epochNumber: EpochNumberSchema, diff --git a/yarn-project/stdlib/src/interfaces/world_state.ts b/yarn-project/stdlib/src/interfaces/world_state.ts index a99bcc1fa35f..d02f05bf2366 100644 --- a/yarn-project/stdlib/src/interfaces/world_state.ts +++ b/yarn-project/stdlib/src/interfaces/world_state.ts @@ -92,7 +92,7 @@ export interface WorldStateSynchronizer extends ReadonlyWorldStateAccess, ForkMe clear(): Promise; } -export const WorldStateSyncStatusSchema: z.ZodType = z.object({ +export const WorldStateSyncStatusSchema: z.ZodType = z.object({ finalizedBlockNumber: BlockNumberSchema, latestBlockNumber: BlockNumberSchema, latestBlockHash: z.string(), diff --git a/yarn-project/stdlib/src/schemas/schemas.ts b/yarn-project/stdlib/src/schemas/schemas.ts index f32e0b2f6a34..4d59edab7c56 100644 --- a/yarn-project/stdlib/src/schemas/schemas.ts +++ b/yarn-project/stdlib/src/schemas/schemas.ts @@ -89,7 +89,10 @@ export const AbiDecodedSchema: ZodFor = z.union([ z.boolean(), schemas.AztecAddress, z.array(z.lazy(() => AbiDecodedSchema)), - z.record(z.lazy(() => AbiDecodedSchema)), + z.record( + z.string(), + z.lazy(() => AbiDecodedSchema), + ), ]); // C++ only supports null values, which we want to convert to undefined. @@ -103,6 +106,8 @@ export { hexSchemaFor, bufferSchemaFor, type ApiSchemaFor, + getSchemaParameters, + getSchemaReturnType, optional, mapSchema, pickFromSchema, diff --git a/yarn-project/stdlib/src/validators/schemas.ts b/yarn-project/stdlib/src/validators/schemas.ts index 1201aecfd05b..33a8de976c86 100644 --- a/yarn-project/stdlib/src/validators/schemas.ts +++ b/yarn-project/stdlib/src/validators/schemas.ts @@ -33,7 +33,7 @@ export const ValidatorStatusHistorySchema = zodFor()( export const ValidatorStatusHistorySchemaArray = z.array(ValidatorStatusHistorySchema); -export const ValidatorStatusHistorySchemaMap = z.record(ValidatorStatusHistorySchemaArray); +export const ValidatorStatusHistorySchemaMap = z.record(z.string(), ValidatorStatusHistorySchemaArray); const ValidatorTimeStatSchema = z.object({ timestamp: schemas.BigInt, @@ -64,7 +64,7 @@ export const ValidatorStatsSchema = zodFor()( export const ValidatorsStatsSchema = zodFor()( z.object({ - stats: z.record(ValidatorStatsSchema), + stats: z.record(z.string(), ValidatorStatsSchema), lastProcessedSlot: schemas.SlotNumber.optional(), initialSlot: schemas.SlotNumber.optional(), slotWindow: schemas.Integer, diff --git a/yarn-project/stdlib/src/versioning/versioning.test.ts b/yarn-project/stdlib/src/versioning/versioning.test.ts index 5cc668bc5801..5db246791712 100644 --- a/yarn-project/stdlib/src/versioning/versioning.test.ts +++ b/yarn-project/stdlib/src/versioning/versioning.test.ts @@ -53,7 +53,7 @@ describe('versioning', () => { describe('json-rpc', () => { type TestApi = { get: () => Promise }; - const TestApiSchema: ApiSchemaFor = { get: z.function().returns(z.number()) }; + const TestApiSchema: ApiSchemaFor = { get: z.function({ input: z.tuple([]), output: z.number() }) }; let context: JsonRpcTestContext; let versions: Partial; @@ -110,7 +110,7 @@ describe('versioning', () => { // Create a schema that expects a string parameter type TestApiWithParam = { getWithParam: (value: string) => Promise }; const TestApiWithParamSchema: ApiSchemaFor = { - getWithParam: z.function().args(z.string()).returns(z.number()), + getWithParam: z.function({ input: z.tuple([z.string()]), output: z.number() }), }; // Server handler with correct version diff --git a/yarn-project/txe/package.json b/yarn-project/txe/package.json index 9f39b19e10a7..db43d45ef508 100644 --- a/yarn-project/txe/package.json +++ b/yarn-project/txe/package.json @@ -75,7 +75,7 @@ "@aztec/simulator": "workspace:^", "@aztec/stdlib": "workspace:^", "@aztec/world-state": "workspace:^", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@jest/globals": "^30.0.0", diff --git a/yarn-project/txe/src/index.ts b/yarn-project/txe/src/index.ts index 408813fe153e..225e77f85a86 100644 --- a/yarn-project/txe/src/index.ts +++ b/yarn-project/txe/src/index.ts @@ -66,8 +66,11 @@ type TXEForeignCallInput = { const TXEForeignCallInputSchema = zodFor()( z.object({ + // Nargo generates session_id as a u64, which may exceed Number.MAX_SAFE_INTEGER. + // Zod 4's `.int()` enforces the safe-integer bound, so we drop it here and only require + // the value to be a non-negative number (it is used solely as a Map key). // eslint-disable-next-line camelcase - session_id: z.number().int().nonnegative(), + session_id: z.number().nonnegative(), function: z.string() as z.ZodType, // eslint-disable-next-line camelcase root_path: z.string(), @@ -266,7 +269,7 @@ class TXEDispatcher { const TXEDispatcherApiSchema: ApiSchemaFor = { // eslint-disable-next-line camelcase - resolve_foreign_call: z.function().args(TXEForeignCallInputSchema).returns(ForeignCallResultSchema), + resolve_foreign_call: z.function({ input: z.tuple([TXEForeignCallInputSchema]), output: ForeignCallResultSchema }), }; /** diff --git a/yarn-project/validator-ha-signer/package.json b/yarn-project/validator-ha-signer/package.json index fbbb272e6f9d..c8266d35483b 100644 --- a/yarn-project/validator-ha-signer/package.json +++ b/yarn-project/validator-ha-signer/package.json @@ -83,7 +83,7 @@ "node-pg-migrate": "^8.0.4", "pg": "^8.11.3", "tslib": "^2.4.0", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@electric-sql/pglite": "^0.3.14", diff --git a/yarn-project/wallet-sdk/src/extension/provider/extension_wallet.ts b/yarn-project/wallet-sdk/src/extension/provider/extension_wallet.ts index c42ed7fa0008..565a8b82d583 100644 --- a/yarn-project/wallet-sdk/src/extension/provider/extension_wallet.ts +++ b/yarn-project/wallet-sdk/src/extension/provider/extension_wallet.ts @@ -2,7 +2,7 @@ import type { ChainInfo } from '@aztec/aztec.js/account'; import { type Wallet, WalletSchema } from '@aztec/aztec.js/wallet'; import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise'; -import { schemaHasMethod } from '@aztec/foundation/schemas'; +import { getSchemaReturnType, schemaHasMethod } from '@aztec/foundation/schemas'; import type { FunctionsOf } from '@aztec/foundation/types'; import { type EncryptedPayload, decrypt, encrypt } from '../../crypto.js'; @@ -160,7 +160,7 @@ export class ExtensionWallet { type: prop.toString() as keyof FunctionsOf, args, }); - return WalletSchema[prop.toString() as keyof typeof WalletSchema].returnType().parseAsync(result); + return getSchemaReturnType(WalletSchema[prop.toString() as keyof typeof WalletSchema]).parseAsync(result); }; } else { return target[prop as keyof ExtensionWallet]; diff --git a/yarn-project/wallet-sdk/src/iframe/handlers/iframe_connection_handler.ts b/yarn-project/wallet-sdk/src/iframe/handlers/iframe_connection_handler.ts index fdb53c92f67b..774cd197aebe 100644 --- a/yarn-project/wallet-sdk/src/iframe/handlers/iframe_connection_handler.ts +++ b/yarn-project/wallet-sdk/src/iframe/handlers/iframe_connection_handler.ts @@ -17,7 +17,7 @@ import type { ChainInfo } from '@aztec/aztec.js/account'; import type { Wallet } from '@aztec/aztec.js/wallet'; import { WalletSchema } from '@aztec/aztec.js/wallet'; import { jsonStringify } from '@aztec/foundation/json-rpc'; -import { parseWithOptionals, schemaHasMethod } from '@aztec/foundation/schemas'; +import { getSchemaParameters, parseWithOptionals, schemaHasMethod } from '@aztec/foundation/schemas'; import { type EncryptedPayload, @@ -301,8 +301,7 @@ export class IframeConnectionHandler { if (!schemaHasMethod(WalletSchema, type)) { throw new Error(`Unknown wallet method: ${type}`); } - // Zod's AnyZodTuple rejects optional tuple items typed as `T | undefined` - const sanitizedArgs = await parseWithOptionals(args, WalletSchema[type].parameters() as any); + const sanitizedArgs = await parseWithOptionals(args, getSchemaParameters(WalletSchema[type])); result = await (wallet as Record Promise>)[type](...sanitizedArgs); } catch (err: unknown) { error = err instanceof Error ? err.message : String(err); diff --git a/yarn-project/wallet-sdk/src/iframe/provider/iframe_wallet.ts b/yarn-project/wallet-sdk/src/iframe/provider/iframe_wallet.ts index 47a72cf14ef2..4ea733bd6ae6 100644 --- a/yarn-project/wallet-sdk/src/iframe/provider/iframe_wallet.ts +++ b/yarn-project/wallet-sdk/src/iframe/provider/iframe_wallet.ts @@ -10,7 +10,7 @@ import type { ChainInfo } from '@aztec/aztec.js/account'; import { type Wallet, WalletSchema } from '@aztec/aztec.js/wallet'; import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise'; -import { schemaHasMethod } from '@aztec/foundation/schemas'; +import { getSchemaReturnType, schemaHasMethod } from '@aztec/foundation/schemas'; import type { FunctionsOf } from '@aztec/foundation/types'; import { type EncryptedPayload, decrypt, encrypt } from '../../crypto.js'; @@ -153,7 +153,7 @@ export class IframeWallet { type: prop.toString() as keyof FunctionsOf, args, }); - return WalletSchema[prop.toString() as keyof typeof WalletSchema].returnType().parseAsync(result); + return getSchemaReturnType(WalletSchema[prop.toString() as keyof typeof WalletSchema]).parseAsync(result); }; } else { return target[prop as keyof IframeWallet]; diff --git a/yarn-project/world-state/package.json b/yarn-project/world-state/package.json index 1e095490f2c9..b269fcaf85a7 100644 --- a/yarn-project/world-state/package.json +++ b/yarn-project/world-state/package.json @@ -74,7 +74,7 @@ "@aztec/telemetry-client": "workspace:^", "msgpackr": "^1.11.2", "tslib": "^2.4.0", - "zod": "^3.23.8" + "zod": "^4" }, "devDependencies": { "@aztec/archiver": "workspace:^", diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index a3a4ead7d03e..4c76b9a61b4f 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -744,7 +744,7 @@ __metadata: tslib: "npm:^2.5.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -822,7 +822,7 @@ __metadata: typescript: "npm:^5.3.3" util: "npm:^0.12.5" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -984,7 +984,7 @@ __metadata: tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" bin: blob-client: ./dest/client/bin/index.js languageName: unknown @@ -1039,7 +1039,7 @@ __metadata: tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1270,7 +1270,7 @@ __metadata: typescript: "npm:^5.3.3" util: "npm:^0.12.5" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1289,7 +1289,7 @@ __metadata: ts-node: "npm:^10.9.1" tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1313,7 +1313,7 @@ __metadata: tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1342,7 +1342,7 @@ __metadata: tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1402,7 +1402,7 @@ __metadata: typescript-eslint: "npm:^8.32.1" undici: "npm:^5.28.5" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1547,7 +1547,7 @@ __metadata: tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -1827,7 +1827,7 @@ __metadata: ts-node: "npm:^10.9.1" tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -2046,7 +2046,7 @@ __metadata: tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -2104,7 +2104,7 @@ __metadata: typescript: "npm:^5.3.3" viem: "npm:@aztec/viem@2.38.2" vitest: "npm:^4.0.0" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -2166,7 +2166,7 @@ __metadata: jest-mock-extended: "npm:^4.0.0" ts-node: "npm:^10.9.1" typescript: "npm:^5.3.3" - zod: "npm:^3.23.8" + zod: "npm:^4" bin: txe: ./dest/bin/index.js languageName: unknown @@ -2235,7 +2235,7 @@ __metadata: ts-node: "npm:^10.9.1" tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -2308,7 +2308,7 @@ __metadata: ts-node: "npm:^10.9.1" tslib: "npm:^2.4.0" typescript: "npm:^5.3.3" - zod: "npm:^3.23.8" + zod: "npm:^4" languageName: unknown linkType: soft @@ -22084,7 +22084,7 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.23.8, zod@npm:^3.24.1, zod@npm:^3.24.2": +"zod@npm:^3.24.1, zod@npm:^3.24.2": version: 3.25.76 resolution: "zod@npm:3.25.76" checksum: 10/f0c963ec40cd96858451d1690404d603d36507c1fc9682f2dae59ab38b578687d542708a7fdbf645f77926f78c9ed558f57c3d3aa226c285f798df0c4da16995 @@ -22097,3 +22097,10 @@ __metadata: checksum: 10/25fc0f62e01b557b4644bf0b393bbaf47542ab30877c37837ea8caf314a8713d220c7d7fe51f68ffa72f0e1018ddfa34d96f1973d23033f5a2a5a9b6b9d9da01 languageName: node linkType: hard + +"zod@npm:^4": + version: 4.4.3 + resolution: "zod@npm:4.4.3" + checksum: 10/804b9a42aa8f35f2b3c5a8dff906291cb749115f83ee2afe3576d70b5b5c53c965365c7f4967690647a9c54af9838ff232a85ff9577a0a36c44b68bc6cdefe36 + languageName: node + linkType: hard