从私有以太坊区块链在浏览器中实时更新用户余额
Update user balance in realtime in the browser from private ethereum blockchain
问题
我想要一个网站,通过私有以太坊区块链实时更新用户的财富。
当前解决方案(已损坏)
我打开了一个到正在挖掘的私有以太坊区块链的 websocket,我想在前端更新我的 coinbase 余额。我的代码如下:
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"));
很明显,这并没有在前端实时更新,尽管我可以在控制台上确认最内层的回调不断触发。我想要三样东西:
- 我应该如何更改此代码,以便前端具有 coinbase 余额的实时行情
- 代码中嵌套的 promise 通常闻起来很糟糕。我该如何重构它,这样我就不必在每次导航到
/ping-ether
时都建立 websocket 连接?
- 欢迎任何其他建议。我对
node.js
很陌生
未经测试,但像这样的东西应该可以工作:
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);
});
主要思想是设置一次websocket连接和订阅,然后只用当前余额响应传入的web请求。我还尝试通过返回订阅承诺来清理嵌套承诺。
更新:我最终使用了 websocket,这是解决方案:
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')
});
这是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>
问题
我想要一个网站,通过私有以太坊区块链实时更新用户的财富。
当前解决方案(已损坏)
我打开了一个到正在挖掘的私有以太坊区块链的 websocket,我想在前端更新我的 coinbase 余额。我的代码如下:
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"));
很明显,这并没有在前端实时更新,尽管我可以在控制台上确认最内层的回调不断触发。我想要三样东西:
- 我应该如何更改此代码,以便前端具有 coinbase 余额的实时行情
- 代码中嵌套的 promise 通常闻起来很糟糕。我该如何重构它,这样我就不必在每次导航到
/ping-ether
时都建立 websocket 连接? - 欢迎任何其他建议。我对
node.js
很陌生
未经测试,但像这样的东西应该可以工作:
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);
});
主要思想是设置一次websocket连接和订阅,然后只用当前余额响应传入的web请求。我还尝试通过返回订阅承诺来清理嵌套承诺。
更新:我最终使用了 websocket,这是解决方案:
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')
});
这是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>