# createConfig

Creates an immutable configuration used by every Core action.

## Import

```ts
import { createConfig } from "@ensforge/core";
```

## Usage

### viem

```ts [config.ts]
// [!include ~/snippets/core/config.ts]
```

### Wagmi

:::code-group
```ts [config.ts]
import { createWagmiConfig } from "@ensforge/core/wagmi";
import { wagmiConfig } from "./wagmi";

const config = createWagmiConfig({
  network: "mainnet",
  wagmiConfig,
});
```

```ts [config.ts]
// [!include ~/snippets/wagmi/config.ts]
```
:::

The scoped adapter keeps Wagmi out of viem-only dependency graphs. Install `wagmi` only when using
`@ensforge/core/wagmi`.

## Custom deployments

Pass a custom network object to use ENS-compatible contracts on another chain, a local node, or
an alternate deployment on an existing chain. Preset strings continue to select their built-in
profiles.

```ts
import { createConfig, type CustomEnsNetwork, type EnsV1DeploymentConfig } from "@ensforge/core";
import { publicClient } from "./client";
import { addresses } from "./deployment";

const v1 = {
  contracts: {
    registry: addresses.registry,
    baseRegistrar: addresses.baseRegistrar,
    ethRegistrarController: addresses.ethRegistrarController,
    bulkRenewal: addresses.bulkRenewal,
    priceOracle: addresses.priceOracle,
    nameWrapper: addresses.nameWrapper,
    publicResolver: addresses.publicResolver,
    universalResolver: addresses.universalResolver,
    reverseRegistrar: addresses.reverseRegistrar,
    defaultReverseRegistrar: addresses.defaultReverseRegistrar,
    dnsRegistrar: addresses.dnsRegistrar,
    dnssecOracle: addresses.dnssecOracle,
    offchainDnsResolver: addresses.offchainDnsResolver,
  },
} satisfies EnsV1DeploymentConfig;

const network = {
  id: "local-ens",
  chainId: 31337,
  protocol: "v1",
  v1,
} satisfies CustomEnsNetwork;

const config = createConfig({ network, publicClient });
```

For V2, supply its complete address groups. V1 is optional and enables legacy routing and migration
operations that require both deployments:

```ts
import type { CustomEnsNetwork, EnsV2DeploymentConfig } from "@ensforge/core";
import { v1, contracts, implementations, migration, infrastructure } from "./deployment";

const v2 = {
  contracts,
  implementations,
  migration,
  infrastructure,
} satisfies EnsV2DeploymentConfig;
const network = {
  id: "local-ens-v2",
  chainId: 31337,
  protocol: "v2",
  v2,
  v1,
} satisfies CustomEnsNetwork;
```

`EnsV1DeploymentConfig` and `EnsV2DeploymentConfig` reuse the address groups from
`@ensforge/contracts/deployments`. V1's `wrappedEthRegistrarController`, V2's
`infrastructure.managedUniversalResolverProxy`, and V2's `experimental` and `testTokens` groups
remain optional. Other contract groups are required; partial deployments are not supported.
`status` defaults to `"active"`; `provenance` is optional. Runtime deployment IDs are derived as
`<network.id>:v1` and `<network.id>:v2`.

Use a unique network ID for each deployment. IDs start with a letter or digit and contain only
letters, digits, dots, underscores, and hyphens; `mainnet` and `sepolia` are reserved. The chain ID
must be a positive safe integer and match the configured public and wallet clients. Address
validation checks format, not deployed bytecode or ABI compatibility. Custom contracts must
implement the ENS interfaces supported by ensforge. For batched reads, configure the Viem chain's
`contracts.multicall3` with a deployed Multicall3 address, or configure the client for deployless
Multicall on an RPC that supports it. ENS contract addresses do not configure Multicall3.

Custom address groups are copied and frozen. Changing the original input does not change an
existing config. `config.network` resolves to the custom ID and `config.chainId` to its chain ID.

Custom networks have no default indexer endpoints and indexing is disabled until an endpoint is
provided. To enable an ENS-compatible indexer, pass `indexer: { endpoints: { v1: indexerUrl } }`
or a V2 endpoint. `indexer: false` always disables it. Public preset endpoints are never inherited.

The same `network` object works with `createWagmiConfig`, `new Ensforge`, and the SDK's
`createEnsforge` Wagmi adapter. Wagmi must include the custom chain in its `chains` and `transports`.

## Parameters

```ts
import type { CreateConfigParameters } from "@ensforge/core";
```

### network

`"mainnet" | "sepolia" | CustomEnsNetwork`

Selects the chain and ENS deployment profile. The supplied client must use the same chain.

### publicClient

`PublicClient | undefined`

Viem client used for reads, simulation, receipts, and event queries.

### walletClient

`WalletClient | undefined`

Default viem wallet client used by writes. It can be omitted for read-only applications or supplied
per action where supported.

### reads

`ReadOptions | undefined`

Default concurrency and Multicall sizing. See [`Config`](/core/api/config#reads).

### writes

`WriteOptions | undefined`

Default simulation, confirmation, and status retry policies. See [`Config`](/core/api/config#writes).

### gateways

`GatewayOptions | undefined`

Network policy for HTTP resources reached through avatar, content, metadata, or DNS workflows. See
[`Config`](/core/api/config#gateways).

### indexer

`IndexerConfig | false | undefined`

Configures the ENS indexers used by actions from `@ensforge/core/indexer`. Override the V1 or V2
GraphQL endpoint, attach request headers, or tune timeout, retry, failure, and pagination policies.
Set this option to `false` for an RPC-only application.

```ts
const config = createConfig({
  network: "mainnet",
  publicClient,
  indexer: {
    endpoints: { v1: process.env.ENS_V1_INDEXER_URL },
    headers: { Authorization: `Bearer ${process.env.INDEXER_TOKEN}` },
    failureMode: "partial",
  },
});
```

See [`Config`](/core/api/config#indexer).

## Return Type

```ts
import type { EnsforgeConfig } from "@ensforge/core";
```

An immutable `EnsforgeConfig`. It contains the resolved network, clients, policies, deployment
profile, and internal Effect services required by actions.

## Error

Throws `ConfigError` (`INVALID_CUSTOM_NETWORK` for invalid custom profiles) when the network is unsupported, a client uses the wrong chain, a required
client is missing, or an option is invalid.
