# Connect to Arkiv

<NetworkNote />

You reach Arkiv through two clients. A public client reads: it queries entities and watches events, and needs no account. A wallet client writes: it signs and sends transactions with an account. Both are [viem clients](https://viem.sh/docs/clients/intro) with Arkiv’s actions added, so they take a chain and a transport like any viem client.

## Make the chain

`rabdi` makes the chain from your [access key](https://docs.arkiv.network/start-here/access-keys/). Arkiv’s public RPC is heavily rate limited to prevent abuse, so get a free key from the [Arkiv Hub](https://hub.arkiv.network/access-keys):

```ts
import { rabdi } from "@arkiv-network/sdk/chains"

const chain = rabdi({ accessKey: process.env.ARKIV_ACCESS_KEY ?? "" })
```

With `accessKey: ""`, the chain uses the public RPC and logs a warning. In a browser app, read the key from your bundler’s public environment variables and [lock it to your site](https://docs.arkiv.network/start-here/access-keys/#lock-the-key-down). The examples below use this `chain`.

## Read with a public client

```ts
import { createPublicClient } from "@arkiv-network/sdk"
import { http } from "viem"

const publicClient = createPublicClient({ chain, transport: http() })
```

A public client holds no account, so it’s safe in the browser. `http()` with no URL uses the chain’s RPC URL, which carries your access key.

<RpcTerms />

## Write from a server

On a server, sign with a private key. Keep the key in an environment variable or a secret store, never in code:

```ts
import { createWalletClient } from "@arkiv-network/sdk"
import { http, type Hex } from "viem"
import { privateKeyToAccount } from "viem/accounts"

const walletClient = createWalletClient({
  chain,
  transport: http(),
  account: privateKeyToAccount(process.env.PRIVATE_KEY as Hex),
})
```

## Write from a browser wallet

In the browser, let the user’s wallet sign. Pass the wallet’s provider as a `custom` transport and the user’s address as the account:

```ts
import { createWalletClient } from "@arkiv-network/sdk"
import { custom } from "viem"

const [address] = await window.ethereum.request({
  method: "eth_requestAccounts",
})
const walletClient = createWalletClient({
  chain,
  transport: custom(window.ethereum),
  account: address,
})
```

This connects to the wallet directly. In an app that uses wagmi, such as one built with RainbowKit, [build the client from wagmi’s connection](https://docs.arkiv.network/guides/react/) instead.

The wallet asks the user to approve every write, and it has to be on Rabdi when it does. `addChain` adds Rabdi to the wallet and asks the user to switch to it. Add the chain without your access key:

```ts
import { rabdi } from "@arkiv-network/sdk/chains"

await walletClient.addChain({ chain: rabdi({ accessKey: "" }) })
```

<RpcTerms />

## Read and write with one setup

A wallet client has only the write actions. Keep a public client next to it for reads. Both can share the transport settings:

```ts
const transport = http()
const publicClient = createPublicClient({ chain, transport })
const walletClient = createWalletClient({ chain, transport, account })
```