Skip to content

Commit

Permalink
clean mrl example (#414)
Browse files Browse the repository at this point in the history
* clean mrl example

* adjust example flow

* reset value
  • Loading branch information
mmaurello authored Jan 7, 2025
1 parent d943d43 commit 731f4c2
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 134 deletions.
262 changes: 129 additions & 133 deletions examples/mrl-simple/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
import { Mrl } from '@moonbeam-network/mrl';
import { Mrl, type TransferData } from '@moonbeam-network/mrl';
import {
agng,
dev,
fantomTestnet,
ftm,
ftmwh,
moonbaseAlpha,
moonbaseBeta,
peaqAlphanet,
peaqEvmAlphanet,
} from '@moonbeam-network/xcm-config';
import type { Asset } from '@moonbeam-network/xcm-types';
import { type Asset, EvmChain, Parachain } from '@moonbeam-network/xcm-types';
import { Keyring } from '@polkadot/api';
import { cryptoWaitReady } from '@polkadot/util-crypto';
import { http, type Address, createWalletClient } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { moonbaseAlpha as moonbaseAlphaViem } from 'viem/chains';
import type { EvmSigner } from '../../packages/sdk/build';

// disable unnecessary warning logs
console.warn = () => null;
console.clear();

const { EVM_PRIVATE_KEY, POLKADOT_PRIVATE_KEY } = process.env;

if (!EVM_PRIVATE_KEY || !POLKADOT_PRIVATE_KEY) {
Expand Down Expand Up @@ -55,176 +45,182 @@ main()
.finally(() => process.exit());

async function main() {
console.warn = () => null;
console.clear();

/**
* Set the source, destination and asset
*/
const source = fantomTestnet;
const destination = moonbaseAlpha;
const asset = ftm;

/**
* Set the transaction to be automatic or not
* If it is automatic, the transaction will be completed by a relayer in the destination chain
* If it is not automatic, you will have to manually complete the transaction in the destination chain
*/
const isAutomatic = false;

// await fromFantomToPeaq(agng, 10, isAutomatic);
// await fromFantomToMoonbase(dev, 1.23, isAutomatic);
// await fromMoonbaseToFantom(ftmwh, 0.01, isAutomatic);
// await fromPeaqToFantom(ftmwh, 0.0121, isAutomatic);
// await fromPeaqEvmToFantom(ftmwh, 1.5, isAutomatic);

await redeemInMoonbaseAlpha();
// await redeemInFantomTestnet();
/**
* Set the tx hash to be redeemed if the transaction is not automatic
*/
const txHashToBeRedeemed: string | undefined = undefined;

if (txHashToBeRedeemed) {
await redeemInEvm(txHashToBeRedeemed, destination);
} else if (EvmChain.is(source)) {
await fromEvmChain(source, destination, asset, isAutomatic);
} else if (Parachain.is(source)) {
await fromParachain(source, destination, asset, isAutomatic);
}
}

async function redeemInMoonbaseAlpha() {
const txId =
'0x59e70ad73c57bce44cbb3e3308fc6a31d29ff0dcbb2957055b05025969545bed';
const walletClient = createWalletClient({
account,
chain: moonbaseAlphaViem,
transport: http(),
});

const data = await Mrl().getRedeemData({ txId, chain: moonbaseAlpha });
console.log('data', data);

await data.redeem(walletClient as EvmSigner);
}

async function redeemInFantomTestnet() {
const txId =
'0xa0032ff270885f7278a42d4d974fceab9e4feb039263db35b09beafe57bd6683';
const walletClient = createWalletClient({
account,
chain: fantomTestnet.getViemChain(),
transport: http(),
});

const data = await Mrl().getRedeemData({ txId, chain: fantomTestnet });
console.log('data', data);

await data.redeem(walletClient as EvmSigner);
function logBalances(data: TransferData): void {
console.log(
`\nBalance on ${data.source.chain.name} ${data.source.balance.toDecimal()} ${data.source.balance.getSymbol()}`,
);
console.log(
`Balance on ${
data.destination.chain.name
} ${data.destination.balance.toDecimal()} ${data.destination.balance.getSymbol()}`,
);
}

async function fromFantomToPeaq(
async function fromEvmChain(
source: EvmChain,
destination: EvmChain,
asset: Asset,
amount: number,
isAutomatic: boolean,
) {
const walletClient = createWalletClient({
const fantomWalletClient = createWalletClient({
account,
chain: fantomTestnet.getViemChain(),
transport: http(),
});

const data = await Mrl()
.setSource(fantomTestnet)
.setDestination(peaqAlphanet)
console.log(`\Source address: ${account.address}`);

const transferData = await Mrl()
.setSource(source)
.setDestination(destination)
.setAsset(asset)
.setIsAutomatic(isAutomatic)
.setAddresses({
sourceAddress: account.address,
destinationAddress: pair.address,
destinationAddress: account.address,
});
logBalances(transferData);

console.log(data);
const amount = +transferData.min.toDecimal() * 1.5 + 0.000001;

await data.transfer(amount, isAutomatic, {
polkadotSigner: pair,
evmSigner: walletClient as EvmSigner,
});
}
console.log(
`\nSending ${amount} ${transferData.source.balance.getSymbol()} from ${transferData.source.chain.name} to ${transferData.destination.chain.name}`,
);

async function fromFantomToMoonbase(
asset: Asset,
amount: number,
isAutomatic: boolean,
) {
const walletClient = createWalletClient({
account,
chain: fantomTestnet.getViemChain(),
transport: http(),
const result = await transferData.transfer(amount, isAutomatic, {
evmSigner: fantomWalletClient,
});

const data = await Mrl()
.setSource(fantomTestnet)
.setDestination(moonbaseAlpha)
.setAsset(asset)
.setAddresses({
sourceAddress: account.address,
destinationAddress: account.address,
const hash = result.pop();

if (!isAutomatic && hash) {
console.log(
`\nYou will have to manually complete the transaction in ${transferData.moonChain.chain.name} and you will need to pay ${transferData.moonChain.fee.toDecimal()} ${transferData.moonChain.fee.getSymbol()} for completing it`,
);
console.log(
`Balance for fees on ${
transferData.moonChain.chain.name
} ${transferData.moonChain.feeBalance.toDecimal()} ${transferData.moonChain.feeBalance.getSymbol()}`,
);

const redeemChainWalletClient = createWalletClient({
account,
chain: transferData.moonChain.chain.getViemChain(),
transport: http(),
});

console.log(data);
console.log('\nWaiting 30 seconds for tx to be confirmed before redeeming');
await new Promise((resolve) => setTimeout(resolve, 30000));

const hash = await data.transfer(amount, isAutomatic, {
polkadotSigner: pair,
evmSigner: walletClient as EvmSigner,
});
console.log('hash', hash);
}
console.log(`Redeeming tx ${hash} in ${transferData.moonChain.chain.name}`);

async function fromMoonbaseToFantom(
asset: Asset,
amount: number,
isAutomatic: boolean,
) {
const walletClient = createWalletClient({
account,
chain: moonbaseAlphaViem,
transport: http(),
});
const data = await Mrl()
.setSource(moonbaseAlpha)
.setDestination(fantomTestnet)
.setAsset(asset)
.setAddresses({
sourceAddress: account.address,
destinationAddress: account.address,
const redeemData = await Mrl().getRedeemData({
txId: hash,
chain: transferData.moonChain.chain,
});

console.log(data);

await data.transfer(amount, isAutomatic, {
polkadotSigner: pair,
evmSigner: walletClient as EvmSigner,
});
await redeemData.redeem(redeemChainWalletClient);
} else {
console.log(
`\nRedeeming will happen automatically for this tx ${hash} in ${transferData.moonChain.chain.name}`,
);
}
}

async function fromPeaqToFantom(
async function fromParachain(
source: Parachain,
destination: EvmChain,
asset: Asset,
amount: number,
isAutomatic: boolean,
) {
const data = await Mrl()
.setSource(peaqAlphanet)
.setDestination(fantomTestnet)
const transferData = await Mrl()
.setSource(source)
.setDestination(destination)
.setAsset(asset)
.setIsAutomatic(isAutomatic)
.setAddresses({
sourceAddress: pair.address,
destinationAddress: account.address,
});
logBalances(transferData);

console.log(data);
console.log(`Source address: ${pair.address}`);
console.log(`Destination address: ${account.address}`);

await data.transfer(amount, isAutomatic, {
const amount = +transferData.min.toDecimal() * 1.5 + 0.000001;

console.log(
`\nSending ${amount} ${transferData.source.balance.getSymbol()} from ${transferData.source.chain.name} to ${transferData.destination.chain.name}`,
);
console.log(
`Sending also ${transferData.moonChain.fee.toDecimal()} ${transferData.moonChain.fee.getSymbol()} from ${transferData.source.chain.name} to ${transferData.moonChain.chain.name} to cover for fees`,
);

await transferData.transfer(amount, isAutomatic, {
polkadotSigner: pair,
});

console.log(
`\nA remote execution will be sent to the computed origin account (${transferData.moonChain.address}) in ${transferData.moonChain.chain.name} which will relay the ${amount} ${transferData.source.balance.getSymbol()} to ${transferData.destination.chain.name}`,
);

if (isAutomatic) {
console.log(
`\nThe transaction will be completed automatically in ${transferData.destination.chain.name} once picked up by a relayer`,
);
} else {
console.log(
`\nYou will have to manually complete the transaction in ${transferData.destination.chain.name} once the transaction is confirmed`,
);
console.log(
'This sdk does not yet return the tx hash that needs to be redeemed, so you will have to look it up in the explorer and paste it in the redeemInEvm function',
);
}
}

async function fromPeaqEvmToFantom(
asset: Asset,
amount: number,
isAutomatic: boolean,
) {
async function redeemInEvm(txHashToBeRedeemed: string, destination: EvmChain) {
const walletClient = createWalletClient({
account,
chain: peaqEvmAlphanet.getViemChain(),
chain: destination.getViemChain(),
transport: http(),
});

const data = await Mrl()
.setSource(peaqEvmAlphanet)
.setDestination(fantomTestnet)
.setAsset(asset)
.setAddresses({
sourceAddress: account.address,
destinationAddress: account.address,
});
const data = await Mrl().getRedeemData({
txId: txHashToBeRedeemed,
chain: fantomTestnet,
});

console.log(data);
console.log(`Redeeming tx ${txHashToBeRedeemed} in ${destination.name}`);

await data.transfer(amount, isAutomatic, {
evmSigner: walletClient as EvmSigner,
});
await data.redeem(walletClient as EvmSigner);
}
7 changes: 6 additions & 1 deletion packages/mrl/src/mrl.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import type {
EvmSigner,
SourceChainTransferData,
} from '@moonbeam-network/xcm-sdk';
import type { AnyChain, AssetAmount } from '@moonbeam-network/xcm-types';
import type {
AnyChain,
AssetAmount,
EvmParachain,
} from '@moonbeam-network/xcm-types';
import type { Signer } from '@polkadot/api/types';
import type { IKeyringPair, ISubmittableResult } from '@polkadot/types/types';
import type { TokenTransfer } from '@wormhole-foundation/sdk-connect';
Expand Down Expand Up @@ -41,6 +45,7 @@ export interface SourceTransferData extends SourceChainTransferData {
export interface DestinationTransferData extends ChainTransferData {}

export type MoonChainTransferData = Omit<ChainTransferData, 'min'> & {
chain: EvmParachain;
address: string;
feeBalance: AssetAmount;
};
Expand Down

0 comments on commit 731f4c2

Please sign in to comment.