lndhub/class/User.js
Overtorment 748b5fd733 FIX
2018-12-03 14:06:12 +00:00

207 lines
5.5 KiB
JavaScript

var crypto = require('crypto');
import { BigNumber } from 'bignumber.js';
export class User {
/**
*
* @param {Redis} redis
*/
constructor(redis, bitcoindrpc) {
this._redis = redis;
this._bitcoindrpc = bitcoindrpc;
this._userid = false;
this._login = false;
this._password = false;
this._balance = 0;
}
getUserId() {
return this._userid;
}
getLogin() {
return this._login;
}
getPassword() {
return this._password;
}
getAccessToken() {
return this._acess_token;
}
getRefreshToken() {
return this._refresh_token;
}
async loadByAuthorization(authorization) {
let access_token = authorization.replace('Bearer ', '');
let userid = await this._redis.get('userid_for_' + access_token);
if (userid) {
this._userid = userid;
return true;
}
return false;
}
async loadByRefreshToken(refresh_token) {
let userid = await this._redis.get('userid_for_' + refresh_token);
if (userid) {
this._userid = userid;
await this._generateTokens();
return true;
}
return false;
}
async create() {
let buffer = crypto.randomBytes(20);
let login = buffer.toString('hex');
buffer = crypto.randomBytes(20);
let password = buffer.toString('hex');
buffer = crypto.randomBytes(48);
let userid = buffer.toString('hex');
this._login = login;
this._password = password;
this._userid = userid;
await this._saveUserToDatabase();
}
async loadByLoginAndPassword(login, password) {
let userid = await this._redis.get('user_' + login + '_' + this._hash(password));
if (userid) {
this._userid = userid;
this._login = login;
this._password = password;
await this._generateTokens();
return true;
}
return false;
}
async getAddress() {
return await this._redis.get('bitcoin_address_for_' + this._userid);
}
async getBalance() {
return (await this._redis.get('balance_for_' + this._userid)) * 1;
}
async saveBalance(balance) {
return await this._redis.set('balance_for_' + this._userid, balance);
}
async savePaidLndInvoice(doc) {
return await this._redis.rpush('txs_for_' + this._userid, JSON.stringify(doc));
}
async addAddress(address) {
await this._redis.set('bitcoin_address_for_' + this._userid, address);
}
/**
* User's onchain txs that are >= 3 confs
*
* @returns {Promise<Array>}
*/
async getTxs() {
let addr = await this.getAddress();
let txs = await this._bitcoindrpc.request('listtransactions', [addr, 100500, 0, true]);
txs = txs.result;
let result = [];
for (let tx of txs) {
if (tx.confirmations >= 3) {
tx.type = 'bitcoind_tx';
result.push(tx);
}
}
let range = await this._redis.lrange('txs_for_' + this._userid, 0, -1);
for (let invoice of range) {
invoice = JSON.parse(invoice);
invoice.type = 'paid_invoice';
invoice.fee = parseInt(invoice.payment_route.total_fees_msat / 1000);
invoice.value = parseInt((invoice.payment_route.total_fees_msat + invoice.payment_route.total_amt_msat) / 1000);
invoice.timestamp = invoice.decoded.timestamp;
result.push(invoice);
}
return result;
}
/**
* Returning onchain txs for user's address that are less than 3 confs
*
* @returns {Promise<Array>}
*/
async getPendingTxs() {
let addr = await this.getAddress();
let txs = await this._bitcoindrpc.request('listtransactions', [addr, 100500, 0, true]);
txs = txs.result;
let result = [];
for (let tx of txs) {
if (tx.confirmations < 3) {
result.push(tx);
}
}
return result;
}
async _generateTokens() {
let buffer = crypto.randomBytes(20);
this._acess_token = buffer.toString('hex');
buffer = crypto.randomBytes(20);
this._refresh_token = buffer.toString('hex');
await this._redis.set('userid_for_' + this._acess_token, this._userid);
await this._redis.set('userid_for_' + this._refresh_token, this._userid);
await this._redis.set('access_token_for_' + this._userid, this._acess_token);
await this._redis.set('refresh_token_for_' + this._userid, this._refresh_token);
}
async _saveUserToDatabase() {
let key;
await this._redis.set((key = 'user_' + this._login + '_' + this._hash(this._password)), this._userid);
}
/**
* Fetches all onchain txs for user's address, and compares them to
* already imported txids (stored in database); Ones that are not imported -
* get their balance added to user's balance, and its txid added to 'imported' list.
*
* @returns {Promise<void>}
*/
async accountForPosibleTxids() {
let imported_txids = await this._redis.lrange('imported_txids_for_' + this._userid, 0, -1);
console.log(':::::::::::imported_txids', imported_txids);
let onchain_txs = await this.getTxs();
for (let tx of onchain_txs) {
if (tx.type !== 'bitcoind_tx') continue;
let already_imported = false;
for (let imported_txid of imported_txids) {
if (tx.txid === imported_txid) already_imported = true;
}
if (!already_imported && tx.category === 'receive') {
let userBalance = await this.getBalance();
userBalance += new BigNumber(tx.amount).multipliedBy(100000000).toNumber();
await this.saveBalance(userBalance);
await this._redis.rpush('imported_txids_for_' + this._userid, tx.txid);
}
}
}
_hash(string) {
return crypto
.createHash('sha256')
.update(string)
.digest()
.toString('hex');
}
}