FIX: properly locked payments
This commit is contained in:
parent
afb07aa9ba
commit
8f2d98774b
@ -2,14 +2,15 @@ var crypto = require('crypto');
|
|||||||
var lightningPayReq = require('bolt11');
|
var lightningPayReq = require('bolt11');
|
||||||
import { BigNumber } from 'bignumber.js';
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
|
||||||
export class Paym {
|
export class Payment {
|
||||||
constructor(redis, bitcoindrpc, lightning) {
|
constructor(redis, bitcoindrpc, lightning) {
|
||||||
this._redis = redis;
|
this._redis = redis;
|
||||||
this._bitcoindrpc = bitcoindrpc;
|
this._bitcoindrpc = bitcoindrpc;
|
||||||
this._lightning = lightning;
|
this._lightning = lightning;
|
||||||
|
this._decoded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async decodePayReq(invoice) {
|
async decodePayReqViaRpc(invoice) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
this._lightning.decodePayReq({ pay_req: invoice }, function(err, info) {
|
this._lightning.decodePayReq({ pay_req: invoice }, function(err, info) {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
@ -17,4 +18,8 @@ export class Paym {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decodePayReq(payReq) {
|
||||||
|
this._decoded = lightningPayReq.decode(payReq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,6 +153,13 @@ export class User {
|
|||||||
calculatedBalance -= +tx.value;
|
calculatedBalance -= +tx.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let lockedPayments = await this.getLockedPayments();
|
||||||
|
for (let paym of lockedPayments) {
|
||||||
|
// TODO: check if payment in determined state and actually evict it from this list
|
||||||
|
calculatedBalance -= +paym.amount;
|
||||||
|
}
|
||||||
|
|
||||||
return calculatedBalance;
|
return calculatedBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,6 +393,59 @@ export class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds invoice to a list of user's locked payments.
|
||||||
|
* Used to calculate balance till the lock is lifted (payment is in
|
||||||
|
* determined state - succeded or failed).
|
||||||
|
*
|
||||||
|
* @param {String} pay_req
|
||||||
|
* @param {Object} decodedInvoice
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async lockFunds(pay_req, decodedInvoice) {
|
||||||
|
let doc = {
|
||||||
|
pay_req,
|
||||||
|
amount: +decodedInvoice.num_satoshis,
|
||||||
|
timestamp: Math.floor(+new Date() / 1000),
|
||||||
|
};
|
||||||
|
|
||||||
|
return this._redis.rpush('locked_payments_for_' + this._userid, JSON.stringify(doc));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strips specific payreq from the list of locked payments
|
||||||
|
* @param pay_req
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async unlockFunds(pay_req) {
|
||||||
|
let payments = await this.getLockedPayments();
|
||||||
|
let saveBack = [];
|
||||||
|
for (let paym of payments) {
|
||||||
|
if (paym.pay_req !== pay_req) {
|
||||||
|
saveBack.push(paym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._redis.del('locked_payments_for_' + this._userid);
|
||||||
|
for (let doc of saveBack) {
|
||||||
|
await this._redis.rpush('locked_payments_for_' + this._userid, JSON.stringify(doc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLockedPayments() {
|
||||||
|
let payments = await this._redis.lrange('locked_payments_for_' + this._userid, 0, -1);
|
||||||
|
let result = [];
|
||||||
|
for (let paym of payments) {
|
||||||
|
let json;
|
||||||
|
try {
|
||||||
|
json = JSON.parse(paym);
|
||||||
|
result.push(json);
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
_hash(string) {
|
_hash(string) {
|
||||||
return crypto
|
return crypto
|
||||||
.createHash('sha256')
|
.createHash('sha256')
|
||||||
|
@ -185,6 +185,7 @@ router.post('/payinvoice', async function(req, res) {
|
|||||||
var call = lightning.sendPayment();
|
var call = lightning.sendPayment();
|
||||||
call.on('data', async function(payment) {
|
call.on('data', async function(payment) {
|
||||||
// payment callback
|
// payment callback
|
||||||
|
await u.unlockFunds(req.body.invoice);
|
||||||
if (payment && payment.payment_route && payment.payment_route.total_amt_msat) {
|
if (payment && payment.payment_route && payment.payment_route.total_amt_msat) {
|
||||||
userBalance -= +payment.payment_route.total_fees + +payment.payment_route.total_amt;
|
userBalance -= +payment.payment_route.total_fees + +payment.payment_route.total_amt;
|
||||||
u.saveBalance(userBalance);
|
u.saveBalance(userBalance);
|
||||||
@ -206,6 +207,7 @@ router.post('/payinvoice', async function(req, res) {
|
|||||||
}
|
}
|
||||||
let inv = { payment_request: req.body.invoice, amt: info.num_satoshis }; // amt is used only for 'tip' invoices
|
let inv = { payment_request: req.body.invoice, amt: info.num_satoshis }; // amt is used only for 'tip' invoices
|
||||||
try {
|
try {
|
||||||
|
await u.lockFunds(req.body.invoice, info);
|
||||||
call.write(inv);
|
call.write(inv);
|
||||||
} catch (Err) {
|
} catch (Err) {
|
||||||
await lock.releaseLock();
|
await lock.releaseLock();
|
||||||
|
@ -20,6 +20,8 @@ User storage schema
|
|||||||
* bitcoin_address_for_{userid} = {address}
|
* bitcoin_address_for_{userid} = {address}
|
||||||
* balance_for_{userid} = {int}
|
* balance_for_{userid} = {int}
|
||||||
* txs_for_{userid} = [] `serialized paid lnd invoices in a list`
|
* txs_for_{userid} = [] `serialized paid lnd invoices in a list`
|
||||||
|
* locked_invoices_for_{userod} = [] `serialized attempts to pay invoice. used in calculating user's balance`
|
||||||
|
: {pay_req:..., amount:666, timestamp:666}
|
||||||
* imported_txids_for_{userid} = [] `list of txids processed for this user`
|
* imported_txids_for_{userid} = [] `list of txids processed for this user`
|
||||||
* metadata_for_{userid}= {serialized json}
|
* metadata_for_{userid}= {serialized json}
|
||||||
* userinvoices_for_{userid} = []
|
* userinvoices_for_{userid} = []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user