Fix invoice validator

This commit is contained in:
Reckless_Satoshi 2022-11-27 03:21:07 -08:00
parent a1ef900469
commit 268e1259d6
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
6 changed files with 115 additions and 77 deletions

View File

@ -1,12 +1,12 @@
{ {
"name": "frontend", "name": "frontend",
"version": "0.3.0", "version": "0.3.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "frontend", "name": "frontend",
"version": "0.3.0", "version": "0.3.1",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-class-properties": "^7.16.7",
@ -30,6 +30,7 @@
"i18next-http-backend": "^1.4.0", "i18next-http-backend": "^1.4.0",
"install": "^0.13.0", "install": "^0.13.0",
"js-sha256": "^0.9.0", "js-sha256": "^0.9.0",
"light-bolt11-decoder": "^2.1.0",
"npm": "^8.19.1", "npm": "^8.19.1",
"openpgp": "^5.2.1", "openpgp": "^5.2.1",
"react": "^18.2.0", "react": "^18.2.0",
@ -4876,6 +4877,11 @@
} }
] ]
}, },
"node_modules/bech32": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
},
"node_modules/big-integer": { "node_modules/big-integer": {
"version": "1.6.51", "version": "1.6.51",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
@ -4985,6 +4991,29 @@
"node-int64": "^0.4.0" "node-int64": "^0.4.0"
} }
}, },
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@ -7468,6 +7497,25 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@ -9811,6 +9859,16 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/light-bolt11-decoder": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-2.1.0.tgz",
"integrity": "sha512-/AaSWTldx3aaFD7DgMVbX77MVEgLEPI0Zyx4Fjg23u3WpEoc536vz5LTXBU8oXAcrEcyDyn5GpBi2pEYuL351Q==",
"dependencies": {
"bech32": "^1.1.2",
"bn.js": "^4.11.8",
"buffer": "^6.0.3"
}
},
"node_modules/lines-and-columns": { "node_modules/lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -18428,6 +18486,11 @@
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
}, },
"bech32": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
},
"big-integer": { "big-integer": {
"version": "1.6.51", "version": "1.6.51",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
@ -18509,6 +18572,15 @@
"node-int64": "^0.4.0" "node-int64": "^0.4.0"
} }
}, },
"buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"buffer-from": { "buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@ -20381,6 +20453,11 @@
"safer-buffer": ">= 2.1.2 < 3" "safer-buffer": ">= 2.1.2 < 3"
} }
}, },
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ignore": { "ignore": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@ -22104,6 +22181,16 @@
"type-check": "~0.4.0" "type-check": "~0.4.0"
} }
}, },
"light-bolt11-decoder": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-2.1.0.tgz",
"integrity": "sha512-/AaSWTldx3aaFD7DgMVbX77MVEgLEPI0Zyx4Fjg23u3WpEoc536vz5LTXBU8oXAcrEcyDyn5GpBi2pEYuL351Q==",
"requires": {
"bech32": "^1.1.2",
"bn.js": "^4.11.8",
"buffer": "^6.0.3"
}
},
"lines-and-columns": { "lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",

View File

@ -68,6 +68,7 @@
"i18next-http-backend": "^1.4.0", "i18next-http-backend": "^1.4.0",
"install": "^0.13.0", "install": "^0.13.0",
"js-sha256": "^0.9.0", "js-sha256": "^0.9.0",
"light-bolt11-decoder": "^2.1.0",
"npm": "^8.19.1", "npm": "^8.19.1",
"openpgp": "^5.2.1", "openpgp": "^5.2.1",
"react": "^18.2.0", "react": "^18.2.0",

View File

@ -204,7 +204,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
useEffect(() => { useEffect(() => {
// Sets Setting network from coordinator API param if accessing via web // Sets Setting network from coordinator API param if accessing via web
if (settings.network == undefined) { if (settings.network == undefined) {
setSettings({ ...settings, network: data.network }); setSettings({ ...settings, network: info.network });
} }
}, [info]); }, [info]);

View File

@ -20,12 +20,14 @@ import {
IconButton, IconButton,
FormHelperText, FormHelperText,
} from '@mui/material'; } from '@mui/material';
import { Order, Settings } from '../../../models'; import { Order, Settings } from '../../../models';
import {decode} from 'light-bolt11-decoder'
import WalletsButton from '../WalletsButton'; import WalletsButton from '../WalletsButton';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import { pn } from '../../../utils'; import { pn } from '../../../utils';
import { ContentCopy, Help, RoundaboutRight, Route, SelfImprovement } from '@mui/icons-material'; import { ContentCopy, Help, SelfImprovement } from '@mui/icons-material';
import { apiClient } from '../../../services/api'; import { apiClient } from '../../../services/api';
import lnproxies from '../../../../static/lnproxies.json'; import lnproxies from '../../../../static/lnproxies.json';
@ -98,12 +100,18 @@ export const LightningPayoutForm = ({
}; };
const validateInvoice = function (invoice: string, targetAmount: number) { const validateInvoice = function (invoice: string, targetAmount: number) {
const invoiceAmount = Number(invoice.substring(4, 5 + Math.floor(Math.log10(targetAmount)))); try {
if (targetAmount != invoiceAmount && invoice.length > 20) { const decoded = decode(invoice)
const invoiceAmount = Math.floor(decoded['sections'][2]['value']/1000)
if (targetAmount != invoiceAmount) {
return 'Invalid invoice amount'; return 'Invalid invoice amount';
} else { } else {
return ''; return '';
} }
} catch(err) {
const error = err.toString()
return `${error.substring(0,100)}${error.length >100 ? '...' : ''}`
}
}; };
useEffect(() => { useEffect(() => {
@ -138,7 +146,6 @@ export const LightningPayoutForm = ({
}, [lightning.lnproxyInvoice, lightning.lnproxyAmount]); }, [lightning.lnproxyInvoice, lightning.lnproxyAmount]);
const lnproxyUrl = function () { const lnproxyUrl = function () {
console.log(settings);
const bitcoinNetwork = settings?.network ?? 'mainnet'; const bitcoinNetwork = settings?.network ?? 'mainnet';
let internetNetwork: 'Clearnet' | 'I2P' | 'TOR' = 'Clearnet'; let internetNetwork: 'Clearnet' | 'I2P' | 'TOR' = 'Clearnet';
if (settings.host?.includes('.i2p')) { if (settings.host?.includes('.i2p')) {
@ -180,7 +187,7 @@ export const LightningPayoutForm = ({
setLoadingLnproxy(true); setLoadingLnproxy(true);
fetch( fetch(
lnproxyUrl() + lnproxyUrl() +
`/api/${lightning.lnproxyInvoice}${ `/api/${lightning.lnproxyInvoice.toLocaleLowerCase()}${
lightning.lnproxyBudgetSats > 0 lightning.lnproxyBudgetSats > 0
? `?routing_msat=${lightning.lnproxyBudgetSats * 1000}` ? `?routing_msat=${lightning.lnproxyBudgetSats * 1000}`
: '' : ''
@ -191,7 +198,8 @@ export const LightningPayoutForm = ({
if (text.includes('lnproxy error')) { if (text.includes('lnproxy error')) {
setLightning({ ...lightning, badLnproxy: text}); setLightning({ ...lightning, badLnproxy: text});
} else { } else {
setLightning({ ...lightning, invoice: text, badLnproxy: '' }); const invoice = text.replace('\n',"")
setLightning({ ...lightning, invoice, badLnproxy: '' });
} }
}) })
.catch(() => { .catch(() => {
@ -513,6 +521,7 @@ export const LightningPayoutForm = ({
fullWidth={true} fullWidth={true}
disabled={!lightning.useLnproxy} disabled={!lightning.useLnproxy}
error={lightning.badLnproxy != ''} error={lightning.badLnproxy != ''}
FormHelperTextProps={{style:{wordBreak: 'break-all'}}}
helperText={lightning.badLnproxy ? t(lightning.badLnproxy) : ''} helperText={lightning.badLnproxy ? t(lightning.badLnproxy) : ''}
label={t('Invoice to wrap')} label={t('Invoice to wrap')}
required required
@ -534,6 +543,7 @@ export const LightningPayoutForm = ({
disabled={lightning.useLnproxy} disabled={lightning.useLnproxy}
error={lightning.badInvoice != ''} error={lightning.badInvoice != ''}
helperText={lightning.badInvoice ? t(lightning.badInvoice) : ''} helperText={lightning.badInvoice ? t(lightning.badInvoice) : ''}
FormHelperTextProps={{style:{wordBreak: 'break-all'}}}
label={lightning.useLnproxy ? t('Wrapped invoice') : t('Payout Lightning Invoice')} label={lightning.useLnproxy ? t('Wrapped invoice') : t('Payout Lightning Invoice')}
required required
value={lightning.invoice} value={lightning.invoice}
@ -555,7 +565,7 @@ export const LightningPayoutForm = ({
disabled={ disabled={
lightning.lnproxyInvoice.length < 20 || lightning.lnproxyInvoice.length < 20 ||
badLnproxyServer != '' || badLnproxyServer != '' ||
lightning.badLnproxy lightning.badLnproxy != ''
} }
onClick={fetchLnproxy} onClick={fetchLnproxy}
variant='outlined' variant='outlined'
@ -568,7 +578,7 @@ export const LightningPayoutForm = ({
)} )}
<LoadingButton <LoadingButton
loading={loading} loading={loading}
disabled={lightning.invoice.length < 20 || lightning.badInvoice} disabled={lightning.invoice.length < 20 || lightning.badInvoice != ''}
onClick={() => onClickSubmit(lightning.invoice)} onClick={() => onClickSubmit(lightning.invoice)}
variant='outlined' variant='outlined'
color='primary' color='primary'
@ -580,65 +590,6 @@ export const LightningPayoutForm = ({
</Box> </Box>
</Grid> </Grid>
{/* <Grid item>
<Box
sx={{
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '0.3em',
width: '18em',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
'&:hover': {
borderColor: theme.palette.mode === 'dark' ? '#ffffff' : '#2f2f2f',
},
}}
>
<Grid
container
direction='column'
justifyContent='flex-start'
alignItems='center'
spacing={0.5}
padding={0.5}
>
<Collapse in={lightning.advancedOptions}>
<Tooltip
enterTouchDelay={0}
leaveTouchDelay={4000}
placement='top'
title={t(
`Set custom routing budget for the payout. If you don't know what this is, simply do not touch.`,
)}
>
<div>
<FormControlLabel
checked={lightning.useCustomBudget}
onChange={(e) =>
setLightning({
...lightning,
useCustomBudget: e.target.checked,
routingBudgetSats: defaultLightning.routingBudgetSats,
routingBudgetPPM: defaultLightning.routingBudgetPPM,
})
}
control={<Checkbox />}
label={
<Typography
style={{ display: 'flex', alignItems: 'center' }}
color={lightning.useCustomBudget ? 'primary' : 'text.secondary'}
>
{t('Use custom routing budget')}
</Typography>
}
/>
</div>
</Tooltip>
</Collapse>
</Grid>
</Box>
</Grid> */}
<Grid item> <Grid item>
<WalletsButton /> <WalletsButton />
</Grid> </Grid>

View File

@ -50,7 +50,6 @@ class UnsafeAlert extends Component {
render() { render() {
const { t } = this.props; const { t } = this.props;
console.log(this.state);
// If alert is hidden return null // If alert is hidden return null
if (!this.state.show) { if (!this.state.show) {

View File

@ -39,7 +39,7 @@ class BaseSettings {
: i18n.resolvedLanguage.substring(0, 2); : i18n.resolvedLanguage.substring(0, 2);
const networkCookie = systemClient.getItem('settings_network'); const networkCookie = systemClient.getItem('settings_network');
this.network = networkCookie !== '' ? networkCookie : 'mainnet'; this.network = networkCookie !== '' ? networkCookie : undefined;
} }
public frontend: 'basic' | 'pro' = 'basic'; public frontend: 'basic' | 'pro' = 'basic';
@ -47,7 +47,7 @@ class BaseSettings {
public fontSize: number = 14; public fontSize: number = 14;
public language?: Language; public language?: Language;
public freezeViewports: boolean = false; public freezeViewports: boolean = false;
public network: 'mainnet' | 'testnet' | undefined = 'mainnet'; public network: 'mainnet' | 'testnet' | undefined = undefined;
public coordinator: Coordinator | undefined = undefined; public coordinator: Coordinator | undefined = undefined;
public host?: string; public host?: string;
public unsafeClient: boolean = false; public unsafeClient: boolean = false;