diff --git a/backend/app.js b/backend/app.js index 163387f..ec954eb 100644 --- a/backend/app.js +++ b/backend/app.js @@ -26,6 +26,8 @@ const rpc = stdrpc({ password: fullnode.password }); +var async = require('async'); + const CoinGeckoClient = new CoinGecko(); var intervalObject = setInterval( function() { @@ -63,6 +65,86 @@ var intervalObject = setInterval( function() { }); }, 90000); +function hexToString(hexString) { + var str = ''; + for (var n=0; n < hexString.length; n +=2) { + str += String.fromCharCode(parseInt(hexString.substr(n, 2), 16)); + } + return str; +} + +var blockInterval = setInterval( function() { + console.log('Node periodic Zcash scan'); + //usermodel.find({}, function (err, docs) { + //if (err) { + //console.log(err); + //} else { + //console.log(session, blocktime); + //console.log(docs); + //} + //}); + rpc.z_listreceivedbyaddress(fullnode.addr, 10).then(txs => { + var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/; + async.each (txs, function(txData, callback) { + var memo = hexToString(txData.memo); + if (re.test(memo)) { + //console.log('Processing tx:', memo); + var match = re.exec(memo); + if (match != null) { + var address = match[2]; + 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); + } + + 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((err) => { + console.log(err); + }); + } + } + }, function (err) { + if (err) { + console.log(err); + } + console.log('Txs synced'); + }); + + }); +}, 90000); + app.use(bodyparser.json()); app.use((req, res, next) => { @@ -73,73 +155,41 @@ app.use((req, res, next) => { next(); }); -app.post('/api/posts', (req, res, next) => { - const post = new postmodel({ - title: req.body.title, - content: req.body.content - }); - post.save(); - //console.log(req.ip); - res.status(201).json({ - message: 'Post added successfully' - }); -}); -app.get('/api/posts', (req, res, next) => { - postmodel.find(). - then((documents) => { - //console.log(documents); - res.status(200).json({ - message: 'Posts Fetched successfully', - posts: documents - }); - }); -}); - -/* - * Add a new user - * @param address: String. Shielded zcash address - * @param session: String. Browser session uuid - * @param blocktime: Number. Blocktime of login zcash transaction - */ - -app.post('/api/users', (req, res, next) => { - console.log('Post: /api/users'); - const user = new usermodel({ - address: req.body.address, - session: req.body.session, - blocktime: req.body.blocktime - }); - user.save(); - res.status(201).json({ - message: 'User added successfully' - }); -}); app.get('/api/users', (req, res, next) => { console.log('Get: /api/users'); usermodel.find({'address': req.query.address, 'session': req.query.session}). then((documents) => { - console.log("Searching"); - res.status(200).json({ - message: 'Users found successfully', - users: documents - }); + if (documents != null) { + res.status(200).json({ + message: 'Users found successfully', + users: documents + }); + } else { + res.status(204).json({ + message: 'User not found', + users: null + }); + } }); }); app.get('/api/getuser', (req, res, next) => { console.log('Get: /api/getuser/', req.query.session); - usermodel.find({'session': req.query.session}). + var today = new Date().getTime() / 1000; + var expiration = today - (7*24*3600); + usermodel.find({'session': req.query.session, 'blocktime': { $gt: expiration }}). then((documents) => { - console.log("Searching for user..."); if(documents.length > 0){ //console.log(documents); + console.log(' found user'); res.status(200).json({ message: 'User found!', user: documents }); } else { + console.log(' did not find user'); res.status(204).json({ message: 'User not found!', user: null @@ -159,9 +209,10 @@ app.get('/api/blockheight', (req, res, next) => { }); + app.get('/api/txs', (req, res, next) => { console.log('Get: /api/txs'); - rpc.z_listreceivedbyaddress(fullnode.addr, 5).then(txs => { + rpc.z_listreceivedbyaddress(fullnode.addr, 10).then(txs => { res.status(200).json({ message: 'Transactions found', txs: txs diff --git a/backend/models/owner.js b/backend/models/owner.js index 38fac2e..195f809 100644 --- a/backend/models/owner.js +++ b/backend/models/owner.js @@ -1,7 +1,7 @@ const mongoose = require('mongoose'); const ownerSchema = mongoose.Schema({ - address: {type: String, required:true}, + address: {type: String, required:true, unique:true}, name: {type: String, required:true} }); diff --git a/package-lock.json b/package-lock.json index e687459..9ea2c22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "sell4zec", + "name": "zgo", "version": "0.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "sell4zec", + "name": "zgo", "version": "0.0.0", "dependencies": { "@angular/animations": "~12.2.0", @@ -20,6 +20,7 @@ "@angular/router": "~12.2.0", "@supercharge/request-ip": "^1.1.2", "angular-local-storage": "^0.7.1", + "async": "^3.2.2", "coingecko-api": "^1.0.10", "easyqrcodejs": "^4.4.6", "material-design-icons": "^3.0.1", @@ -3251,13 +3252,9 @@ } }, "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" }, "node_modules/async-each": { "version": "1.0.3", @@ -10305,6 +10302,15 @@ "node": ">= 0.12.0" } }, + "node_modules/portfinder/node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/portfinder/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -17997,13 +18003,9 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" }, "async-each": { "version": "1.0.3", @@ -23475,6 +23477,15 @@ "mkdirp": "^0.5.5" }, "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, "debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", diff --git a/package.json b/package.json index 21efbb3..2682b3f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@angular/router": "~12.2.0", "@supercharge/request-ip": "^1.1.2", "angular-local-storage": "^0.7.1", + "async": "^3.2.2", "coingecko-api": "^1.0.10", "easyqrcodejs": "^4.4.6", "material-design-icons": "^3.0.1", diff --git a/src/app/fullnode.service.ts b/src/app/fullnode.service.ts index d2e8389..f2cef8f 100644 --- a/src/app/fullnode.service.ts +++ b/src/app/fullnode.service.ts @@ -21,7 +21,6 @@ export class FullnodeService{ constructor(private http: HttpClient, public userService: UserService){ this.getAddr(); this.getHeight(); - this.getMemos(); this.getPrice(); } @@ -60,42 +59,6 @@ export class FullnodeService{ return str; } - getMemos() { - this.http.get<{message: string, txs: any}>('http://localhost:3000/api/txs'). - subscribe((TxData) => { - var memos: string[] = []; - //this.addr = TxData.addr; - var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/; - for (var i=0; i < TxData.txs.length; i++) { - var memo = this.hexToString(TxData.txs[i].memo); - //console.log(TxData.txs[i].blocktime); - if (re.test(memo)){ - memos.push(memo); - var match = re.exec(memo); - if (match != null) { - var address = match[2]; - var session = match[1]; - var blocktime = TxData.txs[i].blocktime; - console.log(memo); - console.log(`Searching for user for ${session}`); - const params = new HttpParams().append('session', session); - this.http.get<{message: string, user: any}>('http://localhost:3000/api/getuser', { headers:{}, params: params, observe: 'response'}). - subscribe((UserDataResponse) => { - console.log(UserDataResponse.status); - if (UserDataResponse.status == 200){ - console.log(`FS: Found user`); - } else { - console.log('FS: Did not find user'); - this.userService.addUser(address, session, blocktime); - } - }); - } - } - } - this.dataStore.memoList = memos; - this._memoUpdated.next(Object.assign({},this.dataStore).memoList); - }); - } getAddr() { diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts index a9942c3..a088018 100644 --- a/src/app/login/login.component.ts +++ b/src/app/login/login.component.ts @@ -17,7 +17,6 @@ var Buffer = require('buffer/').Buffer; export class LoginComponent implements OnInit { intervalHolder: any; - memos: string[] = []; nodeAddress: string = ''; private FullnodeSub: Subscription = new Subscription(); private UserSub: Subscription = new Subscription(); @@ -46,46 +45,47 @@ export class LoginComponent implements OnInit { if(localToken == null){ var token = uuidv4(); localStorage.setItem('s4z_token', token); - console.log('Showing QR code for login'); - console.log(URLSafeBase64.encode(Buffer.from('ZGO::'.concat(token)))); - var codeString = `zcash:${this.nodeAddress}?amount=0.001&memo=${URLSafeBase64.encode(Buffer.from('ZGO::'.concat(token)))}`; - console.log(codeString); - var qrcode = new QRCode(document.getElementById("qrcode"), { - text: codeString, - logo: "/assets/zcash.png", - logoWidth: 80, - logoHeight: 80 - }); - } else { - //this.userService.getUser(localToken); - this.userService.uZaddrUpdate. - subscribe((userAddr: string) => { - if (userAddr.length != 0) { - console.log('Log in found!'); - this.router.navigate(['/view']); - } else { - console.log('No login for existing token found'); - console.log('Showing QR code for login'); - //console.log(URLSafeBase64.encode(Buffer.from('S4ZEC::'.concat(localToken)))); - var codeString = `zcash:${this.nodeAddress}?amount=0.001&memo=${URLSafeBase64.encode(Buffer.from('ZGO::'.concat(localToken!)))}`; - console.log(codeString); - var qrcode = new QRCode(document.getElementById("qrcode"), { - text: codeString, - logo: "/assets/zcash.png", - logoWidth: 80, - logoHeight: 80 - }); - } - }); + localToken = token; } + this.userService.findUser(); + this.userService.uZaddrUpdate. + subscribe((userAddr: string) => { + if (userAddr.length != 0) { + console.log('Log in found!'); + this.router.navigate(['/view']); + } else { + console.log('No login for existing token found'); + console.log('Showing QR code for login'); + //console.log(URLSafeBase64.encode(Buffer.from('S4ZEC::'.concat(localToken)))); + var codeString = `zcash:${this.nodeAddress}?amount=0.001&memo=${URLSafeBase64.encode(Buffer.from('ZGO::'.concat(localToken!)))}`; + console.log(codeString); + var qrcode = new QRCode(document.getElementById("qrcode"), { + text: codeString, + logo: "/assets/zcash.png", + logoWidth: 80, + logoHeight: 80 + }); + } + }); }); this.intervalHolder = setInterval(() => { this.fullnodeService.getHeight(); - this.fullnodeService.getMemos(); + //this.userService.findUser(); + this.loginCheck(); this._changeDetectorRef.markForCheck(); }, 1000 * 75); } + loginCheck(){ + this.userService.findUser(); + this.uZaddrUpdate.subscribe((userAddr: string) => { + if (userAddr.length != 0) { + console.log('Log in found in blockchain!'); + this.router.navigate(['/view']); + } + }); + } + ngOnDestroy(){ this.FullnodeSub.unsubscribe(); this.UserSub.unsubscribe(); diff --git a/src/app/user.service.ts b/src/app/user.service.ts index 0053bf2..b78e1ba 100644 --- a/src/app/user.service.ts +++ b/src/app/user.service.ts @@ -38,38 +38,31 @@ export class UserService{ } findUser() { - const params = new HttpParams().append('session', this.session!); - let obs = this.http.get<{message: string, user: any}>('http://localhost:3000/api/getuser', { headers:{}, params: params, observe: 'response'}); + 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, user: any}>('http://localhost:3000/api/getuser', { headers:{}, params: params, observe: 'response'}); - obs.subscribe((UserDataResponse) => { - console.log(UserDataResponse.status); - if (UserDataResponse.status == 200){ - this.dataStore.user = UserDataResponse.body!.user[0]; - console.log(`US: Found user, returning it`); - this._uZaddrUpdated.next(Object.assign({},this.dataStore).user.address); - this._userUpdated.next(Object.assign({}, this.dataStore).user); - this.getOwner(Object.assign({},this.dataStore.user).address); - } else { - console.log('US: Did not find user'); - } - }); + obs.subscribe((UserDataResponse) => { + console.log(UserDataResponse.status); + if (UserDataResponse.status == 200){ + this.dataStore.user = UserDataResponse.body!.user[0]; + console.log(`US: Found user, returning it`); + this._uZaddrUpdated.next(Object.assign({},this.dataStore).user.address); + this._userUpdated.next(Object.assign({}, this.dataStore).user); + this.getOwner(Object.assign({},this.dataStore.user).address); + } else { + console.log('US: Did not find user'); + } + }); - return obs; + return obs; + } else { + console.log('No session loaded'); + return null; + } } - addUser(address: string, session: string, blocktime: number) { - const user: User={_id: '', address: address, session: session, blocktime: blocktime}; - let obs = this.http.post<{message: string}>('http://localhost:3000/api/users', user); - - obs.subscribe((responseData) => { - console.log(responseData.message); - this.getOwner(address).subscribe((response) => { - console.log('addUser, checking owner', response); - }); - }); - - return obs; - } addOwner(address: string) { const owner: Owner={_id: '', address: address, name: 'Zgo-'.concat(address.substring(0,5))};