diff --git a/docs/dapp/diagrams/opl-router-pingpong-flow.mmd b/docs/dapp/diagrams/opl-router-pingpong-flow.mmd new file mode 100644 index 0000000000..5196a8784d --- /dev/null +++ b/docs/dapp/diagrams/opl-router-pingpong-flow.mmd @@ -0,0 +1,11 @@ +sequenceDiagram + User->>+PingPong.sol (A): iPing() + PingPong.sol (A)->>+Gateway (A): iSend() + Gateway (A)-->>Router Chain & Relayer: Listens to event + Router Chain & Relayer-->>+Gateway (B): Relays message + Gateway (B)->>+PingPong (B): iReceive() + PingPong (B)->>-Gateway (B): Response from iReceive() + Gateway (B)-->>-Router Chain & Relayer: Listens to event + Router Chain & Relayer-->>Gateway (A): Relays message + Gateway (A)->>-PingPong.sol (A): iAck() + \ No newline at end of file diff --git a/docs/dapp/diagrams/opl-router-pingpong-flow.mmd.svg b/docs/dapp/diagrams/opl-router-pingpong-flow.mmd.svg new file mode 100644 index 0000000000..8fa2ea4ea6 --- /dev/null +++ b/docs/dapp/diagrams/opl-router-pingpong-flow.mmd.svg @@ -0,0 +1 @@ +PingPong (B)Gateway (B)Router Chain & RelayerGateway (A)PingPong.sol (A)UserPingPong (B)Gateway (B)Router Chain & RelayerGateway (A)PingPong.sol (A)UseriPing()iSend()Listens to eventRelays messageiReceive()Response from iReceive()Listens to eventRelays messageiAck() diff --git a/docs/dapp/images/opl/compile-pingpong.png b/docs/dapp/images/opl/compile-pingpong.png new file mode 100644 index 0000000000..dbfd8b3251 Binary files /dev/null and b/docs/dapp/images/opl/compile-pingpong.png differ diff --git a/docs/dapp/images/opl/router-approve.png b/docs/dapp/images/opl/router-approve.png new file mode 100644 index 0000000000..eb733d9a39 Binary files /dev/null and b/docs/dapp/images/opl/router-approve.png differ diff --git a/docs/dapp/images/opl/router-architecture.png b/docs/dapp/images/opl/router-architecture.png new file mode 100644 index 0000000000..faead296be Binary files /dev/null and b/docs/dapp/images/opl/router-architecture.png differ diff --git a/docs/dapp/images/opl/router-deploy-pingpong-amoy.png b/docs/dapp/images/opl/router-deploy-pingpong-amoy.png new file mode 100644 index 0000000000..e122c0a2d2 Binary files /dev/null and b/docs/dapp/images/opl/router-deploy-pingpong-amoy.png differ diff --git a/docs/dapp/images/opl/router-deploy-pingpong-sapphire.png b/docs/dapp/images/opl/router-deploy-pingpong-sapphire.png new file mode 100644 index 0000000000..0bbec04052 Binary files /dev/null and b/docs/dapp/images/opl/router-deploy-pingpong-sapphire.png differ diff --git a/docs/dapp/images/opl/router-faucet.png b/docs/dapp/images/opl/router-faucet.png new file mode 100644 index 0000000000..12bb7d629e Binary files /dev/null and b/docs/dapp/images/opl/router-faucet.png differ diff --git a/docs/dapp/images/opl/router-iping.png b/docs/dapp/images/opl/router-iping.png new file mode 100644 index 0000000000..532654e797 Binary files /dev/null and b/docs/dapp/images/opl/router-iping.png differ diff --git a/docs/dapp/images/opl/router-metadata.png b/docs/dapp/images/opl/router-metadata.png new file mode 100644 index 0000000000..1999b5cfdb Binary files /dev/null and b/docs/dapp/images/opl/router-metadata.png differ diff --git a/docs/dapp/opl/router-protocol/README.md b/docs/dapp/opl/router-protocol/README.md new file mode 100644 index 0000000000..92c51a3464 --- /dev/null +++ b/docs/dapp/opl/router-protocol/README.md @@ -0,0 +1,94 @@ +--- +description: Cross-chain dApps with Router Protocol +--- + +# Router Protocol + +Router Protocol offers two frameworks for cross-chain interactions: + +- **Router CrossTalk**: Enables stateless and stateful cross-chain messaging +- **Router Nitro**: Facilitates native cross-chain asset transfers + +For guidance on choosing the appropriate framework, refer to Router's [guide]. + +This documentation focuses on **Router CrossTalk**. If you're primarily +interested in asset transfers, please consult the [Router Nitro documentation]. + +[Router Nitro documentation]: https://docs.routerprotocol.com/develop/category/asset-transfer-via-nitro +[guide]: https://docs.routerprotocol.com/overview/choosing-the-right-framework + +## Router CrossTalk + +Router CrossTalk is designed to enable cross-chain interactions, allowing +developers to create decentralized applications (dApps) that operate across +multiple blockchain networks. This framework supports both stateless and +stateful operations, providing flexible and efficient communication between +contracts on different chains. + +### Architecture + +![Router Architecture](../../images/opl/router-architecture.png) +*High-level architecture diagram for Router CrossTalk[^1]* + +[^1]: The CrossTalk high-level architecture diagram is courtesy of [Router documentation][router-architecture]. + +[router-architecture]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/key-concepts/high-level-architecture + +The **CrossTalk** infrastructure consists of three main components: + +- **Gateway** contracts on source and destination chains +- **Orchestrators** on the Router chain +- **Relayers** that forward messages to the Router Gateway contracts + +The process flow is as follows: + +1. The dApp contract calls the iSend function on the source chain's Gateway + contract. +2. Orchestrators monitor events emitted by the Gateway contract. +3. A Relayer picks up the transaction signed by the orchestrator and forwards + the message to the destination chain's Router Gateway contract. +4. Gateway contract on the destination chain calls the dApp contract's + `iReceive` function. +5. For acknowledgment, the process is reversed, and the Relayer calls the + `iAck` function on the dApp contract on the source chain. + +### Fees + +Fees in the cross-chain messaging process are paid by two parties: + +- The dApp **user** pays when initiating the transaction on the source chain. +- The dApp **fee payer** pre-pays the Relayers for calling the Router Gateway + contract. + +To ensure the correct **fee payer** is used, the dApp's contract must register +the fee payer address as metadata with the Router Gateway. Additionally, the +**fee payer** needs to approve the conntract on the Router chain, which can be +done through the [Router Explorer]. + +For more info about the [fee management], consult the Router documentation. + +[Router Explorer]: https://testnet.routerscan.io/feePayer +[fee management]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/key-concepts/fee-management + + +### Examples + +:::note Example: PingPong + +Explore our [PingPong example] to see Router CrossTalk in action. + +::: + +[PingPong example]: ./pingpong-example.md + +For more examples, refer to the [Router Protocol documentation]: + +- [Cross-Chain NFT] +- [Cross-Chain Read Request] + +and in the Router Protocol [CrossTalk sample repository]. + +[Router Protocol documentation]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk +[Cross-Chain NFT]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/your-first-crosschain-nft-contract +[Cross-Chain Read Request]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/cross-chain-read-requests +[CrossTalk sample repository]: https://github.com/router-protocol/new-crosstalk-sample/ diff --git a/docs/dapp/opl/router-protocol/approve.md b/docs/dapp/opl/router-protocol/approve.md new file mode 100644 index 0000000000..efabe601ce --- /dev/null +++ b/docs/dapp/opl/router-protocol/approve.md @@ -0,0 +1,60 @@ +--- +description: Approving fee payer in Router Protcol +--- + +# Approving the Fee Payer + +According to Router Protocol's [fee management] system, cross-chain requests +initiated by a dApp are paid for by the dApp's corresponding fee payer account +on the Router Chain. This fee payer is registered by calling the +`setDappMetadata` function on the gateway contract. + +## Obtaining Test Tokens + +To interact with the Router Protocol testnet, you'll need `ROUTE` test tokens. +Follow these steps to obtain them from the Router Faucet: + +1. Visit the [Router Faucet] website. +2. Connect your MetaMask wallet. +3. Add the Router Test Network to your MetaMask if prompted. +4. Enter your account address in the provided field. +5. Click the `Get Test Tokens` button. + +![Router Test Faucet](../../images/opl/router-faucet.png) + +## Approving Contracts in Router Explorer + +After deploying your contracts, you need to approve the fee payer for each of +them. Here's how to do it using the Router Explorer: + +1. Navigate to the [Router Explorer]. +2. Connect your wallet by clicking the "Connect Wallet" button. +3. Once connected, you'll see a list of pending approvals for your deployed +contracts. + +![Router Approvals](../../images/opl/router-approve.png) + +4. For each contract listed, click the `Approve` button. +5. Follow the prompts in your wallet to sign the approval message. + +:::info + +If you don't see your deployed contracts in the list, it's possible you used an +incorrect gateway address for the chain during deployment. Verify the current +gateway addresses in the [Router Protocol documentation]. + +::: + +## Troubleshooting + +If you encounter any issues during the approval process, consider the following: + +1. Ensure you have sufficient ROUTE test tokens in your wallet. +2. Verify that you're connected to the correct network in MetaMask. +3. Double-check that the contracts were deployed with the correct gateway +addresses. + +[fee management]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/key-concepts/fee-management +[Router Faucet]: https://faucet.routerprotocol.com/ +[Router Explorer]: https://testnet.routerscan.io/feePayer +[Router Protocol documentation]: https://docs.routerprotocol.com/networks/supported-chains#for-testnet diff --git a/docs/dapp/opl/router-protocol/interface.md b/docs/dapp/opl/router-protocol/interface.md new file mode 100644 index 0000000000..98e3dae078 --- /dev/null +++ b/docs/dapp/opl/router-protocol/interface.md @@ -0,0 +1,164 @@ +--- +description: Router Protocol Interfaces +--- + +# Router Interfaces + +Router Protocol provides a library of `evm-gateway-contracs` to facilitate the +development of cross-chain decentralized applications (dApps). + +## Installation + +### Using Remix + +If you're using [Remix], you can import the contracts directly as shown in the +examples below. + +[Remix]: https://remix.ethereum.org/ + +### Using Hardhat + +For Hardhat projects, install the package via npm, yarn or pnpm: + +```shell npm2yarn +npm install @@outerprotocol/evm-gateway-contracts +``` + +## Gateway + +The Router Gateway is deployed on all chains supported by Router Protocol and +serves as the central communication point between chains. + +### IGateway + +```solidity +import "@routerprotocol/evm-gateway-contracts/contracts/IGateway.sol"; +``` +To develop cross-chain contracts, you should generally: + +1. Import the `IGateway.sol` interface into all cross-chain contracts +2. Create a variable to store the Gateway contract address +3. Initialize it with the corresponding Gateway address of the given chain + +This setup will be used later to call the `iSend` function. + +### iSend() + +```solidity +function iSend( + uint256 version, + uint256 routeAmount, + string calldata routeRecipient, + string calldata destChainId, + bytes calldata requestMetadata, + bytes calldata requestPacket +) external payable returns (uint256); +``` + +`iSend` is the function you'll call on the Gateway of the source chain to +initiate a cross-chain message. Every contract that wants to make a cross-chain +call needs to call it. + +For a detailed description of each parameter, refer to the Router Protocol +[iSend documentation]. + +[iSend documentation]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/iDapp-functions/iSend + +### getRequestMetaData() + +```solidity + function getRequestMetadata( + uint64 destGasLimit, + uint64 destGasPrice, + uint64 ackGasLimit, + uint64 ackGasPrice, + uint128 relayerFees, + uint8 ackType, + bool isReadCall, + string memory asmAddress +) public pure returns (bytes memory) { + bytes memory requestMetadata = abi.encodePacked( + destGasLimit, + destGasPrice, + ackGasLimit, + ackGasPrice, + relayerFees, + ackType, + isReadCall, + asmAddress + ); + return requestMetadata; +} +``` +The `getRequestMetadata` function helps create the `requestMetadata` bytes +object required for the `iSend` function call. + +Here's an overview of the arguments: + +| Argument | Example Value | Description | +| ------------ | ------------- | ------------------------------------------ | +| destGasLimit | 300000 | Gas limit on destination chain | +| destGasPrice | 100000000000 | Gas price on destination chain | +| ackGasLimit | 300000 | Gas limit on source chain for ack | +| ackGasPrice | 100000000000 | Gas price on source chain for ack | +| relayerFees | 10000000000 | Relayer fees on Router chain | +| ackType | 3 | Acknowledge type | +| isReadCall | false | If the call is read-only | +| asmAddress | "0x" | Address for the additional security module | + +Alternatively, you can use `ethers.js` to encode the metadata: +```js +const metadata = ethers.utils.solidityPack( + ['uint64', 'uint64', 'uint64', 'uint64', 'uint128', 'uint8', 'bool', 'string'], + [destGasLimit, destGasPrice, ackGasLimit, ackGasPrice, relayerFees, ackType, isReadCall, asmAddress] +); +``` + +For more information about encoding and the request metadata, see the Router +[metadata documentation]. + +[metadata documentation]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/iDapp-functions/iSend#5-requestmetadata + +## IDapp + +```solidity +import "@routerprotocol/evm-gateway-contracts/contracts/IDapp.sol"; +``` + +The IDapp interface consists of two main functions: + +1. `iReceive`: The entry point for the cross-chain message on the destination + chain +2. `iAck`: The entry point on the source chain to receive the acknowledgment + +### iReceive() + +```solidity +function iReceive( + string memory requestSender, + bytes memory packet, + string memory srcChainId + ) external returns (bytes memory) +``` + +`iReceive` is called by the Gateway on the destination chain. + +For more information about `iReceive`, see the Router [iReceive documentation]. + +[iReceive documentation]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/iDapp-functions/iReceive + +### iAck() + +```solidity +function iAck( + uint256 requestIdentifier, + bool execFlag, + bytes memory execData + ) external +``` + +`iAck` is called by the Gateway on the source chain. + +For more information about `iAck`, see the Router [iAck documentation]. + +[iAck documentation]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/iDapp-functions/iAck diff --git a/docs/dapp/opl/router-protocol/pingpong-example.md b/docs/dapp/opl/router-protocol/pingpong-example.md new file mode 100644 index 0000000000..4fcbeefbd4 --- /dev/null +++ b/docs/dapp/opl/router-protocol/pingpong-example.md @@ -0,0 +1,351 @@ +--- +description: Router Protocol PingPong example +--- + +# PingPong Example + +This tutorial demonstrates how to send a cross-chain message using Router +Protocol's [CrossTalk]. + +You'll learn how to: + + - Deploy Router-compatible contracts + - Approve the feePayer for your contracts + - Prepare metadata for cross-chain calls + - Send cross-chain messages + +We recommend using [Remix] for an easy-to-follow experience. +The only prerequisite is a set-up Metamask account. + +:::info + +If you're new to Remix, follow our basic guide for using Remix +[here][dapp-remix]. + +[dapp-remix]: /dapp/emerald/writing-dapps-on-emerald#create-dapp-on-emerald-with-remix---ethereum-ide + +::: + + +## Overview PingPong + +In this example, you'll deploy the same contract on two different chains. +You'll then send a `ping` from chain A to chain B, facilitated by Router +Protocol's [CrossTalk]. The contract on chain B will receive the `ping` and +respond back to Router Protocol. Finally, Router Protocol will send an +acknowledgment message back to the contract on chain A. + +![PingPong Flow](../../diagrams/opl-router-pingpong-flow.mmd.svg) + +[CrossTalk]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk + +## Contract Setup + +1. Open [Remix] and create a new file called `PingPong.sol` +2. Paste the following contract into it: + +
+ PingPong.sol Contract + + ```solidity title="PingPong.sol" showLineNumbers + //SPDX-License-Identifier: UNLICENSED + pragma solidity >=0.8.0 <0.9.0; + + import "@routerprotocol/evm-gateway-contracts/contracts/IGateway.sol"; + + /// @title PingPong + /// @author Yashika Goyal + /// @notice This is a cross-chain ping pong smart contract to demonstrate how one can + /// utilise Router CrossTalk for cross-chain transactions. + contract PingPong { + address public owner; + uint64 public currentRequestId; + + // srcChainId + requestId => pingFromSource + mapping(string => mapping(uint64 => string)) public pingFromSource; + // requestId => ackMessage + mapping(uint64 => string) public ackFromDestination; + + // instance of the Router's gateway contract + IGateway public gatewayContract; + + // custom error so that we can emit a custom error message + error CustomError(string message); + + // event we will emit while sending a ping to destination chain + event PingFromSource( + string indexed srcChainId, + uint64 indexed requestId, + string message + ); + event NewPing(uint64 indexed requestId); + + // events we will emit while handling acknowledgement + event ExecutionStatus(uint256 indexed eventIdentifier, bool isSuccess); + event AckFromDestination(uint64 indexed requestId, string ackMessage); + + constructor(address payable gatewayAddress, string memory feePayerAddress) { + owner = msg.sender; + + gatewayContract = IGateway(gatewayAddress); + + gatewayContract.setDappMetadata(feePayerAddress); + } + + /// @notice function to set the fee payer address on Router Chain. + /// @param feePayerAddress address of the fee payer on Router Chain. + function setDappMetadata(string memory feePayerAddress) external { + require(msg.sender == owner, "only owner"); + gatewayContract.setDappMetadata(feePayerAddress); + } + + /// @notice function to set the Router Gateway Contract. + /// @param gateway address of the gateway contract. + function setGateway(address gateway) external { + require(msg.sender == owner, "only owner"); + gatewayContract = IGateway(gateway); + } + + /// @notice function to generate a cross-chain request to ping a destination chain contract. + /// @param destChainId chain ID of the destination chain in string. + /// @param destinationContractAddress contract address of the contract that will handle this + /// @param str string to be pinged to destination + /// @param requestMetadata abi-encoded metadata according to source and destination chains + function iPing( + string calldata destChainId, + string calldata destinationContractAddress, + string calldata str, + bytes calldata requestMetadata + ) public payable { + currentRequestId++; + + bytes memory packet = abi.encode(currentRequestId, str); + bytes memory requestPacket = abi.encode(destinationContractAddress, packet); + gatewayContract.iSend{ value: msg.value }( + 1, + 0, + string(""), + destChainId, + requestMetadata, + requestPacket + ); + emit NewPing(currentRequestId); + } + + /// @notice function to get the request metadata to be used while initiating cross-chain request + /// @return requestMetadata abi-encoded metadata according to source and destination chains + function getRequestMetadata( + uint64 destGasLimit, + uint64 destGasPrice, + uint64 ackGasLimit, + uint64 ackGasPrice, + uint128 relayerFees, + uint8 ackType, + bool isReadCall, + string memory asmAddress + ) public pure returns (bytes memory) { + bytes memory requestMetadata = abi.encodePacked( + destGasLimit, + destGasPrice, + ackGasLimit, + ackGasPrice, + relayerFees, + ackType, + isReadCall, + asmAddress + ); + return requestMetadata; + } + + /// @notice function to handle the cross-chain request received from some other chain. + /// @param packet the payload sent by the source chain contract when the request was created. + /// @param srcChainId chain ID of the source chain in string. + function iReceive( + string memory, //requestSender, + bytes memory packet, + string memory srcChainId + ) external returns (uint64, string memory) { + require(msg.sender == address(gatewayContract), "only gateway"); + (uint64 requestId, string memory sampleStr) = abi.decode( + packet, + (uint64, string) + ); + if ( + keccak256(abi.encodePacked(sampleStr)) == keccak256(abi.encodePacked("")) + ) { + revert CustomError("String should not be empty"); + } + pingFromSource[srcChainId][requestId] = sampleStr; + + emit PingFromSource(srcChainId, requestId, sampleStr); + + return (requestId, sampleStr); + } + + /// @notice function to handle the acknowledgement received from the destination chain + /// back on the source chain. + /// @param requestIdentifier event nonce which is received when we create a cross-chain request + /// We can use it to keep a mapping of which nonces have been executed and which did not. + /// @param execFlag a boolean value suggesting whether the call was successfully + /// executed on the destination chain. + /// @param execData returning the data returned from the handleRequestFromSource + /// function of the destination chain. + function iAck( + uint256 requestIdentifier, + bool execFlag, + bytes memory execData + ) external { + (uint64 requestId, string memory ackMessage) = abi.decode( + execData, + (uint64, string) + ); + + ackFromDestination[requestId] = ackMessage; + + emit ExecutionStatus(requestIdentifier, execFlag); + emit AckFromDestination(requestId, ackMessage); + } + } + ``` +
+ +### Key Contract Functions + +- `iPing`: Initiates the cross-chain message by calling Router's + `IGateway.iSend`. +- `iReceive`: Serves as the entry point on the destination contract. +- `iAck`: Handles the acknowledgment in a bidirectional cross-chain message on + the source contract. + +### Compiling the Contract + +For compatibility with Sapphire, compile the contract using Solidity version +**`0.8.24`** or older. + +### Deploying the Contract + +Deploy the PingPong contract on two different chains: `Sapphire Testnet` and +`Polygon Amoy`. + +#### Deploying on Sapphire Testnet + +1. Obtain TEST tokens for `Sapphire Testnet` from the [Oasis faucet]. +2. In Metamask, switch to the `Sapphire Testnet` network and select + `Injected Provider - MetamMask` as the environment in Remix +3. Fill in the deployment parameters: + +- **`gatewayAddress`**: `0xfbe6d1e711cc2bc241dfa682cbbff6d68bf62e67` + (current Sapphire Testnet Gateway) +- **`feePayerAddress`**: Your current account address + (copy from MetaMask or Remix) + +4. Deploy the contract on Sapphire Testnet + +
+ Remix Example + +![Deploy Sapphire](../../images/opl/router-deploy-pingpong-sapphire.png) +
+ +[Oasis Faucet]: https://faucet.testnet.oasis.io/ + +#### Deploying on Polygon Amoy + +1. Obtain POL tokens for `Polygon Amoy` Testnet from the [Polygon faucet]. +2. Switch to the `Polygon Amoy` network in Metamask. +3. Fill in the deployment parameters: + +- **`gatewayAddress`**: `0x778a1f43459a05accd8b57007119f103c249f929` + (current Polygon Amoy Gateway) +- **`feePayerAddress`**: Your current account address + (copy from MetaMask or Remix) + +4. Deploy the contract on Polygon Amoy + +
+ Remix Example + +![Deploy Polygon Amoy](../../images/opl/router-deploy-pingpong-amoy.png) +
+ +[Polygon Faucet]: https://faucet.polygon.technology/ + +## Approving the Fee Payer + +After deploying the contracts, approve the **fee payer** on the Router Chain: + +1. Obtain Router test tokens from the [Router faucet]. +2. Approve the contracts on the [Router Explorer][feepayer]. + +For detailed instructions on fee payer approval, see our [approval guide]. + +[Router faucet]: https://faucet.routerprotocol.com/ +[feepayer]: https://testnet.routerscan.io/feePayer +[approval guide]: /dapp/opl/router-protocol/approve + +## Executing PingPong + +Now that you've deployed the contracts and approved the fee payer, you can play +**PingPong**. This process involves two steps: + +1. Obtaining the Request Metadata +2. Executing the iPing function + +### Step 1: Obtaining Request Metadata + +Call the `getRequestMetadata()` function with the following parameters: + +| Argument | Example Value | Description | +| ------------ | ------------- | ------------------------------------------ | +| destGasLimit | 300000 | Gas limit on destination chain | +| destGasPrice | 100000000000 | Gas price on destination chain | +| ackGasLimit | 300000 | Gas limit on source chain for ack | +| ackGasPrice | 100000000000 | Gas price on source chain for ack | +| relayerFees | 10000000000 | Relayer fees on Router chain | +| ackType | 3 | Acknowledge type | +| isReadCall | false | Weather the call is read-only | +| asmAddress | "0x" | Address for the additional security module | + +
+ Remix Example + + ![Router getRequestMetadata](../../images/opl/router-metadata.png) +
+ +:::info + +The bytes answer you will need in the next step, copy it! + +::: + +For more information about request metadata, see the +[Router documentation][metadata]. + +[metadata]: https://docs.routerprotocol.com/develop/message-transfer-via-crosstalk/evm-guides/iDapp-functions/iSend#5-requestmetadata + +### Step 2: Executing iPing() + +To initiate the cross-chain message, call `iPing` with these parameters: + +| Argument | Value | Description | +| -------------------------- | ------------------ | ------------------------------------------------- | +| destChainId | 23295 | Destination Chain ID (e.g. Sapphire) | +| destinationContractAddress | 0x\ | Contract address on the destination chain | +| str | "Hello" | Message to include in the ping | +| requestMetadata | \ | Bytes response from the getRequestMetada call | + + +After sending the transaction, you can monitor its status on the +[Router Explorer]. + +
+ Remix Example + +![Router iPing](../../images/opl/router-iping.png) +
+ +This completes the PingPong example, demonstrating cross-chain messaging using +Router Protocol's CrossTalk framework. + +[Router Explorer]: https://testnet.routerscan.io/crosschain +[Remix]: https://remix.ethereum.org/ diff --git a/docs/dapp/opl/secret-ballot-example/build.md b/docs/dapp/opl/secret-ballot-example/build.md index c5920ed90a..0d918e08d5 100644 --- a/docs/dapp/opl/secret-ballot-example/build.md +++ b/docs/dapp/opl/secret-ballot-example/build.md @@ -127,7 +127,7 @@ We will use these addresses in our frontend application. #### Testnet -We can likewise deploy to [Testnet](../../dapp/sapphire/guide#testnet-and-mainnet) +We can likewise deploy to [Testnet](../../sapphire/guide.mdx#testnet-and-mainnet) with Sapphire. In this case, we should prepare a wallet with Testnet tokens on both BNB Smart diff --git a/docs/dapp/opl/secret-ballot-example/setup.md b/docs/dapp/opl/secret-ballot-example/setup.md index 6ee6b8bc28..4d75d88c99 100644 --- a/docs/dapp/opl/secret-ballot-example/setup.md +++ b/docs/dapp/opl/secret-ballot-example/setup.md @@ -50,6 +50,7 @@ We would like to set `@oasisprotocol/secret-ballot-backend` as the package name inside `package.json` at `version` of `1.0.0`. Finally, we need to install the following dependencies: + - `@oasisprotocol/sapphire-contracts` contains the OPL Solidity smart contracts. - `@oasisprotocol/sapphire-hardhat` integrates Sapphire using the Hardhat config file. diff --git a/sidebarDapp.ts b/sidebarDapp.ts index 3b62b9a88f..0d7a1ef282 100644 --- a/sidebarDapp.ts +++ b/sidebarDapp.ts @@ -45,12 +45,34 @@ export const sidebarDapp: SidebarsConfig = { id: 'dapp/opl/README', }, items: [ - 'dapp/opl/introduction', - 'dapp/opl/setup', - 'dapp/opl/host', - 'dapp/opl/enclave', - 'dapp/opl/build', - 'dapp/opl/frontend', + { + type: 'category', + label: 'Router Protocol', + link: { + type: 'doc', + id: 'dapp/opl/router-protocol/README', + }, + items: [ + 'dapp/opl/router-protocol/pingpong-example', + 'dapp/opl/router-protocol/interface', + 'dapp/opl/router-protocol/approve', + ], + }, + { + type: 'category', + label: 'Secret Ballot Example', + link: { + type: 'doc', + id: 'dapp/opl/secret-ballot-example/README', + }, + items: [ + 'dapp/opl/secret-ballot-example/setup', + 'dapp/opl/secret-ballot-example/host', + 'dapp/opl/secret-ballot-example/enclave', + 'dapp/opl/secret-ballot-example/build', + 'dapp/opl/secret-ballot-example/frontend', + ], + }, ], }, {