# Connect to a Tempo Zone on testnet

Connect to a Tempo Zone to read your private balance and submit Zone transactions. Your account signs an authorization token so the RPC can scope requests to you.

To connect directly, you need a Tempo account, the Zone's RPC URL and chain metadata, and any endpoint credentials supplied by its operator. The interactive guides handle the connection and authorization for you.

The guides use two shared Zones on Tempo Testnet named Zone A and Zone B.

## Create a Viem client

Use `zoneModerato(...)` from `viem/tempo/zones` for these examples. Zone A and Zone B run an earlier testnet deployment with interfaces that differ from current Tempo Zones. Review the [testnet compatibility notes](https://tempo.xyz/developers/docs/guide/private-zones#testnet-compatibility) before adapting this setup to another deployment.

Obtain [RPC access from Tempo](https://tempo.xyz/contact) before connecting to the shared endpoints directly. The server-side example below reads the operator-provided HTTP `Authorization` header from `ZONE_RPC_AUTHORIZATION`. This endpoint access is separate from the signed `X-Authorization-Token`, which is required even for chain metadata reads.

The example signs that token with an ephemeral account for metadata reads; use your actual account when reading private balances. See [RPC access control](https://tempo.xyz/developers/docs/protocol/zones/rpc) for the token format and scoped methods.

The chain IDs below are the legacy SDK configuration. Confirm the endpoint's `eth_chainId` matches before signing; do not derive current deployment IDs with this older SDK.

```ts
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
import { createClient } from 'viem/tempo'
import { http, zoneModerato } from 'viem/tempo/zones'

const rpcUrl = 'https://rpc-zone-a.testnet.tempo.xyz'
const authorization = process.env.ZONE_RPC_AUTHORIZATION
if (!authorization) throw new Error('Set ZONE_RPC_AUTHORIZATION from your zone operator.')

const zoneClient = createClient({
  account: privateKeyToAccount(generatePrivateKey()),
  chain: zoneModerato(6),
  transport: http(rpcUrl, {
    fetchOptions: { headers: { Authorization: authorization } },
  }),
})

await zoneClient.zone.signAuthorizationToken()

const chainId = await zoneClient.getChainId()
if (chainId !== zoneClient.chain.id) throw new Error('Zone chain ID does not match the client.')

const blockNumber = await zoneClient.getBlockNumber()
console.log(blockNumber)
```

For browser integrations, the RPC gateway must allow `X-Authorization-Token` in its CORS headers. These demos relay requests through the docs server because the shared testnet gateways do not currently allow that header in browsers. The relay preserves your signed token and account-scoped access.

<a id="direct-connection-details" />

## Legacy testnet connection details

### Zone A

| **Property** | **Value** |
|-------------------|-------|
| **Network Name** | Zone A |
| **Zone ID** | `6` |
| **Chain ID** | `4217000006` |
| **HTTP URL** | `https://rpc-zone-a.testnet.tempo.xyz` |
| **Portal Address** | `0x7069DeC4E64Fd07334A0933eDe836C17259c9B23` |
| **Outbox Address** | `0x1c00000000000000000000000000000000000002` |

### Zone B

| **Property** | **Value** |
|-------------------|-------|
| **Network Name** | Zone B |
| **Zone ID** | `7` |
| **Chain ID** | `4217000007` |
| **HTTP URL** | `https://rpc-zone-b.testnet.tempo.xyz` |
| **Portal Address** | `0x3F5296303400B56271b476F5A0B9cBF74350D6Ac` |
| **Outbox Address** | `0x1c00000000000000000000000000000000000002` |

Zones do not expose a public block explorer for private activity. Use authenticated RPC reads instead.
