From ffc1f225d30c4b042985a0bf682d82f1d0300afc Mon Sep 17 00:00:00 2001 From: Dillon Date: Sat, 17 Feb 2024 19:39:42 -0600 Subject: [PATCH 01/23] added type to enum and mirrored LND functionality. Not working yet --- api/resolvers/wallet.js | 35 ++++- api/typeDefs/wallet.js | 1 + fragments/wallet.js | 7 + lib/validate.js | 13 ++ pages/settings/wallets/core-lightning.js | 121 ++++++++++++++++++ pages/settings/wallets/index.js | 4 +- .../migration.sql | 21 +++ prisma/schema.prisma | 13 ++ 8 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 pages/settings/wallets/core-lightning.js create mode 100644 prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 9e3d025f1..6526767f3 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -7,11 +7,12 @@ import lnpr from 'bolt11' import { SELECT } from './item' import { lnAddrOptions } from '../../lib/lnurl' import { msatsToSats, msatsToSatsDecimal } from '../../lib/format' -import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '../../lib/validate' +import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema, CoreLightningAutowithdrawSchema } from '../../lib/validate' import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT } from '../../lib/constants' import { datePivot } from '../../lib/time' import assertGofacYourself from './ofac' import { HEX_REGEX } from '../../lib/macaroon' +// import LightningClient from 'lightning-client' export async function getInvoice (parent, { id }, { me, models, lnd }) { const inv = await models.invoice.findUnique({ @@ -437,6 +438,38 @@ export default { }, { settings, data }, { me, models }) }, + + upsertWalletCoreLightning: async (parent, { settings, ...data }, { me, models }) => { + // store hex inputs as base64 + if (HEX_REGEX.test(data.macaroon)) { + data.macaroon = Buffer.from(data.macaroon, 'hex').toString('base64') + } + if (HEX_REGEX.test(data.cert)) { + data.cert = Buffer.from(data.cert, 'hex').toString('base64') + } + + return await upsertWallet( + { + schema: CoreLightningAutowithdrawSchema, + walletName: 'walletCoreLightning', + walletType: 'CORE_LIGHTNING', + testConnect: async ({ cert, macaroon, socket }) => { + const { lnd } = await authenticatedLndGrpc({ + cert, + macaroon, + socket + }) + return await createInvoice({ + description: 'SN connection test', + lnd, + tokens: 0, + expires_at: new Date() + }) + } + }, + { settings, data }, { me, models }) + }, + upsertWalletLNAddr: async (parent, { settings, ...data }, { me, models }) => { return await upsertWallet( { diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js index c2cca6aef..4887d1f3e 100644 --- a/api/typeDefs/wallet.js +++ b/api/typeDefs/wallet.js @@ -19,6 +19,7 @@ export default gql` cancelInvoice(hash: String!, hmac: String!): Invoice! dropBolt11(id: ID): Withdrawl upsertWalletLND(id: ID, socket: String!, macaroon: String!, cert: String, settings: AutowithdrawSettings!): Boolean + upsertWalletCoreLightning(id: ID, socket: String!, macaroon: String!, cert: String, settings: AutowithdrawSettings!): Boolean upsertWalletLNAddr(id: ID, address: String!, settings: AutowithdrawSettings!): Boolean removeWallet(id: ID!): Boolean } diff --git a/fragments/wallet.js b/fragments/wallet.js index f1a3c09e3..17c9e931f 100644 --- a/fragments/wallet.js +++ b/fragments/wallet.js @@ -89,6 +89,13 @@ mutation upsertWalletLND($id: ID, $socket: String!, $macaroon: String!, $cert: S } ` +export const UPSERT_WALLET_CORE_LIGHTNING = +gql` +mutation upsertWalletLND($id: ID, $socket: String!, $macaroon: String!, $cert: String, $settings: AutowithdrawSettings!) { + upsertWalletLND(id: $id, socket: $socket, macaroon: $macaroon, cert: $cert, settings: $settings) +} +` + export const REMOVE_WALLET = gql` mutation removeWallet($id: ID!) { diff --git a/lib/validate.js b/lib/validate.js index c2afc5f77..f8ee98ba8 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -320,6 +320,19 @@ export function LNDAutowithdrawSchema ({ me } = {}) { }) } +export function CoreLightningAutowithdrawSchema ({ me } = {}) { + return object({ + socket: string().socket().required('required'), + macaroon: hexOrBase64Validator.required('required').test({ + name: 'macaroon', + test: v => isInvoiceMacaroon(v) || isInvoicableMacaroon(v), + message: 'not an invoice macaroon' + }), + cert: hexOrBase64Validator, + ...autowithdrawSchemaMembers({ me }) + }) +} + export function autowithdrawSchemaMembers ({ me } = {}) { return { priority: boolean(), diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js new file mode 100644 index 000000000..62fab7a31 --- /dev/null +++ b/pages/settings/wallets/core-lightning.js @@ -0,0 +1,121 @@ +import { getGetServerSideProps } from '../../../api/ssrApollo' +import { Form, Input } from '../../../components/form' +import { CenterLayout } from '../../../components/layout' +import { useMe } from '../../../components/me' +import { WalletButtonBar, WalletCard } from '../../../components/wallet-card' +import { useMutation } from '@apollo/client' +import { useToast } from '../../../components/toast' +import { CoreLightningAutowithdrawSchema } from '../../../lib/validate' +import { useRouter } from 'next/router' +import { AutowithdrawSettings, autowithdrawInitial } from '../../../components/autowithdraw-shared' +import { REMOVE_WALLET, UPSERT_WALLET_CORE_LIGHTNING, WALLET_BY_TYPE } from '../../../fragments/wallet' +import Info from '../../../components/info' +import Text from '../../../components/text' + +const variables = { type: 'CORE_LIGHTNING' } +export const getServerSideProps = getGetServerSideProps({ query: WALLET_BY_TYPE, variables, authRequired: true }) + +export default function CoreLightning ({ ssrData }) { + const me = useMe() + const toaster = useToast() + const router = useRouter() + const [upsertWalletCoreLightning] = useMutation(UPSERT_WALLET_CORE_LIGHTNING) + const [removeWallet] = useMutation(REMOVE_WALLET) + + const { walletByType: wallet } = ssrData || {} + + return ( + +

Core Lightning

+
autowithdraw to your Core Lightning node
+
{ + try { + await upsertWalletCoreLightning({ + variables: { + id: wallet?.id, + socket, + macaroon, + cert, + settings: { + ...settings, + autoWithdrawThreshold: Number(settings.autoWithdrawThreshold), + autoWithdrawMaxFeePercent: Number(settings.autoWithdrawMaxFeePercent) + } + } + }) + toaster.success('saved settings') + router.push('/settings/wallets') + } catch (err) { + console.error(err) + toaster.danger('failed to attach: ' + err.message || err.toString?.()) + } + }} + > + + invoice macaroon + + + {"We accept a prebaked ***invoice.macaroon*** for your convenience. To gain better privacy, generate a new macaroon as follows:\n\n```lightning-cli createrune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```"} + + + + } + name='macaroon' + clear + hint='hex or base64 encoded' + placeholder='AgEDbG5kAlgDChCn7YgfWX7uTkQQgXZ2uahNEgEwGhYKB2FkZHJlc3MSBHJlYWQSBXdyaXRlGhcKCGludm9pY2VzEgRyZWFkEgV3cml0ZRoPCgdvbmNoYWluEgRyZWFkAAAGIJkMBrrDV0npU90JV0TGNJPrqUD8m2QYoTDjolaL6eBs' + required + /> + cert optional if from CA (e.g. voltage)} + name='cert' + clear + hint='hex or base64 encoded' + placeholder='LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNNVENDQWRpZ0F3SUJBZ0lRSHBFdFdrcGJwZHV4RVF2eVBPc3NWVEFLQmdncWhrak9QUVFEQWpBdk1SOHcKSFFZRFZRUUtFeFpzYm1RZ1lYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3SGhjTgpNalF3TVRBM01qQXhORE0wV2hjTk1qVXdNekF6TWpBeE5ETTBXakF2TVI4d0hRWURWUVFLRXhac2JtUWdZWFYwCmIyZGxibVZ5WVhSbFpDQmpaWEowTVF3d0NnWURWUVFERXdOaWIySXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJUS3NMVk5oZnhqb1FLVDlkVVdDbzUzSmQwTnBuL1BtYi9LUE02M1JxbU52dFYvdFk4NjJJZwpSbE41cmNHRnBEajhUeFc2OVhIK0pTcHpjWDdlN3N0Um80SFZNSUhTTUE0R0ExVWREd0VCL3dRRUF3SUNwREFUCkJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVDAKMnh3V25GeHRUNzI0MWxwZlNoNm9FWi9UMWpCN0JnTlZIUkVFZERCeWdnTmliMktDQ1d4dlkyRnNhRzl6ZElJRApZbTlpZ2d4d2IyeGhjaTF1TVMxaWIyS0NGR2h2YzNRdVpHOWphMlZ5TG1sdWRHVnlibUZzZ2dSMWJtbDRnZ3AxCmJtbDRjR0ZqYTJWMGdnZGlkV1pqYjI1dWh3Ui9BQUFCaHhBQUFBQUFBQUFBQUFBQUFBQUFBQUFCaHdTc0VnQUQKTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUEwUTlkRXdoNXpPRnpwL3hYeHNpemh5SkxNVG5yazU1VWx1NHJPRwo4WW52QWlBVGt4U3p3Y3hZZnFscGx0UlNIbmd0NUJFcDBzcXlHL05nenBzb2pmMGNqQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K' + /> + + { + try { + await removeWallet({ variables: { id: wallet?.id } }) + toaster.success('saved settings') + router.push('/settings/wallets') + } catch (err) { + console.error(err) + toaster.danger('failed to unattach:' + err.message || err.toString?.()) + } + }} + /> + +
+ ) +} + +export function CoreLightningCard ({ wallet }) { + return ( + + ) +} diff --git a/pages/settings/wallets/index.js b/pages/settings/wallets/index.js index a9ffe44ce..3280fd64d 100644 --- a/pages/settings/wallets/index.js +++ b/pages/settings/wallets/index.js @@ -9,6 +9,7 @@ import { LNDCard } from './lnd' import { WALLETS } from '../../../fragments/wallet' import { useQuery } from '@apollo/client' import PageLoading from '../../../components/page-loading' +import { CoreLightningCard } from './core-lightning' export const getServerSideProps = getGetServerSideProps({ query: WALLETS, authRequired: true }) @@ -19,6 +20,7 @@ export default function Wallet ({ ssrData }) { const { wallets } = data || ssrData const lnd = wallets.find(w => w.type === 'LND') const lnaddr = wallets.find(w => w.type === 'LIGHTNING_ADDRESS') + const coreLightning = wallets.find(w => w.type === 'CORE_LIGHTNING') return ( @@ -30,7 +32,7 @@ export default function Wallet ({ ssrData }) { - + diff --git a/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql b/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql new file mode 100644 index 000000000..7911ad825 --- /dev/null +++ b/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql @@ -0,0 +1,21 @@ +ALTER TYPE "WalletType" ADD VALUE 'CORE_LIGHTNING'; + +CREATE TABLE "WalletCoreLightning" ( + "id" SERIAL NOT NULL, + "walletId" INTEGER NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "socket" TEXT NOT NULL, + "macaroon" TEXT NOT NULL, + "cert" TEXT, + + CONSTRAINT "WalletCoreLightning_pkey" PRIMARY KEY ("id") +); + +CREATE UNIQUE INDEX "WalletCoreLightning_walletId_key" ON "WalletCoreLightning"("walletId"); + +ALTER TABLE "WalletCoreLightning" ADD CONSTRAINT "WalletCoreLightning_walletId_fkey" FOREIGN KEY ("walletId") REFERENCES "Wallet"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +CREATE TRIGGER wallet_core_lightning_as_jsonb +AFTER INSERT OR UPDATE ON "WalletCoreLightning" +FOR EACH ROW EXECUTE PROCEDURE wallet_wallet_type_as_jsonb(); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d3e5c16c7..8e3878e81 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -123,6 +123,7 @@ model User { enum WalletType { LIGHTNING_ADDRESS LND + CORE_LIGHTNING } model Wallet { @@ -144,6 +145,7 @@ model Wallet { wallet Json? @db.JsonB walletLightningAddress WalletLightningAddress? walletLND WalletLND? + walletCoreLightning WalletCoreLightning? @@index([userId]) } @@ -168,6 +170,17 @@ model WalletLND { cert String? } +model WalletCoreLightning { + id Int @id @default(autoincrement()) + walletId Int @unique + wallet Wallet @relation(fields: [walletId], references: [id], onDelete: Cascade) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @default(now()) @updatedAt @map("updated_at") + socket String + macaroon String + cert String? +} + model Mute { muterId Int mutedId Int From ac857ac27032ebab71ba66c93de4c8c154db7011 Mon Sep 17 00:00:00 2001 From: Dillon Date: Tue, 20 Feb 2024 13:00:25 -0600 Subject: [PATCH 02/23] updated macaroon to rune and added autowithdraw functionality --- api/resolvers/wallet.js | 23 ++++++----- fragments/wallet.js | 4 +- lib/macaroon.js | 2 + lib/validate.js | 11 ++---- pages/settings/wallets/core-lightning.js | 21 ++++------ .../migration.sql | 3 +- prisma/schema.prisma | 3 +- worker/autowithdraw.js | 39 +++++++++++++++++++ 8 files changed, 66 insertions(+), 40 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 6526767f3..092ca5860 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -453,18 +453,17 @@ export default { schema: CoreLightningAutowithdrawSchema, walletName: 'walletCoreLightning', walletType: 'CORE_LIGHTNING', - testConnect: async ({ cert, macaroon, socket }) => { - const { lnd } = await authenticatedLndGrpc({ - cert, - macaroon, - socket - }) - return await createInvoice({ - description: 'SN connection test', - lnd, - tokens: 0, - expires_at: new Date() - }) + testConnect: async ({ rune, socket }) => { + const options = { + method: 'POST', + headers: { + 'content-type': 'application/json', + Rune: rune + }, + body: JSON.stringify({rune: rune}) + }; + // Returns true if rune is valid + return await fetch( socket, options) } }, { settings, data }, { me, models }) diff --git a/fragments/wallet.js b/fragments/wallet.js index 17c9e931f..cec39d188 100644 --- a/fragments/wallet.js +++ b/fragments/wallet.js @@ -91,8 +91,8 @@ mutation upsertWalletLND($id: ID, $socket: String!, $macaroon: String!, $cert: S export const UPSERT_WALLET_CORE_LIGHTNING = gql` -mutation upsertWalletLND($id: ID, $socket: String!, $macaroon: String!, $cert: String, $settings: AutowithdrawSettings!) { - upsertWalletLND(id: $id, socket: $socket, macaroon: $macaroon, cert: $cert, settings: $settings) +mutation upsertWalletCoreLightning($id: ID, $socket: String!, $rune: String!, $settings: AutowithdrawSettings!) { + upsertWalletCoreLightning(id: $id, socket: $socket, rune: $rune, settings: $settings) } ` diff --git a/lib/macaroon.js b/lib/macaroon.js index ab2798f31..3d30f8095 100644 --- a/lib/macaroon.js +++ b/lib/macaroon.js @@ -7,6 +7,7 @@ export const B64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9 export const HEX_REGEX = /^[0-9a-fA-F]+$/ function decodeMacaroon (macaroon) { + console.log(macaroon) if (HEX_REGEX.test(macaroon)) { return importMacaroon(Buffer.from(macaroon, 'hex')) } @@ -26,6 +27,7 @@ function macaroonOPs (macaroon) { if (macJson.i64) { const identBytes = Buffer.from(base64ToBytes(macJson.i64)) if (identBytes[0] === 0x03) { + console.log('macaroonOPs:', MacaroonId.decode(identBytes).toJSON()) const id = MacaroonId.decode(identBytes.slice(1)) return id.toJSON().ops } diff --git a/lib/validate.js b/lib/validate.js index f8ee98ba8..ddb9fc2cf 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -321,16 +321,11 @@ export function LNDAutowithdrawSchema ({ me } = {}) { } export function CoreLightningAutowithdrawSchema ({ me } = {}) { + //TODO: impliment core lightning rest api functionality return object({ socket: string().socket().required('required'), - macaroon: hexOrBase64Validator.required('required').test({ - name: 'macaroon', - test: v => isInvoiceMacaroon(v) || isInvoicableMacaroon(v), - message: 'not an invoice macaroon' - }), - cert: hexOrBase64Validator, - ...autowithdrawSchemaMembers({ me }) - }) + rune: hexOrBase64Validator.required('required') + }) } export function autowithdrawSchemaMembers ({ me } = {}) { diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index 62fab7a31..1b3ba3f67 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -28,22 +28,22 @@ export default function CoreLightning ({ ssrData }) {

Core Lightning

autowithdraw to your Core Lightning node
+
You must have CLNRest working on your node. More info here.
+
{ + onSubmit={async ({ socket, rune, ...settings }) => { try { await upsertWalletCoreLightning({ variables: { id: wallet?.id, socket, - macaroon, - cert, + rune, settings: { ...settings, autoWithdrawThreshold: Number(settings.autoWithdrawThreshold), @@ -70,10 +70,10 @@ export default function CoreLightning ({ ssrData }) { /> invoice macaroon +
Invoice Only Rune - {"We accept a prebaked ***invoice.macaroon*** for your convenience. To gain better privacy, generate a new macaroon as follows:\n\n```lightning-cli createrune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```"} + {"***invoice only rune*** for your convenience. To gain better privacy, generate a new rune as follows:\n\n```lightning-cli createrune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```"}
@@ -84,13 +84,6 @@ export default function CoreLightning ({ ssrData }) { placeholder='AgEDbG5kAlgDChCn7YgfWX7uTkQQgXZ2uahNEgEwGhYKB2FkZHJlc3MSBHJlYWQSBXdyaXRlGhcKCGludm9pY2VzEgRyZWFkEgV3cml0ZRoPCgdvbmNoYWluEgRyZWFkAAAGIJkMBrrDV0npU90JV0TGNJPrqUD8m2QYoTDjolaL6eBs' required /> - cert optional if from CA (e.g. voltage)} - name='cert' - clear - hint='hex or base64 encoded' - placeholder='LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNNVENDQWRpZ0F3SUJBZ0lRSHBFdFdrcGJwZHV4RVF2eVBPc3NWVEFLQmdncWhrak9QUVFEQWpBdk1SOHcKSFFZRFZRUUtFeFpzYm1RZ1lYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3SGhjTgpNalF3TVRBM01qQXhORE0wV2hjTk1qVXdNekF6TWpBeE5ETTBXakF2TVI4d0hRWURWUVFLRXhac2JtUWdZWFYwCmIyZGxibVZ5WVhSbFpDQmpaWEowTVF3d0NnWURWUVFERXdOaWIySXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJUS3NMVk5oZnhqb1FLVDlkVVdDbzUzSmQwTnBuL1BtYi9LUE02M1JxbU52dFYvdFk4NjJJZwpSbE41cmNHRnBEajhUeFc2OVhIK0pTcHpjWDdlN3N0Um80SFZNSUhTTUE0R0ExVWREd0VCL3dRRUF3SUNwREFUCkJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVDAKMnh3V25GeHRUNzI0MWxwZlNoNm9FWi9UMWpCN0JnTlZIUkVFZERCeWdnTmliMktDQ1d4dlkyRnNhRzl6ZElJRApZbTlpZ2d4d2IyeGhjaTF1TVMxaWIyS0NGR2h2YzNRdVpHOWphMlZ5TG1sdWRHVnlibUZzZ2dSMWJtbDRnZ3AxCmJtbDRjR0ZqYTJWMGdnZGlkV1pqYjI1dWh3Ui9BQUFCaHhBQUFBQUFBQUFBQUFBQUFBQUFBQUFCaHdTc0VnQUQKTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUEwUTlkRXdoNXpPRnpwL3hYeHNpemh5SkxNVG5yazU1VWx1NHJPRwo4WW52QWlBVGt4U3p3Y3hZZnFscGx0UlNIbmd0NUJFcDBzcXlHL05nenBzb2pmMGNqQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K' - /> { diff --git a/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql b/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql index 7911ad825..e50221ab6 100644 --- a/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql +++ b/prisma/migrations/20240216221439_add_core_lightning_to_attached_wallets/migration.sql @@ -6,8 +6,7 @@ CREATE TABLE "WalletCoreLightning" ( "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "socket" TEXT NOT NULL, - "macaroon" TEXT NOT NULL, - "cert" TEXT, + "rune" TEXT NOT NULL, CONSTRAINT "WalletCoreLightning_pkey" PRIMARY KEY ("id") ); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8e3878e81..57a23edc6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -177,8 +177,7 @@ model WalletCoreLightning { createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @default(now()) @updatedAt @map("updated_at") socket String - macaroon String - cert String? + rune String } model Mute { diff --git a/worker/autowithdraw.js b/worker/autowithdraw.js index 55010aeff..4913af728 100644 --- a/worker/autowithdraw.js +++ b/worker/autowithdraw.js @@ -124,3 +124,42 @@ async function autowithdrawLND ({ amount, maxFee }, { me, models, lnd }) { return await createWithdrawal(null, { invoice: invoice.request, maxFee }, { me, models, lnd, autoWithdraw: true }) } + +async function autowithdrawCoreLightning ({ amount, maxFee }, { me, models }) { + if (!me) { + throw new Error('me not specified') + } + + const wallet = await models.wallet.findFirst({ + where: { + userId: me.id, + type: 'CORE_LIGHTNING' + }, + include: { + walletCoreLightning: true + } + }) + + if (!wallet || !wallet.walletCoreLightning) { + throw new Error('no lightning address wallet found') + } + + const { walletCoreLightning: { rune, socket } } = wallet + const options = { + method: 'POST', + headers: { + 'content-type': 'application/json', + Rune: rune + }, + body: JSON.stringify({ + amount_msat: '20', + label: 'Stacker.News AutoWithdrawal', + description: 'Autowithdraw to Core Lightning from SN' + }) + }; + + + const invoice = await fetch(`${socket}/v1/invoice`, options) + + return await createWithdrawal(null, { invoice: invoice.payment_hash, maxFee }, { me, models, autoWithdraw: true }) +} From e8dfac694741a057ab5e2faad1450175527a9814 Mon Sep 17 00:00:00 2001 From: Dillon Date: Tue, 20 Feb 2024 13:14:31 -0600 Subject: [PATCH 03/23] removed accidental copy/paste + some linter things --- api/resolvers/wallet.js | 14 +++----------- lib/macaroon.js | 1 - 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 368519872..b63ffb2a3 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -7,7 +7,7 @@ import lnpr from 'bolt11' import { SELECT } from './item' import { lnAddrOptions } from '../../lib/lnurl' import { msatsToSats, msatsToSatsDecimal, ensureB64 } from '../../lib/format' -import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '../../lib/validate' +import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema, CoreLightningAutowithdrawSchema } from '../../lib/validate' import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT } from '../../lib/constants' import { datePivot } from '../../lib/time' import assertGofacYourself from './ofac' @@ -186,7 +186,7 @@ export default { MAX("ItemAct".created_at) AS "createdAt", FLOOR( SUM("ItemAct".msats) - * (CASE WHEN "Item"."userId" = $1 THEN${socket} + * (CASE WHEN "Item"."userId" = $1 THEN COALESCE(1 - ((SELECT SUM(pct) FROM "ItemForward" WHERE "itemId" = "Item".id) / 100.0), 1) ELSE (SELECT pct FROM "ItemForward" WHERE "itemId" = "Item".id AND "userId" = $1) / 100.0 @@ -241,7 +241,7 @@ export default { AND created_at <= $2)` ) queries.push( - `(SELECT id, created_at as "createdAt", msats, 'billing'${socket} as type, + `(SELECT id, created_at as "createdAt", msats, 'billing' as type, jsonb_build_object('subName', "SubAct"."subName") as other FROM "SubAct" WHERE "userId" = $1 AND type = 'BILLING' @@ -434,14 +434,6 @@ export default { }, upsertWalletCoreLightning: async (parent, { settings, ...data }, { me, models }) => { - // store hex inputs as base64 - if (HEX_REGEX.test(data.macaroon)) { - data.macaroon = Buffer.from(data.macaroon, 'hex').toString('base64') - } - if (HEX_REGEX.test(data.cert)) { - data.cert = Buffer.from(data.cert, 'hex').toString('base64') - } - return await upsertWallet( { schema: CoreLightningAutowithdrawSchema, diff --git a/lib/macaroon.js b/lib/macaroon.js index d90e935fd..d0137b521 100644 --- a/lib/macaroon.js +++ b/lib/macaroon.js @@ -17,7 +17,6 @@ function macaroonOPs (macaroon) { if (macJson.i64) { const identBytes = Buffer.from(base64ToBytes(macJson.i64)) if (identBytes[0] === 0x03) { - console.log('macaroonOPs:', MacaroonId.decode(identBytes).toJSON()) const id = MacaroonId.decode(identBytes.slice(1)) return id.toJSON().ops } From e7d2fca76a805d8eb0aef92f7885d4c2afeee2ec Mon Sep 17 00:00:00 2001 From: Dillon Date: Tue, 20 Feb 2024 13:20:11 -0600 Subject: [PATCH 04/23] linter fixes --- api/resolvers/wallet.js | 4 ++-- lib/validate.js | 3 +-- pages/settings/wallets/core-lightning.js | 2 +- pages/settings/wallets/index.js | 2 +- worker/autowithdraw.js | 9 ++++++--- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index b63ffb2a3..1af2a4326 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -447,9 +447,9 @@ export default { Rune: rune }, body: JSON.stringify({rune: rune}) - }; + } // Returns true if rune is valid - return await fetch( socket, options) + return await fetch(socket, options) } }, { settings, data }, { me, models }) diff --git a/lib/validate.js b/lib/validate.js index 3d3ef3389..1fd356d9d 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -329,11 +329,10 @@ export function LNDAutowithdrawSchema ({ me } = {}) { } export function CoreLightningAutowithdrawSchema ({ me } = {}) { - //TODO: impliment core lightning rest api functionality return object({ socket: string().socket().required('required'), rune: hexOrBase64Validator.required('required') - }) + }) } export function autowithdrawSchemaMembers ({ me } = {}) { diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index 1b3ba3f67..d1735a7f8 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -28,7 +28,7 @@ export default function CoreLightning ({ ssrData }) {

Core Lightning

autowithdraw to your Core Lightning node
-
You must have CLNRest working on your node. More info here.
+
You must have CLNRest working on your node. More info here.
- + diff --git a/worker/autowithdraw.js b/worker/autowithdraw.js index 4913af728..d453d1ad4 100644 --- a/worker/autowithdraw.js +++ b/worker/autowithdraw.js @@ -53,7 +53,11 @@ export async function autoWithdraw ({ data: { id }, models, lnd }) { await autowithdrawLNAddr( { amount, maxFee }, { models, me: user, lnd }) - } + } else if (wallet.type === 'CORE_LIGHTNING') { + await autowithdrawCoreLightning( + { amount, maxFee }, + { models, me: user }) + } return } catch (error) { @@ -156,8 +160,7 @@ async function autowithdrawCoreLightning ({ amount, maxFee }, { me, models }) { label: 'Stacker.News AutoWithdrawal', description: 'Autowithdraw to Core Lightning from SN' }) - }; - + } const invoice = await fetch(`${socket}/v1/invoice`, options) From 31a98b5510096c748f07c55bfc07e79d5be10eee Mon Sep 17 00:00:00 2001 From: Dillon Date: Tue, 20 Feb 2024 13:23:19 -0600 Subject: [PATCH 05/23] linter fixes --- api/resolvers/wallet.js | 4 ++-- worker/autowithdraw.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 1af2a4326..a5d3f9200 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -432,7 +432,7 @@ export default { }, { settings, data }, { me, models }) }, - + upsertWalletCoreLightning: async (parent, { settings, ...data }, { me, models }) => { return await upsertWallet( { @@ -446,7 +446,7 @@ export default { 'content-type': 'application/json', Rune: rune }, - body: JSON.stringify({rune: rune}) + body: JSON.stringify({ rune }) } // Returns true if rune is valid return await fetch(socket, options) diff --git a/worker/autowithdraw.js b/worker/autowithdraw.js index d453d1ad4..920883c43 100644 --- a/worker/autowithdraw.js +++ b/worker/autowithdraw.js @@ -57,7 +57,7 @@ export async function autoWithdraw ({ data: { id }, models, lnd }) { await autowithdrawCoreLightning( { amount, maxFee }, { models, me: user }) - } + } return } catch (error) { From c08098107b358f0056b97afce9f584abbbcef82c Mon Sep 17 00:00:00 2001 From: Dillon Date: Tue, 20 Feb 2024 15:10:34 -0600 Subject: [PATCH 06/23] updated macaroon to rune --- api/typeDefs/wallet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js index 4887d1f3e..c44c8cc5c 100644 --- a/api/typeDefs/wallet.js +++ b/api/typeDefs/wallet.js @@ -19,7 +19,7 @@ export default gql` cancelInvoice(hash: String!, hmac: String!): Invoice! dropBolt11(id: ID): Withdrawl upsertWalletLND(id: ID, socket: String!, macaroon: String!, cert: String, settings: AutowithdrawSettings!): Boolean - upsertWalletCoreLightning(id: ID, socket: String!, macaroon: String!, cert: String, settings: AutowithdrawSettings!): Boolean + upsertWalletCoreLightning(id: ID, socket: String!, rune: String!, settings: AutowithdrawSettings!): Boolean upsertWalletLNAddr(id: ID, address: String!, settings: AutowithdrawSettings!): Boolean removeWallet(id: ID!): Boolean } From 4571c2368664e2e939015c69c964eb9d7f5f1505 Mon Sep 17 00:00:00 2001 From: Dillon Date: Thu, 22 Feb 2024 10:04:30 -0600 Subject: [PATCH 07/23] updated input name --- pages/settings/wallets/core-lightning.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index d1735a7f8..4f20a79b0 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -78,9 +78,9 @@ export default function CoreLightning ({ ssrData }) { } - name='macaroon' + name='rune' clear - hint='hex or base64 encoded' + hint='base64 encoded' placeholder='AgEDbG5kAlgDChCn7YgfWX7uTkQQgXZ2uahNEgEwGhYKB2FkZHJlc3MSBHJlYWQSBXdyaXRlGhcKCGludm9pY2VzEgRyZWFkEgV3cml0ZRoPCgdvbmNoYWluEgRyZWFkAAAGIJkMBrrDV0npU90JV0TGNJPrqUD8m2QYoTDjolaL6eBs' required /> From 1e05fe678934254b720d8ad4ff6e70e83f0c4df5 Mon Sep 17 00:00:00 2001 From: Dillon Date: Thu, 22 Feb 2024 19:41:30 -0600 Subject: [PATCH 08/23] updated validation to check if rune is invoice only --- api/resolvers/wallet.js | 15 ++++++++++++--- docker-compose.yml | 8 ++++---- fragments/wallet.js | 4 ++++ pages/settings/wallets/core-lightning.js | 4 ++-- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index a5d3f9200..377c24a57 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -446,10 +446,19 @@ export default { 'content-type': 'application/json', Rune: rune }, - body: JSON.stringify({ rune }) + body: JSON.stringify({ string: rune }) } - // Returns true if rune is valid - return await fetch(socket, options) + console.log(socket) + await fetch(`${socket}/v1/decode`, options).then((response) => { + const requiredResponse = [{"alternatives": [ + "method=invoice" + ], + "summary": "method (of command) equal to 'invoice'" + }] + if (response.restrictions !== requiredResponse) { + throw new Error('rune is not for invoice only') + } + }) } }, { settings, data }, { me, models }) diff --git a/docker-compose.yml b/docker-compose.yml index 43cb70207..d518be980 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: ports: - "5431:5432" env_file: - - ./.env.sample + - ./.env volumes: - db:/var/lib/postgresql/data app: @@ -24,7 +24,7 @@ services: depends_on: - db env_file: - - ./.env.sample + - ./.env ports: - "3000:3000" volumes: @@ -41,7 +41,7 @@ services: app: condition: service_healthy env_file: - - ./.env.sample + - ./.env ports: - "8080:8080" volumes: @@ -63,7 +63,7 @@ services: retries: 3 restart: always env_file: - - ./.env.sample + - ./.env expose: - "8080" ports: diff --git a/fragments/wallet.js b/fragments/wallet.js index cec39d188..0b7416e14 100644 --- a/fragments/wallet.js +++ b/fragments/wallet.js @@ -142,6 +142,10 @@ export const WALLET_BY_TYPE = gql` macaroon cert } + ... on WalletCoreLIghtning { + socket + rune + } } } } diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index 4f20a79b0..85c79fb6f 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -23,7 +23,7 @@ export default function CoreLightning ({ ssrData }) { const [removeWallet] = useMutation(REMOVE_WALLET) const { walletByType: wallet } = ssrData || {} - + // removeWallet() return (

Core Lightning

@@ -73,7 +73,7 @@ export default function CoreLightning ({ ssrData }) {
Invoice Only Rune - {"***invoice only rune*** for your convenience. To gain better privacy, generate a new rune as follows:\n\n```lightning-cli createrune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions='[[\"method=invoice\"], [\"rate=10\"]]'```"} + {"***invoice only rune*** for your convenience. To gain better privacy, generate a new rune as follows:\n\n```lightning-cli createrune restrictions=invoice```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions=method=invoice```"}
From 952dfa349f5e59a110630d8374f75cce7cb78960 Mon Sep 17 00:00:00 2001 From: Dillon Date: Thu, 22 Feb 2024 19:43:36 -0600 Subject: [PATCH 09/23] reverted docker-compose.yaml --- docker-compose.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d518be980..43cb70207 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: ports: - "5431:5432" env_file: - - ./.env + - ./.env.sample volumes: - db:/var/lib/postgresql/data app: @@ -24,7 +24,7 @@ services: depends_on: - db env_file: - - ./.env + - ./.env.sample ports: - "3000:3000" volumes: @@ -41,7 +41,7 @@ services: app: condition: service_healthy env_file: - - ./.env + - ./.env.sample ports: - "8080:8080" volumes: @@ -63,7 +63,7 @@ services: retries: 3 restart: always env_file: - - ./.env + - ./.env.sample expose: - "8080" ports: From 8b974699bbe199c139c79cc8eb013f4609f0219e Mon Sep 17 00:00:00 2001 From: Dillon Date: Thu, 22 Feb 2024 19:48:57 -0600 Subject: [PATCH 10/23] linter fixes --- api/resolvers/wallet.js | 9 +++++---- pages/settings/wallets/core-lightning.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 377c24a57..08cc18a4b 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -450,10 +450,11 @@ export default { } console.log(socket) await fetch(`${socket}/v1/decode`, options).then((response) => { - const requiredResponse = [{"alternatives": [ - "method=invoice" - ], - "summary": "method (of command) equal to 'invoice'" + const requiredResponse = [{ + alternatives: [ + 'method=invoice' + ], + summary: 'method (of command) equal to \'invoice\'' }] if (response.restrictions !== requiredResponse) { throw new Error('rune is not for invoice only') diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index 85c79fb6f..2104b2860 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -73,7 +73,7 @@ export default function CoreLightning ({ ssrData }) {
Invoice Only Rune - {"***invoice only rune*** for your convenience. To gain better privacy, generate a new rune as follows:\n\n```lightning-cli createrune restrictions=invoice```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions=method=invoice```"} + {'***invoice only rune*** for your convenience. To gain better privacy, generate a new rune as follows:\n\n```lightning-cli createrune restrictions=invoice```\n\nfor older core lightning versions use ```lightning-cli commando-rune restrictions=method=invoice```'}
From e5f654052d32e4aba81527956fe838923261e33b Mon Sep 17 00:00:00 2001 From: Dillon Date: Fri, 23 Feb 2024 11:48:21 -0600 Subject: [PATCH 11/23] updated rune restriction check --- api/resolvers/wallet.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 08cc18a4b..19b44f7e8 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -448,15 +448,10 @@ export default { }, body: JSON.stringify({ string: rune }) } - console.log(socket) + await fetch(`${socket}/v1/decode`, options).then((response) => { - const requiredResponse = [{ - alternatives: [ - 'method=invoice' - ], - summary: 'method (of command) equal to \'invoice\'' - }] - if (response.restrictions !== requiredResponse) { + const requiredResponse = 'method (of command) equal to \'invoice\'' + if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { throw new Error('rune is not for invoice only') } }) From a0bc1a0b3c4e7480f08aaf6b97949e45cde20b69 Mon Sep 17 00:00:00 2001 From: Dillon Date: Sun, 25 Feb 2024 11:16:40 -0600 Subject: [PATCH 12/23] updated core lightning withdrawl to use bolt11 --- worker/autowithdraw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/autowithdraw.js b/worker/autowithdraw.js index 920883c43..00ab055ba 100644 --- a/worker/autowithdraw.js +++ b/worker/autowithdraw.js @@ -164,5 +164,5 @@ async function autowithdrawCoreLightning ({ amount, maxFee }, { me, models }) { const invoice = await fetch(`${socket}/v1/invoice`, options) - return await createWithdrawal(null, { invoice: invoice.payment_hash, maxFee }, { me, models, autoWithdraw: true }) + return await createWithdrawal(null, { invoice: invoice.bolt11, maxFee }, { me, models, autoWithdraw: true }) } From d2fd823dbb91b29a41c796a427475a1ca63d986c Mon Sep 17 00:00:00 2001 From: Dillon Date: Sun, 25 Feb 2024 17:36:03 -0600 Subject: [PATCH 13/23] updated some type defs --- api/resolvers/wallet.js | 13 +++++++------ api/typeDefs/wallet.js | 7 ++++++- fragments/wallet.js | 4 ++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 19b44f7e8..1f2410a50 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -449,12 +449,13 @@ export default { body: JSON.stringify({ string: rune }) } - await fetch(`${socket}/v1/decode`, options).then((response) => { - const requiredResponse = 'method (of command) equal to \'invoice\'' - if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { - throw new Error('rune is not for invoice only') - } - }) + // await fetch(`${socket}/v1/decode`, options).then((response) => { + // const requiredResponse = 'method (of command) equal to \'invoice\'' + // if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { + // throw new Error('rune is not for invoice only') + // } + // }) + return await fetch("https://www.google.com", options) } }, { settings, data }, { me, models }) diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js index c44c8cc5c..7bf4d5304 100644 --- a/api/typeDefs/wallet.js +++ b/api/typeDefs/wallet.js @@ -42,7 +42,12 @@ export default gql` cert: String } - union WalletDetails = WalletLNAddr | WalletLND + type WalletCoreLightning { + socket: String! + rune: String! + } + + union WalletDetails = WalletLNAddr | WalletLND | WalletCoreLightning input AutowithdrawSettings { autoWithdrawThreshold: Int! diff --git a/fragments/wallet.js b/fragments/wallet.js index 0b7416e14..59738164c 100644 --- a/fragments/wallet.js +++ b/fragments/wallet.js @@ -120,6 +120,10 @@ export const WALLET = gql` macaroon cert } + ... on WalletCoreLightning { + socket + rune + } } } } From 09750036a9fe230caa0a4e112ec41483ca24ed8f Mon Sep 17 00:00:00 2001 From: Dillon Date: Sun, 25 Feb 2024 17:38:37 -0600 Subject: [PATCH 14/23] updated test connect --- api/resolvers/wallet.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 1f2410a50..7f0c6cc0e 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -449,13 +449,12 @@ export default { body: JSON.stringify({ string: rune }) } - // await fetch(`${socket}/v1/decode`, options).then((response) => { - // const requiredResponse = 'method (of command) equal to \'invoice\'' - // if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { - // throw new Error('rune is not for invoice only') - // } - // }) - return await fetch("https://www.google.com", options) + return await fetch(`${socket}/v1/decode`, options).then((response) => { + const requiredResponse = 'method (of command) equal to \'invoice\'' + if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { + throw new Error('rune is not for invoice only') + } + }) } }, { settings, data }, { me, models }) From faa28733908e25faef9cf585cd4233ef3cd45f5a Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 10:14:25 -0600 Subject: [PATCH 15/23] updated resolvers to return correct wallet type --- api/resolvers/wallet.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 7f0c6cc0e..a407cb1e2 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -304,7 +304,7 @@ export default { }, WalletDetails: { __resolveType (wallet) { - return wallet.address ? 'WalletLNAddr' : 'WalletLND' + return wallet.address ? 'WalletLNAddr' : wallet.type == 'LND' ? 'WalletLND' : 'WalletCoreLightning' } }, Mutation: { @@ -449,12 +449,13 @@ export default { body: JSON.stringify({ string: rune }) } - return await fetch(`${socket}/v1/decode`, options).then((response) => { - const requiredResponse = 'method (of command) equal to \'invoice\'' - if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { - throw new Error('rune is not for invoice only') - } - }) + // return await fetch(`${socket}/v1/decode`, options).then((response) => { + // const requiredResponse = 'method (of command) equal to \'invoice\'' + // if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { + // throw new Error('rune is not for invoice only') + // } + // }) + return await fetch("https://google.com", options) } }, { settings, data }, { me, models }) From 8aeb41a6cd7040825a5ec7c059a7e2dab404a4e2 Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:02:59 -0600 Subject: [PATCH 16/23] invoice rune check to client side only --- api/resolvers/wallet.js | 19 +++++++++---------- lib/validate.js | 26 +++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index a407cb1e2..068da6bd8 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -77,7 +77,6 @@ export default { if (!me) { throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } }) } - const wallet = await models.wallet.findFirst({ where: { userId: me.id, @@ -304,7 +303,13 @@ export default { }, WalletDetails: { __resolveType (wallet) { - return wallet.address ? 'WalletLNAddr' : wallet.type == 'LND' ? 'WalletLND' : 'WalletCoreLightning' + if (wallet.address) { + return 'WalletLNAddr' + }else if (wallet.type == 'LND') { + return 'WalletLND' + } else { + return 'WalletCoreLightning' + } } }, Mutation: { @@ -446,16 +451,10 @@ export default { 'content-type': 'application/json', Rune: rune }, - body: JSON.stringify({ string: rune }) + body: JSON.stringify({ amount_msat: 0, label: 'SN connection test', description: 'SN connection test' }) } - // return await fetch(`${socket}/v1/decode`, options).then((response) => { - // const requiredResponse = 'method (of command) equal to \'invoice\'' - // if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { - // throw new Error('rune is not for invoice only') - // } - // }) - return await fetch("https://google.com", options) + return await fetch(`${socket}/v1/invoice`, options) } }, { settings, data }, { me, models }) diff --git a/lib/validate.js b/lib/validate.js index 3db86f4a6..a1392f687 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -329,10 +329,34 @@ export function LNDAutowithdrawSchema ({ me } = {}) { }) } +async function isInvoiceOnlyRune (socket, rune) { + const options = { + method: 'POST', + headers: { + 'content-type': 'application/json', + Rune: rune + }, + body: JSON.stringify({ string: rune }) + } + + await fetch(`${socket}/v1/decode`, options).then((response) => { + const requiredResponse = 'method (of command) equal to \'invoice\'' + if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { + return false + } else { + return true + } + }) +} + export function CoreLightningAutowithdrawSchema ({ me } = {}) { return object({ socket: string().socket().required('required'), - rune: hexOrBase64Validator.required('required') + rune: hexOrBase64Validator.required('required').test({ + name: 'rune', + test: v => isInvoiceOnlyRune(socket, v), + message: 'rune is not for invoice only' + }) }) } From 9c9af9de0b2a42fceca4ac0ede2cedbf64e4de14 Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:05:09 -0600 Subject: [PATCH 17/23] added autowithdrawSchemaMembers to validate --- lib/validate.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/validate.js b/lib/validate.js index a1392f687..01c2abb62 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -356,7 +356,8 @@ export function CoreLightningAutowithdrawSchema ({ me } = {}) { name: 'rune', test: v => isInvoiceOnlyRune(socket, v), message: 'rune is not for invoice only' - }) + }), + ...autowithdrawSchemaMembers({ me }) }) } From 6ff4bd73d6a0cb438e9f338ecf17ee1bff1fc293 Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:08:29 -0600 Subject: [PATCH 18/23] fixed typo --- fragments/wallet.js | 2 +- pages/settings/wallets/core-lightning.js | 2 +- pages/settings/wallets/lightning-address.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fragments/wallet.js b/fragments/wallet.js index 59738164c..1bf3e4048 100644 --- a/fragments/wallet.js +++ b/fragments/wallet.js @@ -146,7 +146,7 @@ export const WALLET_BY_TYPE = gql` macaroon cert } - ... on WalletCoreLIghtning { + ... on WalletCoreLightning { socket rune } diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index 2104b2860..2b3323f7d 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -23,7 +23,7 @@ export default function CoreLightning ({ ssrData }) { const [removeWallet] = useMutation(REMOVE_WALLET) const { walletByType: wallet } = ssrData || {} - // removeWallet() + return (

Core Lightning

diff --git a/pages/settings/wallets/lightning-address.js b/pages/settings/wallets/lightning-address.js index d3301dfbb..aed6ab0a3 100644 --- a/pages/settings/wallets/lightning-address.js +++ b/pages/settings/wallets/lightning-address.js @@ -21,7 +21,7 @@ export default function LightningAddress ({ ssrData }) { const [removeWallet] = useMutation(REMOVE_WALLET) const { walletByType: wallet } = ssrData || {} - + return (

lightning address

From 8189259a1c4b9c7fb05b527961ffdd75a8dd589e Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:10:53 -0600 Subject: [PATCH 19/23] linter --- api/resolvers/wallet.js | 1 + pages/settings/wallets/lightning-address.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 068da6bd8..3709f71f4 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -77,6 +77,7 @@ export default { if (!me) { throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } }) } + const wallet = await models.wallet.findFirst({ where: { userId: me.id, diff --git a/pages/settings/wallets/lightning-address.js b/pages/settings/wallets/lightning-address.js index aed6ab0a3..d3301dfbb 100644 --- a/pages/settings/wallets/lightning-address.js +++ b/pages/settings/wallets/lightning-address.js @@ -21,7 +21,7 @@ export default function LightningAddress ({ ssrData }) { const [removeWallet] = useMutation(REMOVE_WALLET) const { walletByType: wallet } = ssrData || {} - + return (

lightning address

From 71de2d8f6f8639f9ad8777e032e35bad91d82dcc Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:11:54 -0600 Subject: [PATCH 20/23] linter --- api/resolvers/wallet.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 3709f71f4..2ae48af57 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -77,7 +77,7 @@ export default { if (!me) { throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } }) } - + const wallet = await models.wallet.findFirst({ where: { userId: me.id, @@ -306,7 +306,7 @@ export default { __resolveType (wallet) { if (wallet.address) { return 'WalletLNAddr' - }else if (wallet.type == 'LND') { + } else if (wallet.type == 'LND') { return 'WalletLND' } else { return 'WalletCoreLightning' From 9687ebfad5e522282290e27fa1765dc3e52f4df4 Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:27:59 -0600 Subject: [PATCH 21/23] linter fixes and switched invoice rune check to node that we know is always up because if the socket is invalid the test will fail --- api/resolvers/wallet.js | 8 ++++---- lib/validate.js | 29 ++++++++++++++++------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index 2ae48af57..a69860de9 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -306,11 +306,11 @@ export default { __resolveType (wallet) { if (wallet.address) { return 'WalletLNAddr' - } else if (wallet.type == 'LND') { - return 'WalletLND' + } else if (wallet.type === 'LND') { + return 'WalletLND' } else { return 'WalletCoreLightning' - } + } } }, Mutation: { @@ -452,7 +452,7 @@ export default { 'content-type': 'application/json', Rune: rune }, - body: JSON.stringify({ amount_msat: 0, label: 'SN connection test', description: 'SN connection test' }) + body: JSON.stringify({ amount_msat: 0, label: 'SN connection test', description: 'SN connection test' }) } return await fetch(`${socket}/v1/invoice`, options) diff --git a/lib/validate.js b/lib/validate.js index 01c2abb62..26aaf55e0 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -330,18 +330,21 @@ export function LNDAutowithdrawSchema ({ me } = {}) { } async function isInvoiceOnlyRune (socket, rune) { + const url = 'https://cln-regtest-demo.blockstream.com/v1/decode'; const options = { - method: 'POST', - headers: { - 'content-type': 'application/json', - Rune: rune - }, - body: JSON.stringify({ string: rune }) - } - - await fetch(`${socket}/v1/decode`, options).then((response) => { + method: 'POST', + headers: { + 'content-type': 'application/json', + Rune: 'YuJqHOZLvCCiL0bY3mT75V_KX_dYNdhTlspcAkGZL5w9MA==' + }, + body: JSON.stringify({string: 'zwcfm5tup11kf2fEObNDDPAcbNE-c_0m4KzbOpvt9gs9MTQmbWV0aG9kPWludm9pY2U='}) +}; + +fetch(url, options).then(res => res.json()) + .then((response) => { + console.log(response) const requiredResponse = 'method (of command) equal to \'invoice\'' - if (requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { + if (!response.restrictions && requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { return false } else { return true @@ -349,12 +352,12 @@ async function isInvoiceOnlyRune (socket, rune) { }) } -export function CoreLightningAutowithdrawSchema ({ me } = {}) { +export function CoreLightningAutowithdrawSchema ({ me, socket } = {}) { return object({ socket: string().socket().required('required'), rune: hexOrBase64Validator.required('required').test({ - name: 'rune', - test: v => isInvoiceOnlyRune(socket, v), + name: 'rune', + test: v => isInvoiceOnlyRune(string().socket(), v), message: 'rune is not for invoice only' }), ...autowithdrawSchemaMembers({ me }) From be06681fab04ce9106ae10f2898063f1fee5554c Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:31:51 -0600 Subject: [PATCH 22/23] linter --- lib/validate.js | 20 +++++++++----------- pages/settings/wallets/core-lightning.js | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/validate.js b/lib/validate.js index 26aaf55e0..ededf8e00 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -332,17 +332,15 @@ export function LNDAutowithdrawSchema ({ me } = {}) { async function isInvoiceOnlyRune (socket, rune) { const url = 'https://cln-regtest-demo.blockstream.com/v1/decode'; const options = { - method: 'POST', - headers: { - 'content-type': 'application/json', - Rune: 'YuJqHOZLvCCiL0bY3mT75V_KX_dYNdhTlspcAkGZL5w9MA==' - }, - body: JSON.stringify({string: 'zwcfm5tup11kf2fEObNDDPAcbNE-c_0m4KzbOpvt9gs9MTQmbWV0aG9kPWludm9pY2U='}) -}; - -fetch(url, options).then(res => res.json()) - .then((response) => { - console.log(response) + method: 'POST', + headers: { + 'content-type': 'application/json', + Rune: 'YuJqHOZLvCCiL0bY3mT75V_KX_dYNdhTlspcAkGZL5w9MA==' + }, + body: JSON.stringify({ string: 'zwcfm5tup11kf2fEObNDDPAcbNE-c_0m4KzbOpvt9gs9MTQmbWV0aG9kPWludm9pY2U=' }) + } + + fetch(url, options).then(res => res.json()).then((response) => { const requiredResponse = 'method (of command) equal to \'invoice\'' if (!response.restrictions && requiredResponse !== response.restrictions[0].alternatives[0].summary && response.restrictions.length > 1) { return false diff --git a/pages/settings/wallets/core-lightning.js b/pages/settings/wallets/core-lightning.js index 2b3323f7d..b51b0477d 100644 --- a/pages/settings/wallets/core-lightning.js +++ b/pages/settings/wallets/core-lightning.js @@ -23,7 +23,7 @@ export default function CoreLightning ({ ssrData }) { const [removeWallet] = useMutation(REMOVE_WALLET) const { walletByType: wallet } = ssrData || {} - + return (

Core Lightning

From 33dbbcbfe526f47f90012c5f5580e5bd3d90aec3 Mon Sep 17 00:00:00 2001 From: Dillon Date: Mon, 26 Feb 2024 13:33:35 -0600 Subject: [PATCH 23/23] linter --- lib/validate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/validate.js b/lib/validate.js index ededf8e00..77cb596d0 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -330,7 +330,7 @@ export function LNDAutowithdrawSchema ({ me } = {}) { } async function isInvoiceOnlyRune (socket, rune) { - const url = 'https://cln-regtest-demo.blockstream.com/v1/decode'; + const url = 'https://cln-regtest-demo.blockstream.com/v1/decode' const options = { method: 'POST', headers: {