how to swap tokens on uniswap using web3 js
Asked Answered
Q

2

15

I am trying to use uniswap contract method to simply swap eth for token, using eth from metamask wallet. Uniswap contract method is:

function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
  external
  payable
  returns (uint[] memory amounts);

My naive impression is that it should look something like this, but I am sure I am missing several crucial parts (like signing the transaction, use apropriate callback method) and I cannot find a full comprehensive example. How should a full working example look like?

const ETHaddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
const DAIaddress = "0x6b175474e89094c44da98b954eedeac495271d0f"

const routerContract = new web3.eth.Contract(
                  UniswapRouterABI,
                  "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
                );

routerContract.methods.swapExactETHForTokens(500,[ETHaddress,DAIaddress],myWalletAddress,someDeadline)
.send(from: myWalletAddress, value: "1000000000000")
Quad answered 25/10, 2020 at 17:52 Comment(3)
Uniswap has a JavaScript SDK. If you are newcomer developer I suggest using their SDK instead of trying to figure out it yourself.Accalia
@MikkoOhtamaa the Uniswap SDK doesn't execute transactions AFAIK.En
@lxx You might be right. Thank you for correcting me.Accalia
M
9

You can check this working example for buying on pancakeswap.finance: https://github.com/religion-counter/onlyone/blob/main/helper-scripts/buy-onlyone-pancakeswap.js

// Helper script that buys ONLYONE token from a specified address specified on text file SPECIFY_ACCOUNTS_YOU_WANT_TO_BUY_FOR_HERE.json
// The amount is specified with 'originalAmountToBuyWith' variable in the source
// The JSON file should have an array with objects with 'address' field and 'privateKey' field.
// Buys ONLYONE for ${bnbAmount} BNB from pancakeswap for address ${targetAccounts[targetIndex].address}
// targetIndex is passed as an argument: process.argv.splice(2)[0]

var fs = require('fs')
var Tx = require('ethereumjs-tx').Transaction;
var Web3 = require('web3')
var Common = require('ethereumjs-common').default;

var web3 = new Web3(new Web3.providers.HttpProvider('https://bsc-dataseed.binance.org/'))
var BSC_FORK = Common.forCustomChain(
    'mainnet',
    {
        name: 'Binance Smart Chain Mainnet',
        networkId: 56,
        chainId: 56,
        url: 'https://bsc-dataseed.binance.org/'
    },
    'istanbul',
);

// SPECIFY_THE_AMOUNT_OF_BNB_YOU_WANT_TO_BUY_FOR_HERE
var originalAmountToBuyWith = '0.007' + Math.random().toString().slice(2,7);
var bnbAmount = web3.utils.toWei(originalAmountToBuyWith, 'ether');

var targetAccounts = JSON.parse(fs.readFileSync('SPECIFY_ACCOUNTS_YOU_WANT_TO_BUY_FOR_HERE.json', 'utf-8'));

var targetIndex = Number(process.argv.splice(2)[0]);
var targetAccount = targetAccounts[targetIndex];

console.log(`Buying ONLYONE for ${originalAmountToBuyWith} BNB from pancakeswap for address ${targetAccount.address}`);

var res = buyOnlyone(targetAccounts[targetIndex], bnbAmount);
console.log(res);

async function buyOnlyone(targetAccount, amount) {

    var amountToBuyWith = web3.utils.toHex(amount);
    var privateKey = Buffer.from(targetAccount.privateKey.slice(2), 'hex')  ;
    var abiArray = JSON.parse(JSON.parse(fs.readFileSync('onlyone-abi.json','utf-8')));
    var tokenAddress = '0xb899db682e6d6164d885ff67c1e676141deaaa40'; // ONLYONE contract address
    var WBNBAddress = '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c'; // WBNB token address

    // var onlyOneWbnbCakePairAddress = '0xd22fa770dad9520924217b51bf7433c4a26067c2';
    // var pairAbi = JSON.parse(fs.readFileSync('cake-pair-onlyone-bnb-abi.json', 'utf-8'));
    // var pairContract = new web3.eth.Contract(pairAbi, onlyOneWbnbCakePairAddress/*, {from: targetAccount.address}*/);
    var amountOutMin = '100' + Math.random().toString().slice(2,6);
    var pancakeSwapRouterAddress = '0x10ed43c718714eb63d5aa57b78b54704e256024e';

    var routerAbi = JSON.parse(fs.readFileSync('pancake-router-abi.json', 'utf-8'));
    var contract = new web3.eth.Contract(routerAbi, pancakeSwapRouterAddress, {from: targetAccount.address});
    var data = contract.methods.swapExactETHForTokens(
        web3.utils.toHex(amountOutMin),
        [WBNBAddress,
         tokenAddress],
        targetAccount.address,
        web3.utils.toHex(Math.round(Date.now()/1000)+60*20),
    );

    var count = await web3.eth.getTransactionCount(targetAccount.address);
    var rawTransaction = {
        "from":targetAccount.address,
        "gasPrice":web3.utils.toHex(5000000000),
        "gasLimit":web3.utils.toHex(290000),
        "to":pancakeSwapRouterAddress,
        "value":web3.utils.toHex(amountToBuyWith),
        "data":data.encodeABI(),
        "nonce":web3.utils.toHex(count)
    };

    var transaction = new Tx(rawTransaction, { 'common': BSC_FORK });
    transaction.sign(privateKey);

    var result = await web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex'));
    console.log(result)
    return result;
}

You can also contribute to the repository if interested.

Montgolfier answered 10/6, 2021 at 12:26 Comment(8)
What is this abi code for var abiArray = JSON.parse(JSON.parse(fs.readFileSync('onlyone-abi.json','utf-8')));?Largely
The ONLYONE token contract ABI is there: github.com/religion-counter/onlyone/blob/main/helper-scripts/… You can also check the token contract ABIs in the bscscan in Contract ABI section: bscscan.com/address/… You can export it from there.Montgolfier
i have all the time this error: Error: Transaction has been reverted by the EVM: this is transaction i made with some token available in bscnan bscscan.com/tx/…Largely
Hi @kasper, I see in your transaction: Gas Used by Transaction: 294,919 (98.31%) Try increasing the gas limit to 460000 or something above and see if you will get the same error.Montgolfier
There is a way to retrive automatically the path of the token?Selfdefense
@Selfdefense You can check github.com/religion-counter/onlyone/issues/10 and github.com/Uniswap/v2-sdk/blob/… in the Uniswap github there is a function that calculates the best path given input and output token.Montgolfier
I think you can also use the graph API to see all pairs for a given token: docs.uniswap.org/protocol/V2/reference/API/… Pancakeswap should have similar API. RegardsMontgolfier
@Largely I see you got this working. Can you share what you did to get it to work? I am getting the same error: "Transaction has been reverted by the EVM"Ddt
G
8

First of all you should login your eth account like below

const keystore = fs.readFileSync("your keystore path", "utf8");
var activeAccount = web3.eth.accounts.decrypt(keystore, password);

Now you can sign and broadcast your transaction. You must encode your swap message and add your tx's data field. Don't miss eth amount how many want to swap with token.

var swap = UniswapV2Router02Contract.methods.swapExactETHForTokens(amountOutMin, [WETH[activeChain].address, token.address], activeAccount.address, timeStamp)
var encodedABI = swap.encodeABI()

var tx = {
    from: activeAccount.address,
    to: UniswapV2RouterAddress,
    gas: 200000,
    data: encodedABI,
    value: ethAmount
  };

var signedTx = await activeAccount.signTransaction(tx)

web3.eth.sendSignedTransaction(signedTx.rawTransaction)
.on('transactionHash', function(hash){

})
.on('confirmation', function(confirmationNumber, receipt){

})
.on('receipt', function(receipt){

})
.on('error', function(error, receipt) { // If the transaction was rejected by the network with a receipt, the second parameter will be the receipt.
    console.error("Error:", error, "Receipt:", receipt)
});
Goldshell answered 31/1, 2021 at 2:35 Comment(3)
where can you find the UniswapV2Router02Contract can you post a complete example?Bacciferous
did you know how to find UniswapV2Router02Contract @Bacciferous please ?Illinois
Here: etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488dGoldshell

© 2022 - 2024 — McMap. All rights reserved.