From 648324ba5f5af254db937973c11f8a2d5ff2db6f Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Tue, 9 Nov 2021 15:00:01 -0600 Subject: [PATCH] Implement monitoring of unconfirmed logins --- backend/app.js | 114 ++++++++++++++++++----------- backend/models/tx.js | 10 +++ src/app/login/login.component.html | 8 +- src/app/login/login.component.ts | 11 +++ src/app/tx.model.ts | 6 ++ src/app/user.service.ts | 36 ++++++++- 6 files changed, 140 insertions(+), 45 deletions(-) create mode 100644 backend/models/tx.js create mode 100644 src/app/tx.model.ts diff --git a/backend/app.js b/backend/app.js index ea5046d..dd4b096 100644 --- a/backend/app.js +++ b/backend/app.js @@ -8,10 +8,10 @@ const ownermodel = require('./models/owner'); const itemmodel = require('./models/item'); const ordermodel = require('./models/order'); const pricemodel = require('./models/price'); +const txmodel = require('./models/tx'); const mongoose = require('mongoose'); const stdrpc = require('stdrpc'); const CoinGecko = require('coingecko-api'); -//const RequestIP = require('@supercharge/request-ip'); var db = require('./config/db'); mongoose.connect('mongodb://'+db.user+':'+db.password+'@'+db.server+'/'+db.database).then(() => { @@ -84,7 +84,7 @@ var blockInterval = setInterval( function() { //console.log(docs); //} //}); - rpc.z_listreceivedbyaddress(fullnode.addr, 10).then(txs => { + rpc.z_listreceivedbyaddress(fullnode.addr, 1).then(txs => { var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/; async.each (txs, function(txData, callback) { var memo = hexToString(txData.memo); @@ -96,46 +96,58 @@ var blockInterval = setInterval( function() { var session = match[1]; var blocktime = txData.blocktime; //console.log(' ', session, blocktime); - usermodel.findOne({address: address, session: session, blocktime: blocktime}).then(function(doc){ - if (doc != null) { - console.log('Found user'); - } else { - console.log('User not found', session, blocktime); - var user = new usermodel({ - address: address, - session: session, - blocktime: blocktime - }); - user.save(function(error) { - if (error) { - console.log(error); - } + if (txData.confirmations >= 10 ) { + usermodel.findOne({address: address, session: session, blocktime: blocktime}).then(function(doc){ + if (doc != null) { + console.log('Found user'); + } else { + console.log('User not found', session, blocktime); + var user = new usermodel({ + address: address, + session: session, + blocktime: blocktime + }); + user.save(function(error) { + if (error) { + console.log(error); + } - console.log('User saved'); - }); - } - }); - ownermodel.findOne({address: address}).then(function (oDoc) { - if (oDoc != null) { - console.log('Found owner'); - } else { - console.log('Owner not found', session); - var owner = new ownermodel({ - address: address, - name: 'Z-Go-'.concat(address.substring(0,5)) - }); - owner.save().then(function(err) { - if (err) { - console.log(err); - } - console.log('Owner saved!'); - }).catch(() => { - console.log('Owner exists'); - }); - } - }).catch((err) => { - console.log(err); - }); + console.log('User saved'); + }); + } + }); + ownermodel.findOne({address: address}).then(function (oDoc) { + if (oDoc != null) { + console.log('Found owner'); + } else { + console.log('Owner not found', session); + var owner = new ownermodel({ + address: address, + name: 'Z-Go-'.concat(address.substring(0,5)) + }); + owner.save().then(function(err) { + if (err) { + console.log(err); + } + console.log('Owner saved!'); + }).catch(() => { + console.log('Owner exists'); + }); + } + }).catch((err) => { + console.log(err); + }); + txmodel.deleteMany({session: session}, function(err) { + if (err) console.log(err); + console.log('Deleted confirmed login'); + }); + } else { + txmodel.updateOne({address: address, session: session}, { confirmations: txData.confirmations, amount:txData.amount}, {new:true, upsert:true}, function(err,docs) { + if (err) { + console.log(err); + } + }); + } } } }, function (err) { @@ -188,6 +200,26 @@ app.get('/api/users', (req, res, next) => { }); }); +app.get('/api/pending', (req, res, next) => { + console.log('Get: /api/pending'); + txmodel.find({'session': req.query.session}). + then((documents) => { + if (documents.length > 0) { + //console.log('pending', documents); + res.status(200).json({ + message: 'Found pending txs', + txs: documents + }); + } else { + //console.log('pending not found', documents); + res.status(204).json({ + message: 'No txs found', + txs: null + }); + } + }); +}); + app.get('/api/getuser', (req, res, next) => { console.log('Get: /api/getuser/', req.query.session); var today = new Date().getTime() / 1000; diff --git a/backend/models/tx.js b/backend/models/tx.js new file mode 100644 index 0000000..d55ba1d --- /dev/null +++ b/backend/models/tx.js @@ -0,0 +1,10 @@ +const mongoose = require('mongoose'); + +const txSchema = mongoose.Schema({ + address: {type: String}, + session: {type: String, required:true}, + confirmations: {type: Number, required:true}, + amount: {type: Number, required:true} +}); + +module.exports = mongoose.model('Tx', txSchema); diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html index 2a20d85..46425dd 100644 --- a/src/app/login/login.component.html +++ b/src/app/login/login.component.html @@ -31,7 +31,13 @@ - + + +

Login received!

+ + It has {{tx.confirmations}} confirmations, needs 10. + +

diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts index 1d93dce..9ac2add 100644 --- a/src/app/login/login.component.ts +++ b/src/app/login/login.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, OnDestroy, Injectable, ChangeDetectorRef } from '@an import { CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot, ActivatedRoute } from '@angular/router'; import { UserService } from '../user.service'; import { FullnodeService } from '../fullnode.service'; +import { Tx } from '../tx.model'; import { Subscription, Observable } from 'rxjs'; import { v4 as uuidv4 } from 'uuid'; var QRCode = require('easyqrcodejs'); @@ -16,12 +17,14 @@ var Buffer = require('buffer/').Buffer; }) export class LoginComponent implements OnInit { + txs: Tx[] = []; intervalHolder: any; nodeAddress: string = ''; private FullnodeSub: Subscription = new Subscription(); private UserSub: Subscription = new Subscription(); public heightUpdate: Observable; public uZaddrUpdate: Observable; + public txsUpdate: Observable; constructor( private activatedRoute: ActivatedRoute, public fullnodeService: FullnodeService, @@ -32,6 +35,10 @@ export class LoginComponent implements OnInit { //this.fullnodeService.getAddr(); this.heightUpdate = fullnodeService.heightUpdate; this.uZaddrUpdate = userService.uZaddrUpdate; + this.txsUpdate = userService.txUpdate; + this.txsUpdate.subscribe((txs) => { + this.txs = txs; + }); } ngOnInit(){ @@ -78,6 +85,10 @@ export class LoginComponent implements OnInit { loginCheck(){ this.userService.findUser(); + this.userService.findPending(); + this.txsUpdate.subscribe((txs) => { + this.txs = txs; + }); this.uZaddrUpdate.subscribe((userAddr: string) => { if (userAddr.length != 0) { console.log('Log in found in blockchain!'); diff --git a/src/app/tx.model.ts b/src/app/tx.model.ts new file mode 100644 index 0000000..9e8d9b8 --- /dev/null +++ b/src/app/tx.model.ts @@ -0,0 +1,6 @@ +export interface Tx { + _id?: string; + address: string; + session: string; + confirmations: number; +} diff --git a/src/app/user.service.ts b/src/app/user.service.ts index b0bac46..f8a403f 100644 --- a/src/app/user.service.ts +++ b/src/app/user.service.ts @@ -3,12 +3,13 @@ import {Subject, BehaviorSubject, Observable} from 'rxjs'; import {HttpClient, HttpParams, HttpHeaders} from '@angular/common/http'; import {User} from './user.model'; import {Owner} from './owner.model'; +import {Tx} from './tx.model'; @Injectable({providedIn: 'root'}) export class UserService{ beUrl = 'http://localhost:3000/'; - private dataStore: { user: User, owner: Owner} = { + private dataStore: { user: User, owner: Owner, txs: Tx[]} = { user: { address: '', session: '', @@ -17,7 +18,8 @@ export class UserService{ owner: { address: '', name: '' - } + }, + txs : [] }; private uZaddr = ''; private oZaddr = ''; @@ -27,18 +29,21 @@ export class UserService{ private _userUpdated: BehaviorSubject = new BehaviorSubject(this.dataStore.user); private uNameUpdated = new Subject(); private _ownerUpdated: BehaviorSubject = new BehaviorSubject(this.dataStore.owner); + private _txsUpdated: BehaviorSubject = new BehaviorSubject(this.dataStore.txs); public readonly uZaddrUpdate: Observable = this._uZaddrUpdated.asObservable(); public readonly ownerUpdate: Observable = this._ownerUpdated.asObservable(); public readonly userUpdate: Observable = this._userUpdated.asObservable(); + public readonly txUpdate: Observable = this._txsUpdated.asObservable(); private reqHeaders: HttpHeaders; private apiKey = 'Le2adeic8Thah4Aeng4daem6i'; constructor(private http: HttpClient){ this.reqHeaders = new HttpHeaders().set('Authorization', this.apiKey); - console.log('US:', this.reqHeaders); + //console.log('US:', this.reqHeaders); this.session = localStorage.getItem('s4z_token'); if (this.session != null) { this.findUser(); + this.findPending(); } } @@ -68,6 +73,31 @@ export class UserService{ } } + findPending() { + this.session = localStorage.getItem('s4z_token'); + if (this.session != null) { + const params = new HttpParams().append('session', this.session!); + let obs = this.http.get<{message: string, txs: any}>(this.beUrl+'api/pending', { headers: this.reqHeaders, params: params, observe: 'response'}); + + obs.subscribe((TxDataResponse) => { + //console.log('US Tx', TxDataResponse); + if (TxDataResponse.status == 200){ + this.dataStore.txs = TxDataResponse.body!.txs; + console.log(`US: Pending logins found`); + this._txsUpdated.next(Object.assign({},this.dataStore).txs); + } else { + console.log('US: Did not find pending txs'); + this.dataStore.txs = []; + this._txsUpdated.next(Object.assign({},this.dataStore).txs); + } + }); + + return obs; + } else { + console.log('No session loaded'); + return null; + } + } addOwner(address: string) { const owner: Owner={_id: '', address: address, name: 'Zgo-'.concat(address.substring(0,5))};