diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js index d3d2cea6..ce690feb 100644 --- a/api/typeDefs/wallet.js +++ b/api/typeDefs/wallet.js @@ -55,6 +55,12 @@ const typeDefs = gql` apiKey: VaultEntryInput! ): WalletSendBlink! + upsertWalletSendCLNRest( + ${shared}, + socket: String!, + rune: VaultEntryInput!, + ): WalletSendCLNRest! + upsertWalletRecvBlink( ${shared}, currency: String!, @@ -212,6 +218,7 @@ const typeDefs = gql` | WalletSendBlink | WalletSendWebLN | WalletSendLNC + | WalletSendCLNRest | WalletRecvNWC | WalletRecvLNbits | WalletRecvPhoenixd @@ -273,6 +280,12 @@ const typeDefs = gql` serverHost: VaultEntry! } + type WalletSendCLNRest { + id: ID! + socket: String! + rune: VaultEntry! + } + type WalletRecvNWC { id: ID! url: String! diff --git a/docker-compose.yml b/docker-compose.yml index 76692875..2100fe57 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -530,8 +530,9 @@ services: - '--bitcoin-rpcuser=${RPC_USER}' - '--bitcoin-rpcpassword=${RPC_PASS}' - '--large-channels' - - '--rest-port=3010' - - '--rest-host=0.0.0.0' + - '--clnrest-port=3010' + - '--clnrest-host=0.0.0.0' + - '--clnrest-protocol=http' expose: - "9735" ports: diff --git a/docker/cln/Dockerfile b/docker/cln/Dockerfile index 3fb6e93f..0b4ef364 100644 --- a/docker/cln/Dockerfile +++ b/docker/cln/Dockerfile @@ -1,4 +1,4 @@ -FROM polarlightning/clightning:23.08 +FROM polarlightning/clightning:24.11 RUN apt-get update -y \ && apt-get install -y jq wget \ diff --git a/lib/cln.js b/lib/cln.js index 58141d74..adeb01f0 100644 --- a/lib/cln.js +++ b/lib/cln.js @@ -1,8 +1,8 @@ -import fetch from 'cross-fetch' +import crossFetch from 'cross-fetch' import crypto from 'crypto' import { getAgent } from '@/lib/proxy' import { assertContentTypeJson, assertResponseOk } from './url' -import { FetchTimeoutError } from './fetch' +import { fetchWithTimeout, FetchTimeoutError } from './fetch' import { WALLET_CREATE_INVOICE_TIMEOUT_MS } from './constants' export const createInvoice = async ({ msats, description, expiry }, { socket, rune, cert }, { signal }) => { @@ -13,15 +13,9 @@ export const createInvoice = async ({ msats, description, expiry }, { socket, ru const method = 'POST' let res try { - res = await fetch(url, { + res = await crossFetch(url, { method, - headers: { - 'Content-Type': 'application/json', - Rune: rune, - // can be any node id, only required for CLN v23.08 and below - // see https://docs.corelightning.org/docs/rest#server - nodeId: '02cb2e2d5a6c5b17fa67b1a883e2973c82e328fb9bd08b2b156a9e23820c87a490' - }, + headers: headers(rune), agent, body: JSON.stringify({ // CLN requires a unique label for every invoice @@ -52,6 +46,42 @@ export const createInvoice = async ({ msats, description, expiry }, { socket, ru return inv } +export const sendPayment = async (bolt11, { socket, rune }, { signal }) => { + // XXX we don't ask for the CA certificate because the browser's fetch API doesn't support http agents to override it. + // Therefore, CLNRest send will only work with common CA certificates. + + // API documentation + // https://docs.corelightning.org/reference/pay + const url = new URL( + '/v1/pay', + process.env.NODE_ENV === 'development' ? `http://${socket}` : `https://${socket}`) + const method = 'POST' + const res = await fetchWithTimeout(url, { + method, + headers: headers(rune), + body: JSON.stringify({ bolt11 }), + signal + }) + assertResponseOk(res, { method }) + assertContentTypeJson(res, { method }) + + const result = await res.json() + if (result.error) { + throw new Error(result.error.message) + } + return result.payment_preimage +} + +function headers (rune) { + const headers = new Headers() + headers.append('Content-Type', 'application/json') + headers.append('Rune', rune) + // can be any node id, only required for CLN v23.08 and below + // see https://docs.corelightning.org/docs/rest#server + headers.append('nodeId', '02cb2e2d5a6c5b17fa67b1a883e2973c82e328fb9bd08b2b156a9e23820c87a490') + return headers +} + // https://github.com/clams-tech/rune-decoder/blob/57c2e76d1ef9ab7336f565b99de300da1c7b67ce/src/index.ts export const decodeRune = (rune) => { const runeBinary = Base64Binary.decode(rune) diff --git a/prisma/migrations/20250829002239_cln_send/migration.sql b/prisma/migrations/20250829002239_cln_send/migration.sql new file mode 100644 index 00000000..a689c3cb --- /dev/null +++ b/prisma/migrations/20250829002239_cln_send/migration.sql @@ -0,0 +1,38 @@ +-- AlterEnum +ALTER TYPE "WalletSendProtocolName" ADD VALUE 'CLN_REST'; COMMIT; + +UPDATE "WalletTemplate" SET "sendProtocols" = array_append("sendProtocols", 'CLN_REST') WHERE "name" = 'CLN'; + +-- CreateTable +CREATE TABLE "WalletSendCLNRest" ( + "id" SERIAL NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "protocolId" INTEGER NOT NULL, + "socket" TEXT NOT NULL, + "runeVaultId" INTEGER NOT NULL, + + CONSTRAINT "WalletSendCLNRest_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "WalletSendCLNRest_protocolId_key" ON "WalletSendCLNRest"("protocolId"); + +-- CreateIndex +CREATE UNIQUE INDEX "WalletSendCLNRest_runeVaultId_key" ON "WalletSendCLNRest"("runeVaultId"); + +-- AddForeignKey +ALTER TABLE "WalletSendCLNRest" ADD CONSTRAINT "WalletSendCLNRest_protocolId_fkey" FOREIGN KEY ("protocolId") REFERENCES "WalletProtocol"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "WalletSendCLNRest" ADD CONSTRAINT "WalletSendCLNRest_runeVaultId_fkey" FOREIGN KEY ("runeVaultId") REFERENCES "Vault"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +CREATE TRIGGER wallet_to_jsonb + AFTER INSERT OR UPDATE ON "WalletSendCLNRest" + FOR EACH ROW + EXECUTE PROCEDURE wallet_to_jsonb(); + +CREATE TRIGGER wallet_clear_vault + AFTER DELETE ON "WalletSendCLNRest" + FOR EACH ROW + EXECUTE PROCEDURE wallet_clear_vault(); \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 168d1a91..b13b6c09 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -220,6 +220,7 @@ model Vault { walletSendLNCLocalKey WalletSendLNC? @relation("lncLocalKey") walletSendLNCRemoteKey WalletSendLNC? @relation("lncRemoteKey") walletSendLNCServerHost WalletSendLNC? @relation("lncServerHost") + walletSendCLNRestRune WalletSendCLNRest? @relation("clnRune") } model WalletLog { @@ -1221,6 +1222,7 @@ enum WalletSendProtocolName { BLINK WEBLN LNC + CLN_REST } enum WalletRecvProtocolName { @@ -1322,6 +1324,7 @@ model WalletProtocol { walletSendBlink WalletSendBlink? walletSendWebLN WalletSendWebLN? walletSendLNC WalletSendLNC? + walletSendCLNRest WalletSendCLNRest? walletRecvNWC WalletRecvNWC? walletRecvLNbits WalletRecvLNbits? @@ -1403,6 +1406,17 @@ model WalletSendLNC { serverHost Vault? @relation("lncServerHost", fields: [serverHostVaultId], references: [id]) } +model WalletSendCLNRest { + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @default(now()) @updatedAt @map("updated_at") + protocolId Int @unique + protocol WalletProtocol @relation(fields: [protocolId], references: [id], onDelete: Cascade) + socket String + runeVaultId Int @unique + rune Vault? @relation("clnRune", fields: [runeVaultId], references: [id]) +} + model WalletRecvNWC { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) @map("created_at") diff --git a/scripts/clnrest_pay.sh b/scripts/clnrest_pay.sh new file mode 100755 index 00000000..3b14b447 --- /dev/null +++ b/scripts/clnrest_pay.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Sends a lightning payment using CLNRest +# Usage: ./clnrest_pay.sh + +if [ $# -eq 0 ]; then + echo "Usage: $0 " + echo "Example: $0 lnbc..." + exit 1 +fi + +BOLT11=$1 +# add rune here +# $ sndev cli cln createrune restrictions='[["method=pay"]]' +RUNE= +NODE_ID=02cb2e2d5a6c5b17fa67b1a883e2973c82e328fb9bd08b2b156a9e23820c87a490 + +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Rune: $RUNE" \ + -H "nodeId: $NODE_ID" \ + -d "{\"bolt11\":\"$BOLT11\"}" \ + --cacert docker/cln/ca.pem \ + -v \ + https://localhost:9092/v1/pay diff --git a/wallets/client/fragments/protocol.js b/wallets/client/fragments/protocol.js index c39a327f..04d107e7 100644 --- a/wallets/client/fragments/protocol.js +++ b/wallets/client/fragments/protocol.js @@ -151,6 +151,22 @@ export const UPSERT_WALLET_RECEIVE_NWC = gql` } ` +export const UPSERT_WALLET_SEND_CLN_REST = gql` + mutation upsertWalletSendCLNRest( + ${shared.variables}, + $socket: String!, + $rune: VaultEntryInput!, + ) { + upsertWalletSendCLNRest( + ${shared.arguments}, + socket: $socket, + rune: $rune, + ) { + id + } + } +` + export const UPSERT_WALLET_RECEIVE_CLN_REST = gql` mutation upsertWalletRecvCLNRest( ${shared.variables}, diff --git a/wallets/client/fragments/wallet.js b/wallets/client/fragments/wallet.js index 6541c565..b8acf0e1 100644 --- a/wallets/client/fragments/wallet.js +++ b/wallets/client/fragments/wallet.js @@ -71,6 +71,13 @@ const WALLET_PROTOCOL_FIELDS = gql` ...VaultEntryFields } } + ... on WalletSendCLNRest { + id + socket + encryptedRune: rune { + ...VaultEntryFields + } + } ... on WalletRecvNWC { id url diff --git a/wallets/client/hooks/query.js b/wallets/client/hooks/query.js index 24cc86f6..439cbcb1 100644 --- a/wallets/client/hooks/query.js +++ b/wallets/client/hooks/query.js @@ -12,6 +12,7 @@ import { UPSERT_WALLET_SEND_NWC, UPSERT_WALLET_SEND_PHOENIXD, UPSERT_WALLET_SEND_WEBLN, + UPSERT_WALLET_SEND_CLN_REST, WALLETS, UPDATE_WALLET_ENCRYPTION, RESET_WALLETS, @@ -295,7 +296,7 @@ function protocolUpsertMutation (protocol) { case 'NWC': return protocol.send ? UPSERT_WALLET_SEND_NWC : UPSERT_WALLET_RECEIVE_NWC case 'CLN_REST': - return protocol.send ? NOOP_MUTATION : UPSERT_WALLET_RECEIVE_CLN_REST + return protocol.send ? UPSERT_WALLET_SEND_CLN_REST : UPSERT_WALLET_RECEIVE_CLN_REST case 'LND_GRPC': return protocol.send ? NOOP_MUTATION : UPSERT_WALLET_RECEIVE_LND_GRPC case 'LNC': diff --git a/wallets/client/protocols/clnRest.js b/wallets/client/protocols/clnRest.js new file mode 100644 index 00000000..2ad88185 --- /dev/null +++ b/wallets/client/protocols/clnRest.js @@ -0,0 +1,13 @@ +import { sendPayment as clnSendPayment } from '@/lib/cln' + +export const name = 'CLN_REST' + +export const sendPayment = async (bolt11, config, { signal }) => { + return await clnSendPayment(bolt11, config, { signal }) +} + +export const testSendPayment = async ({ socket, rune, cert }, { signal }) => { + // We only can use the /pay endpoint with the rune so we can't + // really test the configuration without paying something + // until https://github.com/stackernews/stacker.news/issues/1287 +} diff --git a/wallets/client/protocols/index.js b/wallets/client/protocols/index.js index a7cb149b..c25805f7 100644 --- a/wallets/client/protocols/index.js +++ b/wallets/client/protocols/index.js @@ -4,6 +4,7 @@ import * as phoenixd from './phoenixd' import * as blink from './blink' import * as webln from './webln' import * as lnc from './lnc' +import * as clnRest from './clnRest' export * from './util' @@ -52,5 +53,6 @@ export default [ phoenixd, blink, webln, - lnc + lnc, + clnRest ] diff --git a/wallets/lib/protocols/clnRest.js b/wallets/lib/protocols/clnRest.js index 58116c8a..cc14488c 100644 --- a/wallets/lib/protocols/clnRest.js +++ b/wallets/lib/protocols/clnRest.js @@ -3,53 +3,93 @@ import { certValidator, runeValidator, socketValidator } from '@/wallets/lib//va // Core Lightning REST API // https://docs.corelightning.org/docs/rest -export default { - name: 'CLN_REST', - displayName: 'CLNRest', - send: false, - fields: [ - { - name: 'socket', - label: 'rest host and port', - type: 'text', - placeholder: '55.5.555.55:3010', - hint: 'tor or clearnet', - required: true, - validate: socketValidator() - }, - { - name: 'rune', - label: 'invoice only rune', - type: 'password', - help: [ - 'We only accept runes that *only* allow `method=invoice`.', - 'Run this to generate one if you are on v24.11 or later:', - '```lightning-cli createrune restrictions=\'[["method=invoice"]]\'```', - 'Or this if you are on an earlier version:', - '```lightning-cli createrune restrictions=\'["method=invoice"]\'```', - '[see `createrune` documentation](https://docs.corelightning.org/reference/createrune#restriction-format)' - ], - placeholder: 'S34KtUW-6gqS_hD_9cc_PNhfF-NinZyBOCgr1aIrark9NCZtZXRob2Q9aW52b2ljZQ==', - validate: runeValidator({ method: 'invoice' }), - required: true, - hint: 'must be restricted to method=invoice' - }, - { - name: 'cert', - label: 'certificate', - type: 'password', - placeholder: 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNNVENDQWRpZ0F3SUJBZ0lRSHBFdFdrcGJwZHV4RVF2eVBPc3NWVEFLQmdncWhrak9QUVFEQWpBdk1SOHcKSFFZRFZRUUtFeFpzYm1RZ1lYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3SGhjTgpNalF3TVRBM01qQXhORE0wV2hjTk1qVXdNekF6TWpBeE5ETTBXakF2TVI4d0hRWURWUVFLRXhac2JtUWdZWFYwCmIyZGxibVZ5WVhSbFpDQmpaWEowTVF3d0NnWURWUVFERXdOaWIySXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJUS3NMVk5oZnhqb1FLVDlkVVdDbzUzSmQwTnBuL1BtYi9LUE02M1JxbU52dFYvdFk4NjJJZwpSbE41cmNHRnBEajhUeFc2OVhIK0pTcHpjWDdlN3N0Um80SFZNSUhTTUE0R0ExVWREd0VCL3dRRUF3SUNwREFUCkJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVDAKMnh3V25GeHRUNzI0MWxwZlNoNm9FWi9UMWpCN0JnTlZIUkVFZERCeWdnTmliMktDQ1d4dlkyRnNhRzl6ZElJRApZbTlpZ2d4d2IyeGhjaTF1TVMxaWIyS0NGR2h2YzNRdVpHOWphMlZ5TG1sdWRHVnlibUZzZ2dSMWJtbDRnZ3AxCmJtbDRjR0ZqYTJWMGdnZGlkV1pqYjI1dWh3Ui9BQUFCaHhBQUFBQUFBQUFBQUFBQUFBQUFBQUFCaHdTc0VnQUQKTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUEwUTlkRXdoNXpPRnpwL3hYeHNpemh5SkxNVG5yazU1VWx1NHJPRwo4WW52QWlBVGt4U3p3Y3hZZnFscGx0UlNIbmd0NUJFcDBzcXlHL05nenBzb2pmMGNqQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K', - hint: 'hex or base64 encoded', - help: [ - 'CLN generates self-signed TLS certificates on startup.', - 'The certificate of the certificate authority (CA) is needed to use them.', - 'By default, it is saved at $HOME/.lightning/bitcoin/ca.pem.', - 'This is optional if you are using a common certificate authority (e.g. cloud-hosted platform like Voltage).', - '[see documentation](https://docs.corelightning.org/docs/grpc#generating-the-certificates)' - ], - validate: certValidator(), - required: false - } - ], - relationName: 'walletRecvCLNRest' -} +export default [ + { + name: 'CLN_REST', + displayName: 'CLNRest', + send: false, + fields: [ + { + name: 'socket', + label: 'rest host and port', + type: 'text', + placeholder: '55.5.555.55:3010', + hint: 'tor or clearnet', + required: true, + validate: socketValidator(), + share: true + }, + { + name: 'rune', + label: 'invoice only rune', + type: 'password', + help: [ + 'We only accept runes that *only* allow `method=invoice`.', + 'Run this to generate one if you are on v24.11 or later:', + '```lightning-cli createrune restrictions=\'[["method=invoice"]]\'```', + 'Or this if you are on an earlier version:', + '```lightning-cli createrune restrictions=\'["method=invoice"]\'```', + '[see `createrune` documentation](https://docs.corelightning.org/reference/createrune#restriction-format)' + ], + placeholder: 'S34KtUW-6gqS_hD_9cc_PNhfF-NinZyBOCgr1aIrark9NCZtZXRob2Q9aW52b2ljZQ==', + validate: runeValidator({ method: 'invoice' }), + required: true, + hint: 'must be restricted to method=invoice' + }, + { + name: 'cert', + label: 'certificate', + type: 'password', + placeholder: 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNNVENDQWRpZ0F3SUJBZ0lRSHBFdFdrcGJwZHV4RVF2eVBPc3NWVEFLQmdncWhrak9QUVFEQWpBdk1SOHcKSFFZRFZRUUtFeFpzYm1RZ1lYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3SGhjTgpNalF3TVRBM01qQXhORE0wV2hjTk1qVXdNekF6TWpBeE5ETTBXakF2TVI4d0hRWURWUVFLRXhac2JtUWdZWFYwCmIyZGxibVZ5WVhSbFpDQmpaWEowTVF3d0NnWURWUVFERXdOaWIySXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJUS3NMVk5oZnhqb1FLVDlkVVdDbzUzSmQwTnBuL1BtYi9LUE02M1JxbU52dFYvdFk4NjJJZwpSbE41cmNHRnBEajhUeFc2OVhIK0pTcHpjWDdlN3N0Um80SFZNSUhTTUE0R0ExVWREd0VCL3dRRUF3SUNwREFUCkJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVDAKMnh3V25GeHRUNzI0MWxwZlNoNm9FWi9UMWpCN0JnTlZIUkVFZERCeWdnTmliMktDQ1d4dlkyRnNhRzl6ZElJRApZbTlpZ2d4d2IyeGhjaTF1TVMxaWIyS0NGR2h2YzNRdVpHOWphMlZ5TG1sdWRHVnlibUZzZ2dSMWJtbDRnZ3AxCmJtbDRjR0ZqYTJWMGdnZGlkV1pqYjI1dWh3Ui9BQUFCaHhBQUFBQUFBQUFBQUFBQUFBQUFBQUFCaHdTc0VnQUQKTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUEwUTlkRXdoNXpPRnpwL3hYeHNpemh5SkxNVG5yazU1VWx1NHJPRwo4WW52QWlBVGt4U3p3Y3hZZnFscGx0UlNIbmd0NUJFcDBzcXlHL05nenBzb2pmMGNqQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K', + hint: 'hex or base64 encoded', + help: [ + 'CLN generates self-signed TLS certificates on startup.', + 'The certificate of the certificate authority (CA) is needed to use them.', + 'By default, it is saved at $HOME/.lightning/bitcoin/ca.pem.', + 'This is optional if you are using a common certificate authority (e.g. cloud-hosted platform like Voltage).', + '[see documentation](https://docs.corelightning.org/docs/grpc#generating-the-certificates)' + ], + validate: certValidator(), + required: false + } + ], + relationName: 'walletRecvCLNRest' + }, + { + name: 'CLN_REST', + displayName: 'CLNRest', + send: true, + fields: [ + { + name: 'socket', + label: 'rest host and port', + type: 'text', + placeholder: '55.5.555.55:3010', + required: true, + validate: socketValidator(), + share: true + }, + { + name: 'rune', + label: 'pay only rune', + type: 'password', + help: [ + 'We only accept runes that *only* allow `method=pay`.', + 'Run this to generate one if you are on v24.11 or later:', + '```lightning-cli createrune restrictions=\'[["method=pay"]]\'```', + 'Or this if you are on an earlier version:', + '```lightning-cli createrune restrictions=\'["method=pay"]\'```', + '[see `createrune` documentation](https://docs.corelightning.org/reference/createrune#restriction-format)' + ], + placeholder: 'S34KtUW-6gqS_hD_9cc_PNhfF-NinZyBOCgr1aIrark9NCZtZXRob2Q9aW52b2ljZQ==', + validate: runeValidator({ method: 'pay' }), + required: true, + encrypt: true, + hint: 'must be restricted to method=pay' + } + // XXX we don't ask for the CA certificate because the browser's fetch API doesn't support http agents to override it. + // Therefore, CLNRest send will only work with common CA certificates. + ], + relationName: 'walletSendCLNRest' + } +] diff --git a/wallets/lib/protocols/docs/cln.md b/wallets/lib/protocols/docs/cln.md index f496eb69..21becc42 100644 --- a/wallets/lib/protocols/docs/cln.md +++ b/wallets/lib/protocols/docs/cln.md @@ -1,33 +1,11 @@ -To attach CLNRest as an receiving wallet protocol, you'll need a rune and the cert. +# CLNRest -# host and port +to attach sending: -`cln:3010` +- socket: `localhost:9092` +- rune: `sndev cli cln --regtest createrune restrictions='[["method=pay"]]'` -# host and port (onion) +to attach receiving: -Run: - -```bash -sndev onion cln -``` - -# create rune - -```bash -sndev cli cln --regtest createrune restrictions='["method=invoice"]' -``` - -# get cert - -This is static in dev env so you can use this one: - -```bash -LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlCY2pDQ0FSaWdBd0lCQWdJSkFOclN2UFovWTNLRU1Bb0dDQ3FHU000OUJBTUNNQll4RkRBU0JnTlZCQU1NDQpDMk5zYmlCU2IyOTBJRU5CTUNBWERUYzFNREV3TVRBd01EQXdNRm9ZRHpRd09UWXdNVEF4TURBd01EQXdXakFXDQpNUlF3RWdZRFZRUUREQXRqYkc0Z1VtOXZkQ0JEUVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBDQpCQmptYUh1dWxjZ3dTR09ubExBSFlRbFBTUXdHWEROSld5ZnpWclY5aFRGYUJSZFFrMVl1Y3VqVFE5QXFybkVJDQpyRmR6MS9PeisyWFhENmdBMnhPbmIrNmpUVEJMTUJrR0ExVWRFUVFTTUJDQ0EyTnNib0lKYkc5allXeG9iM04wDQpNQjBHQTFVZERnUVdCQlNFY21OLzlyelMyaFI2RzdFSWdzWCs1MU4wQ2pBUEJnTlZIUk1CQWY4RUJUQURBUUgvDQpNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJSENlUHZOU3Z5aUJZYXdxS2dRcXV3OUoyV1Z5SnhuMk1JWUlxejlTDQpRTDE4QWlFQWg4QlZEejhwWDdOc2xsOHNiMGJPMFJaNDljdnFRb2NDZ1ZhYnFKdVN1aWs9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo= -``` - -Which is generated with the following command - -```bash -openssl base64 -A -in docker/cln/ca.pem -``` \ No newline at end of file +- socket: `cln:3010` or onion via `sndev onion cln` +- rune: `sndev cli cln --regtest createrune restrictions='[["method=invoice"]]'` diff --git a/wallets/lib/protocols/index.js b/wallets/lib/protocols/index.js index 12fbb4ed..c13a5541 100644 --- a/wallets/lib/protocols/index.js +++ b/wallets/lib/protocols/index.js @@ -1,6 +1,6 @@ import nwcSuite from './nwc' import lnAddr from './lnAddr' -import clnRest from './clnRest' +import clnRestSuite from './clnRest' import lndGrpc from './lndGrpc' import lnc from './lnc' import lnbitsSuite from './lnbits' @@ -39,7 +39,7 @@ import webln from './webln' export default [ ...nwcSuite, lnAddr, - clnRest, + ...clnRestSuite, lndGrpc, lnc, ...phoenixdSuite, diff --git a/wallets/server/resolvers/util.js b/wallets/server/resolvers/util.js index 0155a422..f0ffa4af 100644 --- a/wallets/server/resolvers/util.js +++ b/wallets/server/resolvers/util.js @@ -16,7 +16,7 @@ export function mapWalletResolveTypes (wallet) { case 'LNC': return 'WalletSendLNC' case 'CLN_REST': - return 'WalletRecvCLNRest' + return send ? 'WalletSendCLNRest' : 'WalletRecvCLNRest' case 'LND_GRPC': return 'WalletRecvLNDGRPC' default: