diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js
index 8d028514b..0d1d08166 100644
--- a/api/resolvers/wallet.js
+++ b/api/resolvers/wallet.js
@@ -63,9 +63,9 @@ const resolvers = {
export default resolvers
-export async function createWithdrawal (parent, { invoice, maxFee }, { me, models, lnd, headers, protocol, logger }) {
+export async function createWithdrawal (parent, { invoice, maxFee, amount }, { me, models, lnd, headers, protocol, logger }) {
assertApiKeyNotPermitted({ me })
- await validateSchema(withdrawlSchema, { invoice, maxFee })
+ await validateSchema(withdrawlSchema, { invoice, maxFee, amount })
await assertGofacYourself({ models, headers })
// remove 'lightning:' prefix if present
@@ -95,7 +95,10 @@ export async function createWithdrawal (parent, { invoice, maxFee }, { me, model
}
if (!decoded.mtokens || BigInt(decoded.mtokens) <= 0) {
- throw new GqlInputError('invoice must specify an amount')
+ if (!amount) {
+ throw new GqlInputError('invoice must specify an amount')
+ }
+ decoded.mtokens = BigInt(amount) * 1000n
}
if (decoded.mtokens > Number.MAX_SAFE_INTEGER) {
diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js
index 95d4640eb..5ced5075f 100644
--- a/api/typeDefs/wallet.js
+++ b/api/typeDefs/wallet.js
@@ -13,7 +13,7 @@ const typeDefs = gql`
}
extend type Mutation {
- createWithdrawl(invoice: String!, maxFee: Int!): PayIn!
+ createWithdrawl(invoice: String!, maxFee: Int!, amount: Int): PayIn!
sendToLnAddr(addr: String!, amount: Int!, maxFee: Int!, comment: String, identifier: Boolean, name: String, email: String): PayIn!
dropBolt11(hash: String!): Boolean
buyCredits(credits: Int!): PayIn!
diff --git a/fragments/withdrawal.js b/fragments/withdrawal.js
index 4df98ca03..38cf002df 100644
--- a/fragments/withdrawal.js
+++ b/fragments/withdrawal.js
@@ -1,8 +1,8 @@
import { gql } from '@apollo/client'
export const CREATE_WITHDRAWL = gql`
- mutation createWithdrawl($invoice: String!, $maxFee: Int!) {
- createWithdrawl(invoice: $invoice, maxFee: $maxFee) {
+ mutation createWithdrawl($invoice: String!, $maxFee: Int!, $amount: Int) {
+ createWithdrawl(invoice: $invoice, maxFee: $maxFee, amount: $amount) {
id
}
}`
diff --git a/lib/validate.js b/lib/validate.js
index dc6d47ce5..3de0486e4 100644
--- a/lib/validate.js
+++ b/lib/validate.js
@@ -490,7 +490,8 @@ export const lastAuthRemovalSchema = object({
export const withdrawlSchema = object({
invoice: string().required('required').trim(),
- maxFee: intValidator.required('required').min(0, 'must be at least 0')
+ maxFee: intValidator.required('required').min(0, 'must be at least 0'),
+ amount: intValidator.optional().min(1, 'must be at least 1 sat')
})
export const bioSchema = object({
diff --git a/pages/withdraw.js b/pages/withdraw.js
index 4cdc3280f..dcb0984cc 100644
--- a/pages/withdraw.js
+++ b/pages/withdraw.js
@@ -7,7 +7,7 @@ import styles from '@/styles/nav.module.css'
import { useMutation } from '@apollo/client'
import { CREATE_WITHDRAWL, SEND_TO_LNADDR } from '@/fragments/withdrawal'
import { requestProvider } from 'webln'
-import { useEffect, useState } from 'react'
+import { useEffect, useState, useCallback } from 'react'
import { useMe } from '@/components/me'
import { Checkbox, Form, Input, InputUserSuggest, SubmitButton } from '@/components/form'
import { lnAddrSchema, withdrawlSchema } from '@/lib/validate'
@@ -82,6 +82,15 @@ export function InvWithdrawal () {
const [createWithdrawl] = useMutation(CREATE_WITHDRAWL)
const maxFeeDefault = me?.privates?.withdrawMaxFeeDefault
+ const [zeroAmount, setZeroAmount] = useState(false)
+ const checkInvoice = useCallback((invoice) => {
+ try {
+ const decoded = decode(invoice)
+ setZeroAmount(!decoded.mtokens || BigInt(decoded.mtokens) <= 0)
+ } catch {
+ setZeroAmount(false)
+ }
+ }, [])
useEffect(() => {
async function effect () {
@@ -106,11 +115,14 @@ export function InvWithdrawal () {
autoComplete='off'
initial={{
invoice: '',
- maxFee: maxFeeDefault
+ maxFee: maxFeeDefault,
+ amount: ''
}}
schema={withdrawlSchema}
- onSubmit={async ({ invoice, maxFee }) => {
- const { data } = await createWithdrawl({ variables: { invoice, maxFee: Number(maxFee) } })
+ onSubmit={async ({ invoice, maxFee, amount }) => {
+ const variables = { invoice, maxFee: Number(maxFee) }
+ if (zeroAmount) variables.amount = Number(amount)
+ const { data } = await createWithdrawl({ variables })
router.push(`/transactions/${data.createWithdrawl.id}`)
}}
>
@@ -120,8 +132,18 @@ export function InvWithdrawal () {
required
autoFocus
clear
- append={}
+ append={}
+ onChange={(_, e) => { checkInvoice(e.target.value) }}
/>
+ {zeroAmount && (
+
+ )}
{
result = result.toLowerCase()
- if (result.split('lightning=')[1]) {
- helpers.setValue(result.split('lightning=')[1].split(/[&?]/)[0])
- } else if (decode(result.replace(/^lightning:/, ''))) {
- helpers.setValue(result.replace(/^lightning:/, ''))
+ let invoice
+ if (result.includes('lightning=')) {
+ invoice = result.split('lightning=')[1].split(/[&?]/)[0]
+ helpers.setValue(invoice)
} else {
- throw new Error('Not a proper lightning payment request')
+ try {
+ invoice = result.replace(/^lightning:/, '')
+ decode(invoice)
+ helpers.setValue(invoice)
+ } catch {
+ toaster.danger('Not a proper lightning payment request')
+ onClose()
+ return
+ }
}
+ if (onInvoiceChange) onInvoiceChange(invoice)
onClose()
}}
styles={{