> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Bridge

> Bridge Machine NFTs between peaq and Base from ROS 2 via LayerZero V2.

`peaq_ros2_peaqos` exposes the LayerZero V2 ONFT bridge as two services:

| Service                            | Type                                                  | Purpose                                                  |
| :--------------------------------- | :---------------------------------------------------- | :------------------------------------------------------- |
| `/peaqos_node/bridge/nft`          | `peaq_ros2_interfaces/srv/PeaqosBridgeNft`            | Send a Machine NFT between peaq and Base                 |
| `/peaqos_node/bridge/wait_arrival` | `peaq_ros2_interfaces/srv/PeaqosWaitForBridgeArrival` | Poll the destination chain until the bridged NFT arrives |

<Warning>
  Bridging is **mainnet only**. LayerZero V2 has no DVN routes between agung and Base, so bridge calls on testnet won't relay end-to-end. Test the round trip on peaq mainnet ↔ Base mainnet.
</Warning>

## Required configuration

Both directions need the LayerZero ONFT contracts wired into `peaq_robot.yaml`:

```yaml theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
peaq_os:
  contracts:
    machine_nft_adapter: "0x9AD5408702EC204441A88589B99ADfC2514AFAE6"   # peaq mainnet
    # Pass the Base counterpart per call (see base_nft_address below) or
    # leave it blank to fall back to the SDK default.
```

Equivalent env override: `MACHINE_NFT_ADAPTER_ADDRESS`. Base side reference contract: `0xee8A521eA434b11F956E2402beC5eBfa753Babfa` (`MachineNFTBase`).

## peaq → Base

The signer must own the Machine NFT on peaq and hold enough peaq for gas plus the LayerZero fee.

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/bridge/nft \
  peaq_ros2_interfaces/srv/PeaqosBridgeNft \
  "{signer_address: '<OWNER_EVM_ADDRESS>', token_id: 1, source: 'peaq', destination: 'base', recipient: '<RECIPIENT_EVM_ADDRESS>', base_rpc_url: '', base_nft_address: '', options_hex: ''}"
```

Then poll the destination:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/bridge/wait_arrival \
  peaq_ros2_interfaces/srv/PeaqosWaitForBridgeArrival \
  "{dst_rpc_url: 'https://mainnet.base.org', dst_nft_address: '0xee8A521eA434b11F956E2402beC5eBfa753Babfa', token_id: 1, timeout: 900}"
```

`timeout` is in seconds. The service returns once `ownerOf(token_id)` matches the recipient on the destination chain or the deadline is hit.

## Base → peaq

Same service shape, swapped `source` / `destination`. The signer must hold the Machine NFT on Base **and** enough Base ETH to cover gas plus the LayerZero fee — the bridge can't bootstrap funding for you.

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/bridge/nft \
  peaq_ros2_interfaces/srv/PeaqosBridgeNft \
  "{signer_address: '<OWNER_EVM_ADDRESS>', token_id: 1, source: 'base', destination: 'peaq', recipient: '<RECIPIENT_EVM_ADDRESS>', base_rpc_url: 'https://mainnet.base.org', base_nft_address: '0xee8A521eA434b11F956E2402beC5eBfa753Babfa', options_hex: ''}"
```

Wait for arrival on peaq:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/bridge/wait_arrival \
  peaq_ros2_interfaces/srv/PeaqosWaitForBridgeArrival \
  "{dst_rpc_url: 'https://quicknode1.peaq.xyz', dst_nft_address: '0x2943F80e9DdB11B9Dd275499C661Df78F5F691F9', token_id: 1, timeout: 900}"
```

## Field reference

`PeaqosBridgeNft`:

| Field              | Description                                                                                 |
| :----------------- | :------------------------------------------------------------------------------------------ |
| `signer_address`   | Local wallet address that owns the NFT on the source chain                                  |
| `token_id`         | Machine NFT token id                                                                        |
| `source`           | `peaq` or `base`                                                                            |
| `destination`      | `peaq` or `base`                                                                            |
| `recipient`        | Address that receives the NFT on the destination chain                                      |
| `base_rpc_url`     | Base JSON-RPC URL. Required when `source: 'base'`; unused when `source: 'peaq'`             |
| `base_nft_address` | Base `MachineNFTBase` address. Required when `source: 'base'`; unused when `source: 'peaq'` |
| `options_hex`      | Raw LayerZero `extraOptions` payload hex. Leave blank for contract defaults                 |

`PeaqosWaitForBridgeArrival`:

| Field             | Description                                       |
| :---------------- | :------------------------------------------------ |
| `dst_rpc_url`     | RPC for the destination chain                     |
| `dst_nft_address` | NFT contract on the destination chain             |
| `token_id`        | Machine NFT token id                              |
| `timeout`         | Seconds to poll before returning `arrived: false` |

## Operational notes

* Record pre/post balances on both chains for any production bridge test.
* The reverse direction (Base → peaq) is the failure mode most people hit: a fresh Base wallet has no ETH, so the bridge tx reverts on `insufficient funds`. Fund Base first.
* For a deeper protocol view (LayerZero peers, ONFT contracts, supported chains) see the [Activate function](/peaqos/functions/activate) and the [SDK JS](/peaqos/sdk-reference/sdk-js) / [SDK Python](/peaqos/sdk-reference/sdk-python) bridge methods, which this node mirrors 1:1.
