> For the complete documentation index, see [llms.txt](https://docs.telepathy.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.telepathy.xyz/build-with-telepathy/interchain-messaging/example-cross-chain-messaging-demo.md).

# Example: Cross-Chain Messaging Demo

In the [Telepathy Messager Demo](https://demo.telepathy.xyz/), we demonstrate how to concatenate together a string message that includes:

* arbitrary text
* the sender's balance
* the sender's [ENS](https://docs.ens.domains/) name (if applicable)

<figure><img src="/files/EWDI1xQQx0PtjX7OakEc" alt=""><figcaption><p>Play with the demo <a href="https://demo.telepathy.xyz">here</a>.</p></figcaption></figure>

## Contracts

The full source code for the contracts used in this demo can be found at the [Messenger Demo Github](https://github.com/succinctlabs/messenger-demo) in [contracts/src/CrossChainMailbox.sol](https://github.com/succinctlabs/messenger-demo/blob/61cd7d9a71b47e24bd9fbd2d22f7257d752a87ec/contracts/src/CrossChainMailbox.sol). This contains the source contract `CrossChainMailer` and destination contract `CrossChainMailbox`.

#### CrossChainMailer (Source Contract)

This contract needs a reference to the Telepathy [Router](/telepathy-protocol/overview.md), so we pass in that information to the constructor:

```solidity
constructor(address _telepathyRouter) {
    telepathyRouter = ITelepathyRouter(_telepathyRouter);
}
```

The entrypoint for this contract is the `sendMail` function, which a user (EOA) calls to send a message across chains.

```solidity
function sendMail(
    uint32 _destinationChainId, 
    address _destinationMailbox, 
    bytes memory _message
) external payable
{
    if (msg.value < fee) {
        revert InsufficientFee(msg.value, fee);
    }
    string memory data = StringHelper.formatMessage(
        _message, msg.sender.balance, ENSHelper.getName(msg.sender)
    );
    telepathyRouter.send(_destinationChainId, _destinationMailbox, bytes(data));
}
```

The user calling this function specifies which destination chain they would like to send their message to (with the parameter `_destinationChainId`) as well as the `_destinationMailbox` contract address (a `CrossChainMailbox` deployed on the destination chain).&#x20;

The body of `sendMail` uses the `StringHelper` library to piece together the information of message + balance + ENS name in one formatted string. Then we use `send` to send that actual message to our `CrossChainMailbox` through Telepathy.

#### CrossChainMailbox (Destination Contract)

Destination contracts should inherit from the [TelepathyHandler](https://github.com/succinctlabs/telepathy-contracts/blob/fe9566b7837487dfb6d39e708a2c0bfb7c52ceaf/src/amb/interfaces/TelepathyHandler.sol#L5) contract:

```solidity
contract CrossChainMailbox is TelepathyHandler
```

This gives convenient functionality for ensuring that ONLY the Telepathy [Router](/telepathy-protocol/contracts.md#router) can call this function, and gives a function to override to receive messages. To set up this contract a [TelepathyHandler](https://github.com/succinctlabs/telepathy-contracts/blob/fe9566b7837487dfb6d39e708a2c0bfb7c52ceaf/src/amb/interfaces/TelepathyHandler.sol#L5), pass in the Router's address in the constructor:

```solidity
constructor(address _telepathyRouter) TelepathyHandler(_telepathyRouter) {}
```

Then override the [handleTelepathyImpl](https://github.com/succinctlabs/telepathy-contracts/blob/fe9566b7837487dfb6d39e708a2c0bfb7c52ceaf/src/amb/interfaces/TelepathyHandler.sol#L26) function with custom logic:

```solidity
function handleTelepathyImpl(uint32 _sourceChainId, address _sourceAddress, bytes memory _message)
    internal
    override
{
    messages.push(string(_message));
    emit MessageReceived(_sourceChainId, _sourceAddress, string(_message));
}
```

In this case, we store the message and emit an event.
