import { ZoneRpcAuthentication } from 'ox/tempo' import { defineChain, type Chain } from 'viem' import { tempoTestnet } from 'viem/tempo/chains' import type * as Auth from './Auth.js' import * as Viem from './Viem.js' /** Anonymous (public) request principal. */ const publicPrincipal: Auth.Principal = { id: 'pub', type: 'public' } /** Authenticated API-key request principal. */ const apiKeyPrincipal: Auth.Principal = { apiKey: {} as never, environment: 'production', id: 'key_test', orgId: 'org_test', type: 'api_key', } const zone = defineChain({ ...tempoTestnet, contracts: { ...tempoTestnet.contracts, messenger: { address: '0x0000000000000000000000000000000000000001' }, portal: { address: '0x0000000000000000000000000000000000000002' }, }, id: 421_700_001, name: 'Zone E', rpcUrls: { default: { http: ['https://zone.rpc.test'] }, internal: { http: ['https://internal.zone.rpc.test'] }, }, sourceId: tempoTestnet.id, }) satisfies Chain describe('isMainnet', () => { test('is true only for the mainnet chain id', () => { expect(Viem.isMainnet(Viem.chainId.mainnet)).toBe(true) expect(Viem.isMainnet(Viem.chainId.testnet)).toBe(false) expect(Viem.isMainnet(31337)).toBe(false) }) test('mainnet is the default chain', () => { expect(Viem.defaultChainId).toBe(Viem.chainId.mainnet) }) }) describe('configuredChainIds', () => { test('returns ids from object and serialized URL maps', () => { expect(Viem.configuredChainIds({ 31_318: 'https://nextfork.tidx.test' })).toEqual([31_318]) expect( Viem.configuredChainIds( JSON.stringify({ 31_318: 'https://nextfork.tidx.test', 421_700_002: 'https://zone.tidx.test', }), ), ).toEqual([31_318, 421_700_002]) }) test('returns no ids for shared URLs and dynamic resolvers', () => { expect(Viem.configuredChainIds('https://tidx.test')).toEqual([]) expect(Viem.configuredChainIds(() => 'https://tidx.test')).toEqual([]) }) test('rejects malformed chain-id maps', () => { for (const chainId of ['-1', '0', '031318', '0x7a56', '1e3', '9007199254740992', 'devnet']) expect(() => Viem.configuredChainIds(JSON.stringify({ [chainId]: 'https://tidx.test' })), ).toThrow('Expected a URL or a chain-id-to-URL JSON object.') }) }) describe('resolveRpc', () => { test('defaults to the per-chain RPC URL', () => { expect(Viem.resolveRpc(undefined, { chainId: 4217, principal: null })).toMatchInlineSnapshot(` { "basicAuth": undefined, "url": "https://rpc.tempo.xyz", } `) expect(Viem.resolveRpc(undefined, { chainId: 42431, principal: null })).toMatchInlineSnapshot(` { "basicAuth": undefined, "url": "https://rpc.testnet.tempo.xyz", } `) }) test('uses a static config override', () => { expect( Viem.resolveRpc( { auth: 'user:pass', url: (chainId) => `https://${chainId}.rpc.test` }, { chainId: 4217, principal: null }, ), ).toMatchInlineSnapshot(` { "basicAuth": "user:pass", "url": "https://4217.rpc.test", } `) }) test('selects RPC URLs by chain id', () => { const rpc = { publicZoneUrl: JSON.stringify({ 421_700_001: 'https://public.zone.rpc.test' }), url: JSON.stringify({ 4217: 'https://mainnet.rpc.test' }), } expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: null })).toMatchInlineSnapshot(` { "basicAuth": undefined, "url": "https://mainnet.rpc.test", } `) expect(Viem.resolveRpc(rpc, { chainId: zone.id, principal: null, zone })) .toMatchInlineSnapshot(` { "basicAuth": undefined, "publicZoneUrl": "https://public.zone.rpc.test", "url": "https://internal.zone.rpc.test", } `) }) test('selects auth and scheme by chain id', () => { const rpc = { auth: { 4217: 'mainnet:secret', 42431: 'testnet-token' } } expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: null }).basicAuth).toBe( 'mainnet:secret', ) expect(Viem.resolveRpc(rpc, { chainId: 42431, principal: null }).bearerAuth).toBe( 'testnet-token', ) expect( Viem.resolveRpc(rpc, { chainId: 421_700_001, principal: null }).basicAuth, ).toBeUndefined() }) test('parses serialized Basic auth by chain id', () => { const rpc = { auth: JSON.stringify({ 4217: 'mainnet:secret' }) } expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: null }).basicAuth).toBe( 'mainnet:secret', ) expect(Viem.resolveRpc(rpc, { chainId: 42431, principal: null }).basicAuth).toBeUndefined() }) test('the static form ignores the principal', () => { const rpc = { auth: 'user:pass', url: () => 'https://internal.rpc' } expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: publicPrincipal })) .toMatchInlineSnapshot(` { "basicAuth": "user:pass", "url": "https://internal.rpc", } `) expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: apiKeyPrincipal })) .toMatchInlineSnapshot(` { "basicAuth": "user:pass", "url": "https://internal.rpc", } `) }) test('the resolver form routes anonymous callers to a separate upstream', () => { const rpc = ({ principal }: Viem.resolveRpc.Context) => principal?.type === 'public' ? { url: 'https://rpc.tempo.xyz' } : { auth: 'user:pass', url: 'https://internal.rpc' } expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: publicPrincipal })) .toMatchInlineSnapshot(` { "basicAuth": undefined, "url": "https://rpc.tempo.xyz", } `) expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: apiKeyPrincipal })) .toMatchInlineSnapshot(` { "basicAuth": "user:pass", "url": "https://internal.rpc", } `) }) test('a null principal (trusted poller) takes the non-public branch', () => { const rpc = ({ principal }: Viem.resolveRpc.Context) => principal?.type === 'public' ? { url: 'https://rpc.tempo.xyz' } : { auth: 'user:pass', url: 'https://internal.rpc' } expect(Viem.resolveRpc(rpc, { chainId: 4217, principal: null })).toMatchInlineSnapshot(` { "basicAuth": "user:pass", "url": "https://internal.rpc", } `) }) test('a resolver that omits url falls back to the built-in public host', () => { const rpc = () => ({}) expect(Viem.resolveRpc(rpc, { chainId: 42431, principal: publicPrincipal })) .toMatchInlineSnapshot(` { "basicAuth": undefined, "url": "https://rpc.testnet.tempo.xyz", } `) }) test('a resolver that omits url falls back to the Zone internal host', () => { expect(Viem.resolveRpc(() => ({}), { chainId: zone.id, principal: publicPrincipal, zone })) .toMatchInlineSnapshot(` { "basicAuth": undefined, "publicZoneUrl": "https://zone.rpc.test", "url": "https://internal.zone.rpc.test", } `) }) }) describe('getClient', () => { test('disables CCIP-Read', () => { expect(Viem.getClient({ chainId: 4217 }).ccipRead).toBe(false) }) test('disables multicall for Zones', () => { const l1Client = Viem.getClient({ chainId: 4217 }) const zoneClient = Viem.getClient({ chainId: zone.id, zone }) expect(l1Client.batch?.multicall).toEqual({ deployless: true }) expect(zoneClient.batch?.multicall).toBe(false) }) test('sends inferred Bearer auth', async () => { const fetch = vi .spyOn(globalThis, 'fetch') .mockResolvedValue(Response.json({ id: 1, jsonrpc: '2.0', result: '0x1079' })) try { const client = Viem.getClient({ chainId: 4217, rpc: { auth: 'rpc-token', url: 'https://internal.rpc.test' }, }) await client.getChainId() const [input, init] = fetch.mock.calls[0]! const upstream = new Request(input, init) expect(upstream.headers.get('authorization')).toBe('Bearer rpc-token') } finally { fetch.mockRestore() } }) test('does not send RPC auth to a public Zone URL', async () => { const fetch = vi .spyOn(globalThis, 'fetch') .mockResolvedValue(Response.json({ id: 1, jsonrpc: '2.0', result: '0x1079' })) try { const client = Viem.getClient({ chainId: zone.id, rpc: { auth: 'rpc:secret', publicZoneUrl: 'https://public.zone.rpc.test', url: 'https://internal.rpc.test', }, zone, zoneToken: 'zone-token', }) await client.getChainId() const [input, init] = fetch.mock.calls[0]! const upstream = new Request(input, init) expect(upstream.url).toBe('https://public.zone.rpc.test/') expect(upstream.headers.get('authorization')).toBeNull() expect(upstream.headers.get(ZoneRpcAuthentication.headerName)).toBe('zone-token') } finally { fetch.mockRestore() } }) test('sends Zone headers to both internal and public Zone URLs', async () => { const fetch = vi .spyOn(globalThis, 'fetch') .mockResolvedValue(Response.json({ id: 1, jsonrpc: '2.0', result: '0x1079' })) try { const client = Viem.getClient({ chainId: zone.id, rpc: { publicZoneUrl: 'https://public.zone.rpc.test', zoneHeaders: { 'CF-Access-Client-Id': 'client-id', 'CF-Access-Client-Secret': 'client-secret', }, }, zone, zoneToken: 'zone-token', }) await client.getChainId() const [input, init] = fetch.mock.calls[0]! const upstream = new Request(input, init) expect(upstream.headers.get('CF-Access-Client-Id')).toBe('client-id') expect(upstream.headers.get('CF-Access-Client-Secret')).toBe('client-secret') } finally { fetch.mockRestore() } }) }) describe('createGetClient', () => { test('memoizes one client per resolved upstream', () => { const getClient = Viem.createGetClient({ rpc: ({ principal }) => principal?.type === 'public' ? { url: 'https://rpc.tempo.xyz' } : { auth: 'user:pass', url: 'https://internal.rpc' }, }) expect(getClient(4217, apiKeyPrincipal)).toBe(getClient(4217, apiKeyPrincipal)) expect(getClient(4217, publicPrincipal)).toBe(getClient(4217, publicPrincipal)) expect(getClient(4217, publicPrincipal)).not.toBe(getClient(4217, apiKeyPrincipal)) expect(getClient(4217, apiKeyPrincipal)).not.toBe(getClient(42431, apiKeyPrincipal)) }) test('shares a client across principals when they resolve identically', () => { const getClient = Viem.createGetClient() expect(getClient(4217, publicPrincipal)).toBe(getClient(4217, apiKeyPrincipal)) expect(getClient(4217, null)).toBe(getClient(4217, publicPrincipal)) }) test('consults the resolver on cache hits', () => { const seen: (string | undefined)[] = [] const getClient = Viem.createGetClient({ rpc: ({ principal }) => { seen.push(principal?.type) return { url: 'https://internal.rpc' } }, }) const first = getClient(4217, apiKeyPrincipal) const second = getClient(4217, apiKeyPrincipal) getClient(4217, publicPrincipal) expect(seen).toMatchInlineSnapshot(` [ "api_key", "api_key", "public", ] `) expect(first).toBe(second) }) })