Send via CLNRest (#2475)

* Send via CLNRest

* Add cURL script to send payments using CLNRest

* Serve CLNRest over HTTP in dev

Upgrade to 24.11 fixed CORS issue

* Update cln.md
This commit is contained in:
ekzyis 2025-09-04 19:15:14 +02:00 committed by GitHub
parent a794b59b91
commit de463e1f99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 275 additions and 97 deletions

View File

@ -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!

View File

@ -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:

View File

@ -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 \

View File

@ -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)

View File

@ -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();

View File

@ -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")

25
scripts/clnrest_pay.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Sends a lightning payment using CLNRest
# Usage: ./clnrest_pay.sh <bolt11>
if [ $# -eq 0 ]; then
echo "Usage: $0 <bolt11>"
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

View File

@ -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},

View File

@ -71,6 +71,13 @@ const WALLET_PROTOCOL_FIELDS = gql`
...VaultEntryFields
}
}
... on WalletSendCLNRest {
id
socket
encryptedRune: rune {
...VaultEntryFields
}
}
... on WalletRecvNWC {
id
url

View File

@ -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':

View File

@ -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
}

View File

@ -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
]

View File

@ -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'
}
]

View File

@ -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
```
- socket: `cln:3010` or onion via `sndev onion cln`
- rune: `sndev cli cln --regtest createrune restrictions='[["method=invoice"]]'`

View File

@ -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,

View File

@ -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: