Pool IDs update
Mike112
typescript
2 years ago
20 kB
6
Indexable
import { ethers } from 'ethers';
const BlockchainData = {
"Ethereum": { chainID: 101, rpcProvider: 'https://eth.llamarpc.com', stargateRouter: "0x8731d54E9D02c286767d56ac03e8037C07e01e98", routerETH: "0x150f94B44927F078737562f0fcF3C95c01Cc2376"},
"BnbChain": { chainID: 102, rpcProvider: 'https://bsc-dataseed.binance.org', stargateRouter: "0x4a364f8c717cAAD9A442737Eb7b8A55cc6cf18D8", routerETH: ""},
"Avalanche": { chainID: 106, rpcProvider: 'https://avalanche.public-rpc.com', stargateRouter: "0x45A01E4e04F14f7A4a6702c74187c5F6222033cd", routerETH: ""},
"Polygon": { chainID: 109, rpcProvider: 'https://polygon-rpc.com/', stargateRouter: "0x45A01E4e04F14f7A4a6702c74187c5F6222033cd", routerETH: ""},
"Arbitrum": { chainID: 110, rpcProvider: 'https://arbitrum-one.public.blastapi.io', stargateRouter: "0x53Bf833A5d6c4ddA888F69c22C88C9f356a41614", routerETH: "0xbf22f0f184bCcbeA268dF387a49fF5238dD23E40"},
"Optimism": { chainID: 111, rpcProvider: 'https://mainnet.optimism.io', stargateRouter: "0xB0D502E938ed5f4df2E681fE6E419ff29631d62b", routerETH: "0xB49c4e680174E331CB0A7fF3Ab58afC9738d5F8b"},
"Fantom": { chainID: 112, rpcProvider: 'https://rpc.ftm.tools', stargateRouter: "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", routerETH: ""},
"Metis": { chainID: 151, rpcProvider: 'https://andromeda.metis.io/?owner=1088', stargateRouter: "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590", routerETH: ""},
"Base": { chainID: 184, rpcProvider: 'https://mainnet.base.org', stargateRouter: "0x45f1A95A4D3f3836523F5c83673c797f4d4d263B", routerETH: "0x50B6EbC2103BFEc165949CC946d739d5650d7ae4"},
"Linea": { chainID: 183, rpcProvider: 'https://rpc.linea.build', stargateRouter: "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590", routerETH: "0x8731d54E9D02c286767d56ac03e8037C07e01e98"},
"Kava": { chainID: 177, rpcProvider: 'https://evm.kava.io', stargateRouter: "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590", routerETH: ""},
}
// Pool IDs
const poolIDs = {
"Ethereum": {
"USDC": 1,
"USDT": 2,
"DAI": 3,
"FRAX": 7,
"USDD": 11,
"ETH": 13,
"sUSD": 14,
"LUSD": 15,
"MAI": 16,
"METIS": 17,
"metis.USDT": 19
},
"BnbChain": {
"USDT": 2,
"BUSD": 5,
"USDD": 11,
"MAI": 16,
"METIS": 17,
"metis.USDT": 19
},
"Avalanche": {
"USDC": 1,
"USDT": 2,
"FRAX": 7,
"MAI": 16,
"metis.USDT": 19
},
"Polygon": {
"USDC": 1,
"USDT": 2,
"DAI": 3,
"MAI": 16
},
"Arbitrum": {
"USDC": 1,
"USDT": 2,
"FRAX": 7,
"ETH": 13,
"LUSD": 15,
"MAI": 16
},
"Optimism": {
"USDC": 1,
"DAI": 3,
"FRAX": 7,
"ETH": 13,
"sUSD": 14,
"LUSD": 15,
"MAI": 16
},
"Fantom": {
"USDC": 21
},
"Metis": {
"METIS": 17,
"metis.USDT": 19
},
"Base": {
"USDC": 1,
"ETH": 13
},
"Linea": {
"ETH": 13
},
"Kava": {
"USDT": 2
}
}
// ABI for ERC20
const erc20ABI = [
{
"constant": true,
"inputs": [
{ "name": "_owner", "type": "address" },
{ "name": "_spender", "type": "address" }
],
"name": "allowance",
"outputs": [{ "name": "", "type": "uint256" }],
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_spender", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "approve",
"outputs": [{ "name": "", "type": "bool" }],
"type": "function"
}
];
const stargateABI = [
{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_endpoint","type":"address"},{"internalType":"uint16","name":"_mainEndpointId","type":"uint16"},{"internalType":"uint256","name":"_initialSupplyOnMainEndpoint","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"srcChainId","type":"uint16"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"qty","type":"uint256"}],"name":"ReceiveFromChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"dstChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"to","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"qty","type":"uint256"}],"name":"SendToChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstContractLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"txParameters","type":"bytes"}],"name":"estimateSendTokensFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_fromAddress","type":"bytes"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"pauseSendTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_to","type":"bytes"},{"internalType":"uint256","name":"_qty","type":"uint256"},{"internalType":"address","name":"zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"adapterParam","type":"bytes"}],"name":"sendTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_destinationContractAddress","type":"bytes"}],"name":"setDestination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}
];
const routerABI = [
{
"inputs": [
{
"internalType": "uint16",
"name": "_dstChainId",
"type": "uint16"
},
{
"internalType": "uint8",
"name": "_functionType",
"type": "uint8"
},
{
"internalType": "bytes",
"name": "_toAddress",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "_transferAndCallPayload",
"type": "bytes"
},
{
"components": [
{
"internalType": "uint256",
"name": "dstGasForCall",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "dstNativeAmount",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "dstNativeAddr",
"type": "bytes"
}
],
"internalType": "struct IStargateRouter.lzTxObj",
"name": "_lzTxParams",
"type": "tuple"
}
],
"name": "quoteLayerZeroFee",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint16",
"name": "_dstChainId",
"type": "uint16"
},
{
"internalType": "uint256",
"name": "_srcPoolId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_dstPoolId",
"type": "uint256"
},
{
"internalType": "address payable",
"name": "_refundAddress",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amountLD",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_minAmountLD",
"type": "uint256"
},
{
"components": [
{
"internalType": "uint256",
"name": "dstGasForCall",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "dstNativeAmount",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "dstNativeAddr",
"type": "bytes"
}
],
"internalType": "struct IStargateRouter.lzTxObj",
"name": "_lzTxParams",
"type": "tuple"
},
{
"internalType": "bytes",
"name": "_to",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "_payload",
"type": "bytes"
}
],
"name": "swap",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
];
const routerETHABI = [
{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_amountLD","type":"uint256"},{"internalType":"uint256","name":"_minAmountLD","type":"uint256"}],"name":"swapETH","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}
]
async function swapOnStargate(
privateKey: string,
fromNetwork: string,
toNetwork: string,
tokenName: string,
tokenAddress: string, // from token address
amount: string,
recipient: string
) {
let router : ethers.Contract;
const fromNetworkId = BlockchainData[fromNetwork as keyof typeof BlockchainData].chainID;
const toNetworkId = BlockchainData[toNetwork as keyof typeof BlockchainData].chainID;
const provider = new ethers.providers.JsonRpcProvider(BlockchainData[fromNetwork as keyof typeof BlockchainData].rpcProvider);
const providerFeeData = await provider.getFeeData();
console.log('Fee Data: ', providerFeeData)
const signer = new ethers.Wallet(privateKey, provider)
if(tokenName === "STG") {
const tokenContract = new ethers.Contract(tokenAddress, stargateABI, signer);
// Check if we have enough allowance for Router contract
// Approving spend if needed
const allowance = await tokenContract.allowance(signer.address, BlockchainData[fromNetwork as keyof typeof BlockchainData].stargateRouter)
if (allowance.lt(amount)) {
await tokenContract.approve(BlockchainData[fromNetwork as keyof typeof BlockchainData].stargateRouter, amount, {
gasPrice: providerFeeData.gasPrice,
})
}
const feeData = await tokenContract.estimateSendTokensFee(
toNetworkId,
false,
"0x"
);
const tx = await tokenContract.sendTokens(
toNetworkId,
recipient,
amount,
0,
"0x",
{
value: feeData[0],
gasLimit: 600000,
gasPrice: providerFeeData.gasPrice,
}
);
await tx.wait();
} else if(tokenName !== "ETH") {
// Check if we have enough balance for specified amount for swap
const tokenFromContract = new ethers.Contract(tokenAddress, erc20ABI, signer);
// Check if we have enough allowance for Router contract
// Approving spend if needed
const allowance = await tokenFromContract.allowance(signer.address, BlockchainData[fromNetwork as keyof typeof BlockchainData].stargateRouter)
if (allowance.lt(amount)) {
await tokenFromContract.approve(BlockchainData[fromNetwork as keyof typeof BlockchainData].stargateRouter, amount, {
gasPrice: providerFeeData.gasPrice,
})
}
// stargate router
router = new ethers.Contract(BlockchainData[fromNetwork as keyof typeof BlockchainData].stargateRouter, routerABI, signer);
// We initialize router on fromNetwork, as we will specify destination network during swap
const quoteData = await router.quoteLayerZeroFee(
toNetworkId,
1,
signer.address,
"0x",
({
dstGasForCall: 0,
dstNativeAmount: 0,
dstNativeAddr: "0x"
})
);
const feeWei = quoteData[0];
console.log('Quote data: ', quoteData)
const tx = await router.swap(
toNetworkId,
(poolIDs as any)[fromNetwork][tokenName],
(poolIDs as any)[toNetwork][tokenName],
signer.address,
amount,
0,
{dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x"},
recipient,
"0x",
{
value: feeWei,
gasLimit: 600000,
gasPrice: providerFeeData.gasPrice,
}
);
await tx.wait();
} else {
// stargate ETH router
if(!BlockchainData[fromNetwork as keyof typeof BlockchainData].routerETH) {
throw new Error('Unsupported Network');
}
router = new ethers.Contract(BlockchainData[fromNetwork as keyof typeof BlockchainData].routerETH, routerETHABI, signer);
const tx = await router.swapETH(
toNetworkId,
signer.address,
recipient,
amount,
0,
{
value: amount,
gasLimit: 600000,
gasPrice: providerFeeData.gasPrice,
}
);
await tx.wait();
}
}Editor is loading...