# Your First Cross-Chain dApp with XTalk: A Step-by-Step Guide

Welcome, developer! This guide will walk you through integrating your Solidity smart contracts with the L1X XTalk Protocol to send and receive messages across different blockchains. We'll use a simplified example, similar to `SimpleMessageTest.sol`, to illustrate the core concepts.

### Prerequisites

Before you start, you should have a basic understanding of:

* Solidity and smart contract development.
* The concept of cross-chain communication.
* An XTalk environment set up (or access to a testnet where XTalk contracts like `XTalkBeacon` are deployed).

#### Known XTalkBeacon Testnet Addresses

For your convenience, here are some known deployed `XTalkBeacon` contract addresses on common testnets:

* **Sepolia Testnet:**
  * Chain ID: `11155111`
  * `XTalkBeacon` Address: `0x1a99f64254D998d9F6a2912Ca5b19c1DFE326eF8`
* **BSC (Binance Smart Chain) Testnet:**
  * Chain ID: `97`
  * `XTalkBeacon` Address: `0x1a99f64254D998d9F6a2912Ca5b19c1DFE326eF8`

*Note: Always verify contract addresses from official project documentation or trusted sources before interacting with them on mainnet or for critical operations.*

### Goal

Our goal is to create a smart contract that can:

1. **Send a simple text message** to a contract on another EVM-compatible chain using XTalk.
2. **Receive a simple text message** from another chain via XTalk.

### Step 1: Define the `IXTalkBeacon` Interface

To interact with the XTalk system on any EVM chain, your contract needs to know how to call the `XTalkBeacon` contract. This is done by defining an interface in your Solidity file.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IXTalkBeacon {
    // Function to initiate a cross-chain message
    function registerMessage(
        uint32 _destinationChainId,
        bytes32 _destinationAddress,
        bytes memory _messageData,
        uint32 _messageType,
        uint256 _messageNonce
    ) external;

    // Function to get the next valid nonce for your contract
    function getSenderRegistrationNextNonce(address _sender) external view returns (uint256);
}

// Your contract will go here
// contract MyXTalkDApp is ...
```

* `registerMessage`: This is the function you'll call on the `XTalkBeacon` to send your message.
* `getSenderRegistrationNextNonce`: You'll use this to get a unique nonce for each message your contract sends, which is important for security.

### Step 2: Setting Up Your Contract to Send Messages

Let's create a contract `MyXTalkDApp` and add a function to send a message. For a production or testnet dApp, the `XTalkBeacon` address on a specific chain is fixed. You can store this as a constant or an immutable variable in your contract for clarity and safety.

```solidity
contract MyXTalkDApp {
    // Address of the XTalkBeacon on the current chain.
    // For Sepolia Testnet, for example:
    address public immutable XTALK_BEACON_ADDRESS;

    // Event to log message sending attempts (optional)
    event MessageSentToXTalk(
        uint32 indexed destinationChainId,
        bytes32 indexed destinationContractAddress,
        string messageContent,
        uint256 nonceUsed
    );

    constructor(address beaconContractAddress) {
        XTALK_BEACON_ADDRESS = beaconContractAddress;
    }

    // Function to send a cross-chain message
    function sendMessageToOtherChain(
        uint32 destinationChainId,  // The ID of the chain you want to send to
        bytes32 destinationContractAddress, // The address of your target contract on the other chain (as bytes32)
        string memory myTextMessage    // The actual text you want to send
    ) public {
        // 1. Define a message type (application-specific)
        uint32 messageType = 1; // You can define different types for different actions

        // 2. Encode your payload (the string message)
        // The XTalk system transmits data as `bytes`. So, we ABI-encode our string.
        bytes memory encodedMessagePayload = abi.encode(myTextMessage);

        // 3. Get the next valid nonce for your contract
        // This makes each message unique from your contract's perspective on the source chain.
        IXTalkBeacon beacon = IXTalkBeacon(XTALK_BEACON_ADDRESS); // Use the stored beacon address
        uint256 nonce = beacon.getSenderRegistrationNextNonce(address(this));

        // 4. Call `registerMessage` on the XTalkBeacon
        beacon.registerMessage(
            destinationChainId,
            destinationContractAddress,
            encodedMessagePayload,
            messageType,
            nonce
        );

        // Optional: Emit an event in your contract to log that a message was sent
        emit MessageSentToXTalk(destinationChainId, destinationContractAddress, myTextMessage, nonce);
    }
}
```

**Explanation:**

1. **`XTALK_BEACON_ADDRESS`**: This is now an `immutable` state variable, set in the `constructor`. When deploying `MyXTalkDApp`, you would pass the known `XTalkBeacon` address for the chain you are deploying to (e.g., `0x1a99f64254D998d9F6a2912Ca5b19c1DFE326eF8` for Sepolia or BSC Testnet as per our known addresses list). This makes it clear which beacon your contract is configured to use.
2. **`sendMessageToOtherChain` Parameters**: The function now only takes parameters specific to the message itself, as the `beaconAddress` is already configured for the contract instance.
3. **Using the Stored Address**: Inside `sendMessageToOtherChain`, `IXTalkBeacon(XTALK_BEACON_ADDRESS)` is used, referencing the immutable address.
4. **Important Security Note:** In a production system, you might want to add a check\
   to ensure `msg.sender` is the legitimate XTalkBeacon contract on this chain.\
   For example: require(msg.sender == XTALK\_BEACON\_ADDRESS, "Unauthorized XTalk caller");

### Step 3: Setting Up Your Contract to Receive Messages

To receive a message from another chain via XTalk, your contract (or a specific contract you deploy on the destination chain) must implement a special callback function: `_xtalkMessageReceived`.

```solidity
// Continuing our MyXTalkDApp contract...
contract MyXTalkDApp {
    // ... (sendMessageToOtherChain function from above) ...

    // Data structure to store received message details
    struct ReceivedMessage {
        bytes32 messageId;          // Unique ID from XTalk system
        address sourceInvokerAddress; // Address of the contract that sent the message (on source chain)
        uint32 sourceChainId;       // ID of the chain the message came from
        uint32 messageType;         // Application-specific type from sender
        string actualMessage;       // The decoded text message
        bytes rawMessageData;       // The raw payload received
    }

    mapping(bytes32 => ReceivedMessage) public receivedXTalkMessages;
    event MessageReceived(bytes32 indexed messageId, address sourceInvoker, string message);

    // This is the REQUIRED callback function for XTalk
    function _xtalkMessageReceived(
        bytes32 _messageId,             // The unique XTalk message ID
        address _sourceInvokerAddress,  // Who sent it on the source chain
        uint32 _sourceChainId,          // Which chain it came from
        uint32 _messageType,            // The type defined by the sender
        bytes memory _messageData       // The raw payload (our ABI-encoded string)
    ) public {
        // Important Security Note: In a production system, you might want to add a check
        // to ensure `msg.sender` is the legitimate XTalkBeacon contract on this chain.
        // For example: require(msg.sender == XTALK_BEACON_ADDRESS, "Unauthorized XTalk caller");

        // 1. Decode the message payload if you know its type
        // Assuming the sender used `abi.encode(string)` like our `sendMessageToOtherChain` function
        string memory decodedTextMessage = abi.decode(_messageData, (string));

        // 2. Store the received message details
        receivedXTalkMessages[_messageId] = ReceivedMessage({
            messageId: _messageId,
            sourceInvokerAddress: _sourceInvokerAddress,
            sourceChainId: _sourceChainId,
            messageType: _messageType,
            actualMessage: decodedTextMessage,
            rawMessageData: _messageData
        });

        // 3. Emit an event to signal the message was received and processed
        emit MessageReceived(_messageId, _sourceInvokerAddress, decodedTextMessage);

        // 4. (Optional) Add any custom logic here to act upon the received message
        // For example, update state, call another function, etc.
    }
}
```

**Explanation:**

1. **`_xtalkMessageReceived` Signature**: The function name and parameters (`bytes32`, `address`, `uint32`, `uint32`, `bytes`) **must exactly match** this signature. The `XTalkBeacon` on your contract's chain is programmed to call this specific function when it has a message for your contract.
2. **Security (Caller Verification - Optional but Recommended):** Although not shown in the most basic `SimpleMessageTest.sol`, in a real-world scenario, you should verify that `msg.sender` of the `_xtalkMessageReceived` call is indeed the trusted `XTalkBeacon` contract address on the current chain. This prevents unauthorized contracts from spoofing XTalk messages directly to your callback.
3. **Decoding Payload**: The `_messageData` arrives as `bytes`. Since our `sendMessageToOtherChain` function sent an ABI-encoded string, we use `abi.decode(_messageData, (string))` to get the original text back.
4. **Storing Data**: The example stores the message details in a mapping. You can adapt this to your dApp's needs.
5. **Custom Logic**: After decoding and storing, you can add any logic your dApp needs to perform based on the received message content or type.

### Step 4: Deployment and Interaction Flow

1. **Deploy `MyXTalkDApp` (or similar contracts) on both the source and destination chains.**
   * The instance on the source chain will use `sendMessageToOtherChain`.
   * The instance on the destination chain will receive the message via `_xtalkMessageReceived`.
2. **Identify `XTalkBeacon` Addresses:** You'll need the deployed addresses of the `XTalkBeacon` contracts on both chains. (See the "Known XTalkBeacon Testnet Addresses" section above for examples).
3. **Sending a Message:**
   * Call `sendMessageToOtherChain` on the source chain with the appropriate parameters.
   * The message will be sent to the destination chain via XTalk.
   * The destination chain's `_xtalkMessageReceived` function will handle the message reception.

By following these steps, you'll be able to send and receive messages across different blockchains using the XTalk Protocol.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://l1x-sdk.gitbook.io/l1x-developer-interface/multi-chain-with-x-talk/start-building-with-x-talk/cross-chain-data-and-message-passing-xcdp/v1.1-latest/your-first-cross-chain-dapp-with-xtalk-a-step-by-step-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
