From 424c367e90a3aa362199afd51666a4f7750965d4 Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Mon, 30 Sep 2024 12:36:47 +0200 Subject: [PATCH 1/4] update docs --- .nvmrc | 2 +- .../.env.sample | 1 + .../substrate-to-evm-fungible-transfer/README.md | 15 +++++++-------- .../src/transfer.ts | 9 +++++---- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.nvmrc b/.nvmrc index 0828ab794..a2ad731bb 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18 \ No newline at end of file +v18.20.4 \ No newline at end of file diff --git a/examples/substrate-to-evm-fungible-transfer/.env.sample b/examples/substrate-to-evm-fungible-transfer/.env.sample index 6d9d03039..d820a0faa 100644 --- a/examples/substrate-to-evm-fungible-transfer/.env.sample +++ b/examples/substrate-to-evm-fungible-transfer/.env.sample @@ -1,3 +1,4 @@ PRIVATE_MNEMONIC="YOUR TWELVE WORD MNEMONIC HERE WITH SPACES" SOURCE_SUBSTRATE_RPC_URL="TANGLE_RPC_URL_HERE" +RECIPIENT_ADDRESS="RECIPIENT_EVM_ADDRESS" SYGMA_ENV="testnet" \ No newline at end of file diff --git a/examples/substrate-to-evm-fungible-transfer/README.md b/examples/substrate-to-evm-fungible-transfer/README.md index 44c40acbc..4707cc906 100644 --- a/examples/substrate-to-evm-fungible-transfer/README.md +++ b/examples/substrate-to-evm-fungible-transfer/README.md @@ -1,14 +1,13 @@ ## Sygma SDK Substrate Asset Transfer Example - This is an example script that demonstrates the functionality of the SDK using the Sygma ecosystem. The script showcases a Substrate Asset transfer between a Substrate network and an EVM network using the Sygma SDK. ## Prerequisites Before running the script, ensure that you have the following: -- Node.js installed on your machine +- Node.js installed on your machine (v18.20.4) - Yarn (version 3.4.1 or higher) -- A Substrate development wallet funded with `PHA` tokens; **you may wish** to run the [EVM-to-Substrate example](../evm-to-substrate-fungible-transfer/) first to preload `PHA` tokens into a Substrate wallet +- A Substrate development wallet funded with `TANGLE` tokens; **you may wish** to run the [EVM-to-Substrate example](../evm-to-substrate-fungible-transfer/) first to preload `PHA` tokens into a Substrate wallet - The 12-word mnemonic for your Substrate development wallet - An Ethereum wallet to receive tokens into (the example presets an existing wallet address already) - A Substrate provider (in case the hardcoded WSS within the script does not work) @@ -63,15 +62,15 @@ To send a Substrate token to an EVM chain example transfer run: yarn run transfer ``` -The example will use `@polkadot/keyring` in conjuction with the sygma-sdk to -create a transfer from `Roccoco Phala` to `Sepolia`. +The example will use `@polkadot/keyring` in conjunction with the sygma-sdk to +create a transfer from `Tangle` to `Sepolia`. Replace the placeholder values in the `.env` file with your own Substrate wallet mnemonic, and your own destination EVM address within the script. **Note** -To replace default rpc Rhala urls use env variables: -- `RHALA_RPC_URL="RHALA_RPC_URL_HERE"` +To replace default rpc TANGLE url use env variable: +- `SOURCE_SUBSTRATE_RPC_URL="TANGLE_RPC_URL_HERE"` ## Script Functionality @@ -80,7 +79,7 @@ This example script performs the following steps: - initializes the SDK and establishes a connection to the Substrate node. - retrieves the list of supported domains and resources from the SDK configuration. - Searches for the Substrate asset resource with the specified ResourceId -- Searches for the Cronos and Sepolia domains in the list of supported domains based on their chain IDs +- Searches for the Tangle and Sepolia domains in the list of supported domains based on their chain IDs - Constructs a transfer object that defines the details of the Substrate asset transfer - Retrieves the fee required for the transfer from the SDK. - Builds the final transfer transaction and sends it using the Substrate account. diff --git a/examples/substrate-to-evm-fungible-transfer/src/transfer.ts b/examples/substrate-to-evm-fungible-transfer/src/transfer.ts index d4f5709a1..361552aed 100644 --- a/examples/substrate-to-evm-fungible-transfer/src/transfer.ts +++ b/examples/substrate-to-evm-fungible-transfer/src/transfer.ts @@ -12,16 +12,17 @@ if (!MNEMONIC) { throw new Error("Missing environment variable: PRIVATE_MNEMONIC"); } -const SEPOLIA_CHAIN_ID = 11155111; const TANGLE_CHAIN_ID = 3799; +const SEPOLIA_CHAIN_ID = 11155111; +const RECIPIENT_ADDRESS = + process.env.RECIPIENT_ADDRESS || "0xE39bb23F17a2cf7C9a8C4918376A32036A8867db"; const RESOURCE_ID_SYGMA_USD = "0x0000000000000000000000000000000000000000000000000000000000002000"; -const recipient = "0xE39bb23F17a2cf7C9a8C4918376A32036A8867db"; +const SYGMA_EXPLORER_URL = "https://scan.test.buildwithsygma.com"; const TANGLE_RPC_URL = process.env.SOURCE_SUBSTRATE_RPC_URL ?? "wss://rpc.tangle.tools"; -const SYGMA_EXPLORER_URL = "https://scan.test.buildwithsygma.com"; const getSygmaExplorerTransferUrl = (params: { blockNumber: number; extrinsicIndex: number; @@ -43,7 +44,7 @@ const substrateTransfer = async (): Promise => { sourceAddress: account.address, resource: RESOURCE_ID_SYGMA_USD, amount: BigInt(1) * BigInt(1e18), - destinationAddress: recipient, + destinationAddress: RECIPIENT_ADDRESS, }; const transfer = await createSubstrateFungibleAssetTransfer(transferParams); From 16f78b2e078c1657618497061307d9b8878efb3a Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Mon, 7 Oct 2024 11:55:18 +0200 Subject: [PATCH 2/4] substrate docs update --- .../README.md | 49 ++++++++++++++----- .../src/transfer.ts | 2 + 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/examples/substrate-to-evm-fungible-transfer/README.md b/examples/substrate-to-evm-fungible-transfer/README.md index 4707cc906..3ae91bc9c 100644 --- a/examples/substrate-to-evm-fungible-transfer/README.md +++ b/examples/substrate-to-evm-fungible-transfer/README.md @@ -1,4 +1,4 @@ -## Sygma SDK Substrate Asset Transfer Example +## Sygma SDK Substrate to EVM (Tangle to Sepolia) Asset Transfer Example This is an example script that demonstrates the functionality of the SDK using the Sygma ecosystem. The script showcases a Substrate Asset transfer between a Substrate network and an EVM network using the Sygma SDK. ## Prerequisites @@ -7,7 +7,7 @@ Before running the script, ensure that you have the following: - Node.js installed on your machine (v18.20.4) - Yarn (version 3.4.1 or higher) -- A Substrate development wallet funded with `TANGLE` tokens; **you may wish** to run the [EVM-to-Substrate example](../evm-to-substrate-fungible-transfer/) first to preload `PHA` tokens into a Substrate wallet +- A Substrate development wallet funded with `TANGLE` tokens; **you may wish** to run the [EVM-to-Substrate example](../evm-to-substrate-fungible-transfer) first to preload `PHA` tokens into a Substrate wallet - The 12-word mnemonic for your Substrate development wallet - An Ethereum wallet to receive tokens into (the example presets an existing wallet address already) - A Substrate provider (in case the hardcoded WSS within the script does not work) @@ -39,23 +39,47 @@ To start the example you need to build the sdk first with: yarn sdk:build ``` +### Obtaining sygUSD Tokens +The `RESOURCE_ID_SYGMA_USD` represents the ID for `sygUSD` tokens in the Sygma protocol. You will need `sygUSD` testnet tokens to complete this transfer. If you are transferring a different asset, you may need to replace this ID with the appropriate resource ID. + +You can obtain testnet `sygUSD` tokens for the Tangle testnet by visiting the [Sygma Testnet Faucet](https://docs.buildwithsygma.com/resources/environments/testnet/obtain-testnet-tokens/?ref=blog.buildwithsygma.com). + ## Usage This example uses the `dotenv` module to import the 12-word private mnemonic. To run the example, you will need to configure your environment variable to include your test development account's [12-word seed](https://support.polkadot.network/support/solutions/articles/65000169731-polkadot-extension-how-can-i-view-my-mnemonic-phrase-). A `.env.sample` is provided as a template. -**DO NOT COMMIT YOUR MENOMONIC WITH REAL FUNDS TO GITHUB. DOING SO COULD RESULT IN COMPLETE LOSS OF YOUR FUNDS.** +**DO NOT COMMIT YOUR MNEMONIC WITH REAL FUNDS TO GITHUB. DOING SO COULD RESULT IN COMPLETE LOSS OF YOUR FUNDS.** +### Environment Variables Create a `.env` file in the substrate-to-evm example folder: ```bash -cd examples/substrate-to-evm-fungible-transfer touch .env ``` +The file should contain the following environment variables: + +- PRIVATE_MNEMONIC: The 12-word mnemonic for your Substrate wallet. +- SOURCE_SUBSTRATE_RPC_URL: The WebSocket URL of the Substrate network (Tangle in this example). +- RECIPIENT_ADDRESS: The destination EVM address that will receive the tokens (Sepolia testnet in this example). +- SYGMA_ENV: The Sygma environment you’re using, e.g., testnet. + +Here’s an example of the .env file: +```bash +PRIVATE_MNEMONIC="YOUR TWELVE WORD MNEMONIC HERE" +SOURCE_SUBSTRATE_RPC_URL="wss://rpc.tangle.tools" +RECIPIENT_ADDRESS="YOUR EVM ADDRESS" +SYGMA_ENV="testnet" +```` + +### Obtaining Your 12-Word Mnemonic + +To create a Substrate wallet and obtain the 12-word mnemonic, follow this [Polkadot wallet guide](https://support.polkadot.network/support/solutions/articles/65000169731-polkadot-extension-how-can-i-view-my-mnemonic-phrase-). Replace between the quotation marks your 12-word mnemonic: `PRIVATE_MNEMONIC="YOUR TWELVE WORD MNEMONIC HERE WITH SPACES"` +### Run the example To send a Substrate token to an EVM chain example transfer run: ```bash @@ -67,6 +91,10 @@ create a transfer from `Tangle` to `Sepolia`. Replace the placeholder values in the `.env` file with your own Substrate wallet mnemonic, and your own destination EVM address within the script. +### Monitoring the Transfer + +Once the transaction is finalized, you can view the transaction details in the [Sygma Explorer](https://scan.test.buildwithsygma.com). + **Note** To replace default rpc TANGLE url use env variable: @@ -76,10 +104,9 @@ To replace default rpc TANGLE url use env variable: This example script performs the following steps: -- initializes the SDK and establishes a connection to the Substrate node. -- retrieves the list of supported domains and resources from the SDK configuration. -- Searches for the Substrate asset resource with the specified ResourceId -- Searches for the Tangle and Sepolia domains in the list of supported domains based on their chain IDs -- Constructs a transfer object that defines the details of the Substrate asset transfer -- Retrieves the fee required for the transfer from the SDK. -- Builds the final transfer transaction and sends it using the Substrate account. +1. **Initializes the SDK**: It connects to the Substrate node via WebSocket and initializes the SDK. +2. **Retrieves Supported Domains and Resources**: It fetches the list of supported domains (Tangle and Sepolia in this case) and resources like `sygUSD`. +3. **Constructs a Transfer Object**: A transfer object is built, specifying the token amount, the source, and destination chains (Tangle and Sepolia). +4. **Fetches Transfer Fees**: The SDK calculates the fees required for the transfer. +5. **Signs and Sends the Transaction**: The transfer transaction is signed with your Substrate account and broadcasted to the network. +6. **Monitors Transaction Status**: The script logs transaction statuses such as `InBlock` and `Finalized`. It provides a link to the [Sygma Explorer](https://scan.test.buildwithsygma.com) where the transaction can be monitored. diff --git a/examples/substrate-to-evm-fungible-transfer/src/transfer.ts b/examples/substrate-to-evm-fungible-transfer/src/transfer.ts index 361552aed..ba4de3050 100644 --- a/examples/substrate-to-evm-fungible-transfer/src/transfer.ts +++ b/examples/substrate-to-evm-fungible-transfer/src/transfer.ts @@ -72,6 +72,8 @@ const substrateTransfer = async (): Promise => { } unsub(); process.exit(0); + } else if (status.isDropped || status.isInvalid || status.isUsurped) { + console.error("Transaction failed. Status:", status.toString()); } }); }; From 32aee083e8e862d8c709de17152abd90f703259e Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Tue, 8 Oct 2024 17:11:55 +0200 Subject: [PATCH 3/4] update docs --- .../evm-to-evm-fungible-transfer/README.md | 169 ++++++++++++--- .../README.md | 196 ++++++++++++++---- .../src/transfer.ts | 6 +- .../README.md | 15 +- 4 files changed, 299 insertions(+), 87 deletions(-) diff --git a/examples/evm-to-evm-fungible-transfer/README.md b/examples/evm-to-evm-fungible-transfer/README.md index fb66a013a..a27cd9648 100644 --- a/examples/evm-to-evm-fungible-transfer/README.md +++ b/examples/evm-to-evm-fungible-transfer/README.md @@ -1,30 +1,42 @@ -## Sygma SDK ERC20 Example +# EVM-to-EVM (Sepolia to Base Sepolia) token transfer example -This is an example script that demonstrates the functionality of the SDK using the Sygma ecosystem. The script showcases an ERC20 token transfer between the same account on two different testnets using the Sygma SDK. +In the following example, we will use the `TESTNET` environment to perform a cross-chain ERC-20 transfer with 5 `ERC20LRTST` tokens. The transfer will be initiated on the EVM-side via the Cronos testnet and received on the EVM-side via the Sepolia Ethereum testnet. -## Prerequisites +This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of relayers and bridge and handler contracts. The complete example can be found in this [repo]( +https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-evm-fungible-transfer). + +### Prerequisites Before running the script, ensure that you have the following: -- Node.js +- Node.js v18 - Yarn (version 3.4.1 or higher) -- A development wallet funded with `ERC20LRTest` tokens from the [Sygma faucet](https://faucet-ui-stage.buildwithsygma.com/) - The [exported private key](https://support.metamask.io/hc/en-us/articles/360015289632-How-to-export-an-account-s-private-key) of your development wallet -- [Sepolia ETH](https://www.alchemy.com/faucets/ethereum-sepolia) for gas +- Testnet [CRO](https://docs.cronos.org/for-users/testnet-faucet) for gas - An Ethereum [provider](https://www.infura.io/) (in case the hardcoded RPC within the script does not work) +- A development wallet funded with `ERC20LRTest` tokens from the [Sygma faucet](https://faucet-ui-stage.buildwithsygma.com/) (you can use the UI below; please allow some time for minting as testnet may be congested) + +import App from '../../../../src/Faucet/App'; + + +
+ +:::danger +We make use of the dotenv module to manage exported private keys with environment variables. Please note that accidentally committing a .env file containing private keys to a wallet with real funds, onto GitHub, could result in the complete loss of your funds. **Never expose your private keys.** +::: -## Getting started +### Getting started -### 1. Clone the repository +1. Clone the repository -To get started, clone this repository to your local machine with: +Clone the sygma-sdk repository into a directory of your choice, and then `cd` into the folder: ```bash -git clone git@github.com:sygmaprotocol/sygma-sdk.git +git clone https://github.com/sygmaprotocol/sygma-sdk.git cd sygma-sdk/ ``` -### 2. Install dependencies +2. Install dependencies Install the project dependencies by running: @@ -32,15 +44,15 @@ Install the project dependencies by running: yarn install ``` -### 3. Build the sdk +3. Build the SDK -To start the example you need to build the sdk first with: +Build the SDK by running the following command: ```bash -yarn build:all +yarn build ``` -## Usage +4. Usage This example uses the `dotenv` module to manage private keys. To run the example, you will need to configure your environment variable to include your test development account's [exported private key](https://support.metamask.io/hc/en-us/articles/360015289632-How-to-export-an-account-s-private-key). A `.env.sample` is provided as a template. @@ -55,34 +67,125 @@ touch .env Replace between the quotation marks your exported private key: -`PRIVATE_KEY="YOUR_PRIVATE_KEY_HERE"` +```dotenv +PRIVATE_KEY="YOUR_PRIVATE_KEY_HERE" +``` -To send an ERC20 example transfer run: +To send an ERC-20 example transfer from EVM to EVM, run: ```bash +cd examples/evm-to-evm-fungible-transfer yarn run transfer ``` -The example will use `ethers` in conjuction with the sygma-sdk to -create a transfer from `Sepolia` to `Holesky` with a test ERC20 token. +The example will use `ethers` in conjunction with the sygma-sdk to create a transfer from Cronos to Sepolia with the `ERC20LRTST` token. It will be received on Sepolia as the `ERC20LRTST` token. + +## Script functionality + +This example script performs a cross-chain ERC-20 token transfer using the Sygma SDK. The transfer starts on one EVM chain (e.g., Cronos or Sepolia) and is received on another EVM chain (e.g., Sepolia or BASE). Here’s how the script works: + +### 1. Imports the Required Packages: +The script first imports all the necessary modules, including those from the Sygma SDK (for asset transfer) and ethers.js (for interacting with Ethereum wallets and providers). +```ts +import { getSygmaScanLink, type Eip1193Provider } from "@buildwithsygma/core"; +import { + createFungibleAssetTransfer, + FungibleTransferParams, +} from "@buildwithsygma/evm"; +import dotenv from "dotenv"; +import { Wallet, providers } from "ethers"; +import Web3HttpProvider from "web3-providers-http"; +``` +Constants like SEPOLIA_CHAIN_ID, RESOURCE_ID, and CRONOS_RPC_URL are defined based on the specific environment you are working in. +```ts +const SEPOLIA_CHAIN_ID = 11155111; +const BASE_SEPOLIA_CHAIN_ID = 84532; +const RESOURCE_ID = + "0x0000000000000000000000000000000000000000000000000000000000001200"; +const SEPOLIA_RPC_URL = + process.env.SEPOLIA_RPC_URL || + "https://eth-sepolia.g.alchemy.com/v2/MeCKDrpxLkGOn4LMlBa3cKy1EzzOzwzG"; +``` + +### 2. Configures dotenv Module: +The script loads environment variables using the dotenv module. This includes sensitive information like your private key, which should be stored in a .env file for security purposes. -Replace the placeholder values in the `.env` file with your own Ethereum wallet private key. +```ts +import dotenv from "dotenv"; -**Note** +dotenv.config() -To replace default rpc Cronos and Sepolia urls use env variables: +const privateKey = process.env.PRIVATE_KEY; -- `SEPOLIA_RPC_URL="SEPOLIA_RPC_URL_HERE"` +if (!privateKey) { + throw new Error("Missing environment variable: PRIVATE_KEY"); +} +``` -## Script Functionality +The PRIVATE_KEY environment variable is critical for signing transactions with your Ethereum wallet. -This example script performs the following steps: +### 3. Defines the Transfer Function: +The erc20Transfer function is the main function that handles the token transfer. It initializes the provider and wallet, sets up the asset transfer, and constructs the transfer object. +```ts +export async function erc20Transfer(): Promise {} +``` -- initializes the SDK and establishes a connection to the Ethereum provider. -- retrieves the list of supported domains and resources from the SDK configuration. -- Searches for the ERC20 token resource with the specified symbol -- Searches for the Cronos and Sepolia domains in the list of supported domains based on their chain IDs -- Constructs a transfer object that defines the details of the ERC20 token transfer -- Retrieves the fee required for the transfer from the SDK. -- Builds the necessary approval transactions for the transfer and sends them using the Ethereum wallet. The approval transactions are required to authorize the transfer of ERC20 tokens. -- Builds the final transfer transaction and sends it using the Ethereum wallet. +### 4. Sets Up the Provider and Wallet: + +The script sets up a Web3 provider and creates a wallet using the provided private key. In this case, the script is interacting with the Sepolia network. + +```ts +const provider = new providers.JsonRpcProvider(CRONOS_RPC_URL); +const wallet = new Wallet(privateKey ?? "", provider); +``` + +### 5. Initializes the Asset Transfer Object: +The Sygma SDK’s EVMAssetTransfer object is initialized using the TESTNET environment. This object is used to build and manage the cross-chain ERC-20 transfer. +```ts +const assetTransfer = new EVMAssetTransfer(); +await assetTransfer.init(provider, Environment.TESTNET); +``` +### 6. Constructs the Transfer Object: +The script constructs a transfer object using the sender’s address, recipient’s address (same in this case but on a different chain), and the amount to be transferred (5 tokens, represented with 18 decimal places). + +```ts + const transfer = assetTransfer.createFungibleTransfer( + await wallet.getAddress(), + SEPOLIA_CHAIN_ID, + await wallet.getAddress(), // Sending to the same address on a different chain + RESOURCE_ID, + "5000000000000000000" // 18 decimal places, so in this case, 5 tokens would be sent + ); +``` + +### 7. Builds and Sends Approval Transactions: +Before the actual transfer, approval transactions must be sent to authorize the transfer of ERC-20 tokens. The script iterates over the approval transactions, sends them, and logs their transaction hashes. +```ts +const approvals = await transfer.getApprovalTransactions(); +console.log(`Approving Tokens (${approvals.length})...`); +for (const approval of approvals) { + const response = await wallet.sendTransaction(approval); + await response.wait(); + console.log( + `Approved, transaction: ${getTxExplorerUrl({txHash: response.hash, chainId: SEPOLIA_CHAIN_ID})}` + ); +} +``` + + +### 8. Builds and Sends the Final Transfer Transaction: +After approval, the script builds the transfer transaction and sends it to the Ethereum network. Once the transaction is sent, it logs the transaction hash. +```ts + const transferTx = await transfer.getTransferTransaction(); + const response = await wallet.sendTransaction(transferTx); + await response.wait(); +console.log( + `Depositted, transaction: ${getSygmaScanLink(response.hash, process.env.SYGMA_ENV)}` +); +``` + +### 9. Call the method +Call the described method above +```ts +erc20Transfer().finally(() => {}); +``` diff --git a/examples/evm-to-substrate-fungible-transfer/README.md b/examples/evm-to-substrate-fungible-transfer/README.md index 5fa1c8388..b3301dcd6 100644 --- a/examples/evm-to-substrate-fungible-transfer/README.md +++ b/examples/evm-to-substrate-fungible-transfer/README.md @@ -1,29 +1,41 @@ -## Sygma SDK Substrate Asset Transfer Example +# EVM to Substrate (Sepolia to Tangle) Token Transfer Example -This is an example script that demonstrates the functionality of the SDK using the Sygma ecosystem. The script showcases a EVM Asset transfer between a EVM network and an Substrate network using the Sygma SDK. +The following example demonstrates how to use the Sygma SDK to transfer ERC-20 tokens from an EVM chain (in this case, Sepolia) to a Substrate chain (Tangle) using the SDK’s functionalities and Ethereum’s ethers.js library. -## Prerequisites +In the following example, we will use the `TESTNET` environment to perform a cross-chain ERC-20 transfer with 0.5 Sepolia sygUSD `sygUSD` tokens. The transfer will be initiated on the EVM-side via the Sepolia Ethereum testnet and received on the Substrate-side via the Rococo-Phala testnet. + +This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of relayers and bridge and handler contracts/pallets. The complete example can be found in this [repo]( +https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-substrate-fungible-transfer#sygma-sdk-erc20-example). + +### Prerequisites Before running the script, ensure that you have the following: -- Node.js installed on your machine -- Yarn (version 3.4.1 or higher) -- A EVM development wallet funded with `SepoliaETH` tokens -- The Private key for your EVM development wallet -- An Substrate wallet to receive tokens into (the example presets an existing wallet address already) +- Node.js installed on your machine (v18.20.4) +- Yarn (version 4 or higher) +- The [exported private key](https://support.metamask.io/hc/en-us/articles/360015289632-How-to-export-an-account-s-private-key) of your development wallet +- A Substrate wallet to receive tokens into (the example presets an existing wallet address already) +- [Sepolia ETH](https://sepoliafaucet.com/) for gas +- An Ethereum [provider](https://www.infura.io/) (in case the hardcoded RPC within the script does not work) +- A development wallet funded with `sygUSD` tokens from the [Sygma faucet](https://faucet-ui-stage.buildwithsygma.com/) + +import App from '../../../../src/Faucet/App'; -## Getting started + +
-### 1. Clone the repository +### Getting started -To get started, clone this repository to your local machine with: +1. Clone the repository + +Clone the sygma-sdk repository into a directory of your choice, and then `cd` into the folder: ```bash -git clone git@github.com:sygmaprotocol/sygma-sdk.git +git clone https://github.com/sygmaprotocol/sygma-sdk.git cd sygma-sdk/ ``` -### 2. Install dependencies +2. Install dependencies Install the project dependencies by running: @@ -31,55 +43,157 @@ Install the project dependencies by running: yarn install ``` -### 3. Build the sdk +3. Build the SDK -To start the example you need to build the sdk first with: +Build the SDK by running the following command: ```bash -yarn sdk:build +yarn build ``` -## Usage +4. Usage + +:::danger Important Security Notice +This example uses the dotenv module to manage sensitive information like private keys. Never expose your private keys or commit them to public repositories. Doing so could lead to the loss of all your funds. Make sure you handle private keys with care and follow best practices for security. +::: -This example uses the `dotenv` module to manage private keys. To run the example, you will need to configure your environment variable to include your test development account's [exported private key](https://support.metamask.io/hc/en-us/articles/360015289632-How-to-export-an-account-s-private-key). A `.env.sample` is provided as a template. +This script relies on the dotenv module to securely manage your private keys via environment variables. To run the example, you need to configure the environment variables for your test development account’s exported private key. A .env.sample file is provided as a template for you to create and manage these variables. -**DO NOT COMMIT PRIVATE KEYS WITH REAL FUNDS TO GITHUB. DOING SO COULD RESULT IN COMPLETE LOSS OF YOUR FUNDS.** +### Steps to Set Up Environment Variables -Create a `.env` file in the evm-to-evm example folder: +1. Create a .env file in the evm-to-substrate-fungible-transfer example folder: ```bash cd examples/evm-to-substrate-fungible-transfer touch .env ``` +2. Add your exported private key to the .env file. Replace the placeholder text with your actual private key: +```dotenv +PRIVATE_KEY="YOUR_PRIVATE_KEY_HERE" +``` -Replace between the quotation marks your exported private key: - -`PRIVATE_KEY="YOUR_PRIVATE_KEY_HERE"` - -To send an ERC20 example transfer run: +### Running the Example +To send an ERC-20 token transfer from an EVM chain (Sepolia) to a Substrate chain (Tangle), use the following command: ```bash +cd examples/evm-to-substrate-fungible-transfer yarn run transfer ``` -The example will use `ethers` in conjuction with the sygma-sdk to -create a transfer from `Sepolia` to `Tangle` with a test ERC20 token. +This script uses **ethers.js** in conjunction with the sygma-sdk to handle the cross-chain transfer. The example demonstrates how to transfer sygUSD tokens from the Sepolia Ethereum testnet to the Tangle Substrate testnet, where it will be received as the same token (sygUSD). + + +### Script functionality +The script performs the following steps: + +1. Importing Required Packages + +The first step is to import all necessary libraries, including the Sygma SDK, dotenv for managing environment variables, and ethers.js for interacting with the Ethereum blockchain. +```ts +import type { Eip1193Provider } from "@buildwithsygma/core"; +import { createFungibleAssetTransfer } from "@buildwithsygma/evm"; +import dotenv from "dotenv"; +import { Wallet, providers } from "ethers"; +import Web3HttpProvider from "web3-providers-http"; + +dotenv.config(); +``` +Here, dotenv.config() loads environment variables (such as private keys) from a .env file into process.env. + +2. Loading and Validating the Private Key + +The script fetches the **PRIVATE_KEY** from the .env file. If the private key is not found, an error is thrown to prevent the script from running without the necessary credentials. +```ts +const privateKey = process.env.PRIVATE_KEY; + +if (!privateKey) { + throw new Error("Missing environment variable: PRIVATE_KEY"); +} +``` + +3. Setting up Constants + Key constants are defined for the Sepolia and Tangle chain IDs, the sygUSD token’s Resource ID, and the Sepolia RPC URL. The script also sets up a function to generate the transaction URL for Etherscan, enabling easy tracking of the transaction. +```ts +const SEPOLIA_CHAIN_ID = 11155111; +const TANGLE_CHAIN_ID = 3799; +const RESOURCE_ID = "0x0000000000000000000000000000000000000000000000000000000000002000"; +const SEPOLIA_RPC_URL = process.env.SOURCE_EVM_RPC_URL ?? "https://eth-sepolia.g.alchemy.com/v2/MeCKDrpxLkGOn4LMlBa3cKy1EzzOzwzG"; + +const explorerUrls: Record = { + [SEPOLIA_CHAIN_ID]: "https://sepolia.etherscan.io", +}; + +const getTxExplorerUrl = (params: { txHash: string; chainId: number }): string => + `${explorerUrls[params.chainId]}/tx/${params.txHash}`; +``` +4. Defining the ERC-20 Transfer Function + +The core logic for the token transfer is encapsulated in the erc20Transfer function. This function sets up the provider and wallet using ethers.js, connects to the Sepolia network, and prepares for the cross-chain transfer. +Set up the provider, wallet, and asset transfer objects using the TESTNET environment. + +```ts +export async function erc20Transfer(): Promise { + const web3Provider = new Web3HttpProvider(SEPOLIA_RPC_URL); + const ethersWeb3Provider = new providers.Web3Provider(web3Provider); + const wallet = new Wallet(privateKey ?? "", ethersWeb3Provider); + const sourceAddress = await wallet.getAddress(); + const destinationAddress = "5GjowPEaFNnwbrmpPuDmBVdF2e7n3cHwk2LnUwHXsaW5KtEL"; // Substrate address +``` + +5. Constructing the Transfer Object + +The transfer object is created by specifying the source and destination chain IDs, the source and destination addresses, the amount to transfer (1 sygUSD token), and the token’s Resource ID. +```ts + const params = { + source: SEPOLIA_CHAIN_ID, + destination: TANGLE_CHAIN_ID, + sourceNetworkProvider: web3Provider as unknown as Eip1193Provider, + resource: RESOURCE_ID, + amount: BigInt(1) * BigInt(1e18), // 1 sygUSD token (18 decimals) + recipientAddress: destinationAddress, + sourceAddress: sourceAddress, + }; +``` -Replace the placeholder values in the `.env` file with your own Ethereum wallet private key. +Here, the transfer object specifies the details of the cross-chain transfer, including the network provider and the token amount. +6. Getting and Sending Approval Transactions + +Before sending the transfer, the script needs to obtain and send approval transactions to allow the smart contract to move the user’s tokens. This step ensures that the tokens are authorized for transfer. + +```ts + const transfer = await createFungibleAssetTransfer(params); + const approvals = await transfer.getApprovalTransactions(); + console.log(`Approving Tokens (${approvals.length})...`); + + for (const approval of approvals) { + const response = await wallet.sendTransaction(approval); + await response.wait(); + console.log( + `Approved, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` + ); + } +``` + +This loop iterates through each approval transaction, sending them through the Ethereum network and logging the transaction hash for tracking purposes. + +7. Sending the Transfer Transaction + +After the approvals are complete, the script constructs and sends the actual cross-chain transfer transaction. The transfer is confirmed once the transaction is finalized on the Ethereum side. +```ts + const transferTx = await transfer.getTransferTransaction(); + const response = await wallet.sendTransaction(transferTx); + await response.wait(); + console.log( + `Deposited, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` + ); +``` -**Note** +Once the transaction is confirmed, the console logs the deposit confirmation and provides the Etherscan link to track the transaction. -To replace default Sepolia url use env variables: -- `SOURCE_EVM_RPC_URL="EVM_RPC_URL"` -## Script Functionality +8. Executing the Transfer Function -This example script performs the following steps: -- initializes the SDK and establishes a connection to the Ethereum provider. -- retrieves the list of supported domains and resources from the SDK configuration. -- Searches for the ERC20 token resource with the specified symbol -- Searches for the Sepolia and Tangle domains in the list of supported domains based on their chain IDs -- Constructs a transfer object that defines the details of the ERC20 token transfer -- Retrieves the fee required for the transfer from the SDK. -- Builds the necessary approval transactions for the transfer and sends them using the Ethereum wallet. The approval transactions are required to authorize the transfer of ERC20 tokens. -- Builds the final transfer transaction and sends it using the Ethereum wallet. +Finally, the erc20Transfer function is executed. The .finally() method ensures that any necessary cleanup is performed once the function has completed. +```ts +erc20Transfer().finally(() => {}); +``` \ No newline at end of file diff --git a/examples/evm-to-substrate-fungible-transfer/src/transfer.ts b/examples/evm-to-substrate-fungible-transfer/src/transfer.ts index 07cddaafa..936d8bc3b 100644 --- a/examples/evm-to-substrate-fungible-transfer/src/transfer.ts +++ b/examples/evm-to-substrate-fungible-transfer/src/transfer.ts @@ -1,5 +1,5 @@ import type { Eip1193Provider } from "@buildwithsygma/core"; -import { createEvmFungibleAssetTransfer } from "@buildwithsygma/evm"; +import { createFungibleAssetTransfer } from "@buildwithsygma/evm"; import dotenv from "dotenv"; import { Wallet, providers } from "ethers"; import Web3HttpProvider from "web3-providers-http"; @@ -41,11 +41,11 @@ export async function erc20Transfer(): Promise { sourceNetworkProvider: web3Provider as unknown as Eip1193Provider, resource: RESOURCE_ID, amount: BigInt(1) * BigInt(1e18), - destinationAddress: destinationAddress, + recipientAddress: destinationAddress, sourceAddress: sourceAddress, }; - const transfer = await createEvmFungibleAssetTransfer(params); + const transfer = await createFungibleAssetTransfer(params); const approvals = await transfer.getApprovalTransactions(); console.log(`Approving Tokens (${approvals.length})...`); for (const approval of approvals) { diff --git a/examples/substrate-to-evm-fungible-transfer/README.md b/examples/substrate-to-evm-fungible-transfer/README.md index 3ae91bc9c..9cfc8026f 100644 --- a/examples/substrate-to-evm-fungible-transfer/README.md +++ b/examples/substrate-to-evm-fungible-transfer/README.md @@ -1,4 +1,4 @@ -## Sygma SDK Substrate to EVM (Tangle to Sepolia) Asset Transfer Example +# Sygma SDK Substrate to EVM (Tangle to Sepolia) Asset Transfer Example This is an example script that demonstrates the functionality of the SDK using the Sygma ecosystem. The script showcases a Substrate Asset transfer between a Substrate network and an EVM network using the Sygma SDK. ## Prerequisites @@ -7,7 +7,7 @@ Before running the script, ensure that you have the following: - Node.js installed on your machine (v18.20.4) - Yarn (version 3.4.1 or higher) -- A Substrate development wallet funded with `TANGLE` tokens; **you may wish** to run the [EVM-to-Substrate example](../evm-to-substrate-fungible-transfer) first to preload `PHA` tokens into a Substrate wallet +- A Substrate development wallet funded with TANGLE `TNT` tokens; **you may wish** to run the [EVM-to-Substrate example](https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-substrate-fungible-transfer/) first to preload `TNT` tokens into a Substrate wallet - The 12-word mnemonic for your Substrate development wallet - An Ethereum wallet to receive tokens into (the example presets an existing wallet address already) - A Substrate provider (in case the hardcoded WSS within the script does not work) @@ -19,7 +19,7 @@ Before running the script, ensure that you have the following: To get started, clone this repository to your local machine with: ```bash -git clone git@github.com:sygmaprotocol/sygma-sdk.git +git clone https://github.com/sygmaprotocol/sygma-sdk.git cd sygma-sdk/ ``` @@ -36,7 +36,7 @@ yarn install To start the example you need to build the sdk first with: ```bash -yarn sdk:build +yarn build ``` ### Obtaining sygUSD Tokens @@ -64,7 +64,7 @@ The file should contain the following environment variables: - SYGMA_ENV: The Sygma environment you’re using, e.g., testnet. Here’s an example of the .env file: -```bash +```dotenv PRIVATE_MNEMONIC="YOUR TWELVE WORD MNEMONIC HERE" SOURCE_SUBSTRATE_RPC_URL="wss://rpc.tangle.tools" RECIPIENT_ADDRESS="YOUR EVM ADDRESS" @@ -95,11 +95,6 @@ Replace the placeholder values in the `.env` file with your own Substrate wallet Once the transaction is finalized, you can view the transaction details in the [Sygma Explorer](https://scan.test.buildwithsygma.com). -**Note** - -To replace default rpc TANGLE url use env variable: -- `SOURCE_SUBSTRATE_RPC_URL="TANGLE_RPC_URL_HERE"` - ## Script Functionality This example script performs the following steps: From 30d09fd188a0d21047f5cdf18d3fa1e2175b4749 Mon Sep 17 00:00:00 2001 From: Saad Ahmed Siddiqui Date: Mon, 21 Oct 2024 12:54:36 +0200 Subject: [PATCH 4/4] reconcile docs with examples --- .../evm-to-evm-fungible-transfer/README.md | 96 +++++++-------- .../src/transfer.ts | 9 +- .../.env.sample | 3 +- .../README.md | 114 ++++++++++-------- .../src/environment.d.ts | 1 + .../src/transfer.ts | 10 +- .../README.md | 14 ++- .../src/transfer.ts | 10 +- 8 files changed, 138 insertions(+), 119 deletions(-) diff --git a/examples/evm-to-evm-fungible-transfer/README.md b/examples/evm-to-evm-fungible-transfer/README.md index a27cd9648..83c7d6fee 100644 --- a/examples/evm-to-evm-fungible-transfer/README.md +++ b/examples/evm-to-evm-fungible-transfer/README.md @@ -1,9 +1,8 @@ # EVM-to-EVM (Sepolia to Base Sepolia) token transfer example -In the following example, we will use the `TESTNET` environment to perform a cross-chain ERC-20 transfer with 5 `ERC20LRTST` tokens. The transfer will be initiated on the EVM-side via the Cronos testnet and received on the EVM-side via the Sepolia Ethereum testnet. +In the following example, we will use the `TESTNET` environment to perform a cross-chain ERC-20 transfer with 1 testnet `USDC` tokens. The transfer will be initiated on the EVM-side via the Ethereum Sepolia testnet and received on Base Sepolia testnet. -This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of relayers and bridge and handler contracts. The complete example can be found in this [repo]( -https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-evm-fungible-transfer). +This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of relayers and bridge and handler contracts. The complete example can be found in this [repo](https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-evm-fungible-transfer). ### Prerequisites @@ -12,14 +11,9 @@ Before running the script, ensure that you have the following: - Node.js v18 - Yarn (version 3.4.1 or higher) - The [exported private key](https://support.metamask.io/hc/en-us/articles/360015289632-How-to-export-an-account-s-private-key) of your development wallet -- Testnet [CRO](https://docs.cronos.org/for-users/testnet-faucet) for gas +- Testnet [ETH](https://cloud.google.com/application/web3/faucet/ethereum/sepolia) for gas - An Ethereum [provider](https://www.infura.io/) (in case the hardcoded RPC within the script does not work) -- A development wallet funded with `ERC20LRTest` tokens from the [Sygma faucet](https://faucet-ui-stage.buildwithsygma.com/) (you can use the UI below; please allow some time for minting as testnet may be congested) - -import App from '../../../../src/Faucet/App'; - - -
+- A development wallet funded with `USDC` tokens from the [USDC Faucet](https://faucet.circle.com) :::danger We make use of the dotenv module to manage exported private keys with environment variables. Please note that accidentally committing a .env file containing private keys to a wallet with real funds, onto GitHub, could result in the complete loss of your funds. **Never expose your private keys.** @@ -78,14 +72,16 @@ cd examples/evm-to-evm-fungible-transfer yarn run transfer ``` -The example will use `ethers` in conjunction with the sygma-sdk to create a transfer from Cronos to Sepolia with the `ERC20LRTST` token. It will be received on Sepolia as the `ERC20LRTST` token. +The example will use `ethers` in conjunction with the sygma-sdk to create a transfer from Sepolia to Base Sepolia with the `USDC` token. It will be received on Sepolia as the `USDC` token. ## Script functionality -This example script performs a cross-chain ERC-20 token transfer using the Sygma SDK. The transfer starts on one EVM chain (e.g., Cronos or Sepolia) and is received on another EVM chain (e.g., Sepolia or BASE). Here’s how the script works: +This example script performs a cross-chain ERC-20 token transfer using the Sygma SDK. The transfer starts on one EVM chain (e.g., Sepolia) and is received on another EVM chain (e.g., BASE). Here’s how the script works: + +### 1. Imports the Required Packages: -### 1. Imports the Required Packages: The script first imports all the necessary modules, including those from the Sygma SDK (for asset transfer) and ethers.js (for interacting with Ethereum wallets and providers). + ```ts import { getSygmaScanLink, type Eip1193Provider } from "@buildwithsygma/core"; import { @@ -96,24 +92,26 @@ import dotenv from "dotenv"; import { Wallet, providers } from "ethers"; import Web3HttpProvider from "web3-providers-http"; ``` -Constants like SEPOLIA_CHAIN_ID, RESOURCE_ID, and CRONOS_RPC_URL are defined based on the specific environment you are working in. + +Constants like `SEPOLIA_CHAIN_ID`, `RESOURCE_ID`, and `BASE_SEPOLIA_CHAIN_ID` are defined based on the specific environment you are working in. + ```ts const SEPOLIA_CHAIN_ID = 11155111; const BASE_SEPOLIA_CHAIN_ID = 84532; const RESOURCE_ID = "0x0000000000000000000000000000000000000000000000000000000000001200"; const SEPOLIA_RPC_URL = - process.env.SEPOLIA_RPC_URL || - "https://eth-sepolia.g.alchemy.com/v2/MeCKDrpxLkGOn4LMlBa3cKy1EzzOzwzG"; + process.env.SEPOLIA_RPC_URL || "https://ethereum-sepolia-rpc.publicnode.com"; ``` ### 2. Configures dotenv Module: + The script loads environment variables using the dotenv module. This includes sensitive information like your private key, which should be stored in a .env file for security purposes. ```ts import dotenv from "dotenv"; -dotenv.config() +dotenv.config(); const privateKey = process.env.PRIVATE_KEY; @@ -124,8 +122,10 @@ if (!privateKey) { The PRIVATE_KEY environment variable is critical for signing transactions with your Ethereum wallet. -### 3. Defines the Transfer Function: +### 3. Defines the Transfer Function: + The erc20Transfer function is the main function that handles the token transfer. It initializes the provider and wallet, sets up the asset transfer, and constructs the transfer object. + ```ts export async function erc20Transfer(): Promise {} ``` @@ -135,57 +135,57 @@ export async function erc20Transfer(): Promise {} The script sets up a Web3 provider and creates a wallet using the provided private key. In this case, the script is interacting with the Sepolia network. ```ts -const provider = new providers.JsonRpcProvider(CRONOS_RPC_URL); -const wallet = new Wallet(privateKey ?? "", provider); +const web3Provider = new Web3HttpProvider(SEPOLIA_RPC_URL); +const ethersWeb3Provider = new providers.Web3Provider(web3Provider); +const wallet = new Wallet(privateKey ?? "", ethersWeb3Provider); +const sourceAddress = await wallet.getAddress(); +const destinationAddress = await wallet.getAddress(); ``` ### 5. Initializes the Asset Transfer Object: -The Sygma SDK’s EVMAssetTransfer object is initialized using the TESTNET environment. This object is used to build and manage the cross-chain ERC-20 transfer. -```ts -const assetTransfer = new EVMAssetTransfer(); -await assetTransfer.init(provider, Environment.TESTNET); -``` -### 6. Constructs the Transfer Object: -The script constructs a transfer object using the sender’s address, recipient’s address (same in this case but on a different chain), and the amount to be transferred (5 tokens, represented with 18 decimal places). + +The Sygma SDK’s EVM Asset Transfer object is initialized using the TESTNET environment. This object is used to build and manage the cross-chain ERC-20 transfer. The script constructs a transfer object using the sender’s address, recipient’s address (same in this case but on a different chain), and the amount to be transferred (1 token, represented with 6 decimal places). ```ts - const transfer = assetTransfer.createFungibleTransfer( - await wallet.getAddress(), - SEPOLIA_CHAIN_ID, - await wallet.getAddress(), // Sending to the same address on a different chain - RESOURCE_ID, - "5000000000000000000" // 18 decimal places, so in this case, 5 tokens would be sent - ); +const params: FungibleTransferParams = { + source: SEPOLIA_CHAIN_ID, + destination: BASE_SEPOLIA_CHAIN_ID, + sourceNetworkProvider: web3Provider as unknown as Eip1193Provider, + resource: RESOURCE_ID, + amount: BigInt(1) * BigInt(1e6), + recipientAddress: destinationAddress, + sourceAddress: sourceAddress, +}; + +const transfer = await createFungibleAssetTransfer(params); ``` -### 7. Builds and Sends Approval Transactions: +### 6. Builds and Sends Approval Transactions: + Before the actual transfer, approval transactions must be sent to authorize the transfer of ERC-20 tokens. The script iterates over the approval transactions, sends them, and logs their transaction hashes. + ```ts const approvals = await transfer.getApprovalTransactions(); -console.log(`Approving Tokens (${approvals.length})...`); for (const approval of approvals) { - const response = await wallet.sendTransaction(approval); - await response.wait(); - console.log( - `Approved, transaction: ${getTxExplorerUrl({txHash: response.hash, chainId: SEPOLIA_CHAIN_ID})}` - ); + const response = await wallet.sendTransaction(approval); + await response.wait(); } ``` +### 7. Builds and Sends the Final Transfer Transaction: -### 8. Builds and Sends the Final Transfer Transaction: After approval, the script builds the transfer transaction and sends it to the Ethereum network. Once the transaction is sent, it logs the transaction hash. + ```ts - const transferTx = await transfer.getTransferTransaction(); - const response = await wallet.sendTransaction(transferTx); - await response.wait(); -console.log( - `Depositted, transaction: ${getSygmaScanLink(response.hash, process.env.SYGMA_ENV)}` -); +const transferTx = await transfer.getTransferTransaction(); +const response = await wallet.sendTransaction(transferTx); +await response.wait(); ``` ### 9. Call the method + Call the described method above + ```ts erc20Transfer().finally(() => {}); ``` diff --git a/examples/evm-to-evm-fungible-transfer/src/transfer.ts b/examples/evm-to-evm-fungible-transfer/src/transfer.ts index 9ce0b159d..4554c6be2 100644 --- a/examples/evm-to-evm-fungible-transfer/src/transfer.ts +++ b/examples/evm-to-evm-fungible-transfer/src/transfer.ts @@ -1,4 +1,8 @@ -import { getSygmaScanLink, type Eip1193Provider } from "@buildwithsygma/core"; +import { + Environment, + getSygmaScanLink, + type Eip1193Provider, +} from "@buildwithsygma/core"; import { createFungibleAssetTransfer, FungibleTransferParams, @@ -20,8 +24,7 @@ const BASE_SEPOLIA_CHAIN_ID = 84532; const RESOURCE_ID = "0x0000000000000000000000000000000000000000000000000000000000001200"; const SEPOLIA_RPC_URL = - process.env.SEPOLIA_RPC_URL || - "https://eth-sepolia.g.alchemy.com/v2/MeCKDrpxLkGOn4LMlBa3cKy1EzzOzwzG"; + process.env.SEPOLIA_RPC_URL || "https://ethereum-sepolia-rpc.publicnode.com"; const explorerUrls: Record = { [SEPOLIA_CHAIN_ID]: "https://sepolia.etherscan.io", diff --git a/examples/evm-to-substrate-fungible-transfer/.env.sample b/examples/evm-to-substrate-fungible-transfer/.env.sample index 383a13dc8..ed4e2f715 100644 --- a/examples/evm-to-substrate-fungible-transfer/.env.sample +++ b/examples/evm-to-substrate-fungible-transfer/.env.sample @@ -1,3 +1,4 @@ PRIVATE_KEY="" SOURCE_EVM_RPC_URL="SEPOLIA_RPC_URL_HERE" -SYGMA_ENV="testnet" \ No newline at end of file +SYGMA_ENV="testnet" +RECIPIENT_ADDRESS="" \ No newline at end of file diff --git a/examples/evm-to-substrate-fungible-transfer/README.md b/examples/evm-to-substrate-fungible-transfer/README.md index b3301dcd6..df090eb9c 100644 --- a/examples/evm-to-substrate-fungible-transfer/README.md +++ b/examples/evm-to-substrate-fungible-transfer/README.md @@ -2,10 +2,9 @@ The following example demonstrates how to use the Sygma SDK to transfer ERC-20 tokens from an EVM chain (in this case, Sepolia) to a Substrate chain (Tangle) using the SDK’s functionalities and Ethereum’s ethers.js library. -In the following example, we will use the `TESTNET` environment to perform a cross-chain ERC-20 transfer with 0.5 Sepolia sygUSD `sygUSD` tokens. The transfer will be initiated on the EVM-side via the Sepolia Ethereum testnet and received on the Substrate-side via the Rococo-Phala testnet. +In the following example, we will use the `TESTNET` environment to perform a cross-chain ERC-20 transfer with 1 Sepolia `tTNT` token. The transfer will be initiated on the EVM-side via the Sepolia Ethereum testnet and received on the Substrate-side via the Rococo-Phala testnet. -This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of relayers and bridge and handler contracts/pallets. The complete example can be found in this [repo]( -https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-substrate-fungible-transfer#sygma-sdk-erc20-example). +This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of relayers and bridge and handler contracts/pallets. The complete example can be found in this [repo](https://github.com/sygmaprotocol/sygma-sdk/tree/main/examples/evm-to-substrate-fungible-transfer#sygma-sdk-erc20-example). ### Prerequisites @@ -19,11 +18,6 @@ Before running the script, ensure that you have the following: - An Ethereum [provider](https://www.infura.io/) (in case the hardcoded RPC within the script does not work) - A development wallet funded with `sygUSD` tokens from the [Sygma faucet](https://faucet-ui-stage.buildwithsygma.com/) -import App from '../../../../src/Faucet/App'; - - -
- ### Getting started 1. Clone the repository @@ -61,18 +55,21 @@ This script relies on the dotenv module to securely manage your private keys via ### Steps to Set Up Environment Variables -1. Create a .env file in the evm-to-substrate-fungible-transfer example folder: +1. Create a `.env` file in the evm-to-substrate-fungible-transfer example folder: ```bash cd examples/evm-to-substrate-fungible-transfer touch .env ``` + 2. Add your exported private key to the .env file. Replace the placeholder text with your actual private key: + ```dotenv PRIVATE_KEY="YOUR_PRIVATE_KEY_HERE" ``` ### Running the Example + To send an ERC-20 token transfer from an EVM chain (Sepolia) to a Substrate chain (Tangle), use the following command: ```bash @@ -80,15 +77,16 @@ cd examples/evm-to-substrate-fungible-transfer yarn run transfer ``` -This script uses **ethers.js** in conjunction with the sygma-sdk to handle the cross-chain transfer. The example demonstrates how to transfer sygUSD tokens from the Sepolia Ethereum testnet to the Tangle Substrate testnet, where it will be received as the same token (sygUSD). - +This script uses **ethers.js** in conjunction with the sygma-sdk to handle the cross-chain transfer. The example demonstrates how to transfer `tTNT` tokens from the Sepolia Ethereum testnet to the Tangle Substrate testnet, where it will be received as the same token (`tTNT`). ### Script functionality + The script performs the following steps: 1. Importing Required Packages The first step is to import all necessary libraries, including the Sygma SDK, dotenv for managing environment variables, and ethers.js for interacting with the Ethereum blockchain. + ```ts import type { Eip1193Provider } from "@buildwithsygma/core"; import { createFungibleAssetTransfer } from "@buildwithsygma/evm"; @@ -98,61 +96,70 @@ import Web3HttpProvider from "web3-providers-http"; dotenv.config(); ``` -Here, dotenv.config() loads environment variables (such as private keys) from a .env file into process.env. + +Here, `dotenv.config()` loads environment variables (such as private keys) from a .env file into process.env. 2. Loading and Validating the Private Key The script fetches the **PRIVATE_KEY** from the .env file. If the private key is not found, an error is thrown to prevent the script from running without the necessary credentials. + ```ts const privateKey = process.env.PRIVATE_KEY; if (!privateKey) { - throw new Error("Missing environment variable: PRIVATE_KEY"); + throw new Error("Missing environment variable: PRIVATE_KEY"); } ``` 3. Setting up Constants Key constants are defined for the Sepolia and Tangle chain IDs, the sygUSD token’s Resource ID, and the Sepolia RPC URL. The script also sets up a function to generate the transaction URL for Etherscan, enabling easy tracking of the transaction. + ```ts const SEPOLIA_CHAIN_ID = 11155111; const TANGLE_CHAIN_ID = 3799; -const RESOURCE_ID = "0x0000000000000000000000000000000000000000000000000000000000002000"; -const SEPOLIA_RPC_URL = process.env.SOURCE_EVM_RPC_URL ?? "https://eth-sepolia.g.alchemy.com/v2/MeCKDrpxLkGOn4LMlBa3cKy1EzzOzwzG"; +const RESOURCE_ID = + "0x0000000000000000000000000000000000000000000000000000000000002000"; +const SEPOLIA_RPC_URL = + process.env.SOURCE_EVM_RPC_URL ?? + "https://ethereum-sepolia-rpc.publicnode.com"; const explorerUrls: Record = { - [SEPOLIA_CHAIN_ID]: "https://sepolia.etherscan.io", + [SEPOLIA_CHAIN_ID]: "https://sepolia.etherscan.io", }; - -const getTxExplorerUrl = (params: { txHash: string; chainId: number }): string => - `${explorerUrls[params.chainId]}/tx/${params.txHash}`; +const getTxExplorerUrl = (params: { + txHash: string; + chainId: number; +}): string => `${explorerUrls[params.chainId]}/tx/${params.txHash}`; ``` + 4. Defining the ERC-20 Transfer Function The core logic for the token transfer is encapsulated in the erc20Transfer function. This function sets up the provider and wallet using ethers.js, connects to the Sepolia network, and prepares for the cross-chain transfer. Set up the provider, wallet, and asset transfer objects using the TESTNET environment. ```ts -export async function erc20Transfer(): Promise { - const web3Provider = new Web3HttpProvider(SEPOLIA_RPC_URL); - const ethersWeb3Provider = new providers.Web3Provider(web3Provider); - const wallet = new Wallet(privateKey ?? "", ethersWeb3Provider); - const sourceAddress = await wallet.getAddress(); - const destinationAddress = "5GjowPEaFNnwbrmpPuDmBVdF2e7n3cHwk2LnUwHXsaW5KtEL"; // Substrate address +const web3Provider = new Web3HttpProvider(SEPOLIA_RPC_URL); +const ethersWeb3Provider = new providers.Web3Provider(web3Provider); +const wallet = new Wallet(privateKey ?? "", ethersWeb3Provider); +const sourceAddress = await wallet.getAddress(); +const recipientAddress = process.env.RECIPIENT_ADDRESS; ``` 5. Constructing the Transfer Object -The transfer object is created by specifying the source and destination chain IDs, the source and destination addresses, the amount to transfer (1 sygUSD token), and the token’s Resource ID. +The transfer object is created by specifying the source and destination chain IDs, the source and destination addresses, the amount to transfer (1 tTNT token), and the token’s Resource ID. + ```ts - const params = { - source: SEPOLIA_CHAIN_ID, - destination: TANGLE_CHAIN_ID, - sourceNetworkProvider: web3Provider as unknown as Eip1193Provider, - resource: RESOURCE_ID, - amount: BigInt(1) * BigInt(1e18), // 1 sygUSD token (18 decimals) - recipientAddress: destinationAddress, - sourceAddress: sourceAddress, - }; +const params = { + source: SEPOLIA_CHAIN_ID, + destination: TANGLE_CHAIN_ID, + sourceNetworkProvider: web3Provider as unknown as Eip1193Provider, + resource: RESOURCE_ID, + amount: BigInt(1) * BigInt(1e18), + recipientAddress: destinationAddress, + sourceAddress: sourceAddress, +}; +const transfer = await createFungibleAssetTransfer(params); ``` Here, the transfer object specifies the details of the cross-chain transfer, including the network provider and the token amount. @@ -162,17 +169,16 @@ Here, the transfer object specifies the details of the cross-chain transfer, inc Before sending the transfer, the script needs to obtain and send approval transactions to allow the smart contract to move the user’s tokens. This step ensures that the tokens are authorized for transfer. ```ts - const transfer = await createFungibleAssetTransfer(params); - const approvals = await transfer.getApprovalTransactions(); - console.log(`Approving Tokens (${approvals.length})...`); - - for (const approval of approvals) { - const response = await wallet.sendTransaction(approval); - await response.wait(); - console.log( - `Approved, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` - ); - } +const approvals = await transfer.getApprovalTransactions(); +console.log(`Approving Tokens (${approvals.length})...`); + +for (const approval of approvals) { + const response = await wallet.sendTransaction(approval); + await response.wait(); + console.log( + `Approved, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` + ); +} ``` This loop iterates through each approval transaction, sending them through the Ethereum network and logging the transaction hash for tracking purposes. @@ -180,13 +186,14 @@ This loop iterates through each approval transaction, sending them through the E 7. Sending the Transfer Transaction After the approvals are complete, the script constructs and sends the actual cross-chain transfer transaction. The transfer is confirmed once the transaction is finalized on the Ethereum side. + ```ts - const transferTx = await transfer.getTransferTransaction(); - const response = await wallet.sendTransaction(transferTx); - await response.wait(); - console.log( - `Deposited, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` - ); +const transferTx = await transfer.getTransferTransaction(); +const response = await wallet.sendTransaction(transferTx); +await response.wait(); +console.log( + `Deposited, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` +); ``` Once the transaction is confirmed, the console logs the deposit confirmation and provides the Etherscan link to track the transaction. @@ -194,6 +201,7 @@ Once the transaction is confirmed, the console logs the deposit confirmation and 8. Executing the Transfer Function Finally, the erc20Transfer function is executed. The .finally() method ensures that any necessary cleanup is performed once the function has completed. + ```ts erc20Transfer().finally(() => {}); -``` \ No newline at end of file +``` diff --git a/examples/evm-to-substrate-fungible-transfer/src/environment.d.ts b/examples/evm-to-substrate-fungible-transfer/src/environment.d.ts index 3749b0e87..19c91d8b3 100644 --- a/examples/evm-to-substrate-fungible-transfer/src/environment.d.ts +++ b/examples/evm-to-substrate-fungible-transfer/src/environment.d.ts @@ -6,6 +6,7 @@ declare global { SYGMA_ENV: Environment; PRIVATE_KEY: string; SOURCE_EVM_RPC_URL: string; + RECIPIENT_ADDRESS: string; } } } diff --git a/examples/evm-to-substrate-fungible-transfer/src/transfer.ts b/examples/evm-to-substrate-fungible-transfer/src/transfer.ts index 936d8bc3b..b0c07fa99 100644 --- a/examples/evm-to-substrate-fungible-transfer/src/transfer.ts +++ b/examples/evm-to-substrate-fungible-transfer/src/transfer.ts @@ -18,7 +18,7 @@ const RESOURCE_ID = "0x0000000000000000000000000000000000000000000000000000000000002000"; const SEPOLIA_RPC_URL = process.env.SOURCE_EVM_RPC_URL ?? - "https://eth-sepolia.g.alchemy.com/v2/MeCKDrpxLkGOn4LMlBa3cKy1EzzOzwzG"; + "https://ethereum-sepolia-rpc.publicnode.com"; const explorerUrls: Record = { [SEPOLIA_CHAIN_ID]: "https://sepolia.etherscan.io", @@ -33,7 +33,7 @@ export async function erc20Transfer(): Promise { const ethersWeb3Provider = new providers.Web3Provider(web3Provider); const wallet = new Wallet(privateKey ?? "", ethersWeb3Provider); const sourceAddress = await wallet.getAddress(); - const destinationAddress = "5GjowPEaFNnwbrmpPuDmBVdF2e7n3cHwk2LnUwHXsaW5KtEL"; + const recipientAddress = process.env.RECIPIENT_ADDRESS; const params = { source: SEPOLIA_CHAIN_ID, @@ -41,7 +41,7 @@ export async function erc20Transfer(): Promise { sourceNetworkProvider: web3Provider as unknown as Eip1193Provider, resource: RESOURCE_ID, amount: BigInt(1) * BigInt(1e18), - recipientAddress: destinationAddress, + recipientAddress, sourceAddress: sourceAddress, }; @@ -52,7 +52,7 @@ export async function erc20Transfer(): Promise { const response = await wallet.sendTransaction(approval); await response.wait(); console.log( - `Approved, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}`, + `Approved, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` ); } @@ -60,7 +60,7 @@ export async function erc20Transfer(): Promise { const response = await wallet.sendTransaction(transferTx); await response.wait(); console.log( - `Deposited, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}`, + `Deposited, transaction: ${getTxExplorerUrl({ txHash: response.hash, chainId: SEPOLIA_CHAIN_ID })}` ); } diff --git a/examples/substrate-to-evm-fungible-transfer/README.md b/examples/substrate-to-evm-fungible-transfer/README.md index 9cfc8026f..1499e3160 100644 --- a/examples/substrate-to-evm-fungible-transfer/README.md +++ b/examples/substrate-to-evm-fungible-transfer/README.md @@ -1,4 +1,5 @@ # Sygma SDK Substrate to EVM (Tangle to Sepolia) Asset Transfer Example + This is an example script that demonstrates the functionality of the SDK using the Sygma ecosystem. The script showcases a Substrate Asset transfer between a Substrate network and an EVM network using the Sygma SDK. ## Prerequisites @@ -40,9 +41,10 @@ yarn build ``` ### Obtaining sygUSD Tokens -The `RESOURCE_ID_SYGMA_USD` represents the ID for `sygUSD` tokens in the Sygma protocol. You will need `sygUSD` testnet tokens to complete this transfer. If you are transferring a different asset, you may need to replace this ID with the appropriate resource ID. -You can obtain testnet `sygUSD` tokens for the Tangle testnet by visiting the [Sygma Testnet Faucet](https://docs.buildwithsygma.com/resources/environments/testnet/obtain-testnet-tokens/?ref=blog.buildwithsygma.com). +The `RESOURCE_ID` represents the ID for `tTNT` tokens in the Sygma protocol. You will need `tTNT` testnet tokens to complete this transfer. If you are transferring a different asset, you may need to replace this ID with the appropriate resource ID. + +You can obtain testnet `tTNT` tokens for the Tangle testnet by visiting the [Sygma Testnet Faucet](https://docs.buildwithsygma.com/resources/environments/testnet/obtain-testnet-tokens/?ref=blog.buildwithsygma.com). ## Usage @@ -51,11 +53,13 @@ This example uses the `dotenv` module to import the 12-word private mnemonic. To **DO NOT COMMIT YOUR MNEMONIC WITH REAL FUNDS TO GITHUB. DOING SO COULD RESULT IN COMPLETE LOSS OF YOUR FUNDS.** ### Environment Variables + Create a `.env` file in the substrate-to-evm example folder: ```bash touch .env ``` + The file should contain the following environment variables: - PRIVATE_MNEMONIC: The 12-word mnemonic for your Substrate wallet. @@ -64,12 +68,13 @@ The file should contain the following environment variables: - SYGMA_ENV: The Sygma environment you’re using, e.g., testnet. Here’s an example of the .env file: + ```dotenv PRIVATE_MNEMONIC="YOUR TWELVE WORD MNEMONIC HERE" SOURCE_SUBSTRATE_RPC_URL="wss://rpc.tangle.tools" RECIPIENT_ADDRESS="YOUR EVM ADDRESS" SYGMA_ENV="testnet" -```` +``` ### Obtaining Your 12-Word Mnemonic @@ -80,6 +85,7 @@ Replace between the quotation marks your 12-word mnemonic: `PRIVATE_MNEMONIC="YOUR TWELVE WORD MNEMONIC HERE WITH SPACES"` ### Run the example + To send a Substrate token to an EVM chain example transfer run: ```bash @@ -100,7 +106,7 @@ Once the transaction is finalized, you can view the transaction details in the [ This example script performs the following steps: 1. **Initializes the SDK**: It connects to the Substrate node via WebSocket and initializes the SDK. -2. **Retrieves Supported Domains and Resources**: It fetches the list of supported domains (Tangle and Sepolia in this case) and resources like `sygUSD`. +2. **Retrieves Supported Domains and Resources**: It fetches the list of supported domains (Tangle and Sepolia in this case) and resources like `tTNT`. 3. **Constructs a Transfer Object**: A transfer object is built, specifying the token amount, the source, and destination chains (Tangle and Sepolia). 4. **Fetches Transfer Fees**: The SDK calculates the fees required for the transfer. 5. **Signs and Sends the Transaction**: The transfer transaction is signed with your Substrate account and broadcasted to the network. diff --git a/examples/substrate-to-evm-fungible-transfer/src/transfer.ts b/examples/substrate-to-evm-fungible-transfer/src/transfer.ts index ba4de3050..d47c8c32a 100644 --- a/examples/substrate-to-evm-fungible-transfer/src/transfer.ts +++ b/examples/substrate-to-evm-fungible-transfer/src/transfer.ts @@ -17,7 +17,7 @@ const SEPOLIA_CHAIN_ID = 11155111; const RECIPIENT_ADDRESS = process.env.RECIPIENT_ADDRESS || "0xE39bb23F17a2cf7C9a8C4918376A32036A8867db"; -const RESOURCE_ID_SYGMA_USD = +const RESOURCE_ID = "0x0000000000000000000000000000000000000000000000000000000000002000"; const SYGMA_EXPLORER_URL = "https://scan.test.buildwithsygma.com"; const TANGLE_RPC_URL = @@ -42,7 +42,7 @@ const substrateTransfer = async (): Promise => { destination: SEPOLIA_CHAIN_ID, sourceNetworkProvider: api, sourceAddress: account.address, - resource: RESOURCE_ID_SYGMA_USD, + resource: RESOURCE_ID, amount: BigInt(1) * BigInt(1e18), destinationAddress: RECIPIENT_ADDRESS, }; @@ -56,7 +56,7 @@ const substrateTransfer = async (): Promise => { if (status.isInBlock) { console.log( - `Transaction included at blockHash ${status.asInBlock.toString()}`, + `Transaction included at blockHash ${status.asInBlock.toString()}` ); } else if (status.isFinalized) { const blockNumber = results.blockNumber?.toNumber(); @@ -64,10 +64,10 @@ const substrateTransfer = async (): Promise => { if (blockNumber && extrinsicIndex) { console.log( - `Transaction finalized at blockHash ${status.asFinalized.toString()}`, + `Transaction finalized at blockHash ${status.asFinalized.toString()}` ); console.log( - `Explorer URL: ${getSygmaExplorerTransferUrl({ blockNumber, extrinsicIndex })}`, + `Explorer URL: ${getSygmaExplorerTransferUrl({ blockNumber, extrinsicIndex })}` ); } unsub();