From 6aac9eeed48215f8fa2f8308b9d1686bd2819cc9 Mon Sep 17 00:00:00 2001 From: k00b Date: Thu, 17 Oct 2024 13:25:49 -0500 Subject: [PATCH 01/12] update breaking change in estimateRouteFee --- api/lnd/index.js | 23 ++++++++++++++--------- docker/lnd/Dockerfile | 2 +- wallets/wrap.js | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/api/lnd/index.js b/api/lnd/index.js index 6d4659db..94264daf 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 } 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/wallets/wrap.js b/wallets/wrap.js index b9e22e5c..410582ba 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) { From d91c5c90def087609e041cb9648d46619f40f8f1 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Thu, 17 Oct 2024 21:14:04 +0200 Subject: [PATCH 02/12] Fix infinite loop of loading wallet logs --- components/wallet-logger.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/components/wallet-logger.js b/components/wallet-logger.js index 94eda656..9414166b 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() @@ -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 } } From 70858b97f7303003646708cb3fb8950ca3d4abdc Mon Sep 17 00:00:00 2001 From: ekzyis Date: Thu, 17 Oct 2024 21:22:45 +0200 Subject: [PATCH 03/12] Center more button --- components/wallet-logger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/wallet-logger.js b/components/wallet-logger.js index 9414166b..6f07cea8 100644 --- a/components/wallet-logger.js +++ b/components/wallet-logger.js @@ -43,7 +43,7 @@ export function WalletLogs ({ wallet, embedded }) { ?
loading...
: logs.length === 0 &&
empty
} {hasMore - ? + ?
:
------ start of logs ------
} From aba212f6ec0f353f74c75da326cefa7554b2819c Mon Sep 17 00:00:00 2001 From: k00b Date: Thu, 17 Oct 2024 14:23:03 -0500 Subject: [PATCH 04/12] don't abort on blinded path feature bits --- wallets/wrap.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wallets/wrap.js b/wallets/wrap.js index 410582ba..ae63a6ed 100644 --- a/wallets/wrap.js +++ b/wallets/wrap.js @@ -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}`) From ab1104e115125abd56edc82eae37c87debb729ce Mon Sep 17 00:00:00 2001 From: ekzyis Date: Fri, 18 Oct 2024 14:19:40 +0200 Subject: [PATCH 05/12] Fix lnaddr withdrawals --- api/lnd/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/lnd/index.js b/api/lnd/index.js index 94264daf..3e49ce74 100644 --- a/api/lnd/index.js +++ b/api/lnd/index.js @@ -131,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}`) From 49ddace73f29dab53d1262a7068ab990b3d9e19f Mon Sep 17 00:00:00 2001 From: ekzyis Date: Fri, 18 Oct 2024 15:10:27 +0200 Subject: [PATCH 06/12] Fix first page of wallet logs loaded twice --- components/wallet-logger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/wallet-logger.js b/components/wallet-logger.js index 6f07cea8..8855badb 100644 --- a/components/wallet-logger.js +++ b/components/wallet-logger.js @@ -225,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) From 6cc49e937b89fb3ea5f8d1c76e2cf68b9c662c6b Mon Sep 17 00:00:00 2001 From: ekzyis Date: Fri, 18 Oct 2024 18:57:39 +0200 Subject: [PATCH 07/12] Fix missing autowithdraw settings validation --- lib/validate.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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({ From bcd8adae4551bee636c3390dc9de94a6577b2b86 Mon Sep 17 00:00:00 2001 From: k00b Date: Fri, 18 Oct 2024 20:20:45 -0500 Subject: [PATCH 08/12] fix interval in sql template --- api/resolvers/wallet.js | 2 +- worker/wallet.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 03945fec..e73da998 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -482,7 +482,7 @@ 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 ( diff --git a/worker/wallet.js b/worker/wallet.js index 33f6d1a7..329058e7 100644 --- a/worker/wallet.js +++ b/worker/wallet.js @@ -346,7 +346,7 @@ 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 ( From 01580d9ee812f0cb5a1424b62982dad2227c6208 Mon Sep 17 00:00:00 2001 From: k00b Date: Sat, 19 Oct 2024 09:51:24 -0500 Subject: [PATCH 09/12] delete primage when invoice is deleted --- api/resolvers/wallet.js | 4 ++-- worker/wallet.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index e73da998..daa41ab8 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -487,7 +487,7 @@ const resolvers = { 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/worker/wallet.js b/worker/wallet.js index 329058e7..57156b9d 100644 --- a/worker/wallet.js +++ b/worker/wallet.js @@ -351,7 +351,7 @@ export async function autoDropBolt11s ({ models, lnd }) { 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 } }) } } From 69c80e3d5cb8441e071e78a13ea16b1b60e6596e Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 19 Oct 2024 22:33:37 +0200 Subject: [PATCH 10/12] Fix wallet client validation --- wallets/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wallets/index.js b/wallets/index.js index a1349a85..243a59dd 100644 --- a/wallets/index.js +++ b/wallets/index.js @@ -125,7 +125,7 @@ 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 + 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 +198,9 @@ function useConfig (wallet) { if (transformedConfig) { newClientConfig = Object.assign(newClientConfig, transformedConfig) } + + delete newClientConfig.autoWithdrawMaxFeePercent + delete newClientConfig.autoWithdrawMaxFeeTotal } catch { valid = false } From 1f9ab08228349760cb0715320e7a2e8e8c6ee92d Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 19 Oct 2024 22:36:26 +0200 Subject: [PATCH 11/12] Add comments --- wallets/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wallets/index.js b/wallets/index.js index 243a59dd..fee17703 100644 --- a/wallets/index.js +++ b/wallets/index.js @@ -125,6 +125,7 @@ function extractConfig (fields, config, client) { const field = fields.find(({ name }) => name === key) // filter server config which isn't specified as wallet fields + // (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 @@ -198,7 +199,7 @@ function useConfig (wallet) { if (transformedConfig) { newClientConfig = Object.assign(newClientConfig, transformedConfig) } - + // these are stored on the server delete newClientConfig.autoWithdrawMaxFeePercent delete newClientConfig.autoWithdrawMaxFeeTotal } catch { From 50e153df7cf2699c9107c8134935e3a09a3ef972 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 20 Oct 2024 01:25:25 +0200 Subject: [PATCH 12/12] Fix territory unarchive schema validation --- api/resolvers/sub.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) {