diff --git a/api/lnd/index.js b/api/lnd/index.js index 6d4659db..3e49ce74 100644 --- a/api/lnd/index.js +++ b/api/lnd/index.js @@ -21,19 +21,24 @@ getWalletInfo({ lnd }, (err, result) => { export async function estimateRouteFee ({ lnd, destination, tokens, mtokens, request, timeout }) { return await new Promise((resolve, reject) => { + const params = {} + if (request) { + params.payment_request = request + } else { + params.dest = Buffer.from(destination, 'hex') + params.amt_sat = tokens ? toPositiveNumber(tokens) : toPositiveNumber(BigInt(mtokens) / BigInt(1e3)) + } + lnd.router.estimateRouteFee({ - dest: Buffer.from(destination, 'hex'), - amt_sat: tokens ? toPositiveNumber(tokens) : toPositiveNumber(BigInt(mtokens) / BigInt(1e3)), - payment_request: request, + ...params, timeout }, (err, res) => { if (err) { - reject(err) - return - } - - if (res?.failure_reason) { - reject(new Error(`Unable to estimate route: ${res.failure_reason}`)) + if (res?.failure_reason) { + reject(new Error(`Unable to estimate route: ${res.failure_reason}`)) + } else { + reject(err) + } return } @@ -126,7 +131,7 @@ export const getBlockHeight = cachedFetcher(async function fetchBlockHeight ({ l export const getOurPubkey = cachedFetcher(async function fetchOurPubkey ({ lnd, ...args }) { try { - const { identity } = await getIdentity({ lnd, ...args }) + const identity = await getIdentity({ lnd, ...args }) return identity.public_key } catch (err) { throw new Error(`Unable to fetch identity: ${err.message}`) diff --git a/api/resolvers/sub.js b/api/resolvers/sub.js index 1f49e353..09279869 100644 --- a/api/resolvers/sub.js +++ b/api/resolvers/sub.js @@ -260,7 +260,7 @@ export default { const { name } = data - await ssValidate(territorySchema, data, { models, me, sub: { name } }) + await ssValidate(territorySchema, data, { models, me }) const oldSub = await models.sub.findUnique({ where: { name } }) if (!oldSub) { diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 03945fec..daa41ab8 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -482,12 +482,12 @@ const resolvers = { FROM "Withdrawl" WHERE "userId" = ${me.id} AND id = ${Number(id)} - AND now() > created_at + interval '${retention}' + AND now() > created_at + ${retention}::INTERVAL AND hash IS NOT NULL AND status IS NOT NULL ), updated_rows AS ( UPDATE "Withdrawl" - SET hash = NULL, bolt11 = NULL + SET hash = NULL, bolt11 = NULL, preimage = NULL FROM to_be_updated WHERE "Withdrawl".id = to_be_updated.id) SELECT * FROM to_be_updated;` @@ -499,7 +499,7 @@ const resolvers = { console.error(error) await models.withdrawl.update({ where: { id: invoice.id }, - data: { hash: invoice.hash, bolt11: invoice.bolt11 } + data: { hash: invoice.hash, bolt11: invoice.bolt11, preimage: invoice.preimage } }) throw new GqlInputError('failed to drop bolt11 from lnd') } diff --git a/components/wallet-logger.js b/components/wallet-logger.js index 94eda656..8855badb 100644 --- a/components/wallet-logger.js +++ b/components/wallet-logger.js @@ -12,10 +12,7 @@ import useIndexedDB from './use-indexeddb' import { SSR } from '@/lib/constants' export function WalletLogs ({ wallet, embedded }) { - const { logs, setLogs, hasMore, loadMore, loadLogs, loading } = useWalletLogs(wallet) - useEffect(() => { - loadLogs() - }, [loadLogs]) + const { logs, setLogs, hasMore, loadMore, loading } = useWalletLogs(wallet) const showModal = useShowModal() @@ -46,7 +43,7 @@ export function WalletLogs ({ wallet, embedded }) { ?
loading...
: logs.length === 0 &&
empty
} {hasMore - ? + ?
:
------ start of logs ------
} @@ -228,7 +225,7 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) { const loadMore = useCallback(async () => { if (hasMore) { setLoading(true) - const result = await loadLogsPage(page, logsPerPage, wallet) + const result = await loadLogsPage(page + 1, logsPerPage, wallet) setLogs(prevLogs => [...prevLogs, ...result.data]) setHasMore(result.hasMore) setTotal(result.total) @@ -247,5 +244,9 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) { setLoading(false) }, [wallet, loadLogsPage]) + useEffect(() => { + loadLogs() + }, [wallet]) + return { logs, hasMore, total, loadMore, loadLogs, setLogs, loading } } diff --git a/docker/lnd/Dockerfile b/docker/lnd/Dockerfile index 37bac3a5..87ffafb6 100644 --- a/docker/lnd/Dockerfile +++ b/docker/lnd/Dockerfile @@ -1,4 +1,4 @@ -FROM polarlightning/lnd:0.17.5-beta +FROM polarlightning/lnd:0.18.0-beta ARG LN_NODE_FOR ENV LN_NODE_FOR=$LN_NODE_FOR diff --git a/lib/validate.js b/lib/validate.js index 00215d1a..9c53047f 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -726,7 +726,8 @@ export const lnbitsSchema = object().shape({ test: invoiceKey => adminKey !== invoiceKey, message: 'invoice key cannot be the same as admin key' }) - }) + }), + ...autowithdrawSchemaMembers // need to set order to avoid cyclic dependencies in Yup schema // see https://github.com/jquense/yup/issues/176#issuecomment-367352042 }, ['adminKey', 'invoiceKey']) @@ -745,7 +746,8 @@ export const nwcSchema = object().shape({ test: nwcUrlRecv => nwcUrlRecv !== nwcUrl, message: 'connection for receiving cannot be the same as for sending' }) - }) + }), + ...autowithdrawSchemaMembers }, ['nwcUrl', 'nwcUrlRecv']) export const blinkSchema = object({ @@ -796,7 +798,8 @@ export const phoenixdSchema = object().shape({ test: secondary => primary !== secondary, message: 'secondary password cannot be the same as primary password' }) - }) + }), + ...autowithdrawSchemaMembers }, ['primaryPassword', 'secondaryPassword']) export const bioSchema = object({ diff --git a/wallets/index.js b/wallets/index.js index a1349a85..fee17703 100644 --- a/wallets/index.js +++ b/wallets/index.js @@ -125,7 +125,8 @@ function extractConfig (fields, config, client) { const field = fields.find(({ name }) => name === key) // filter server config which isn't specified as wallet fields - if (client && (key.startsWith('autoWithdraw') || key === 'id')) return acc + // (we allow autowithdraw members to pass validation) + if (client && key === 'id') return acc // field might not exist because config.enabled doesn't map to a wallet field if (!field || (client ? isClientField(field) : isServerField(field))) { @@ -198,6 +199,9 @@ function useConfig (wallet) { if (transformedConfig) { newClientConfig = Object.assign(newClientConfig, transformedConfig) } + // these are stored on the server + delete newClientConfig.autoWithdrawMaxFeePercent + delete newClientConfig.autoWithdrawMaxFeeTotal } catch { valid = false } diff --git a/wallets/wrap.js b/wallets/wrap.js index b9e22e5c..ae63a6ed 100644 --- a/wallets/wrap.js +++ b/wallets/wrap.js @@ -36,7 +36,7 @@ export default async function wrapInvoice (bolt11, { msats, description, descrip throw new Error('Unable to decode invoice') } - console.log('invoice', inv.mtokens, inv.expires_at, inv.cltv_delta) + console.log('invoice', inv.id, inv.mtokens, inv.expires_at, inv.cltv_delta, inv.destination) // validate outgoing amount if (inv.mtokens) { @@ -77,6 +77,8 @@ export default async function wrapInvoice (bolt11, { msats, description, descrip case 49: case 149: // trampoline routing case 151: // electrum trampoline routing + case 262: + case 263: // blinded paths break default: throw new Error(`Unsupported feature bit: ${f.bit}`) diff --git a/worker/wallet.js b/worker/wallet.js index 33f6d1a7..57156b9d 100644 --- a/worker/wallet.js +++ b/worker/wallet.js @@ -346,12 +346,12 @@ export async function autoDropBolt11s ({ models, lnd }) { SELECT id, hash, bolt11 FROM "Withdrawl" WHERE "userId" IN (SELECT id FROM users WHERE "autoDropBolt11s") - AND now() > created_at + interval '${retention}' + AND now() > created_at + ${retention}::INTERVAL AND hash IS NOT NULL AND status IS NOT NULL ), updated_rows AS ( UPDATE "Withdrawl" - SET hash = NULL, bolt11 = NULL + SET hash = NULL, bolt11 = NULL, preimage = NULL FROM to_be_updated WHERE "Withdrawl".id = to_be_updated.id) SELECT * FROM to_be_updated;` @@ -364,7 +364,7 @@ export async function autoDropBolt11s ({ models, lnd }) { console.error(`Error removing invoice with hash ${invoice.hash}:`, error) await models.withdrawl.update({ where: { id: invoice.id }, - data: { hash: invoice.hash, bolt11: invoice.bolt11 } + data: { hash: invoice.hash, bolt11: invoice.bolt11, preimage: invoice.preimage } }) } }