From d0189481112f4aebad893c4e96ca245639cc37d7 Mon Sep 17 00:00:00 2001 From: Tom Trevethan Date: Mon, 19 Feb 2024 23:32:26 +0000 Subject: [PATCH] update to fiat --- src/controllers/api_controller.js | 73 ++++++++++++++++++----------- src/env.js | 8 ++-- src/models/models.js | 1 + src/utils/constants.js | 3 +- src/view/Footer.jsx | 6 +-- src/view/modals/CreateSlotModal.jsx | 14 ++---- 6 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/controllers/api_controller.js b/src/controllers/api_controller.js index e0dfe0f..97e6aee 100644 --- a/src/controllers/api_controller.js +++ b/src/controllers/api_controller.js @@ -35,7 +35,8 @@ const { AWAITING_ATTEST, ARG_TOKEN_ID, ARG_SLOT_ID, - EXPIRY_DATE_ERROR + EXPIRY_DATE_ERROR, + BAD_COMMITMENT } = require('../utils/constants'); const { @@ -59,13 +60,12 @@ const { const DATE_FORMAT = 'HH:mm:ss L z'; -const C_LIGHTNING_URL = env.c_lightning.url; -const MACAROON_HEX = env.c_lightning.macaroon_hex; -const FEE_RATE_PER_MONTH_IN_MSAT = env.c_lightning.fee_rate_per_month_in_msat; +const LIGHTNING_URL = env.lightning.url; +const API_KEY = env.lightning.api_key; +const FEE_RATE_PER_MONTH_IN_EUR = env.lightning.fee_rate_per_month_in_eur; const INVOICE_DESCRIPTION = 'Invoice for Mainstay token'; -const C_LIGHTNING_REQUEST_HEADERS = { - 'encodingtype': 'hex', - 'macaroon': MACAROON_HEX, +const LIGHTNING_REQUEST_HEADERS = { + 'Api-Key': API_KEY, 'Content-Type': 'application/json' }; @@ -439,6 +439,15 @@ module.exports = { return reply_err(res, MISSING_PAYLOAD_TOKEN, startTime); } + + if (payload.commitment.length !== 64) { + return reply_err(res, BAD_COMMITMENT, startTime); + } + if (payload.commitment.split('').every(c => '0123456789ABCDEFabcdef'.indexOf(c) !== -1)) { + return reply_err(res, BAD_COMMITMENT, startTime); + } + + const signatureCommitment = data[MAINSTAY_SIGNATURE]; try { // try get client details @@ -1181,18 +1190,27 @@ module.exports = { } const token_id = uuidv4(); try { - const response = await axios.post(C_LIGHTNING_URL + '/v1/invoice/genInvoice', { - amount: amount, - label: token_id, - description: INVOICE_DESCRIPTION + const response = await axios.post(LIGHTNING_URL + '/checkout', { + title: token_id, + description: INVOICE_DESCRIPTION, + amount: amount, + unit: "EUR", + redirectAfterPaid: "", + email: "", + emailLanguage: "en", + onChain: true, + delay: 60, + extra: { + tag: "invoice-web" + } }, { - headers: C_LIGHTNING_REQUEST_HEADERS + headers: LIGHTNING_REQUEST_HEADERS }); const invoice = response.data; - if (invoice) { const tokenDetailsData = { token_id: token_id, + pp_id: invoice.id, value: amount, confirmed: false, amount: 0 @@ -1201,15 +1219,15 @@ module.exports = { await tokenDetails.save(); reply_msg(res, { "lightning_invoice": { - "bolt11": invoice.bolt11, - "expires_at": invoice.expires_at, - "payment_hash": invoice.payment_hash + "bolt11": invoice.pr, }, "token_id": token_id, - "value": amount + "value": amount, + "bitcoin_address": invoice.onChainAddr, }, startTime); } } catch (error) { + console.log(error); reply_err(res, INTERNAL_ERROR_API, startTime); } }, @@ -1221,21 +1239,22 @@ module.exports = { return; } try { - const response = await axios.get(C_LIGHTNING_URL + '/v1/invoice/listInvoices?label=' + token_id, + const tokenDetails = await models.tokenDetails.findOne({token_id: token_id}); + const response = await axios.get(LIGHTNING_URL + '/checkout/' + tokenDetails.pp_id, { - headers: C_LIGHTNING_REQUEST_HEADERS + headers: LIGHTNING_REQUEST_HEADERS }); - const invoice = response.data.invoices[0]; + console.log(response); + const pp_response = response.data; let invoice_paid = false; - if (invoice && invoice.status === "paid") { - const tokenDetails = await models.tokenDetails.findOne({token_id: token_id}); + if (pp_response.isPaid) { tokenDetails.confirmed = true; - tokenDetails.amount = invoice.msatoshi; + tokenDetails.amount = pp_response.fiatAmount; await tokenDetails.save(); invoice_paid = true; } reply_msg(res, { - amount: invoice.msatoshi, + amount: pp_response.amount, confirmed: invoice_paid }, startTime); } catch (error) { @@ -1266,7 +1285,7 @@ module.exports = { const startTime = start_time(); try { reply_msg(res, { - fee_rate: FEE_RATE_PER_MONTH_IN_MSAT + fee_rate: FEE_RATE_PER_MONTH_IN_EUR }, startTime); } catch (error) { reply_err(res, INTERNAL_ERROR_API, startTime); @@ -1287,8 +1306,8 @@ module.exports = { const slot_id = data[ARG_SLOT_ID]; const tokenDetails = await models.tokenDetails.findOne({token_id: token_id}); - if (tokenDetails.amount >= FEE_RATE_PER_MONTH_IN_MSAT) { - const months = tokenDetails.amount / FEE_RATE_PER_MONTH_IN_MSAT; + if (tokenDetails.amount >= FEE_RATE_PER_MONTH_IN_EUR) { + const months = tokenDetails.amount / FEE_RATE_PER_MONTH_IN_EUR; if (slot_id === 0) { const clientDetailsData = await create_slot_with_token(months); reply_msg(res, { diff --git a/src/env.js b/src/env.js index 9defab9..2fc2048 100644 --- a/src/env.js +++ b/src/env.js @@ -80,9 +80,9 @@ module.exports = { secret: onfidoWebhookSecret } }, - c_lightning: { - url: env.C_LIGHTNING_URL, - macaroon_hex: env.MACAROON_HEX, - fee_rate_per_month_in_msat: env.FEE_RATE_PER_MONTH_IN_MSAT + lightning: { + url: env.LIGHTNING_URL, + api_key: env.API_KEY, + fee_rate_per_month_in_eur: env.FEE_RATE_PER_MONTH_IN_EUR } }; diff --git a/src/models/models.js b/src/models/models.js index b78a5dc..597f4ff 100644 --- a/src/models/models.js +++ b/src/models/models.js @@ -131,6 +131,7 @@ schemaClientSignup.index({'verify_code': 1}); const schemaTokenDetails = new Schema({ token_id: String, + pp_id: String, value: Number, confirmed: Boolean, amount: Number diff --git a/src/utils/constants.js b/src/utils/constants.js index 3edacf9..2b61507 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -9,6 +9,7 @@ const constants = { ARG_SLOT_ID: 'slot_id', BAD_LENGTH_TXID: 'txid string parameter must contain 64 characters', BAD_LENGTH_COMMITMENT: 'commitment string parameter must contain 64 characters', + BAD_COMMITMENT: 'commitment is not a valid hex string', BAD_TYPE_POSITION: 'position expects a int', BAD_TYPE_VALUE: 'value expects an int', COMMITMENT_POSITION_UNKNOWN: 'your commitment or position is unknown to us', @@ -54,4 +55,4 @@ const constants = { constants.BAD_LENGTH_MERKLE_ROOT = constants.BAD_LENGTH_COMMITMENT; -module.exports = constants; \ No newline at end of file +module.exports = constants; diff --git a/src/view/Footer.jsx b/src/view/Footer.jsx index 84c1642..0bc278d 100644 --- a/src/view/Footer.jsx +++ b/src/view/Footer.jsx @@ -28,11 +28,7 @@ const Footer = () => ( favicon - © 2020 CommerceBlock Limited. All rights reserved. -
- Powered by - logo -
+ © 2024 CommerceBlock Limited. All rights reserved. diff --git a/src/view/modals/CreateSlotModal.jsx b/src/view/modals/CreateSlotModal.jsx index 972477e..88a2793 100644 --- a/src/view/modals/CreateSlotModal.jsx +++ b/src/view/modals/CreateSlotModal.jsx @@ -6,10 +6,6 @@ import {Button, Form, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, Mo import apiService from '../../helpers/api-service'; -function milliSatsToSats(milliSats) { - return milliSats / 1000; -} - class CreateSlotModal extends React.PureComponent { constructor(props) { @@ -19,7 +15,7 @@ class CreateSlotModal extends React.PureComponent { inputs: { months: 1, }, - fee_rate_per_month_in_msat: '', + fee_rate_per_month_in_eur: '', invoice: '', copied: false, confirmed: false, @@ -32,7 +28,7 @@ class CreateSlotModal extends React.PureComponent { apiService.axiosClient.get('/api/v1/feerate') .then(({ data, error }) => { if (data?.response) { - this.setState({ fee_rate_per_month_in_msat: data.response.fee_rate }); + this.setState({ fee_rate_per_month_in_eur: data.response.fee_rate }); } }); } @@ -66,7 +62,7 @@ class CreateSlotModal extends React.PureComponent { return this.showErrorAlert('Months field is empty'); } - const fee_rate = this.state.fee_rate_per_month_in_msat; + const fee_rate = this.state.fee_rate_per_month_in_eur; const amount = fee_rate * months; apiService.axiosClient.get(`/api/v1/token/init/?value=${amount}`) @@ -154,9 +150,9 @@ class CreateSlotModal extends React.PureComponent { > {this.props.slotDetails.new_slot ? -
Pay with lightning to reserve a unique proof-of-publication slot for {milliSatsToSats(this.state.fee_rate_per_month_in_msat)} sats a month
+
Pay with lightning to reserve a unique proof-of-publication slot for {this.state.fee_rate_per_month_in_eur} EUR a month
: -
Pay with lightning to keep using slot number {this.props.slotDetails.slot_id} for {milliSatsToSats(this.state.fee_rate_per_month_in_msat)} sats a month
+
Pay with lightning to keep using slot number {this.props.slotDetails.slot_id} for {this.state.fee_rate_per_month_in_eur} EUR a month
}