Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 109 additions & 3 deletions interchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The `@avalanche-sdk/interchain` package provides a developer-friendly TypeScript
npm install @avalanche-sdk/interchain viem
```

## Quickstart
## Sending Messages Cross-Chain

Here’s a minimal example demonstrating how to send a cross-chain message using `createICMClient`:

Expand All @@ -31,8 +31,7 @@ import { createICMClient } from "@avalanche-sdk/interchain";
import { privateKeyToAccount } from "viem/accounts";

// these will be made available in a separate SDK soon
import { avalancheFuji } from "./chains/avalancheFuji";
import { dispatch } from "./chains/dispatch";
import { avalancheFuji, dispatch } from "@avalanche-sdk/interchain/chains";

// Load your signer/account
const account = privateKeyToAccount('0x63e0730edea86f6e9e95db48dbcab18406e60bebae45ad33e099f09d21450ebf');
Expand All @@ -58,3 +57,110 @@ async function main() {

main();
```

## Sending Tokens Cross-Chain

Sending ERC20 tokens from one Avalanche L1 to another is possible using Teleporter.
Before sending tokens, we need to setup some contracts on both source and destination chains. Here's a quick summary of steps we'd need to follow:

- Deploy ERC20 Token.
- Deploy `TokenHome` contract on the source chain.
- Deploy `TokenRemote` contract on the destination chain.
- Register `TokenRemote` on `TokenHome` by issuing a transaction on `TokenRemote` contract, which in turn will emit an event on the source chain.
- Approve `TokenHome` contract to spend (and hence lock) ERC20 tokens.
- Send ERC20 Token from source to destination chain.

Here's a demo to do that with the Interchain SDK.

```typescript
import { http, createWalletClient } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { createICTTClient } from "@avalanche-sdk/interchain";

// These will be made available in separate SDK
import { avalancheFuji, dispatch } from "@avalanche-sdk/interchain/chains";

const account = privateKeyToAccount('0x63e0730edea86f6e9e95db48dbcab18406e60bebae45ad33e099f09d21450ebf');

// We need separate wallet clients for each to do certain operations
const fujiWallet = createWalletClient({
chain: avalancheFuji,
transport: http(),
account,
})
const dispatchWallet = createWalletClient({
chain: dispatch,
transport: http(),
account,
})

// We can create ICTT client with or without default source/destination chains
const ictt = createICTTClient();

async function main() {
// Deploy ERC20 token on Avalanche Fuji
const { contractAddress: tokenAddress } = await ictt.deployERC20Token({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
name: 'Test Token',
symbol: 'TEST',
initialSupply: 1000000,
});
console.log(`Token deployed on Avalanche Fuji: ${tokenAddress}`);

// Deploy Token Home Contract on Avalanche Fuji. This is one-time process for each token we
// want to send to another chain.
const { contractAddress: tokenHomeContract } = await ictt.deployTokenHomeContract({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
erc20TokenAddress: tokenAddress,
minimumTeleporterVersion: 1,
});
console.log(`Token home contract deployed on Avalanche Fuji: ${tokenHomeContract}`);

// Deploy Token Remote Contract on Dispatch. This is one-time process for each token we
// want to send to another chain.
const { contractAddress: tokenRemoteContract } = await ictt.deployTokenRemoteContract({
walletClient: dispatchWallet,
sourceChain: avalancheFuji,
destinationChain: dispatch,
tokenHomeContract,
});
console.log(`Token remote contract deployed on Dispatch: ${tokenRemoteContract}`);

// Register Token Remote Contract with Token Home Contract on Dispatch. This is one-time process for each token we
// want to send to another chain.
const { txHash: registerRemoteWithHomeTxHash } = await ictt.registerRemoteWithHome({
walletClient: dispatchWallet,
sourceChain: avalancheFuji,
destinationChain: dispatch,
tokenRemoteContract,
})
console.log(`Token remote contract registered with home on Dispatch: ${registerRemoteWithHomeTxHash}`);

// Approve token on Avalanche Fuji. This operation approves the HomeContract to
// lock token on Fuji as collateral for the interchain transfer.
const { txHash: approveTokenTxHash } = await ictt.approveToken({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
tokenHomeContract,
tokenAddress,
amountInBaseUnit: 2,
})
console.log(`Token approved on Avalanche Fuji: ${approveTokenTxHash}`);

// Send token from Avalanche Fuji to Dispatch.
const { txHash: sendTokenTxHash } = await ictt.sendToken({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
destinationChain: dispatch,
tokenHomeContract,
tokenRemoteContract,
amountInBaseUnit: 1,
recipient: '0x909d71Ed4090ac6e57E3645dcF2042f8c6548664',
})
console.log(`Token sent from Avalanche Fuji to Dispatch: ${sendTokenTxHash}`);
}

main().catch(console.error);
```
4 changes: 2 additions & 2 deletions interchain/examples/sendICM.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createWalletClient, http } from "viem";
import { createICMClient } from "../src/icm/icm";
import { privateKeyToAccount } from "viem/accounts";
import { avalancheFuji } from "./chains/avalancheFuji";
import { dispatch } from "./chains/dispatch";
import { avalancheFuji } from "../src/chains/avalancheFuji";
import { dispatch } from "../src/chains/dispatch";

const account = privateKeyToAccount('0x63e0730edea86f6e9e95db48dbcab18406e60bebae45ad33e099f09d21450ebf');

Expand Down
81 changes: 81 additions & 0 deletions interchain/examples/sendTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { createWalletClient } from "viem";
import { http } from "viem";
import { createICTTClient } from "../src/ictt/ictt";
import { privateKeyToAccount } from "viem/accounts";
import { avalancheFuji, dispatch } from "../src/chains";

const account = privateKeyToAccount('0x63e0730edea86f6e9e95db48dbcab18406e60bebae45ad33e099f09d21450ebf');

const fujiWallet = createWalletClient({
chain: avalancheFuji,
transport: http(),
account,
})

const dispatchWallet = createWalletClient({
chain: dispatch,
transport: http(),
account,
})

const ictt = createICTTClient(
avalancheFuji,
dispatch,
);

async function main() {
const { contractAddress: tokenAddress } = await ictt.deployERC20Token({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
name: 'Test Token',
symbol: 'TEST',
initialSupply: 1000000,
});
console.log(`Token deployed on Avalanche Fuji: ${tokenAddress}`);

const { contractAddress: tokenHomeContract } = await ictt.deployTokenHomeContract({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
erc20TokenAddress: tokenAddress,
minimumTeleporterVersion: 1,
});
console.log(`Token home contract deployed on Avalanche Fuji: ${tokenHomeContract}`);

const { contractAddress: tokenRemoteContract } = await ictt.deployTokenRemoteContract({
walletClient: dispatchWallet,
sourceChain: avalancheFuji,
destinationChain: dispatch,
tokenHomeContract,
});
console.log(`Token remote contract deployed on Dispatch: ${tokenRemoteContract}`);

const { txHash: registerRemoteWithHomeTxHash } = await ictt.registerRemoteWithHome({
walletClient: dispatchWallet,
sourceChain: avalancheFuji,
destinationChain: dispatch,
tokenRemoteContract,
})
console.log(`Token remote contract registered with home on Dispatch: ${registerRemoteWithHomeTxHash}`);

const { txHash: approveTokenTxHash } = await ictt.approveToken({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
tokenHomeContract,
tokenAddress,
amountInBaseUnit: 2,
})
console.log(`Token approved on Avalanche Fuji: ${approveTokenTxHash}`);

const { txHash: sendTokenTxHash } = await ictt.sendToken({
walletClient: fujiWallet,
sourceChain: avalancheFuji,
destinationChain: dispatch,
tokenHomeContract,
tokenRemoteContract,
amountInBaseUnit: 1,
recipient: '0x909d71Ed4090ac6e57E3645dcF2042f8c6548664',
})
console.log(`Token sent from Avalanche Fuji to Dispatch: ${sendTokenTxHash}`);
}

main().catch(console.error);
Loading