NodeJS Web3 Example

An example of how to use NodeJS with Web3 and the 1inch API
  1. To access the 1inch API, send a GET request to any of the URLs outlined in the docs depending on what function you need.

  2. For the example below, the swap request is being called. Before any swap request is called, make sure 1inch v3 has approval to spend the token being traded. Approvals can be done with the request found here https://docs.1inch.exchange/api/approve

  3. The "tx" JSON object can be signed with a private key after adding the nonce field. Once signed, the transaction needs to be serialized for it to be in the correct data format to be broadcast.

  4. Finally, the transaction can be converted over to a hexadecimal string and the web3 provider is used to broadcast the transaction.

boilerplate.js
/** NodeJS example of using the 1INCH API with web3{js} */
const axios = require('axios'); //used for getting api data, install with "yarn add axios"
const Web3 = require('web3'); //used for web3 functions, install with "yarn add web3"
const Common = require('ethereumjs-common').default;//used for creating custom chains, install with "yarn add '@ethereumjs/[email protected]'"
var Tx = require('ethereumjs-tx').Transaction; //used to sign and broadcast the transaction, install with "yarn add ethereumjs-tx"
let ETHprovider = new Web3.providers.WebsocketProvider('wss://mainnet.infura.io/ws/v3/*Find_On_Infura*')
//websocket provider for Ethereum mainnet can be found here: infura.io
let BSCprovider = new Web3.providers.WebsocketProvider('wss://apis.ankr.com/wss/*FIND_ON_ANKR_PROJECT_WEBPAGE*/*FIND_ON_ANKR_PROJECT_WEBPAGE*/binance/full/main');
//websocket provider for binance smart chain can be found here: app.ankr.com/apps/api
let web3 = new Web3(ETHprovider);
var privateKey = Buffer.from('*Your_Private_Key*', 'hex');
//some variables/constnats we'll use
const ADDRESS = '*Your_Address*';//your address
let callURL = 'https://api.1inch.exchange/v3.0/1/swap?fromTokenAddress=0x111111111117dc0aa78b770fa6a738034120c302&' +
'toTokenAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&' +
'amount=1000000000000000000&fromAddress=' +
ADDRESS +
'&slippage=1';
let approveURL = 'https://api.1inch.exchange/v3.0/1/approve/calldata';
//the common configuration for Binance Smart Chain
//docs: https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/common
const binanceSmartChain = Common.forCustomChain(
'mainnet',
{ //Custom chain parameters
name: 'Binance',
networkId: 56,
chainId: 56,
},
'petersburg' //Supported hard forks
)
//the configuration for ETH mainnet
const ethereumMainnet = { 'chain': 'mainnet' }
/**
* The driver of the program, this will execute anything you put in it
*/
async function driver() {
//where the 1000000000000000000 is the amount in wei wanting to be unlocked
globalData = await approveApiCaller(approveURL, 1000000000000000000, "0x111111111117dc0aa78b770fa6a738034120c302", "0xfe");
console.log(globalData);
transaction = signTx(globalData); //sign the transaction with
console.log(transaction); //print the serialized transaction
sendTransaction(transaction); //send the transaction
globalData = await apiCaller(callURL, '0xff'); //call the api to get the data, and wait until it returns
console.log(globalData["tx"]); //log the data
transaction = signTx(globalData["tx"]); //sign the transaction
console.log(transaction); //print the bytes
sendTransaction(transaction); //send the transaction
console.log("transaction success");
}
/**
* Sends a transaction based on serialized data
* @param {the serialized transaction you want to send} tx
*/
function sendTransaction(tx) {
let temp = '0x' + tx.toString('hex'); //make the transaction into a hexadecimal string
web3.eth.sendSignedTransaction(temp).on('receipt', console.log);
}
/**
* Will sign a transaction with a private key based on the transaction data provided
* @param {the transaction you'd like signed} tx
* @returns serialized transaction
*/
function signTx(tx) {
let temp = new Tx(tx, ethereumMainnet);
//let temp = new Tx(tx, { common: ethereumMainnet });
temp.sign(privateKey);
console.log(temp);
return temp.serialize();
}
/**
* This will call the api to get an approve transaction, some tokens need to be approved to 0 before increasing again later
* @param {the url used to access the } url
* @param {the number of tokens that are requested to be unlocked, if "null" infinite will be unlocked } value
* @param {the token address of what tokens needs to be unlocked} tokenAddress
* @param {the nonce of the transaction} nonce
* @returns approve transaction
*/
async function approveApiCaller(url, value, tokenAddress, nonce) {
url += (value > -1 || value != null ? "?amount=" + value + "&" : "") //tack on the value if it's greater than -1
+ "tokenAddress=" + tokenAddress //complete the called URL
console.log(url);
let temp = await axios.get(url); //wait for the request to be complete
temp = temp.data; //we only want the data object from the api call
//we need to convert the gas price to hex
let gasPrice = parseInt(temp["gasPrice"]);
console.log(gasPrice)
gasPrice = '0x' + gasPrice.toString(16); //convert to hexadecimal string
temp["value"] = "0x" + temp["value"]; //convert value to hecadecimal
temp["gasPrice"] = gasPrice; //change the gas price in the tx object
temp["gas"] = "0xc350"; //gas limit of 50,000, may need to be higher for certain tokens
temp["from"] = ADDRESS;
temp["nonce"] = nonce;
return temp;
}
/**
* Will call the api and return the data needed
* @param {the url of what api call you want} url
* @param {the nonce of the transaction, the user must keep track of this} nonce
* @returns swap transaction
*/
async function apiCaller(url, nonce) {
let temp = await axios.get(url); //get the api call
temp = temp.data; //we only want the data object from the api call
//we need to convert the gasPrice to hex
let gasPrice = parseInt(temp.tx["gasPrice"]); //get the gasPrice from the tx
gasPrice = '0x' + gasPrice.toString(16); //add a leading 0x after converting from decimal to hexadecimal
temp.tx["gasPrice"] = gasPrice; //set the value of gasPrice in the transaction object
//we also need value in the form of hex
let value = parseInt(temp.tx["value"]); //get the value from the transaction
value = '0x' + value.toString(16); //add a leading 0x after converting from decimal to hexadecimal
temp.tx["value"] = value; //set the value of value in the transaction object
temp.tx["nonce"] = nonce; //it's the users responsibility to keep track of the nonce
return temp; //return the data
}
driver();