Then function not executing - callback

So I've been trying to execute the mint function after the contract.methods.registerVoter function goes through but I had no luck. Only the contract.methods.registerVoter function gets executed and nothing happens in the then function. What am I doing wrong?
export async function registerVoter(walletAddress) {
const contract = await getContract();
const votingToken = await getTokenCotract();
const tokenAddress = await getTokenAddress();
const web3 = window.web3;
contract.methods.registerVoter(walletAddress, tokenAddress).send({from: walletAddress}).then(() => {
votingToken.methods.mint(walletAddress, 1).send({from: walletAddress})
})
}

Because the send function into getContract is not a promise

Related

Error [ERR_HTTP_HEADERS_SENT] : Can't figure out the multipe requests

I have this error : Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. From my understanding, the problem is that I am trying to send more than one response to the same http request. My instinct tell me that it’s this part that messes up :
catch (err) {
res.status(400).json(err);
}
Because if no user/password found in the DB, we already send status(400). Am I right ? More importantly (and that’s what drives me crazy), I am following a YT tuto and his code is exactly like mine, yet his seems to be working without any problem.
My code :
const router = require("express").Router();
const User = require("../models/Users");
const bcrypt = require("bcrypt");
//LOGIN
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ username: req.body.username });
!user && res.status(400).json("Wrong credentials!");
const validated = await bcrypt.compare(req.body.password, user.password);
!validated && res.status(400).json("Wrong credentiaaaals!");
const { password, ...others } = user._doc;
res.status(200).json(others);
} catch (err) {
res.status(500).json(err);
}
});
module.exports = router;
His code :
//LOGIN
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ username: req.body.username });
!user && res.status(400).json("Wrong credentials!");
const validated = await bcrypt.compare(req.body.password, user.password);
!validated && res.status(400).json("Wrong credentials!");
const { password, ...others } = user._doc;
res.status(200).json(others);
} catch (err) {
res.status(500).json(err);
}
});
module.exports = router;
Am I doing something wrong ? Is my reflexion bad ? Thanks !
You are right, your code is trying to send data to the client multiple times. The issue is that after the call .json("Wrong credentials!") completed, the write stream to the client will be closed, and you will not be able to send any other data to the client. The framework knows to detect it and show you the bug.
In your code, after the method .json("Wrong credentials!") finishes own execution, your program will continue and will try to execute the next lines...
You just need to add return, so the program will exit the current flow after it sends the response to the client.
const router = require("express").Router();
const User = require("../models/Users");
const bcrypt = require("bcrypt");
//LOGIN
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ username: req.body.username });
if (!user) {
return res.status(400).json("Wrong credentials!"); // without return the code will continue to execute next lines
}
const validated = await bcrypt.compare(req.body.password, user.password);
if (!validated) {
return res.status(400).json("Wrong credentiaaaals!"); // without return the code will continue to execute next lines
}
const { password, ...others } = user._doc;
res.status(200).json(others); // return is not necessary, because there is no cod which will be executed after we back from the json method
} catch (err) {
res.status(500).json(err); // return is not necessary, because there is no cod which will be executed after we back from the json method
}
});
module.exports = router;

How to inject a stub function when using Hapi.js server.inject

I have a hapijs project which is using the hapi-mongodb plugin.
In the handler I am using the hapi-mongodb plugin to make db calls. See below
internals.getById = async (request, h) => {
try {
const db = request.mongo.db;
const ObjectId = request.mongo.ObjectID;
const query = {
_id: ObjectId(request.params.id)
};
const record = await db.collection(internals.collectionName).findOne(query);
//etc.....
I want to be able to test this using server.inject(), but I am not sure how to stub the request.mongo.db and the request.mongo.ObjectID
it('should return a 200 HTTP status code', async () => {
const server = new Hapi.Server();
server.route(Routes); //This comes from a required file
const options = {
method: 'GET',
url: `/testData/1`
};
//stub request.mongo.db and request.mongo.ObjectID
const response = await server.inject(options);
expect(response.statusCode).to.equal(200);
});
Any ideas?
I worked this out and realised that the mongo plugin decorates the server object which can be stubbed.

access document.documentElement from puppeteer

I can get access to the entire HTML for any URL by opening dev-tools and typing:
document.documentElement
I am trying to replicate the same behavior using puppeteer, however, the snippet below returns {}
const puppeteer = require('puppeteer'); // v 1.1.0
const iPhone = puppeteer.devices['Pixel 2 XL'];
async function start(canonical_url) {
const browserURL = 'http://127.0.0.1:9222';
const browser = await puppeteer.connect({browserURL});
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto(canonical_url, {
waitUntil: 'networkidle2',
});
const data = await page.evaluate(() => document.documentElement);
console.log(data);
}
returns:
{}
Any idea on what I could be doing wrong here?

Cannot read property innerText of null for valid selector using playwright

This script is supposed to retrieve the innerText of a DOM element, the elements selector is
('div[class=QzVHcLdwl2CEuEMpTUFaj]') and I've hand-tested the selector and called the getSharePrice function in the REPL which also works.
const { chromium } = require('playwright');
const util = require('util');
const setTimeoutPromise = util.promisify(setTimeout);
(async () => {
const userDataDir = 'path'
const browser = await chromium.launchPersistentContext(userDataDir, {headless: false });
const page = await browser.newPage();
await page.goto('https://robinhood.com', {timeout: 60000, waitUntil: 'domcontentloaded'});
await getSharePrice(page)
await setTimeoutPromise(1000);
await browser.close();
})();
async function getSharePrice(page) {
const price = await page.evaluate(() => {
return {
price: document.querySelector('div[class=QzVHcLdwl2CEuEMpTUFaj]').innerText.replace(/\D/g,'')
}
});
console.log(price)
}
for some reason, I am getting a (node:59324) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'innerText' of null error, not sure why.
The only thing that I could come up with is that the element hasn't been loaded yet, causing it to evaluate to null which is why innerText can't be called.
adding await page.waitForSelector('div[class=QzVHcLdwl2CEuEMpTUFaj]') before my evaluate block fixed this. Looks like the issue was caused by the element not being loaded yet

Connect Apollo with mongodb

I want to connect my Apollo server with my mongoDB. I know there are many examples out there, but I get stuck at the async part and did not found a solution or example for that (that's strange, am I completly wrong?)
I started with the example from next.js https://github.com/zeit/next.js/tree/master/examples/api-routes-apollo-server-and-client .
But the mongodb integration is missing.
My code
pages/api/graphql.js
import {ApolloServer} from 'apollo-server-micro';
import {schema} from '../../apollo/schema';
const apolloServer = new ApolloServer({schema});
export const config = {
api: {
bodyParser: false
}
};
export default apolloServer.createHandler({path: '/api/graphql'});
apollo/schema.js
import {makeExecutableSchema} from 'graphql-tools';
import {typeDefs} from './type-defs';
import {resolvers} from './resolvers';
export const schema = makeExecutableSchema({
typeDefs,
resolvers
});
apollo/resolvers.js
const Items = require('./connector').Items;
export const resolvers = {
Query: {
item: async (_parent, args) => {
const {id} = args;
const item = await Items.findOne(objectId(id));
return item;
},
...
}
}
apollo/connector.js
require('dotenv').config();
const MongoClient = require('mongodb').MongoClient;
const password = process.env.MONGO_PASSWORD;
const username = process.env.MONGO_USER;
const uri = `mongodb+srv://${username}:${password}#example.com`;
const client = await MongoClient.connect(uri);
const db = await client.db('databaseName')
const Items = db.collection('items')
module.exports = {Items}
So the problem is the await in connector.js. I have no idea how to call this in an async function or how to provide the MongoClient on an other way to the resolver. If I just remove the await, it returns – obviously – an pending promise and can't call the function .db('databaseName') on it.
Unfortunately, we're still a ways off from having top-level await.
You can delay running the rest of your code until the Promise resolves by putting it inside the then callback of the Promise.
async function getDb () {
const client = await MongoClient.connect(uri)
return client.db('databaseName')
}
getDb()
.then(db => {
const apollo = new ApolloServer({
schema,
context: { db },
})
apollo.listen()
})
.catch(e => {
// handle any errors
})
Alternatively, you can create your connection the first time you need it and just cache it:
let db
const apollo = new ApolloServer({
schema,
context: async () => {
if (!db) {
try {
const client = await MongoClient.connect(uri)
db = await client.db('databaseName')
catch (e) {
// handle any errors
}
}
return { db }
},
})
apollo.listen()