nodejs web3 bsc bep20 token transfer no confirmation - javascript
I'm trying to transfer a BEP-20 token on BSC from one Wallet to Another. I actually had it at one point and somehow messed up while doing code cleanup. Anway, I need some help. When I send my transaction I never get a confirmation.
I get a hash for example : 0xd18ee37686b00d45edb9974d8a119534f3403052e3ed4908ac8ca80bde385416
But it never goes anywhere. I've beat my head on the wall with this for two days, any help would be greatly appreciated. - Note Endpoint and Private Key are fake
// Ethereum javascript libraries needed
var Web3 = require('web3')
var Tx = require("ethereumjs-tx").Transaction;
const Common = require('ethereumjs-common');
const mysql = require('mysql');
//KLUV Contract Address KLUV - BSC
const _ContractAddress_ = '0x3A68A9Cd188C324a45c06866eFD1C79605B66827';
const _ContractABI_ = JSON.parse('[{"inputs":[],"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":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":"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":[],"name":"getunlockedAfter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"lockedPeriodOver","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"renounceOwnership","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"},{"inputs":[],"name":"withdrawLockedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]');
//To Wallet Address
const _ToWalletAddress_ = '0x76D52CF51D9a4B8C84Bf01b7AA3f801c52A328D8';
//My MetaMask Wallet
const _FromWalletAddress_ = '0xDeBCBca7f21aB70DA4e7860a112FEB3d8Fd04db5';
//My MetaMask Private Key
const _FromWalletPrivateKey_ = 'f777980edfc1c92446XXXXXXXXXXXXXXXe615ffcccc0744f0a4054c8f924773d';
//Node URL
const BSCNode = 'https://nd-098-532-742.p2pify.com/super_secret_address';
const web3 = new Web3(new Web3.providers.HttpProvider(BSCNode));
const main = async () => {
console.log(`web3 version: ${web3.version}`)
// Who holds the token now?
var senderWalletAddress = _FromWalletAddress_;
// Who are we trying to send this token to?
var receiverWalletAddress = _ToWalletAddress_;
// The address of the contract which created MFIL
var contractAddress = _ContractAddress_;
var contract = new web3.eth.Contract(_ContractABI_, contractAddress, {
from: senderWalletAddress
});
// How many tokens do I have before sending?
var balance = await contract.methods.balanceOf(senderWalletAddress).call();
console.log(`Balance before send: ${balance} sKLUV\n------------------------`);
// Use Gwei for the unit of gas price
var gasPriceGwei = 5;
var gasLimit = 5000000;
// .00000001 KLUV
var transferAmount = 1;
// Determine the nonce - This isn't always good, you need to keep track of it
var count = await web3.eth.getTransactionCount(senderWalletAddress);
console.log(`num transactions so far: ${count}`);
/* Override count - especially if testing */
count = 77;
var rawTransaction = {
"from": senderWalletAddress,
"nonce": "0x" + count.toString(16),
"gasPrice": web3.utils.toHex(gasPriceGwei * 1e9),
"gasLimit": web3.utils.toHex(gasLimit),
"to": contractAddress,
"value": "0x0",
"chainId": 56,
"data": contract.methods.transfer(receiverWalletAddress, transferAmount).encodeABI(),
};
console.log(`Raw of Transaction: \n${JSON.stringify(rawTransaction, null, '\t')}\n------------------------`);
// Create Buffer containing hex of private key
var privKey = new Buffer.from(_FromWalletPrivateKey_, 'hex');
/* Define What Block Chain we're using */
const chain = Common.default.forCustomChain(
'mainnet', {
name: 'bnb',
networkId: 56,
chainId: 56
},
'petersburg'
)
/* generate transaction including my block chain */
var tx = new Tx(rawTransaction, {common: chain});
/* sign the transaction with my buffered private key */
tx.sign(privKey);
/* Serialize the result */
var serializedTx = tx.serialize();
/* Get Ready to send */
console.log(`Attempting to send signed tx: ${serializedTx.toString('hex')}\n------------------------`);
/* Limit the number of confirms we're looking for */
let numberOfConfirms = 5;
web3.eth.transactionConfirmationBlocks = numberOfConfirms;
/* Use Event Method so we can see where things are hanging up */
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'))
.on("sending", (payload) => {
console.log('sending ');
console.log(payload);
})
.on("sent", (payload) => {
console.log('Sent Payload');
console.log(payload);
})
.on('transactionHash', (transactionHash) => {
console.log('Received Transaction hash');
console.log(transactionHash);
})
.on("receipt", (receipt) => {
console.log('Received Receipt');
console.log(`Receipt info: \n${JSON.stringify(receipt, null, '\t')}\n------------------------`);
})
.on("confirmation", (confNumber, receipt, latestBlockHash) => {
console.log('Received Confirmation ', confNumber);
if (confNumber == numberOfConfirms) {
// The balance may not be updated yet, but let's check
contract.methods.balanceOf(senderWalletAddress).call().then((balance) => {
console.log(`Balance after send: ${balance} sKLUV`);
});
}
console.log(confNumber, receipt, latestBlockHash);
})
.on('error', err => {
console.log('Error Sending Transaction');
console.log(err.message);
}).catch(reason => {
console.log('Promise failed in catch');
console.log(reason);
});
};
main();
the only thing I see chainId in rawTransaction is not in hex format. should be
"chainId":web3.utils.toHex(56)
Related
Transaction Fail when trying to swap on Uniswap V3 programmatically
I'm trying to create a script to execute a swap on Uniswap V3. The code below works perfectly well on the Goerli Testnet Network but NOT on Mainnet. In order to make in run on mainnet: i've changed the tokens addresses to match the mainnet ones and also changed the INFURA_URL to the mainnet url but I keep getting failed transactions.. const address0 = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' const address1 = '0x6B175474E89094C44Da98b954EedeAC495271d0F' Seems like the error might come from the swapRouterAddress but not sure.. Moreover, when I execute the swap manually using Uniswap website, i can see that the swap was executed using Uniswap V3: Router 2, but even if I use this Router Address on my script the transaction keep failing.. Does anyone knows how to solve this ? Thanks a lot ! const { ethers } = require('ethers') const { abi: IUniswapV3PoolABI } = require('#uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Pool.sol/IUniswapV3Pool.json') const { abi: SwapRouterABI} = require('#uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json') const { abi: UniswapV3Factory } = require('#uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json') const { getPoolImmutables, getPoolState } = require('./helpers') const ERC20ABI = require('./abi.json') require('dotenv').config() const INFURA_URL_TESTNET = process.env.INFURA_URL_TESTNET // Wallets const WALLETS = [process.env.WALLET_ADDRESS_1]; var SECRET = new Object(); SECRET[process.env.WALLET_ADDRESS_1] = process.env.WALLET_SECRET_1; // Provider const provider = new ethers.providers.JsonRpcProvider(INFURA_URL_TESTNET) // Goerli const swapRouterAddress = '0xE592427A0AEce92De3Edee1F18E0157C05861564' // Wrapped Ether const name0 = 'Wrapped Ether' const symbol0 = 'WETH' const decimals0 = 18 const address0 = '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6' // Token info const name1 = 'Token' const decimals1 = 18 const address1 = '0x11fE4B6AE13d2a6055C8D9cF65c55bac32B5d844' // DAI // SWAP const factoryAddress = '0x1F98431c8aD98523631AE4a59f267346ea31F984' async function buy(WETH_amount) { const factoryContract = new ethers.Contract( factoryAddress, UniswapV3Factory, provider ) const poolAddress = await factoryContract.getPool(address0, address1, 500) for (const WALLET of WALLETS) { const poolContract = new ethers.Contract( poolAddress, IUniswapV3PoolABI, provider ) const immutables = await getPoolImmutables(poolContract) const state = await getPoolState(poolContract) var WALLET_SECRET = SECRET[WALLET]; const wallet = new ethers.Wallet(WALLET_SECRET) const connectedWallet = wallet.connect(provider) const swapRouterContract = new ethers.Contract( swapRouterAddress, SwapRouterABI, provider ) const inputAmount = WETH_amount // .001 => 1 000 000 000 000 000 const amountIn = ethers.utils.parseUnits( inputAmount.toString(), decimals0 ) const params = { tokenIn: immutables.token1, tokenOut: immutables.token0, fee: immutables.fee, recipient: WALLET, deadline: Math.floor(Date.now() / 1000) + (60 * 5), amountIn: amountIn, amountOutMinimum: 0, sqrtPriceLimitX96: 0, } const transaction = swapRouterContract.connect(connectedWallet).exactInputSingle( params, { gasLimit: ethers.utils.hexlify(1000000) } ).then(transaction => { console.log(transaction) }) } } // MAIN buy(WETH_amount_=0.001)
Note that the token address for WETH is different on mainnet - your code has the address for WETH on Goerli. See https://docs.uniswap.org/protocol/reference/deployments for some token addresses
Getting Error: Returned error: Must be authenticated! , while sending erc20 code using web3.js
const fs = require('fs'); let web3 = new Web3(new Web3.providers.HttpProvider('http:127.0.0.1')) const abi = fs.readFileSync('erc20_abi.json', 'utf-8') const contractAddress = '0xB4...' const privateKey = '...' let contract = new web3.eth.Contract(JSON.parse(abi), contractAddress); let transfer = contract.methods.transfer("0xd...", 10); let encodedABI = transfer.encodeABI(); var tx = { from: "0xF...", to: contractAddress, gas: 2000000, data: encodedABI }; web3.eth.accounts.signTransaction(tx, privateKey).then(signed => { var tran = web3.eth.sendSignedTransaction(signed.rawTransaction); tran.on('confirmation', (confirmationNumber, receipt) => { console.log('confirmation: ' + confirmationNumber); }); tran.on('transactionHash', hash => { console.log('hash'); console.log(hash); }); tran.on('receipt', receipt => { console.log('reciept'); console.log(receipt); }); tran.on('error', console.error); }); I am using the above code to send ERC20 tokens from account to another account, Its throwing this error UnhandledPromiseRejectionWarning: Error: Returned error: Must be authenticated
I have figured it out I am using wrong rpc provider, changing the Rpc provider fixes this issue.
Listing NFT on OpenSea via JS API: Failed to extract transfer calldata Error 400
I am trying to use the OpenSea JavaScript API in order to list NFTs for sale automatically. I can't seem to figure out why I keep getting the error Error: API Error 400: ['Failed to extract transfer calldata']. Perhaps I have not entered some data correctly? My code is adapted from this example. SOURCE const opensea = require("opensea-js"); const OpenSeaPort = opensea.OpenSeaPort; const Network = opensea.Network; const MnemonicWalletSubprovider = require("#0x/subproviders") .MnemonicWalletSubprovider; const RPCSubprovider = require("web3-provider-engine/subproviders/rpc"); const Web3ProviderEngine = require("web3-provider-engine"); const MNEMONIC = "SECRET ..."; const NODE_API_KEY = "FROM INFURA"; const isInfura = true; //const FACTORY_CONTRACT_ADDRESS = process.env.FACTORY_CONTRACT_ADDRESS; const NFT_CONTRACT_ADDRESS = "0x495f947276749Ce646f68AC8c248420045cb7b5e"; const OWNER_ADDRESS = "0x3eb8eea9565418281f4cae934dd69e7ff2bb5949"; const NETWORK = "mainnet"; const API_KEY = process.env.API_KEY || ""; // API key is optional but useful if you're doing a high volume of requests. const BASE_DERIVATION_PATH = `44'/60'/0'/0`; const mnemonicWalletSubprovider = new MnemonicWalletSubprovider({ mnemonic: MNEMONIC, baseDerivationPath: BASE_DERIVATION_PATH, }); const network = NETWORK === "mainnet" || NETWORK === "live" ? "mainnet" : "rinkeby"; const infuraRpcSubprovider = new RPCSubprovider({ rpcUrl: isInfura ? "https://" + network + ".infura.io/v3/" + NODE_API_KEY : "https://eth-" + network + ".alchemyapi.io/v2/" + NODE_API_KEY, }); const providerEngine = new Web3ProviderEngine(); providerEngine.addProvider(mnemonicWalletSubprovider); providerEngine.addProvider(infuraRpcSubprovider); providerEngine.start(); const seaport = new OpenSeaPort( providerEngine, { networkName: NETWORK === "mainnet" || NETWORK === "live" ? Network.Main : Network.Rinkeby, apiKey: API_KEY, }, (arg) => console.log(arg) ); exports.helloWorld = async (req, res) => { // Example: simple fixed-price sale of an item owned by a user. console.log("Auctioning an item for a fixed price..."); try { const fixedPriceSellOrder = await seaport.createSellOrder({ asset: { tokenId: "28370143653034713195993216915191765879963367987017833025925208213530804748289", tokenAddress: NFT_CONTRACT_ADDRESS, }, startAmount: 0.1, expirationTime: 0, accountAddress: OWNER_ADDRESS, }); console.log( `Successfully created a fixed-price sell order! ${fixedPriceSellOrder.asset.openseaLink}\n` ); } catch (error) { console.log("ERROR",error); } }; FULL LOGS WHERE I GOT DATA ASSET URL
What is your Token Standard? If it is not ERC721, you need to specify it as your schemaName inside the asset object, like this : const fixedPriceSellOrder = await seaport.createSellOrder({ asset: { tokenId: "28370143653034713195993216915191765879963367987017833025925208213530804748289", tokenAddress: NFT_CONTRACT_ADDRESS, schemaName: "ERC1155" }, startAmount: 0.1, expirationTime: 0, accountAddress: OWNER_ADDRESS, }); You can find Token Standard in Details tab, on Opensea asset page : Remove the dash and you're good. ERC1155 was fine for me.
Struggling with chaining postgres db async/await promises to get a result sent to client (express)
I have spent a while looking around at similar problems online but I seem to be really struggling to wrap my head around this. I've reviewed a few sources online for help but was unable to apply the logic I seen to my own codebase, I'm hoping somebody out there might be able to help. I'm running an express server with a pg Pool to handle DB logic. I am able to successfully log out the information from within the pg.Pool logic however despite banging my head against multiple attempts I have been unable to successfully pass the data onto the clientside. dbQueries.js const { Pool } = require('pg'); const pool = new Pool({ user: process.env.DB_USER, host: process.env.DB_HOST, database:process.env.DB_NAME, password: process.env.DB_PASSWORD, port: process.env.DB_PORT }); // Main function called in server.js // step 1. fetches distinct name values from pg table // step 2. fetches values to get full list of reviews for those distinct names // step 3. does some data modification to make the data formatted for frontend usecase const getFormattedReviews = async function(){ console.log('Fetching all unique therapist review names.') const getDistinct = { name: 'distinct-reviews', text: 'SELECT DISTINCT therapist_name FROM reviews' }; // step 1 const res = await pool.query(getDistinct, (err, res) => { let data = [] if (err) { console.log(err.stack); } else { // console.log(res.rows); data = res.rows.map( // step 2 therapist => getSpecificTherapistReviews(therapist.therapist_name) ) } console.log(`\n DEBUG3 - getFormattedReviews data: ${JSON.stringify(data)} \n`) return data; }); return res; } const getSpecificTherapistReviews = async function(therapist_name){ console.log(`Fetching reviews for: ${therapist_name}.`) const getSpecificTherapistReviews = { name: `${therapist_name}-reviews`, text: `SELECT * FROM reviews WHERE therapist_name LIKE '%${therapist_name}%'` }; const res = await pool.query(getSpecificTherapistReviews, (err, res) => { let data = [] if (err) { console.log(err.stack); } else { // console.log(res.rows); // step 3 data = filteringDataForFrontend(res.rows); } console.log(`\n DEBUG2 - GetSpecificTherapistReviews ${JSON.stringify(data)} \n`) return data; }); return res; } const filteringDataForFrontend = function(data){ console.log(`Filtering Data for Frontend.`) // Based on length of the reviews array, each review = 1 object const total_reviews = data.length; // Underlying logic assumes consistent data across all entries for these values const therapist_name = data[0].therapist_name; const type = data[0].type; const image = data[0].image; const location = data[0].location; // Summing the rating values across multiple review entries const ratings = data.reduce((acc, obj) => ({ rating_friendliness: acc.rating_friendliness + obj.rating_friendliness, rating_techniques: acc.rating_techniques + obj.rating_techniques, rating_progression: acc.rating_progression + obj.rating_progression, rating_cost: acc.rating_progression + obj.rating_progression, rating_listening: acc.rating_listening + obj.rating_listening, rating_overall: acc.rating_overall + obj.rating_overall }) ) // Placeholder as string, most likely restructure to an array of objects const comments = data.reduce ((acc, obj) => ({ feedback_comments: acc.feedback_comments + obj.feedback_comments }) ) // Filtered data for returning const filteredData = { therapist_name, type, image, location, rating_friendliness: ratings.rating_friendliness / total_reviews, rating_techniques: ratings.rating_techniques / total_reviews, rating_progression: ratings.rating_progression / total_reviews, rating_cost: ratings.rating_cost / total_reviews, rating_listening: ratings.rating_listening / total_reviews, rating_overall: ratings.rating_overall / total_reviews, feedback_comments: comments.feedback_comments } console.log(`\n DEBUG 1 - filteredData -> ${JSON.stringify(filteredData)} \n`) return filteredData; } module.exports = { getFormattedReviews, }; An ideal setup I would like to have on the server.js side of things running express would be: server.js const express = require('express'); const DB = require('./dbQueries.js'); const app = express(); const port = process.env.SERVER_PORT || 8000; app.get('/get-reviews', async (req, res) => { const data = await DB.getFormattedReviews(); console.log(`data check ${data}`); res.send({data}); }); Currently the endpoint is logging 'data check undefined'. DEBUG checks 1 & 2 successfully appear to log information, however I spotted that DEBUG 3 only logs DEBUG3 - getFormattedReviews data: [{},{},{}] so perhaps I'm doing something wrong around there? Any help/insight appreciated.
Thanks #Abraham & #Labkovsky for the suggestions -> Ill review them properly during the week. I managed to get the basic fuctionality up and running with this code - it likely needs some refactoring but for reference: dbQueries.js const getFormattedReviews = async function(){ const getDistinct = { name: 'distinct-reviews', text: 'SELECT DISTINCT therapist_name FROM reviews' }; const res = await new Promise(resolve => { pool.query(getDistinct, (err, res) => { let data = [] if (err) { console.log(err.stack); } else { // console.log(res.rows); data = res.rows.map( async therapist => await getSpecificTherapistReviews(therapist.therapist_name) ) // Promise.all(data).then(results => console.log(`\n DEBUG3 - getFormattedReviews data: ${JSON.stringify(results)} \n`)) } Promise.all(data).then(results => resolve(results)); }); }); return res; } const getSpecificTherapistReviews = async function(therapist_name){ // console.log(`Fetching reviews for: ${therapist_name}.`) const getSpecificTherapistReviews = { name: `${therapist_name}-reviews`, text: `SELECT * FROM reviews WHERE therapist_name LIKE '%${therapist_name}%'` }; const res = await new Promise(resolve => { pool.query(getSpecificTherapistReviews, (err, res) => { let data = [] if (err) { console.log(err.stack); } else { // console.log(res.rows); data = filteringDataForFrontend(res.rows); } // console.log(`\n DEBUG2 - GetSpecificTherapistReviews ${JSON.stringify(data)} \n`) resolve(data); }); }); return res; } const filteringDataForFrontend = function(data){ // Based on length of the reviews array, each review = 1 object const total_reviews = data.length; // Underlying logic assumes consistent data across all entries for these values const therapist_name = data[0].therapist_name; const type = data[0].type; const image = data[0].image; const location = data[0].location; // Summing the rating values across multiple review entries const ratings = data.reduce((acc, obj) => ({ rating_friendliness: acc.rating_friendliness + obj.rating_friendliness, rating_techniques: acc.rating_techniques + obj.rating_techniques, rating_progression: acc.rating_progression + obj.rating_progression, rating_cost: acc.rating_progression + obj.rating_progression, rating_listening: acc.rating_listening + obj.rating_listening, rating_overall: acc.rating_overall + obj.rating_overall }) ) // Placeholder as string, most likely restructure to an array of objects const comments = data.reduce ((acc, obj) => ({ feedback_comments: acc.feedback_comments + obj.feedback_comments }) ) // Filtered data for returning const filteredData = { therapist_name, type, image, location, total_reviews, rating_friendliness: ratings.rating_friendliness / total_reviews, rating_techniques: ratings.rating_techniques / total_reviews, rating_progression: ratings.rating_progression / total_reviews, rating_cost: ratings.rating_cost / total_reviews, rating_listening: ratings.rating_listening / total_reviews, rating_overall: ratings.rating_overall / total_reviews, feedback_comments: comments.feedback_comments } // console.log(`\n DEBUG 1 - filteredData -> ${JSON.stringify(filteredData)} \n`) return filteredData; } module.exports = { getFormattedReviews, }; server.js const express = require('express'); const DB = require('./dbQueries.js'); const app = express(); const port = process.env.SERVER_PORT || 8000; app.get('/get-reviews', async (req, res) => { const data = await DB.getFormattedReviews(); // data.then(data => console.log(`data2 check ${JSON.stringify(data)}`)) res.send(data); }); Ultimately I think my limited understanding of Promises/Async/Await & Promise.all failed me a bit here, the Promise.all in the getFormattedReviews was the missing trick. Some of the code was rewritten with some new Promise syntax which can likely be redacted however I noted when doing this with the getFormattedReviews method that it broke sending the data to the /get-reviews endpoint. Something I'll investigate later.
You are awaiting a callback. I don't think that works. Try wrapping in a Promise. That might be the issue. Full disclosure: I did not read your code very in depth... const res = await new Promise(resolve => { pool.query(getSpecificTherapistReviews, (err, res) => { let data = [] if (err) { console.log(err.stack); } else { // console.log(res.rows); // step 3 data = filteringDataForFrontend(res.rows); } console.log(`\n DEBUG2 - GetSpecificTherapistReviews ${JSON.stringify(data)} \n`) resolve(data); }); })
How to send an ERC20 token with web3js
I'm currently using the 0.2x.x version of the Web3 JavaScript API. I deployed my custom ERC20 token by creating smart contract in solidity (on REMIX IDE). I installed the MetaMask and had a test on https://wallet.ethereum.org/ to send some custom ERC token to another my account. It worked well. I want to add the 'send custom ERC20 Token' function in my JavaScript code using Web3js. Here is my code below. var http = require('http'); var Web3 = require('web3'); var Tx = require('ethereumjs-tx'); var abi = [{"...."}]; var data = '0x00..'; var contract_addr = '0x00..'; var owner = '0x00..'; var web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/")); web3.eth.getBlock("latest", (error, result) => { //console.log('error:', error); //console.log('results', result); }); var myContract = web3.eth.contract(abi); var myContractInstance = myContract.at(address); eb3.eth.getDefaultAccount = owner; var defaultAccount = web3.eth.getDefaultAccount; console.log('DefaultAccount => ', defaultAccount); var total = myContractInstance.totalSupply(); var balance = myContractInstance.balanceOf(defaultAccount); console.log('DefulatAccount total => ',total); console.log('DefaultAccount balance => ',balance); var to = '0x00..'; var isAddress = web3.isAddress(to); console.log('isAddress(to) => ',isAddress); console.log('balanceOf(to) => ',myContractInstance.balanceOf(to)); I'm working on the 'Ropsten Testnet' and I sent some 'ether' for test using sendRawTransaction(). But what I want to do is just sending my custom ERC20 token. not the ether. How can I send my own token in this script? I have no idea. I tried to use sendTransaction() like below. var rawTx = { from : defaultAccount, nonce : nonceHex, gasPrice : gasPriceHex, gas : gasHex, to : to, value : 100, data : data }; web3.eth.sendTransaction(rawTx, function(err, transactionHash) { if (!err) console.log('transactionHash => ',transactionHash); else console.log(err); }); I continuously received the error. Error: Invalid JSON RPC response: "" at Object.InvalidResponse (/Users/rachel/dev/test/node_modules/web3/lib/web3/errors.js:38:16) at XMLHttpRequest.request.onreadystatechange (/Users/rachel/dev/test/node_modules/web3/lib/web3/httpprovider.js:119:24) at XMLHttpRequestEventTarget.dispatchEvent (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:64:18) at XMLHttpRequest._setReadyState (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:354:12) at XMLHttpRequest._onHttpResponseEnd (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:509:12) at IncomingMessage.<anonymous> (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:469:24) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1056:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) I really can't understand what is wrong with it. Please let me know some way to deal with this. Thanks!
Take EOS token transfering as the example. Below code need web3 and ethereumjs-tx. If you've not install them, install them with npm install web3 ethereumjs-tx var Tx = require('ethereumjs-tx'); var Web3 = require('web3') var web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545/')) // set token source, destination and amount var myAddress = "0xaa597b7e8aaffe9f2a187bedb472ef3455957560" var toAddress = "0xa013927bffe9e879134061b9330a01884a65497c" var amount = web3.utils.toHex(1e16) // get transaction count, later will used as nonce web3.eth.getTransactionCount(myAddress).then(function(v){console.log(v); count = v}) // set your private key here, we'll sign the transaction below var privateKey = new Buffer('6d...', 'hex') // Get abi array here https://etherscan.io/address/0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0#code var abiArray = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint128"}],"name":"push","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"name_","type":"bytes32"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"mint","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"wad","type":"uint128"}],"name":"pull","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"burn","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"start","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"guy","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"symbol_","type":"bytes32"}],"payable":false,"type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}] // Here you may get the abicode from a string or a file, here is a string case // var abiArray = JSON.parse('[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint128"}],"name":"push","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"name_","type":"bytes32"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"mint","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"wad","type":"uint128"}],"name":"pull","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"burn","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"start","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"guy","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"symbol_","type":"bytes32"}],"payable":false,"type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]', 'utf-8') var contractAddress = '0x86Fa049857E0209aa7D9e616F7eb3b3B78ECfdb0' var contract = new web3.eth.Contract(abiArray, contractAddress, {from: myAddress}) var rawTransaction = {"from":myAddress, "gasPrice":web3.utils.toHex(2 * 1e9),"gasLimit":web3.utils.toHex(210000),"to":contractAddress,"value":"0x0","data":contract.methods.transfer(toAddress, amount).encodeABI(),"nonce":web3.utils.toHex(count)} var transaction = new Tx(rawTransaction) transaction.sign(privateKey) web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex')) // check the balance contract.methods.balanceOf(myAddress).call().then(function(balance){console.log(balance)}) You also can check the transaction with https://etherscan.io. After the transaction send, you can check it with https://etherscan.io/address/0xaa597b7e8aaffe9f2a187bedb472ef3455957560#tokentxns, and you'll see the pending transaction as below on the Transactions filed, but you cannot see it in the Token Transfers field. Wait about 1 minute, you can see the successed on both Transactions filed and the Token Transfers field.
Error: Invalid JSON RPC response: "" means web3 cant connect to rpc node. Try running one with :: -for testnet geth --testnet --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpccorsdomain '*' --rpcapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --ws --wsaddr 127.0.0.1 --wsport 8546 --wsorigins '*' --wsapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --maxpeers 25 0 --gasprice 100 -for mainnet geth --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpccorsdomain '*' --rpcapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --ws --wsaddr 127.0.0.1 --wsport 8546 --wsorigins '*' --wsapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --maxpeers 25 0 --gasprice 100 Now in your case (using infura testnet node), get a id from infura.io. It should be like this :: https://ropsten.infura.io/id
You need to call the transfer method of the ERC20 contract. e.g.: myContractInstance.methods.transfer(toAddress, amount); And in your raw transaction object: You don't need the amount To address should be to the contract (not the toAddress in the method call) e.g.: var rawTx = { from : defaultAccount, nonce : nonceHex, gasPrice : gasPriceHex, gas : gasHex, to : <contractAddress>, data : data };
Well you can try something like this-: `myContractInstance.transfer(to,amount, {gas:estimateGas, gasPrice:gasPrice,from:fromAddr, nonce: nonceis}, function(err,txhash) { console.log("error: "+err); console.log("txhash: "+txhash); } ` Here 'to' is the address to whom you want to send tokens 'amount' amount of tokens you want to send 'estimateGas' gas limit you want to put of the transaction execution 'gasPrice' price of each gas unit in terms of wei 'fromAddr' the address from where you want to send these tokens. As the transaction will be signed using this address, this should be the address selected in metamask or passed to infura 'nonceis' nonce for the transaction
We can do it with only 'ethers'. In this case, I use backend api with node js. const fs = require('fs'); const express = require('express'); const router = express.Router(); const { ethers, BigNumber } = require('ethers'); const ethUtil = require('ethereumjs-util'); const BridgeEth = require("../../client/src/components/contract/EthBridge.json"); const BridgeBsc = require("../../client/src/components/contract/BridgeBsc.json"); const addresses = require("../../client/src/components/contract/config.json"); const eth_bridge = addresses.eth_bridge; const bsc_bridge = addresses.bsc_bridge; const net_config = require("../../net.config.json"); const ethnet = net_config.eth_url; const bscnet = net_config.bsc_url; const eth_provider = new ethers.providers.JsonRpcProvider(ethnet); const bsc_provider = new ethers.providers.JsonRpcProvider(bscnet); const eth_contract = new ethers.Contract(eth_bridge, BridgeEth, eth_provider); const bsc_contract = new ethers.Contract(bsc_bridge, BridgeBsc, bsc_provider); var privateKey = fs.readFileSync('./secret', 'utf-8'); const adminaccount = { publicKey: net_config.admin_public_key, privateKey: privateKey } console.log(`Admin account is ${adminaccount.publicKey}`); const adminEthWallet = new ethers.Wallet(adminaccount.privateKey, eth_provider); const adminBscWallet = new ethers.Wallet(adminaccount.privateKey, bsc_provider); const signedEthContract = eth_contract.connect(adminEthWallet); const signedBscContract = bsc_contract.connect(adminBscWallet); const sig = "0x6162636400000000000000000000000000000000000000000000000000000000"; router.post('/eth2bsc', async (req, res) => { var account = req.body.account; var amount = req.body.amount; var signature = req.body.signature; var msg = req.body.hash; const isValidAddress = ethUtil.isValidAddress(account); const isValidAmount = amount > 0; const isValidSign = ethUtil.isHexPrefixed(String(signature)); const isValidHash = ethUtil.isHexPrefixed(String(msg)); if (!(isValidAddress && isValidAmount && isValidSign && isValidHash)) { return res.status(500).json({ step: 1, message: `Security error! Server received invalid prams!${isValidAddress}, ${amount}, ${isValidSign}, ${isValidHash}` }); } var msgBuffer = ''; var msgHash = ''; var signatureBuffer = ''; try { msgBuffer = ethUtil.toBuffer(msg); msgHash = ethUtil.hashPersonalMessage(msgBuffer); signatureBuffer = ethUtil.toBuffer(signature); } catch (e) { return res.status(500).json({ step: 1, message: 'Security error! Request with invalid params!' }) } const signatureParams = ethUtil.fromRpcSig(signatureBuffer); const publicKey = ethUtil.ecrecover(msgHash, signatureParams.v, signatureParams.r, signatureParams.s); const adddressBuffer = ethUtil.publicToAddress(publicKey); const address = ethUtil.bufferToHex(adddressBuffer); console.log(`recvered address is ${address}`); const isMatched = account.toLowerCase() == address.toLowerCase(); if (!isMatched) { return res.status(500).json({ step: 1, message: 'Security error! Transaction caller is not signer!' }) } console.log(`I will burn BSCFloki from ${account}`) try { var tx = await signedEthContract.burn(account, BigNumber.from(String(amount * Math.pow(10, 18))), 0, sig) console.log(tx.hash); console.log("First transaction successed(ETHFloki burned)"); } catch (e) { console.log("Transaction to burn ETHFloki faild"); return res.status(500).json({ step: 1, message: 'Transaction Faild! \nCheck your account and token balance.' }) } console.log(`I will mint BSCFloki to ${account}`) try { var tx1 = await signedBscContract.mint(account, account, BigNumber.from(String(amount * Math.pow(10, 18))), 0, sig); console.log(tx1.hash); console.log("Second transaction successed(BSCFloki minted)"); } catch (e) { console.log("Transanction to mint BSCFloki faild"); return res.status(500).json({ step: 2, message: 'Transaction Faild! \nCheck your account.' }) } return res.send(`Success! \n ${amount} ETHFloki converted to ${amount} BSCFloki in your wallet.`); }); router.post('/bsc2eth', async (req, res) => { var account = req.body.account; var amount = req.body.amount; var signature = req.body.signature; var msg = req.body.hash; const isValidAddress = ethUtil.isValidAddress(account); const isValidAmount = amount > 0; const isValidSign = ethUtil.isHexPrefixed(String(signature)); const isValidHash = ethUtil.isHexPrefixed(String(msg)); if (!(isValidAddress && isValidAmount && isValidSign && isValidHash)) { return res.status(500).json({ step: 1, message: 'Security error! Server received invalid prams!' }); } var msgBuffer = ''; var msgHash = ''; var signatureBuffer = ''; try { msgBuffer = ethUtil.toBuffer(msg); msgHash = ethUtil.hashPersonalMessage(msgBuffer); signatureBuffer = ethUtil.toBuffer(signature); } catch (e) { return res.status(500).json({ step: 1, message: 'Security error! Request with invalid params!' }) } const signatureParams = ethUtil.fromRpcSig(signatureBuffer); const publicKey = ethUtil.ecrecover(msgHash, signatureParams.v, signatureParams.r, signatureParams.s); const adddressBuffer = ethUtil.publicToAddress(publicKey); const address = ethUtil.bufferToHex(adddressBuffer); console.log(`recvered address is ${address}`); const isMatched = account.toLowerCase() == address.toLowerCase(); if (!isMatched) { return res.status(500).json({ step: 0, message: 'Security error! Transaction caller is not signer!' }) } console.log(`I will burn BSCFloki from ${account}`) try { var tx = await signedBscContract.burn(account, BigNumber.from(String(amount * Math.pow(10, 18))), 0, sig) console.log(tx.hash); console.log("First transaction successed(BTK burned)"); } catch (e) { console.log("Transaction to burn ETHFloki faild"); return res.status(500).json({ step: 1, message: 'Transaction Faild! \nCheck your account and token balance.' }) } console.log(`I will mint ETHFloki to ${account}`) try { var tx1 = await signedEthContract.mint(account, account, BigNumber.from(String(amount * Math.pow(10, 18))), 0, sig); console.log(tx1.hash); console.log("Second transaction successed(ETHFloki minted)"); } catch (e) { console.log("Transaction to mint ETHFloki faild"); return res.status(500).json({ step: 2, message: 'Transaction Faild! \nCheck your account.' }) } return res.send(`Success! \n ${amount} BSCFloki converted to ${amount} ETHFloki in your wallet.`); }); module.exports = router; This api is sign client's request and send transaction with signed wallet and its private key.