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

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:
How should I change this code so that the front end has a live ticker of the coinbase balance
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?

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 incoming 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>

Related

CONNECTION SOCKET.IO

I've been stuck for a few days now with a socket.io problem, more precisely between server to client.
On the client side, (Angular) I can emit an event, the server can grab and execute all the logic, but after the server to the client it doesn't show signs of life.
I've already expressed all the events, I've reformulated all the settings as it says in the documentation and nothing works, can anyone see where I'm going wrong?
"socket.io": "^4.5.1"
"socket.io-client": "^4.5.1",
ANGULAR (CLIENT-SIDE)
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { io, Socket } from 'socket.io-client';
import { environment } from 'src/environments/environment';
#Injectable({
providedIn: 'root'
})
export class SocketIoService {
socket: Socket;
constructor() {}
connect(token: string, userName: string){
this.socket = io(environment.path.hermsUrl, {
query: {
token,
userName
}
});
}
disconnect(){
this.socket.disconnect();
}
sendMessage(msg: any) {
this.socket.emit('send-message', (msg));
}
getConversation(){
this.socket.on('update-conversation', (conversation)=> {
console.log('############################################');
});
}
}
NODE.JS (SERVER-SIDE)
require('dotenv').config();
require('./Helpers/init_mongodb');
const express = require('express');
const cors = require('cors');
const createError = require('http-errors');
const chatController = require('./Controllers/chat.controller');
const Chat = require('./Models/chat.model');
const app = express();
const httServer = require('http').createServer(app);
const { verifyAccessToken } = require('./Helpers/jwt_token');
const userRoute = require('./Routes/user.routes');
const eventRoute = require('./Routes/event.routes');
const chatRoute = require('./Routes/chat.routes');
const decode = require('jwt-decode');
const PORT = process.env.PORT || 5005;
const io = require('socket.io')(httServer, {
cors: {
origins: ["*"]
}
});
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use('/path/user', userRoute);
app.use('/path/event', eventRoute);
app.use('/path/chat', chatRoute);
app.use(async (req, res, next) => {
next(createError.NotFound('THIS ROUTE DOES NOT EXIST'))
});
app.get('/', verifyAccessToken, async (req, res, next) => {
res.send('HELLO THERE')
});
app.use((err, req, res, next) => {
res.status(err.status || 500)
res.send({
error: {
status: err.status || 500,
message: err.message,
},
})
});
io.on("connection", (socket) => {
const decodedObj = decode(socket.handshake.query.token);
socket.id = decodedObj.aud;
const userName = socket.handshake.query.userName;
console.log("========= SOCKET.IO CONNECTED =========");
console.log("");
console.log("USERNAME: " + userName);
console.log("ID: " + socket.id);
console.log("");
console.log("=======================================");
socket.on('send-message', async (message) => {
try{
const chatId = message.chatId;
const decodedObj = decode(message.sender);
const senderId = decodedObj.ID;
const userSocketId = message.userId;
const date = new Date();
const day = date.getDate();
const month = date.getMonth();
const year = date.getFullYear();
const hour = date.getHours();
const minuts = date.getMinutes();
const sendingDate = day + "/" + month + "/" + year + " " + hour + ":" + minuts;
const newMsg = {
msgType: message.typeOfMsg,
message: message.msg,
date: sendingDate,
sender: senderId
}
const conversation = await Chat.findById(chatId);
if(!conversation){
throw createError.NotFound();
}
conversation.messages.push(newMsg);
const updateConversation = await Chat.findByIdAndUpdate(chatId, conversation);
if(!updateConversation){
throw createError.InternalServerError();
}
console.log("!!!!!!!!!!! SEND EMIT FROM SOCKET/SERVER !!!!!!!!!!!!!!!");
io.emit('update-conversation', 'FROM SERVER');
io.emit('update-conversation');
io.local.emit('update-conversation');
io.local.emit('update-conversation', 'FROM SERVER');
socket.emit('update-conversation', 'FROM SERVER');
socket.emit('update-conversation');
socket.broadcast('update-conversation', 'FROM SERVER');
console.log("!!!!!!!!!!! EMIT SENDED !!!!!!!!!!!!!!!");
} catch (error) {
console.log(error);
}
});
socket.on("disconnect", () => {
console.log("########### SOCKET.IO DISCONNECTED ###########");
console.log("");
console.log("USERNAME: " + userName);
console.log("ID: " + socket.id);
console.log("");
console.log("##############################################");
});
});
httServer.listen(PORT, () => {
console.log(`SERVER RUNNING ON PORT ${PORT}`);
})
It appears you aren't yet listening for the update-conversation message in the client. Thus, when the server sends it, you don't have any client code to actually receive it.
You need to register the listener this.socket.on('update-conversation', ...) on the client-side when you first create the socket.io connection. Then, it will be ready to receive that message whenever the server sends that message.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client in Node JS

I am trying to update a data using a specific ID which is not working but gives above error.
When I update, first I search the database for that specific id and then save the data to MongoDB
here is my server.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
//importing MongoDB model schema
let ToDo = require('./todo.model');
const app = express();
const todoRoutes = express.Router();
const PORT = 4000;
//middlewares
app.use(bodyParser.json());
app.use(cors());
app.use('/todos', todoRoutes);
//connection to the MongoDB database
mongoose.connect('mongodb://127.0.0.1:27017/todos', {useNewUrlParser: true});
const connection = mongoose.connection;
connection.once('open', () =>{
console.log("Connected to the MongoDB through port: 27017");
});
app.listen(PORT, () => {
console.log(`Listening to port: ${PORT}`);
});
//get all data - removed to show only the code snippet I am getting errors
//get data by an ID - removed to show only the code snippet I am getting errors
//add items to database -removed to show only the code snippet I am getting errors
//update items
todoRoutes.route('/update/:id').post((req, res) => {
let id = req.params.id;
ToDo.findById(id, (err, todo) => {
if(err) throw err;
if(!todo) res.status(400).send("No data found");
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
res.end();
todo.save().then(todo => {
res.json(200).send("Data Updated! " + todo);
res.end();
}).catch(err => {
res.status(400).send("Error occured! " + err);
});
});
});
This is the error I am getting...
Can someone please help me?
This error usually means that you send a response more than once.
Notice that you send two responses one after the other res.json() and res.end()
If you want for some reason to just end the response, use res.end(), otherwise use res.status(200).json({ result: ‘Data updated’ + todo })
If you send both, it will complain about trying to modify the response (via res.end()) after sending it (via res.status().json())
In the '/update/:id' route, you're sending a res.end() then doing it again 3 lines later. If you remove the first res.end(), it should work.
You should also return if todo is missing:
todoRoutes.route('/update/:id').post((req, res) => {
let id = req.params.id;
ToDo.findById(id, (err, todo) => {
if(err) throw err;
if(!todo) return res.status(400).send("No data found");
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
todo.save().then(todo => {
res.status(200).send("Data Updated! " + todo);
}).catch(err => {
res.status(400).send("Error occured! " + err);
});
});
});

Node JS/ Socket.IO - Receive only over TCP/IP [duplicate]

I'm trying to create a dummy socket for use in some of my tests
var net = require("net");
var s = new net.Socket();
s.on("data", function(data) {
console.log("data received:", data);
});
s.write("hello!");
Getting this error
Error: This socket is closed.
I've also tried creating the socket with
var s = new net.Socket({allowHalfOpen: true});
What am I doing wrong?
For reference, the complete test looks like this
it("should say hello on connect", function(done) {
var socket = new net.Socket();
var client = Client.createClient({socket: socket});
socket.on("data", function(data){
assert.equal("hello", data);
done();
});
client.connect();
// writes "hello" to the socket
});
I don't think the server is put into listening state. This what I use..
// server
require('net').createServer(function (socket) {
console.log("connected");
socket.on('data', function (data) {
console.log(data.toString());
});
})
.listen(8080);
// client
var s = require('net').Socket();
s.connect(8080);
s.write('Hello');
s.end();
Client only..
var s = require('net').Socket();
s.connect(80, 'google.com');
s.write('GET http://www.google.com/ HTTP/1.1\n\n');
s.on('data', function(d){
console.log(d.toString());
});
s.end();
Try this.
The production code app.js:
var net = require("net");
function createSocket(socket){
var s = socket || new net.Socket();
s.write("hello!");
}
exports.createSocket = createSocket;
The test code: test.js: (Mocha)
var sinon = require('sinon'),
assert = require('assert'),
net = require('net'),
prod_code=require('./app.js')
describe('Example Stubbing net.Socket', function () {
it("should say hello on connect", function (done) {
var socket = new net.Socket();
var stub = sinon.stub(socket, 'write', function (data, encoding, cb) {
console.log(data);
assert.equal("hello!", data);
done();
});
stub.on = socket.on;
prod_code.createSocket(socket);
});
});
We can create socket server using net npm module and listen from anywhere. after creating socket server we can check using telnet(client socket) to interact server.
server.js
'use strict';
const net = require('net');
const MongoClient= require('mongodb').MongoClient;
const PORT = 5000;
const ADDRESS = '127.0.0.1';
const url = 'mongodb://localhost:27017/gprs';
let server = net.createServer(onClientConnected);
server.listen(PORT, ADDRESS);
function onClientConnected(socket) {
console.log(`New client: ${socket.remoteAddress}:${socket.remotePort}`);
socket.destroy();
}
console.log(`Server started at: ${ADDRESS}:${PORT}`);
function onClientConnected(socket) {
let clientName = `${socket.remoteAddress}:${socket.remotePort}`;
console.log(`${clientName} connected.`);
socket.on('data', (data) => {
let m = data.toString().replace(/[\n\r]*$/, '');
var d = {msg:{info:m}};
insertData(d);
console.log(`${clientName} said: ${m}`);
socket.write(`We got your message (${m}). Thanks!\n`);
});
socket.on('end', () => {
console.log(`${clientName} disconnected.`);
});
}
function insertData(data){
console.log(data,'data');
MongoClient.connect(url, function(err, db){
console.log(data);
db.collection('gprs').save(data.msg , (err,result)=>{
if(err){
console.log("not inserted");
}else {
console.log("inserted");
}
});
});
}
using telnet:
$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hi
We got your message (hi). Thanks!
you need to connect your socket before you can write to it:
var PORT = 41443;
var net = require("net");
var s = new net.Socket();
s.on("data", function(data) {
console.log("data received:", data);
});
s.connect(PORT, function(){
s.write("hello!");
});
It will useful code for websocket
'use strict';
const express = require('express');
const { Server } = require('ws');
const bodyParser = require('body-parser');
const cors = require('cors');
const PORT = process.env.PORT || 5555;
const INDEX = '/public/index.html';
const router = express.Router();
var urlencodedParser = bodyParser.urlencoded({ extended: false });
router.get('/', function(req, res) {
res.sendFile(INDEX, { root: __dirname });
});
const server = express()
.use(router)
.use(bodyParser.json())
.use(cors)
.listen(PORT, () => {
console.log(`Listening on ${PORT}`)
});
const wss = new Server({ server });
wss.on('connection', (ws) => {
ws.on('message', message => {
var current = new Date();
console.log('Received '+ current.toLocaleString()+': '+ message);
wss.clients.forEach(function(client) {
client.send(message);
var getData = JSON.parse(message);
var newclip = getData.clipboard;
var newuser = getData.user;
console.log("User ID : "+ newuser);
console.log("\nUser clip : "+ newclip);
});
});
});

Node.JS + Socket.io, moving socket event handlers to external module?

I have a server.js file like this:
var express = require('express'),
app = express(),
server = require('http').createServer(app),
mongoose = require('mongoose'),
bodyParser = require('body-parser'),
apiRouter = require('./app/routes/api.js'),
io = require('socket.io')(server),
socketEvents = require('./app/modules/socketEvents.js')(io);
//Clears Node Console.
process.stdout.write('\033c');
console.log('Server starting!');
socketEvents.attachEventHandlers();
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use('/api', apiRouter);
app.use(express.static('public'));
app.use('*', function(req, res, next) {
//All requests return single page angular application.
res.sendFile(__dirname + '/public/index.html');
});
mongoose.connect('localhost', 'triviaattack', function(err) {
if (err) {
console.log('An error occured when connecting to the MongoDB Database');
throw err;
}
});
server.listen(1337);
And socketEvents.js
module.exports = function(io) {
return {
attachEventHandlers: function() {
io.on('connection', function(socket) {
console.log('client connected');
socket.on('joinMatchMaking', function(data) {
//Every time a player joins the matchmaking queue, check if a game can be created.
matchMakingQueue.push(data);
var matchedPlayers = [];
for (i = 0; i < matchMakingQueue.length; i++) {
switch (data.gameType) {
case '1v1':
matchedPlayers.push(matchMakingQueue[i].username);
if (matchedPlayers.length == 2) {
socket.emit('matchFound', {players: matchedPlayers});
}
console.log('user joined 1v1 queue');
case '2v2':
matchedPlayers.push(matchMakingQueue[i].username);
if (matchedPlayers.length == 4) {
socket.emit('matchFound', {players: matchedPlayers});
}
console.log('user joined 2v2 queue');
}
}
console.log(data.username + ' joined the ' + data.gameType + ' matchmaking queue');
console.log('users in queue: ' + matchMakingQueue.length);
});
socket.on('leaveMatchMaking', function(username) {
matchMakingQueue.splice(matchMakingQueue.indexOf(username), 1);
console.log(username + ' left matchmaking queue.');
console.log('users in queue: ' + matchMakingQueue.length);
});
});
console.log('events attached');
}
}
};
When I load my site in my browser, the io.on('connection), function () {...}) event handler is not being called, which should output a console.log message whenever a client connects. I want to keep my socket.io events outside of my main server.js file because there will be alot of them and I wanted to separate them into their own module.
You need to have some socket code in the html file to connect.. can you include it as well?
I do this by stuffing all of my socket events in a middleware:
var io = require('socket.io');
// listen stuff
var SocketEvents = require('./socket-events.js')(io);
io.use(SocketEvents);
... and then in socket-events.js something like:
module.exports = function(io) {
return function(socket, next) {
// do stuff
return next();
}
}
I should add that in this case the on("connection") listener appears not to be necessary, as each middleware function is executed on each incoming socket connection already.

can't create a new directory using mongoose and express

Like the title entails.
I'm trying to make an application that when i put in certain info, it creates a link using mongoose _id. and express's app.get what i don't get is that to be able to join that directory i have to reload the whole server, which for the users and my sake a i don't want to do.
var mongoose = require("mongoose");
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
var router = express.Router();
app.get("/", function (req, res) {
var ip = req.connection.remoteAddress;
res.sendFile(__dirname + "/index.html");
});
mongoose.connect("mongodb://localhost:27017/NEW_DB1");
console.log("Connection to database has been established");
var collectedData = new mongoose.Schema({
ipAddress: String,
name: {
type: String,
unique: false
}
});
var collectionOfData = mongoose.model("dataType", collectedData);
io.on("connection", function (socket) {
socket.on("name", function (e) {
var ip = socket.request.socket.remoteAddress;
var dataBase = mongoose.connection;
var Maindata = new collectionOfData({
ipAddress: ip,
name: e
});
Maindata.save(function (err, Maindata) {
if (err) {
return console.error(err);
} else {
console.dir(Maindata);
}
});
});
});
app.get("/mix", function (req, res) {
collectionOfData.find(function (err, data) {
res.send(data);
});
});
collectionOfData.find(function (err, data) {
data.forEach(function (uniqueURL) {
app.get("/" + uniqueURL._id, function (req, res) {
res.send("<h1>Hello " + uniqueURL.ipAddress + "</h1><p>" + uniqueURL.name + "</p>");
});
});
});
http.listen(10203, function () {
console.log("Server is up");
});
So what i'm trying to do is make it so i don't have to reload the whole server, and i'm able to just join the created directory when it's done being loaded.
figured i should put a quick example:
localhost:10203/55c2b2f39e09aeed245f2996
is a link a user just created the long
55c2b2f39e09aeed245f2996
is the effect of the _id, but when the user try's to connect to that site it won't work until i reload the server and obviously i'd like to avoid that haha.
I have a index.html file, but all that has is a socket.emit that sends "name" to the server
app.get("/", function (req, res) {
var ip = req.connection.remoteAddress;
res.sendFile(__dirname + "/index.html");
});
app.get('/:uniqueURL', function(req, res){
var id = req.params.uniqueURL;
res.send("Your requested id : " + id);
})
Try to use this above.
You are creating fix get path inside collectionData.find. That is the problem. So each time you have to reload the server by restarting.

Categories