> For the complete documentation index, see [llms.txt](https://canary-1.gitbook.io/canary/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://canary-1.gitbook.io/canary/integrate/configuration-file.md).

# Integration guide: configuration file

The recommended integration path. One configuration file and one wire command.

If your application is built on the LayerZero devtools or Hardhat toolbox, this is the simplest way to configure DVNs. Cross-check against the live LayerZero documentation, which is the source of truth for the toolbox API. Most production teams are live on testnet in an afternoon and on mainnet within a few days of testing.

{% hint style="info" %}
This guide is an example. Do your own due diligence on the providers you choose, and verify every address and setting against the sources of truth before mainnet.
{% endhint %}

## 1. Install the toolbox

```bash
pnpm add -D @layerzerolabs/toolbox-hardhat @layerzerolabs/metadata-tools
```

## 2. Define the DVN set

Define the DVN set in `layerzero.config.ts`. Names are resolved to per-chain addresses by the LayerZero metadata service, so you do not need to hardcode addresses unless you want to verify them manually.

{% code title="layerzero.config.ts" %}

```typescript
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { generateConnectionsConfig } from '@layerzerolabs/metadata-tools'

const ETHEREUM_CONTRACT = {
    eid: EndpointId.ETHEREUM_V2_MAINNET,
    contractName: 'MyOApp',
}

const ARBITRUM_CONTRACT = {
    eid: EndpointId.ARBITRUM_V2_MAINNET,
    contractName: 'MyOApp',
}

// Set enforced options per your application's execution needs.
const enforcedOptions = []

// Primary recommendation: 4-of-5.
// All 3 required DVNs must sign, plus at least 1 of 2 optional DVNs.
// Replace YOUR_CHOSEN_DVN with your pick from the recommended list.
const DVN_CONFIG = {
    requiredDVNs: ['Canary', 'LayerZero Labs', 'Deutsche Telekom'],
    optionalDVNs: ['Horizen', 'YOUR_CHOSEN_DVN'],
    optionalDVNThreshold: 1,
}

const pathways = [
    [
        ETHEREUM_CONTRACT,
        ARBITRUM_CONTRACT,
        [DVN_CONFIG.requiredDVNs, [DVN_CONFIG.optionalDVNs, DVN_CONFIG.optionalDVNThreshold]],
        [15, 20], // [Ethereum confirmations, Arbitrum confirmations]
        [enforcedOptions, enforcedOptions],
    ],
    // Add a pathway for every source-destination pair your application uses.
]

export default async function () {
    const connections = await generateConnectionsConfig(pathways)
    return {
        contracts: [{ contract: ETHEREUM_CONTRACT }, { contract: ARBITRUM_CONTRACT }],
        connections,
    }
}
```

{% endcode %}

The confirmation values above are illustrative. Canary enforces its own per-chain floor regardless of the value you set, as described on [Confirmation floors](/canary/how-it-works/confirmation-floors.md).

## 3. Apply the configuration

```bash
pnpm hardhat lz:oapp:wire --oapp-config layerzero.config.ts
```

The wire command compares your current onchain configuration against the target, generates the required `setSendLibrary`, `setReceiveLibrary` and `setConfig` transactions, and prompts your admin multisig or deployer key to sign them.

## 4. Verify the live configuration

Read the configuration back rather than assuming it.

```bash
pnpm hardhat lz:oapp:config:get --oapp-config layerzero.config.ts
```

This reads the current onchain settings through `getConfig` and prints them for review. Confirm the same settings on LayerZero Scan for every pathway, in both directions.

## Next

* Not using the toolbox, or integrating from a non-EVM environment? Use [direct contract calls](/canary/integrate/direct-contract-calls.md).
* Before mainnet, read [Confirmation counts and common pitfalls](/canary/integrate/confirmations-and-pitfalls.md).
