1

I am wondering how to use web3.js in my node.js web server in the correct way. I have a button in the homepage where allows users to connect to their wallet, and it is done in my front end. After connecting to their wallet, they will be directed to the dashboard, and I wanted to recheck if they are connected to their wallet in the dashboard page. For safety concerns (I am not very sure if doing it in front end is safe due to the fact people can modify js in developer tools), I decided to check it in my backend web server. I am running on localhost:3000 if this information is useful.

This is what I've tried:

const express = require('express');
const Web3 = require('web3');

const app = express();
const port = process.env.PORT || 3000;

app.set('view engine', 'ejs');

app.listen(port, () => {
  console.log("Connected!");
});

app.get('/', (request, response) => {
    // User connects to wallet in this page
    response.render('index');
});

app.get('/dashboard', async (request, response) => {

    // Check if wallet is connected
    if (typeof web3 !== "undefined") {
      // This should run because I have Metamask installed but didn't
      web3 = new Web3(web3.currentProvider);
      const accounts = await web3.eth.getAccounts()
    } else {
      // This runs
      web3 = new Web3(new Web3.providers.HttpProvider(infura provider));
      const accounts = await web3.eth.getAccounts() // Returns []
    }

    response.render('dashboard');
});

But the thing is web3 is undefined even if I have Metamask installed in my browser. And by using the infura provider, await web3.eth.getAccounts() returns an empty array despite that I have connected my wallet to the website in the homepage.

Maybe I am doing everything wrong. I am not familiar with how Web3 works, even if I did many research. I could not find any videos of people using node.js web server to work with accounts.

And I have one more concern, is it okay if the Infura provider can be publicly viewed? I don't remember where but I've seen people using it in the front end.

3 Answers 3

2

I think you're mixing things up. You have to understand which code runs in the frontend (browser) and in the backend (server). window.ethereum is injected by metamask but it's only available in the frontend. That code above using Express runs in your backend so window.ethereum is going to be undefined.

To get your desired result, do the metamask check in the frontend. In your dashboard page check if the user has connected his account and, if not, redirect him to your home page. Something around these lines:

// script in your dashboard page

if (window.ethereum) {
    // checks accounts connected
    const accounts = await window.ethereum.request({
      method: 'eth_requestAccounts',
    })
    console.log('accounts :>> ', accounts)
    if(accounts.length == 0){
       // redirect if no accounts found
       window.location.replace('http://my-home-age-url')
    }
}else{
    console.log('Metamask not detected')
    window.location.replace('http://my-home-age-url')
}
0

You're using deprecated code which is not working anymore with MetaMask. They replaced web3 with window.ethereum. Change your code to:

if (window.ethereum) {
    web3 = new Web3(window.ethereum);
    const accounts = await ethereum.request({method: 'eth_requestAccounts'});
    console.log(accounts, 'accounts');
}

But ofcourse your MetaMask extension should be installed on your browser else window.ethereum will be undefined.

Another thing is that when you want to request data which is in your MetaMask extension then you should use only the MetaMask provider. I see in your comments that you tried requesting the accounts with the infura provider, but this won't work since Infura cannot know what's included in your MetaMask extension.

1
  • The whole thing is on the server side, I am doing it in a node.js web server. Which window isn't an object in the server side... I've tried using ethereum directly and it is still undefined.
    – Chock
    Commented Mar 29, 2022 at 8:46
0

window.ethereum is a provider injected in-page by MetaMask browser wallet extension and is not available in Nodejs environment. I created a package to achieve something similar here: https://www.npmjs.com/package/web3-nodejs-provider

You can create a provider on server-side and use it with Web3 instance Github: https://github.com/naftalimurgor/web3-nodejs-provider

const Web3NodejsProvider = require("web3-nodejs-provider");
const Web3 = require("web3");
const mnemonicPhrase = "mountains supernatural bird..."; // 12 word mnemonic

let provider = new Web3NodejsProvider({
  mnemonic: {
    phrase: mnemonicPhrase
  },
  providerOrUrl: "http://localhost:8545"
});

// Or, alternatively pass in a zero-based address index.
provider = new Web3NodejsProvider({
  mnemonic: mnemonicPhrase,
  providerOrUrl: "http://localhost:8545",
  addressIndex: 5
});

// Or, use your own hierarchical derivation path
provider = new Web3NodejsProvider({
  mnemonic: mnemonicPhrase,
  providerOrUrl: "http://localhost:8545",
  numberOfAddresses: 1,
  shareNonce: true,
  derivationPath: "m/44'/137'/0'/0/"
});

// To make HDWallet less "chatty" over JSON-RPC,
// configure a higher value for the polling interval.
provider = new Web3NodejsProvider({
  mnemonic: {
    phrase: mnemonicPhrase
  },
  providerOrUrl: "http://localhost:8545",
  pollingInterval: 8000
});

// HDWalletProvider is compatible with Web3. Use it at Web3 constructor, just like any other Web3 Provider
const web3 = new Web3(provider);

// Or, if web3 is alreay initialized, you can call the 'setProvider' on web3, web3.eth, web3.shh and/or web3.bzz
web3.setProvider(provider)

// ...
// Write your code here.
// ...

// At termination, `provider.engine.stop()' should be called to finish the process elegantly.
provider.engine.stop();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.