FIX: Debit correct amount in case of overpaid userinvoice (closes #138)
This commit is contained in:
parent
4138082a02
commit
61353a71e2
@ -38,7 +38,7 @@ export class Invo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!paymentHash) throw new Error('Could not find payment hash in invoice tags');
|
if (!paymentHash) throw new Error('Could not find payment hash in invoice tags');
|
||||||
return await this._setIsPaymentHashPaidInDatabase(paymentHash, true);
|
return await this._setIsPaymentHashPaidInDatabase(paymentHash, decoded.satoshis);
|
||||||
}
|
}
|
||||||
|
|
||||||
async markAsUnpaidInDatabase() {
|
async markAsUnpaidInDatabase() {
|
||||||
@ -54,9 +54,9 @@ export class Invo {
|
|||||||
return await this._setIsPaymentHashPaidInDatabase(paymentHash, false);
|
return await this._setIsPaymentHashPaidInDatabase(paymentHash, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _setIsPaymentHashPaidInDatabase(paymentHash, isPaid) {
|
async _setIsPaymentHashPaidInDatabase(paymentHash, settleAmountSat) {
|
||||||
if (isPaid) {
|
if (settleAmountSat) {
|
||||||
return await this._redis.set('ispaid_' + paymentHash, 1);
|
return await this._redis.set('ispaid_' + paymentHash, settleAmountSat);
|
||||||
} else {
|
} else {
|
||||||
return await this._redis.del('ispaid_' + paymentHash);
|
return await this._redis.del('ispaid_' + paymentHash);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ export class User {
|
|||||||
let self = this;
|
let self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self._lightning.newAddress({ type: 0 }, async function(err, response) {
|
self._lightning.newAddress({ type: 0 }, async function(err, response) {
|
||||||
if (err) return reject('LND failure');
|
if (err) return reject('LND failure when trying to generate new address');
|
||||||
await self.addAddress(response.address);
|
await self.addAddress(response.address);
|
||||||
self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
|
self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
|
||||||
resolve();
|
resolve();
|
||||||
@ -226,8 +226,8 @@ export class User {
|
|||||||
* @see Invo._setIsPaymentHashPaidInDatabase
|
* @see Invo._setIsPaymentHashPaidInDatabase
|
||||||
* @see Invo.markAsPaidInDatabase
|
* @see Invo.markAsPaidInDatabase
|
||||||
*/
|
*/
|
||||||
async setPaymentHashPaid(payment_hash) {
|
async setPaymentHashPaid(payment_hash, settleAmountSat) {
|
||||||
return await this._redis.set('ispaid_' + payment_hash, 1);
|
return await this._redis.set('ispaid_' + payment_hash, settleAmountSat);
|
||||||
}
|
}
|
||||||
|
|
||||||
async lookupInvoice(payment_hash) {
|
async lookupInvoice(payment_hash) {
|
||||||
@ -254,7 +254,7 @@ export class User {
|
|||||||
const ispaid = invoice.settled; // TODO: start using `state` instead as its future proof, and this one might get deprecated
|
const ispaid = invoice.settled; // TODO: start using `state` instead as its future proof, and this one might get deprecated
|
||||||
if (ispaid) {
|
if (ispaid) {
|
||||||
// so invoice was paid after all
|
// so invoice was paid after all
|
||||||
await this.setPaymentHashPaid(payment_hash);
|
await this.setPaymentHashPaid(payment_hash, invoice.amt_paid_msat ? Math.floor(invoice.amt_paid_msat / 1000) : invoice.amt_paid_sat);
|
||||||
await this.clearBalanceCache();
|
await this.clearBalanceCache();
|
||||||
}
|
}
|
||||||
return ispaid;
|
return ispaid;
|
||||||
@ -283,17 +283,28 @@ export class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invoice.ispaid = _invoice_ispaid_cache[invoice.payment_hash] || !!(await this.getPaymentHashPaid(invoice.payment_hash));
|
let paymentHashPaidAmountSat = 0;
|
||||||
|
if (_invoice_ispaid_cache[invoice.payment_hash]) {
|
||||||
|
// static cache hit
|
||||||
|
invoice.ispaid = true;
|
||||||
|
paymentHashPaidAmountSat = _invoice_ispaid_cache[invoice.payment_hash];
|
||||||
|
} else {
|
||||||
|
// static cache miss, asking redis cache
|
||||||
|
paymentHashPaidAmountSat = await this.getPaymentHashPaid(invoice.payment_hash);
|
||||||
|
if (paymentHashPaidAmountSat) invoice.ispaid = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!invoice.ispaid) {
|
if (!invoice.ispaid) {
|
||||||
if (decoded && decoded.timestamp > +new Date() / 1000 - 3600 * 24 * 5) {
|
if (decoded && decoded.timestamp > +new Date() / 1000 - 3600 * 24 * 5) {
|
||||||
// if invoice is not too old we query lnd to find out if its paid
|
// if invoice is not too old we query lnd to find out if its paid
|
||||||
invoice.ispaid = await this.syncInvoicePaid(invoice.payment_hash);
|
invoice.ispaid = await this.syncInvoicePaid(invoice.payment_hash);
|
||||||
|
paymentHashPaidAmountSat = await this.getPaymentHashPaid(invoice.payment_hash); // since we have just saved it
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_invoice_ispaid_cache[invoice.payment_hash] = true;
|
_invoice_ispaid_cache[invoice.payment_hash] = paymentHashPaidAmountSat;
|
||||||
}
|
}
|
||||||
|
|
||||||
invoice.amt = decoded.satoshis;
|
invoice.amt = (paymentHashPaidAmountSat && parseInt(paymentHashPaidAmountSat) > decoded.satoshis) ? parseInt(paymentHashPaidAmountSat) : decoded.satoshis;
|
||||||
invoice.expire_time = 3600 * 24;
|
invoice.expire_time = 3600 * 24;
|
||||||
// ^^^default; will keep for now. if we want to un-hardcode it - it should be among tags (`expire_time`)
|
// ^^^default; will keep for now. if we want to un-hardcode it - it should be among tags (`expire_time`)
|
||||||
invoice.timestamp = decoded.timestamp;
|
invoice.timestamp = decoded.timestamp;
|
||||||
|
@ -60,7 +60,7 @@ const subscribeInvoicesCallCallback = async function (response) {
|
|||||||
memo: response.memo,
|
memo: response.memo,
|
||||||
preimage: response.r_preimage.toString('hex'),
|
preimage: response.r_preimage.toString('hex'),
|
||||||
hash: response.r_hash.toString('hex'),
|
hash: response.r_hash.toString('hex'),
|
||||||
amt_paid_sat: response.value_msat ? Math.floor(response.value_msat / 1000) : response.value,
|
amt_paid_sat: response.amt_paid_msat ? Math.floor(response.amt_paid_msat / 1000) : response.amt_paid_sat,
|
||||||
};
|
};
|
||||||
// obtaining a lock, to make sure we push to groundcontrol only once
|
// obtaining a lock, to make sure we push to groundcontrol only once
|
||||||
// since this web server can have several instances running, and each will get the same callback from LND
|
// since this web server can have several instances running, and each will get the same callback from LND
|
||||||
@ -70,7 +70,7 @@ const subscribeInvoicesCallCallback = async function (response) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let invoice = new Invo(redis, bitcoinclient, lightning);
|
let invoice = new Invo(redis, bitcoinclient, lightning);
|
||||||
await invoice._setIsPaymentHashPaidInDatabase(LightningInvoiceSettledNotification.hash, true);
|
await invoice._setIsPaymentHashPaidInDatabase(LightningInvoiceSettledNotification.hash, LightningInvoiceSettledNotification.amt_paid_sat || 1);
|
||||||
const user = new User(redis, bitcoinclient, lightning);
|
const user = new User(redis, bitcoinclient, lightning);
|
||||||
user._userid = await user.getUseridByPaymentHash(LightningInvoiceSettledNotification.hash);
|
user._userid = await user.getUseridByPaymentHash(LightningInvoiceSettledNotification.hash);
|
||||||
await user.clearBalanceCache();
|
await user.clearBalanceCache();
|
||||||
@ -253,7 +253,7 @@ router.post('/payinvoice', async function(req, res) {
|
|||||||
memo: info.description,
|
memo: info.description,
|
||||||
r_preimage: Buffer.from(preimage, 'hex'),
|
r_preimage: Buffer.from(preimage, 'hex'),
|
||||||
r_hash: Buffer.from(info.payment_hash, 'hex'),
|
r_hash: Buffer.from(info.payment_hash, 'hex'),
|
||||||
value: +info.num_satoshis,
|
amt_paid_sat: +info.num_satoshis,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await lock.releaseLock();
|
await lock.releaseLock();
|
||||||
@ -355,7 +355,7 @@ router.get('/balance', postLimiter, async function(req, res) {
|
|||||||
if (balance < 0) balance = 0;
|
if (balance < 0) balance = 0;
|
||||||
res.send({ BTC: { AvailableBalance: balance } });
|
res.send({ BTC: { AvailableBalance: balance } });
|
||||||
} catch (Error) {
|
} catch (Error) {
|
||||||
logger.log('', [req.id, 'error getting balance:', Error.message, 'userid:', u.getUserId()]);
|
logger.log('', [req.id, 'error getting balance:', Error, 'userid:', u.getUserId()]);
|
||||||
return errorGeneralServerError(res);
|
return errorGeneralServerError(res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user