Various LUD-18 fixes

* Debounce the `onAddrChange` event handler when sending to a LN Address,
so we more accurately display the input form for LUD-12 and LUD-18 options

* Remove explicit URI encoding of Payer Data when sending to a LN Addr, since we're getting encoding for free via URLSearchParams

* Append `@stacker.news` to identifier values sent in payer data

* Don't do extra decoding when receiving LUD-18 data
This commit is contained in:
Satoshi Nakamoto 2023-10-05 10:27:01 -04:00
parent c77d761ab6
commit e9c0c06779
5 changed files with 12 additions and 9 deletions

View File

@ -290,7 +290,7 @@ export default {
if (payer) { if (payer) {
payer = { payer = {
...payer, ...payer,
identifier: payer.identifier ? me.name : undefined identifier: payer.identifier ? `${me.name}@stacker.news` : undefined
} }
payer = Object.fromEntries( payer = Object.fromEntries(
Object.entries(payer).filter(([, value]) => !!value) Object.entries(payer).filter(([, value]) => !!value)
@ -305,10 +305,10 @@ export default {
callback.searchParams.append('comment', comment) callback.searchParams.append('comment', comment)
} }
let encodedPayerData = '' let stringifiedPayerData = ''
if (payer && Object.entries(payer).length) { if (payer && Object.entries(payer).length) {
encodedPayerData = encodeURIComponent(JSON.stringify(payer)) stringifiedPayerData = JSON.stringify(payer)
callback.searchParams.append('payerdata', encodedPayerData) callback.searchParams.append('payerdata', stringifiedPayerData)
} }
// call callback with amount and conditionally comment // call callback with amount and conditionally comment
@ -320,7 +320,7 @@ export default {
// decode invoice // decode invoice
try { try {
const decoded = await decodePaymentRequest({ lnd, request: res.pr }) const decoded = await decodePaymentRequest({ lnd, request: res.pr })
if (decoded.description_hash !== lnurlPayDescriptionHash(`${options.metadata}${encodedPayerData}`)) { if (decoded.description_hash !== lnurlPayDescriptionHash(`${options.metadata}${stringifiedPayerData}`)) {
throw new Error('description hash does not match') throw new Error('description hash does not match')
} }
if (!decoded.mtokens || BigInt(decoded.mtokens) !== BigInt(milliamount)) { if (!decoded.mtokens || BigInt(decoded.mtokens) !== BigInt(milliamount)) {

1
package-lock.json generated
View File

@ -36,6 +36,7 @@
"graphql-type-json": "^0.3.2", "graphql-type-json": "^0.3.2",
"jose1": "npm:jose@^1.27.2", "jose1": "npm:jose@^1.27.2",
"ln-service": "^56.11.0", "ln-service": "^56.11.0",
"lodash.debounce": "^4.0.8",
"mathjs": "^11.9.1", "mathjs": "^11.9.1",
"mdast-util-find-and-replace": "^3.0.0", "mdast-util-find-and-replace": "^3.0.0",
"mdast-util-from-markdown": "^2.0.0", "mdast-util-from-markdown": "^2.0.0",

View File

@ -39,6 +39,7 @@
"graphql-type-json": "^0.3.2", "graphql-type-json": "^0.3.2",
"jose1": "npm:jose@^1.27.2", "jose1": "npm:jose@^1.27.2",
"ln-service": "^56.11.0", "ln-service": "^56.11.0",
"lodash.debounce": "^4.0.8",
"mathjs": "^11.9.1", "mathjs": "^11.9.1",
"mdast-util-find-and-replace": "^3.0.0", "mdast-util-find-and-replace": "^3.0.0",
"mdast-util-from-markdown": "^2.0.0", "mdast-util-from-markdown": "^2.0.0",

View File

@ -50,7 +50,7 @@ export default async ({ query: { username, amount, nostr, comment, payerdata: pa
let parsedPayerData let parsedPayerData
if (payerData) { if (payerData) {
try { try {
parsedPayerData = JSON.parse(decodeURIComponent(payerData)) parsedPayerData = JSON.parse(payerData)
} catch (err) { } catch (err) {
console.error('failed to parse payerdata', err) console.error('failed to parse payerdata', err)
return res.status(400).json({ status: 'ERROR', reason: 'Invalid JSON supplied for payerdata parameter' }) return res.status(400).json({ status: 'ERROR', reason: 'Invalid JSON supplied for payerdata parameter' })

View File

@ -8,7 +8,7 @@ import { CenterLayout } from '../components/layout'
import InputGroup from 'react-bootstrap/InputGroup' import InputGroup from 'react-bootstrap/InputGroup'
import { WithdrawlSkeleton } from './withdrawals/[id]' import { WithdrawlSkeleton } from './withdrawals/[id]'
import { useMe } from '../components/me' import { useMe } from '../components/me'
import { useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { requestProvider } from 'webln' import { requestProvider } from 'webln'
import Alert from 'react-bootstrap/Alert' import Alert from 'react-bootstrap/Alert'
import { CREATE_WITHDRAWL, SEND_TO_LNADDR } from '../fragments/wallet' import { CREATE_WITHDRAWL, SEND_TO_LNADDR } from '../fragments/wallet'
@ -21,6 +21,7 @@ import styles from '../components/user-header.module.css'
import HiddenWalletSummary from '../components/hidden-wallet-summary' import HiddenWalletSummary from '../components/hidden-wallet-summary'
import AccordianItem from '../components/accordian-item' import AccordianItem from '../components/accordian-item'
import { lnAddrOptions } from '../lib/lnurl' import { lnAddrOptions } from '../lib/lnurl'
import debounce from 'lodash.debounce'
export const getServerSideProps = getGetServerSideProps({ authRequired: true }) export const getServerSideProps = getGetServerSideProps({ authRequired: true })
@ -300,7 +301,7 @@ export function LnAddrWithdrawal () {
const [addrOptions, setAddrOptions] = useState(defaultOptions) const [addrOptions, setAddrOptions] = useState(defaultOptions)
const [formSchema, setFormSchema] = useState(lnAddrSchema()) const [formSchema, setFormSchema] = useState(lnAddrSchema())
const onAddrChange = async (formik, e) => { const onAddrChange = useCallback(debounce(async (formik, e) => {
let options let options
try { try {
options = await lnAddrOptions(e.target.value) options = await lnAddrOptions(e.target.value)
@ -312,7 +313,7 @@ export function LnAddrWithdrawal () {
setAddrOptions(options) setAddrOptions(options)
setFormSchema(lnAddrSchema(options)) setFormSchema(lnAddrSchema(options))
} }, 500), [lnAddrOptions, lnAddrSchema])
return ( return (
<> <>