import { RpcSchema } from 'ox' import { z } from 'ox/zod' import { expectTypeOf, test } from 'vp/test' test('ToViem: converts ox schema to viem schema', () => { type OxSchema = | { Request: { method: 'eth_blockNumber'; params?: undefined } ReturnType: `0x${string}` } | { Request: { method: 'eth_chainId'; params?: undefined } ReturnType: `0x${string}` } type Result = RpcSchema.ToViem expectTypeOf().toMatchTypeOf< readonly { Method: string Parameters?: unknown ReturnType: unknown }[] >() type Item = Result[number] expectTypeOf().toEqualTypeOf< 'eth_blockNumber' | 'eth_chainId' >() }) test('ToViem: preserves params', () => { type OxSchema = { Request: { method: 'eth_getBalance' params: [address: `0x${string}`, block: string] } ReturnType: `0x${string}` } type Result = RpcSchema.ToViem expectTypeOf().toEqualTypeOf<'eth_getBalance'>() expectTypeOf().toEqualTypeOf< [address: `0x${string}`, block: string] >() expectTypeOf().toEqualTypeOf<`0x${string}`>() }) test('FromViem: converts viem schema to ox schema', () => { type ViemSchema = [ { Method: 'eth_blockNumber' Parameters?: undefined ReturnType: `0x${string}` }, { Method: 'eth_chainId' Parameters?: undefined ReturnType: `0x${string}` }, ] type Result = RpcSchema.FromViem expectTypeOf().toMatchTypeOf() type BlockNumber = Extract expectTypeOf().toEqualTypeOf<`0x${string}`>() }) test('FromViem: preserves params', () => { type ViemSchema = [ { Method: 'eth_getBalance' Parameters: [address: `0x${string}`, block: string] ReturnType: `0x${string}` }, ] type Result = RpcSchema.FromViem type Item = Extract expectTypeOf().toEqualTypeOf< [address: `0x${string}`, block: string] >() expectTypeOf().toEqualTypeOf<`0x${string}`>() }) test('roundtrip: ToViem -> FromViem preserves schema', () => { type Original = { Request: { method: 'eth_getBalance' params: [address: `0x${string}`, block: string] } ReturnType: `0x${string}` } type Roundtrip = RpcSchema.FromViem> type Item = Extract expectTypeOf().toEqualTypeOf<'eth_getBalance'>() expectTypeOf().toEqualTypeOf<`0x${string}`>() }) test('roundtrip: FromViem -> ToViem preserves schema', () => { type Original = [ { Method: 'eth_blockNumber' Parameters?: undefined ReturnType: `0x${string}` }, ] type Roundtrip = RpcSchema.ToViem> expectTypeOf().toEqualTypeOf<'eth_blockNumber'>() expectTypeOf().toEqualTypeOf<`0x${string}`>() }) test('FromZod: derives Generic from a record of zod schemas', () => { const namespace = { eth_blockNumber: { params: z.optional(z.tuple([])), returns: z.Hex.Hex, }, abe_foo: { params: z.tuple([z.number()]), returns: z.string(), }, } type Schema = RpcSchema.FromZod type MethodName = RpcSchema.ExtractMethodName expectTypeOf().toEqualTypeOf<'eth_blockNumber' | 'abe_foo'>() expectTypeOf< RpcSchema.ExtractReturnType >().toEqualTypeOf<`0x${string}`>() expectTypeOf< RpcSchema.ExtractReturnType >().toEqualTypeOf() expectTypeOf>().toEqualTypeOf< [number] >() }) test('FromZod: accepts an ox/zod namespace', () => { type Schema = RpcSchema.FromZod expectTypeOf< RpcSchema.ExtractReturnType >().toEqualTypeOf<`0x${string}`>() }) test('ToGeneric: resolves a zod namespace to a Generic', () => { const namespace = { abe_foo: { params: z.tuple([z.number()]), returns: z.string(), }, } type Schema = RpcSchema.ToGeneric expectTypeOf< RpcSchema.ExtractReturnType >().toEqualTypeOf() expectTypeOf>().toEqualTypeOf< [number] >() }) test('ToGeneric: passes a Generic through', () => { type Schema = RpcSchema.ToGeneric<{ Request: { method: 'abe_bar'; params: [id: string] } ReturnType: string }> expectTypeOf< RpcSchema.ExtractReturnType >().toEqualTypeOf() }) test('ToGeneric: falls back to Default for undefined', () => { expectTypeOf< RpcSchema.ToGeneric >().toEqualTypeOf() }) test('from: no-arg type tag still works', () => { const schema = RpcSchema.from< | RpcSchema.Default | { Request: { method: 'abe_bar'; params: [id: string] } ReturnType: string } >() expectTypeOf< RpcSchema.ExtractReturnType >().toEqualTypeOf() }) test('eth_call accepts a 4-tuple with state + block overrides', () => { type Params = RpcSchema.ExtractParams expectTypeOf< [ transaction: { to: `0x${string}` }, block: 'latest', stateOverrides: {}, blockOverrides: { number: `0x${string}` }, ] >().toExtend() })