最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Update user balance in realtime in the browser from private ethereum blockchain - Stack Overflow

programmeradmin12浏览0评论

I would like to have a website that updates live the user's wealth from a private Ethereum blockchain.

Current Solution (broken)

I opened a websocket to a private Ethereum blockchain that is mining, I would like to update my Coinbase balance on the front end. My code is as follow:

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


var app  = express();

app.get("/", (req, res) => res.send("hello world from ping ether application"));
app.get("/ping-ether", function(req, res){


    var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));

    var event_newBlockHeaders = web3.eth.subscribe("newBlockHeaders", function(err, result){

        if (err){ 
         
            console.log(err) 

        } else {

            let acctPromise = web3.eth.getAccounts().then(function(accts){

                let balance = web3.eth.getBalance(accts[0]).then(function(bal){

                    console.log("user: ", accts[0]);
                    console.log("balance: ", bal);

                    res.end("new balance for user: " + bal)

                });

            });
        }

    });


});


// run the server
app.listen(3000, () => console.log("web app listening on port 3000"));

Clearly this is not updating live in the frontend even though the inner most callback is firing constantly as I can confirm on the console. I would like three things:

  1. How should I change this code so that the front end has a live ticker of the coinbase balance

  2. The code in general just smells bad with its nested promises. How can I refactor it so that I do not have to establish a websocket connection each time I navigate to /ping-ether?

I would like to have a website that updates live the user's wealth from a private Ethereum blockchain.

Current Solution (broken)

I opened a websocket to a private Ethereum blockchain that is mining, I would like to update my Coinbase balance on the front end. My code is as follow:

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


var app  = express();

app.get("/", (req, res) => res.send("hello world from ping ether application"));
app.get("/ping-ether", function(req, res){


    var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));

    var event_newBlockHeaders = web3.eth.subscribe("newBlockHeaders", function(err, result){

        if (err){ 
         
            console.log(err) 

        } else {

            let acctPromise = web3.eth.getAccounts().then(function(accts){

                let balance = web3.eth.getBalance(accts[0]).then(function(bal){

                    console.log("user: ", accts[0]);
                    console.log("balance: ", bal);

                    res.end("new balance for user: " + bal)

                });

            });
        }

    });


});


// run the server
app.listen(3000, () => console.log("web app listening on port 3000"));

Clearly this is not updating live in the frontend even though the inner most callback is firing constantly as I can confirm on the console. I would like three things:

  1. How should I change this code so that the front end has a live ticker of the coinbase balance

  2. The code in general just smells bad with its nested promises. How can I refactor it so that I do not have to establish a websocket connection each time I navigate to /ping-ether?

Share Improve this question edited Sep 16, 2022 at 19:09 TylerH 21.1k78 gold badges79 silver badges114 bronze badges asked Jan 14, 2018 at 21:29 xiaolingxiaoxiaolingxiao 4,8956 gold badges44 silver badges91 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

Untested, but something like this should work:

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

var app  = express();
var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
var balance = -1;

web3.eth.getAccounts().then(accounts => {
  return web3.eth.subscribe("newBlockHeaders", (err, result) => {
    if (err) {
      console.log(err);
    } else {
      web3.eth.getBalance(accounts[0]).then(bal => {
        console.log("user: ", accounts[0]);
        console.log("balance: ", bal);
        balance = bal;
      });
    }
  })
}).then(() => {
  app.listen(3000, () => console.log("web app listening on port 3000"));
});

app.get("/", (req, res) => res.send("hello world from ping ether application"));
app.get("/ping-ether", function (req, res) {
  res.end("new balance for user: " + balance);
});

The main idea is to set up the websocket connection and subscription once, and then just respond to ining web requests with the current balance. I also tried to clean up the nested promises by returning the subscription promise.

Update: I ended up using websocket, here's the solution:

import * as Web3     from 'web3'     ; 
import * as express  from 'express'  ;
import * as socketIO from 'socket.io';
import * as http      from 'http'    ;


const CLIENT_PATH = 'path/to/directory'

var app    = express();
var server = http.Server(app);
var io     = socketIO(server);
var web3   = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));

app.get('/', (req,res) => {
    res.sendFile(CLIENT_PATH + '/index.html');
});


web3.eth.getAccounts().then(accounts => {

    display_account(accounts)
})

function display_account(accounts){

    var user_0 = accounts[0]

    web3.eth.subscribe('newBlockHeaders', (err, ret) => {

        if (err){ 

            console.log("error: ", err)

        } else {

            web3.eth.getBalance(user_0).then(bal => {

                var msg = 'Balance for user ' + user_0 + ' is ' + bal  
                io.emit('message-1', msg)
                console.log('emitted message: ', msg)

            })
        }

    })

}


// use this instead of app.listen
server.listen(3000, () => {

    console.log('listening on 3000')

});

And this is index.html.

<html>
<head></head>

<body>
  <div id="message"></div>

  <script src="/socket.io/socket.io.js"></script>
  <script>

    var socket = io();

    socket.on('message-1', function(msg){
      console.log(msg);
      document.getElementById("message").innerHTML = msg;
    });

  </script>
</body>
</html>
发布评论

评论列表(0)

  1. 暂无评论