Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit f20d786

Browse files
feat: semi fungible evm (#554)
Closes #374 --------- Co-authored-by: Saad Ahmed Siddiqui <[email protected]>
1 parent a49fc05 commit f20d786

22 files changed

+614
-20
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
PRIVATE_KEY=""
2+
CRONOS_RPC_URL="CRONOS_RPC_URL_HERE"
3+
SEPOLIA_RPC_URL="SEPOLIA_RPC_URL_HERE"
4+
SYGMA_ENV="testnet"
5+
TOKEN_ID=""
6+
AMOUNT=""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# Sygma SDK ERC1155 Semi-Fungible Token Transfer Example
2+
3+
This example script demonstrates how to perform a **semi-fungible ERC1155 token transfer** between two accounts on testnet using the Sygma SDK.
4+
5+
## Prerequisites
6+
7+
Before running the script, ensure that you have the following:
8+
9+
- **Node.js** 18+ installed on your machine.
10+
- **Yarn** (version 3.4.1 or higher).
11+
- 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.
12+
- **Sepolia ETH** for gas fees, obtainable from [Sepolia Faucet](https://sepoliafaucet.com/).
13+
- An Ethereum **provider URL** (e.g., from [Infura](https://www.infura.io/) or [Alchemy](https://www.alchemy.com/)). (in case the hardcoded RPC within the script does not work)
14+
- An **ERC1155 semi-fungible token** deployed on the source network.
15+
- The [**resource ID**](https://docs.buildwithsygma.com/resources/environments/testnet/#registered-resources) corresponding to your ERC1155 token registered with the Sygma protocol.
16+
17+
## Getting Started
18+
19+
### 1. Clone the Repository
20+
21+
To get started, clone the Sygma SDK repository to your local machine:
22+
23+
```bash
24+
git clone [email protected]:sygmaprotocol/sygma-sdk.git
25+
cd sygma-sdk/
26+
```
27+
28+
### 2. Install Dependencies
29+
30+
Install the project dependencies by running:
31+
32+
```bash
33+
yarn install
34+
```
35+
36+
### 3. Build the SDK
37+
38+
To build the SDK, run:
39+
40+
```bash
41+
yarn build
42+
```
43+
44+
## Usage
45+
46+
This example uses the `dotenv` module to manage private keys and environment variables. Before running the example, you need to set up your environment variables, including your wallet's private key, the token ID, and other necessary information.
47+
48+
**⚠️ WARNING: DO NOT COMMIT PRIVATE KEYS WITH REAL FUNDS TO GITHUB OR ANY PUBLIC REPOSITORY. DOING SO COULD RESULT IN COMPLETE LOSS OF YOUR FUNDS.**
49+
50+
### 1. Set Up Environment Variables
51+
52+
Create a `.env` file in the `examples/evm-to-evm-erc1155-transfer` directory:
53+
54+
```bash
55+
cd examples/evm-to-evm-erc1155-transfer
56+
touch .env
57+
```
58+
59+
Use the provided `.env.sample` as a template. Replace the placeholder values with your own:
60+
61+
- `PRIVATE_KEY`: Your wallet's private key.
62+
- `TOKEN_ID`: The ID of the ERC1155 token you wish to transfer.
63+
- `AMOUNT`: The amount of token that needs to be transferred.
64+
- `SYGMA_ENV`: The Sygma environment you're using (e.g., `testnet` or `mainnet`).
65+
- `SEPOLIA_RPC_URL`: (Optional) Custom RPC URL for the Sepolia network.
66+
- `CRONOS_RPC_URL`: (Optional) Custom RPC URL for the Cronos testnet.
67+
68+
Example `.env` file:
69+
70+
```env
71+
PRIVATE_KEY="your_private_key_here"
72+
TOKEN_ID="1"
73+
AMOUNT="1"
74+
SYGMA_ENV="testnet"
75+
SEPOLIA_RPC_URL="https://your-sepolia-rpc-url"
76+
CRONOS_RPC_URL="https://your-cronos-rpc-url"
77+
```
78+
79+
### 2. Run the ERC1155 Semi-Fungible Token Transfer Script
80+
81+
To execute the ERC1155 transfer script, run:
82+
83+
```bash
84+
yarn run transfer
85+
```
86+
87+
This command will execute the script located in `examples/evm-to-evm-erc1155-transfer/src/transfer.ts`.
88+
89+
## Script Functionality
90+
91+
The example script performs the following steps:
92+
93+
1. **Initialize the SDK and Ethereum Provider**: Sets up the Sygma SDK and connects to the Ethereum provider to interact with the blockchain.
94+
95+
2. **Retrieve Supported Domains and Resources**: Fetches the list of supported domains and resources from the SDK configuration to ensure the networks and tokens involved are supported.
96+
97+
3. **Set Up Transfer Parameters**: Defines the details of the ERC1155 semi-fungible token transfer, including source and destination chain IDs, resource ID, token ID, and recipient address.
98+
99+
4. **Create the Transfer Object**: Uses the SDK to create a transfer object that encapsulates the transfer details and logic.
100+
101+
5. **Check for Required Approvals**: Builds the necessary approval transactions to authorize the bridge contract to transfer your ERC1155 token. It checks if approvals are already in place to avoid redundant transactions.
102+
103+
6. **Send Approval Transactions**: Sends any required approval transactions using your Ethereum wallet.
104+
105+
7. **Retrieve Transfer Fee**: Fetches the fee required for the transfer from the SDK. This fee may vary depending on the networks and token involved.
106+
107+
8. **Build and Send the Transfer Transaction**: Constructs the final transfer transaction using the SDK and sends it using your Ethereum wallet.
108+
109+
9. **Monitor Transfer Progress**: Logs transaction hashes and provides links to blockchain explorers and SygmaScan to monitor the transfer status.
110+
111+
## Notes
112+
113+
- **ERC1155 Semi-Fungible Tokens**: This script is specifically designed for ERC1155 tokens that represent semi-fungible assets (ERC1155 standard). Ensure that the `TOKEN_ID` you provide corresponds to a Semi-fungible token with a balance of `1` in your wallet.
114+
115+
- **Sygma Environment**: The `SYGMA_ENV` variable should match the environment your resources are registered in (e.g., `testnet` or `mainnet`).
116+
117+
- **Custom RPC URLs**: If you encounter issues with the default RPC URLs, you can specify custom URLs using environment variables like `SEPOLIA_RPC_URL` and `CRONOS_RPC_URL`.
118+
119+
- **Gas Fees**: Ensure your wallet has sufficient ETH on the source network to cover gas fees for transactions.
120+
121+
## Example Script Breakdown
122+
123+
The script (`transfer.ts`) performs the following actions:
124+
125+
### **Imports Required Modules and Configurations**
126+
127+
```typescript
128+
import {
129+
Eip1193Provider,
130+
Environment,
131+
getSygmaScanLink,
132+
} from "@buildwithsygma/core";
133+
import {
134+
createSemiFungibleAssetTransfer,
135+
EvmAssetTransferParams,
136+
} from "@buildwithsygma/evm";
137+
import dotenv from "dotenv";
138+
import { Wallet, providers } from "ethers";
139+
import Web3HttpProvider from "web3-providers-http";
140+
```
141+
142+
### **Loads Environment Variables**
143+
144+
```typescript
145+
dotenv.config();
146+
const privateKey = process.env.PRIVATE_KEY;
147+
if (!privateKey) {
148+
throw new Error("Missing environment variable: PRIVATE_KEY");
149+
}
150+
```
151+
152+
### **Sets Up Network and Resource Configurations**
153+
154+
```typescript
155+
const SEPOLIA_CHAIN_ID = 11155111;
156+
const CRONOS_TESTNET_CHAIN_ID = 338;
157+
const RESOURCE_ID = "0x..."; // Replace with your ERC1155 resource ID
158+
const SEPOLIA_RPC_URL =
159+
process.env.SEPOLIA_RPC_URL || "https://default-sepolia-rpc-url";
160+
const CRONOS_RPC_URL =
161+
process.env.CRONOS_RPC_URL || "https://default-cronos-rpc-url";
162+
```
163+
164+
### **Initializes Providers and Wallets**
165+
166+
```typescript
167+
const web3Provider = new Web3HttpProvider(SEPOLIA_RPC_URL);
168+
const ethersWeb3Provider = new providers.Web3Provider(web3Provider);
169+
const wallet = new Wallet(privateKey, ethersWeb3Provider);
170+
const sourceAddress = await wallet.getAddress();
171+
const destinationAddress = "0xRecipientAddress"; // Replace with the actual recipient address
172+
```
173+
174+
### **Defines Transfer Parameters**
175+
176+
```typescript
177+
const params: SemiFungibleTransferParams = {
178+
source: SEPOLIA_CHAIN_ID,
179+
destination: CRONOS_TESTNET_CHAIN_ID,
180+
sourceNetworkProvider: web3Provider as unknown as Eip1193Provider,
181+
resource: RESOURCE_ID,
182+
tokenIds: [process.env.TOKEN_ID], // Ensure TOKEN_ID of NFT is set in your .env file
183+
amounts: [BigInt(process.env.AMOUNT)], // Amount is always 1 for Semi-fungible tokens
184+
recipientAddress: destinationAddress,
185+
sourceAddress,
186+
};
187+
```
188+
189+
### **Creates the Transfer Object**
190+
191+
```typescript
192+
const transfer = await createSemiFungibleAssetTransfer(params);
193+
```
194+
195+
### **Handles Approval Transactions**
196+
197+
```typescript
198+
const approvals = await transfer.getApprovalTransactions();
199+
console.log(`Approving Tokens (${approvals.length})...`);
200+
for (const approval of approvals) {
201+
const response = await wallet.sendTransaction(approval);
202+
await response.wait();
203+
console.log(`Approved, transaction: ${response.hash}`);
204+
}
205+
```
206+
207+
### **Builds and Sends the Transfer Transaction**
208+
209+
```typescript
210+
const transferTx = await transfer.getTransferTransaction();
211+
const response = await wallet.sendTransaction(transferTx);
212+
await response.wait();
213+
console.log(
214+
`Deposited, transaction: ${getSygmaScanLink(response.hash, process.env.SYGMA_ENV as Environment)}`
215+
);
216+
```
217+
218+
### **Error Handling**
219+
220+
```typescript
221+
erc1155Transfer().catch((error) => {
222+
console.error("Error during ERC1155 Semi-fungible transfer:", error);
223+
});
224+
```
225+
226+
## Additional Information
227+
228+
- **Security**: Keep your private keys secure. Never share them or commit them to version control systems.
229+
230+
- **Resource Registration**: Before running the script, ensure that your ERC1155 token and its corresponding resource ID are registered with the Sygma protocol.
231+
232+
- **Troubleshooting**: If you encounter errors, check the console output for detailed error messages. Common issues include insufficient balance, incorrect token ID, or missing approvals.
233+
234+
## Support
235+
236+
If you have any questions or need assistance, please refer to the [Sygma SDK documentation](https://docs.buildwithsygma.com/) or reach out to the Sygma community.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@buildwithsygma/evm-to-evm-erc1155-transfer-example",
3+
"version": "0.1.0",
4+
"type": "module",
5+
"description": "Sygma sdk examples",
6+
"sideEffects": false,
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/sygmaprotocol/sygma-sdk"
10+
},
11+
"keywords": [
12+
"sygma",
13+
"sygmaprotocol",
14+
"buildwithsygma",
15+
"web3",
16+
"bridge",
17+
"ethereum"
18+
],
19+
"scripts": {
20+
"transfer": "tsx src/transfer.ts"
21+
},
22+
"author": "Sygmaprotocol Product Team",
23+
"license": "LGPL-3.0-or-later",
24+
"devDependencies": {
25+
"dotenv": "^16.3.1",
26+
"eslint": "8",
27+
"ts-node": "10.9.1",
28+
"typescript": "5.0.4"
29+
},
30+
"dependencies": {
31+
"@buildwithsygma/core": "workspace:^",
32+
"@buildwithsygma/evm": "workspace:^",
33+
"ethers": "5.7.2",
34+
"tsx": "^4.15.4",
35+
"web3-providers-http": "1.10.4"
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { Environment } from "@buildwithsygma/core";
2+
3+
declare global {
4+
namespace NodeJS {
5+
interface ProcessEnv {
6+
SYGMA_ENV: Environment;
7+
AMOUNT: string;
8+
TOKEN_ID: string;
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { Eip1193Provider, getSygmaScanLink } from "@buildwithsygma/core";
2+
import {
3+
createSemiFungibleAssetTransfer,
4+
SemiFungibleTransferParams,
5+
} from "@buildwithsygma/evm";
6+
import dotenv from "dotenv";
7+
import { Wallet, providers } from "ethers";
8+
import Web3HttpProvider from "web3-providers-http";
9+
10+
dotenv.config();
11+
12+
const privateKey = process.env.PRIVATE_KEY ?? "";
13+
14+
if (!privateKey) {
15+
throw new Error("Missing environment variable: PRIVATE_KEY");
16+
}
17+
18+
const SEPOLIA_CHAIN_ID = 11155111;
19+
const CRONOS_TESTNET_CHAIN_ID = 338;
20+
const RESOURCE_ID =
21+
"0x0000000000000000000000000000000000000000000000000000000000000300";
22+
const SEPOLIA_RPC_URL =
23+
process.env.SEPOLIA_RPC_URL || "https://eth-sepolia.public.blastapi.io";
24+
25+
const explorerUrls: Record<number, string> = {
26+
[SEPOLIA_CHAIN_ID]: "https://sepolia.etherscan.io",
27+
};
28+
const getTxExplorerUrl = (params: {
29+
txHash: string;
30+
chainId: number;
31+
}): string => `${explorerUrls[params.chainId]}/tx/${params.txHash}`;
32+
33+
export async function erc1155Transfer(): Promise<void> {
34+
const web3Provider = new Web3HttpProvider(SEPOLIA_RPC_URL);
35+
const ethersWeb3Provider = new providers.Web3Provider(web3Provider);
36+
const wallet = new Wallet(privateKey, ethersWeb3Provider);
37+
const sourceAddress = await wallet.getAddress();
38+
const destinationAddress = await wallet.getAddress(); // Replace with the actual recipient address
39+
40+
const params: SemiFungibleTransferParams = {
41+
source: SEPOLIA_CHAIN_ID,
42+
destination: CRONOS_TESTNET_CHAIN_ID,
43+
sourceNetworkProvider: web3Provider as unknown as Eip1193Provider,
44+
resource: RESOURCE_ID,
45+
tokenIds: [process.env.TOKEN_ID], // Ensure TOKEN_ID of NFT is set in your .env file
46+
amounts: [BigInt(process.env.AMOUNT)], // Amount is always 1 for non-fungible tokens
47+
recipientAddress: destinationAddress,
48+
sourceAddress,
49+
};
50+
51+
const transfer = await createSemiFungibleAssetTransfer(params);
52+
const approvals = await transfer.getApprovalTransactions();
53+
54+
console.log(`Approving Tokens (${approvals.length})...`);
55+
for (const approval of approvals) {
56+
const response = await wallet.sendTransaction(approval);
57+
await response.wait();
58+
console.log(
59+
`Approved, transaction: ${getTxExplorerUrl({
60+
txHash: response.hash,
61+
chainId: SEPOLIA_CHAIN_ID,
62+
})}`
63+
);
64+
}
65+
66+
const transferTx = await transfer.getTransferTransaction();
67+
const response = await wallet.sendTransaction(transferTx);
68+
await response.wait();
69+
console.log(
70+
`Deposited, transaction: ${getSygmaScanLink(
71+
response.hash,
72+
process.env.SYGMA_ENV
73+
)}`
74+
);
75+
}
76+
77+
erc1155Transfer().catch((error) => {
78+
console.error("Error during ERC1155 transfer:", error);
79+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compilerOptions": {
3+
"composite": true,
4+
"module": "ES2022",
5+
"allowJs": true,
6+
"declaration": true,
7+
"sourceMap": true,
8+
"declarationMap": true,
9+
"resolveJsonModule": true,
10+
"skipLibCheck": true,
11+
"strict": true,
12+
"esModuleInterop": true,
13+
"downlevelIteration": true,
14+
"allowSyntheticDefaultImports": true,
15+
"forceConsistentCasingInFileNames": true,
16+
"moduleResolution": "node"
17+
},
18+
"include": ["src"]
19+
}

0 commit comments

Comments
 (0)