@openreceive/elements 0.4.10 → 0.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-OMG254JS.js → chunk-DQ6FMWVX.js} +71 -11
- package/dist/index.js +1 -1
- package/dist/wrapper-shared.js +1 -1
- package/package.json +2 -2
- package/skills/integrate-openreceive/SKILL.md +4 -3
- package/skills/integrate-openreceive/references/btcpay.md +67 -36
- package/skills/integrate-openreceive/references/django.md +291 -244
- package/skills/integrate-openreceive/references/fastapi.md +206 -155
- package/skills/integrate-openreceive/references/fastify.md +200 -147
- package/skills/integrate-openreceive/references/laravel.md +294 -234
- package/skills/integrate-openreceive/references/next.md +210 -162
- package/skills/integrate-openreceive/references/node.md +188 -138
- package/skills/integrate-openreceive/references/php.md +248 -193
- package/skills/integrate-openreceive/references/rails.md +262 -218
- package/skills/integrate-openreceive/references/woocommerce.md +68 -51
|
@@ -244,11 +244,13 @@ function createElementCheckoutSession(host) {
|
|
|
244
244
|
const session = createCheckoutSession({
|
|
245
245
|
snapshot: () => host.latestCheckoutSnapshot(),
|
|
246
246
|
reference: currentReference,
|
|
247
|
-
|
|
247
|
+
prefix: currentPrefix,
|
|
248
|
+
requestCheckout: (reference, signal) => {
|
|
248
249
|
const metadata = host.createMetadata();
|
|
249
250
|
const csrfHeader = currentCsrfHeader();
|
|
250
251
|
return requestCheckout({
|
|
251
252
|
prefix: currentPrefix(),
|
|
253
|
+
signal,
|
|
252
254
|
reference,
|
|
253
255
|
...metadata === void 0 ? {} : { metadata },
|
|
254
256
|
...csrfHeader === void 0 ? {} : { csrfHeader },
|
|
@@ -290,17 +292,21 @@ function createElementCheckoutSession(host) {
|
|
|
290
292
|
creating = true;
|
|
291
293
|
createdKey = key;
|
|
292
294
|
session.resetLightningRequest();
|
|
295
|
+
const action = session.capture();
|
|
293
296
|
try {
|
|
294
297
|
createError = void 0;
|
|
295
298
|
host.syncResumePath(reference);
|
|
296
299
|
const prepared = await prepareCheckout({
|
|
300
|
+
signal: action.signal,
|
|
297
301
|
prefix,
|
|
298
302
|
reference,
|
|
299
303
|
...csrfHeader === void 0 ? {} : { csrfHeader },
|
|
300
304
|
fetch: globalThis.fetch
|
|
301
305
|
});
|
|
306
|
+
if (!action.isCurrent()) return;
|
|
302
307
|
const resumeHash = host.resumePaymentHash();
|
|
303
308
|
const checkout = resumeHash === void 0 ? prepared : await resumeSwapAttempt({
|
|
309
|
+
signal: action.signal,
|
|
304
310
|
fetch: globalThis.fetch,
|
|
305
311
|
prefix,
|
|
306
312
|
...csrfHeader === void 0 ? {} : { csrfHeader },
|
|
@@ -308,7 +314,7 @@ function createElementCheckoutSession(host) {
|
|
|
308
314
|
paymentHash: resumeHash,
|
|
309
315
|
snapshot: prepared
|
|
310
316
|
});
|
|
311
|
-
if (
|
|
317
|
+
if (!action.isCurrent()) return;
|
|
312
318
|
if (checkout.active?.swap !== void 0) {
|
|
313
319
|
host.swapSelection.setSelectedAsset(checkout.active.swap.pay_in_asset);
|
|
314
320
|
host.swapSelection.setDismissedInvoiceId(null);
|
|
@@ -323,15 +329,17 @@ function createElementCheckoutSession(host) {
|
|
|
323
329
|
host.render();
|
|
324
330
|
host.startCheckoutController();
|
|
325
331
|
} catch (error) {
|
|
326
|
-
if (
|
|
332
|
+
if (!action.isCurrent()) return;
|
|
327
333
|
createError = error instanceof Error && error.message.length > 0 ? error.message : "Could not start checkout.";
|
|
328
334
|
host.dispatchError(error);
|
|
329
335
|
host.render();
|
|
330
336
|
} finally {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
void
|
|
337
|
+
if (action.isCurrent()) {
|
|
338
|
+
creating = false;
|
|
339
|
+
const current = currentCreateKey();
|
|
340
|
+
if (host.element.isConnected && current !== void 0 && current !== key && host.isCreateMode()) {
|
|
341
|
+
void createCheckout();
|
|
342
|
+
}
|
|
335
343
|
}
|
|
336
344
|
}
|
|
337
345
|
}
|
|
@@ -370,9 +378,19 @@ function createElementCheckoutSession(host) {
|
|
|
370
378
|
retryCreateCheckout,
|
|
371
379
|
ensureLightning: () => session.ensureLightning(),
|
|
372
380
|
startSwap: (payInAsset) => session.startSwap(payInAsset),
|
|
381
|
+
clearSwapStartError: () => session.clearSwapStartError(),
|
|
373
382
|
applyOwnAttributes,
|
|
374
383
|
writeOwnAttributes,
|
|
384
|
+
capture: () => session.capture(),
|
|
385
|
+
dispose() {
|
|
386
|
+
session.dispose();
|
|
387
|
+
if (creating) createdKey = void 0;
|
|
388
|
+
creating = false;
|
|
389
|
+
},
|
|
375
390
|
forgetCreateKey() {
|
|
391
|
+
session.reset();
|
|
392
|
+
creating = false;
|
|
393
|
+
createError = void 0;
|
|
376
394
|
createdKey = void 0;
|
|
377
395
|
}
|
|
378
396
|
};
|
|
@@ -1471,7 +1489,7 @@ function renderCheckoutHtml(view) {
|
|
|
1471
1489
|
const settled = statusLabel === "settled";
|
|
1472
1490
|
const swapFocused = (view.wizard?.selectedSwapAsset ?? null) !== null;
|
|
1473
1491
|
const methodGridShowing = view.payment_wizard !== false && view.wizard?.selectedMethod == null && !swapFocused;
|
|
1474
|
-
const hideLightning = !settled && (view.lightningRequested === false || swapFocused
|
|
1492
|
+
const hideLightning = !settled && (view.lightningRequested === false || swapFocused || methodGridShowing && !expired);
|
|
1475
1493
|
const wizard = expired && !swapFocused || settled || view.payment_wizard === false ? "" : renderPaymentWizardHtml(view.wizard);
|
|
1476
1494
|
const copyButton = `<button part="${OPENRECEIVE_CHECKOUT_ELEMENT_PARTS.copy}" class="${orClasses6.btn}" type="button">${COPY_INVOICE_ICON}<span ${OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES6.swapCopyLabel}>${escapeHtml7(checkoutLabels6.copyInvoice)}</span></button>`;
|
|
1477
1495
|
const decodeInvoice = view.invoice.trim() !== "" ? view.invoice : typeof view.wizard?.lightningInvoice === "string" && view.wizard.lightningInvoice.trim() !== "" ? view.wizard.lightningInvoice : void 0;
|
|
@@ -1721,8 +1739,12 @@ function defineElements(options = {}) {
|
|
|
1721
1739
|
this.startCheckoutController();
|
|
1722
1740
|
}
|
|
1723
1741
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
1724
|
-
if (
|
|
1742
|
+
if (this.session.applyingOwnAttributes) return;
|
|
1743
|
+
const identityChanged = name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.reference || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.prefix;
|
|
1744
|
+
if (!this.isConnected && !identityChanged) return;
|
|
1725
1745
|
if (oldValue === newValue) return;
|
|
1746
|
+
if (name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.prefix && oldValue?.replace(/\/+$/, "") === newValue?.replace(/\/+$/, ""))
|
|
1747
|
+
return;
|
|
1726
1748
|
const displayOnly = name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.theme || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.syncUrl || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.resumePathPrefix || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.routeReference || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.resumable || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.decodeLinkUrl;
|
|
1727
1749
|
if (displayOnly) {
|
|
1728
1750
|
this.render();
|
|
@@ -1738,8 +1760,40 @@ function defineElements(options = {}) {
|
|
|
1738
1760
|
}
|
|
1739
1761
|
const createInputChanged = name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.reference || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.prefix || name === OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.invoice;
|
|
1740
1762
|
if (createInputChanged) {
|
|
1763
|
+
const managed = this.latestCheckoutSnapshot !== void 0;
|
|
1764
|
+
this.stopCheckoutController();
|
|
1741
1765
|
this.session.forgetCreateKey();
|
|
1766
|
+
this.latestCheckoutSnapshot = void 0;
|
|
1767
|
+
this.lastCheckoutState = void 0;
|
|
1768
|
+
this.lastSnapshotDisplayKey = void 0;
|
|
1769
|
+
this.startedSwapInvoice = void 0;
|
|
1770
|
+
this.dismissedSwapInvoiceId = null;
|
|
1771
|
+
this.selectedSwapAsset = null;
|
|
1772
|
+
this.selectedPickerKey = null;
|
|
1773
|
+
this.selectedSwapAssetByGroup = {};
|
|
1774
|
+
this.selection = createPaymentWizardSelection();
|
|
1775
|
+
this.swapOptions = [];
|
|
1776
|
+
this.swapOptionsLoaded = false;
|
|
1777
|
+
this.clearRefundAddressDraft();
|
|
1778
|
+
if (managed && name !== OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3.invoice) {
|
|
1779
|
+
this.session.writeOwnAttributes(() => {
|
|
1780
|
+
for (const key of [
|
|
1781
|
+
"invoice",
|
|
1782
|
+
"invoiceId",
|
|
1783
|
+
"paymentHash",
|
|
1784
|
+
"rail",
|
|
1785
|
+
"amountMsats",
|
|
1786
|
+
"fiatCurrency",
|
|
1787
|
+
"fiatValue",
|
|
1788
|
+
"status",
|
|
1789
|
+
"expiresAt"
|
|
1790
|
+
]) {
|
|
1791
|
+
this.removeAttribute(OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES3[key]);
|
|
1792
|
+
}
|
|
1793
|
+
});
|
|
1794
|
+
}
|
|
1742
1795
|
}
|
|
1796
|
+
if (!this.isConnected) return;
|
|
1743
1797
|
if (this.isCreateMode()) {
|
|
1744
1798
|
this.render();
|
|
1745
1799
|
this.syncThemeAncestorObserver();
|
|
@@ -1753,6 +1807,7 @@ function defineElements(options = {}) {
|
|
|
1753
1807
|
this.startCheckoutController();
|
|
1754
1808
|
}
|
|
1755
1809
|
disconnectedCallback() {
|
|
1810
|
+
this.session.dispose();
|
|
1756
1811
|
this.stopCheckoutController();
|
|
1757
1812
|
this.stopThemeAncestorObserver();
|
|
1758
1813
|
}
|
|
@@ -2219,6 +2274,7 @@ function defineElements(options = {}) {
|
|
|
2219
2274
|
button.addEventListener("click", () => {
|
|
2220
2275
|
const target = button.getAttribute(OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES7.breadcrumb);
|
|
2221
2276
|
if (target === "swap-asset") {
|
|
2277
|
+
this.session.clearSwapStartError();
|
|
2222
2278
|
this.selectedSwapAsset = null;
|
|
2223
2279
|
this.selectedPickerKey = null;
|
|
2224
2280
|
this.selectedSwapAssetByGroup = {};
|
|
@@ -2279,6 +2335,7 @@ function defineElements(options = {}) {
|
|
|
2279
2335
|
});
|
|
2280
2336
|
root.querySelector(OPENRECEIVE_PAYMENT_WIZARD_SELECTORS3.swapBack)?.addEventListener("click", () => {
|
|
2281
2337
|
const current = this.currentSwapInvoice();
|
|
2338
|
+
this.session.clearSwapStartError();
|
|
2282
2339
|
this.dismissedSwapInvoiceId = current?.invoice_id ?? null;
|
|
2283
2340
|
this.selectedSwapAsset = null;
|
|
2284
2341
|
this.selectedPickerKey = null;
|
|
@@ -2426,12 +2483,15 @@ function defineElements(options = {}) {
|
|
|
2426
2483
|
async refundSwap(attemptId, refundAddress, confirm) {
|
|
2427
2484
|
const controller = this.controller;
|
|
2428
2485
|
if (controller === void 0) return;
|
|
2486
|
+
const action = this.session.capture();
|
|
2429
2487
|
try {
|
|
2430
|
-
|
|
2488
|
+
const invoice = confirm ? await controller.confirmSwapRefund({ attemptId, refundAddress }) : await controller.stageSwapRefund({ attemptId, refundAddress });
|
|
2489
|
+
if (!action.isCurrent() || this.controller !== controller) return;
|
|
2490
|
+
this.startedSwapInvoice = invoice;
|
|
2431
2491
|
this.dismissedSwapInvoiceId = null;
|
|
2432
2492
|
this.render();
|
|
2433
2493
|
} catch (error) {
|
|
2434
|
-
this.dispatchError(error);
|
|
2494
|
+
if (action.isCurrent() && this.controller === controller) this.dispatchError(error);
|
|
2435
2495
|
}
|
|
2436
2496
|
}
|
|
2437
2497
|
currentSwapInvoice() {
|
package/dist/index.js
CHANGED
package/dist/wrapper-shared.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openreceive/elements",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.12",
|
|
4
4
|
"description": "Bitcoin Lightning checkout for any website using custom elements, with optional USDT, USDC, SOL and ETH swaps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bitcoin",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"main": "./dist/index.js",
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@openreceive/browser": "0.4.
|
|
24
|
+
"@openreceive/browser": "0.4.12"
|
|
25
25
|
},
|
|
26
26
|
"exports": {
|
|
27
27
|
".": {
|
|
@@ -34,9 +34,10 @@ code** (`NWC_URI`).
|
|
|
34
34
|
- BTCPay Server: [references/btcpay.md](references/btcpay.md) — a plugin,
|
|
35
35
|
configured in BTCPay's store UI or Greenfield API; no application code,
|
|
36
36
|
no npm packages, no gem. The rest of this file is about the library.
|
|
37
|
-
3. Follow its **Step 0** first:
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
3. Follow its **Step 0** first: before writing code or searching the machine,
|
|
38
|
+
ask the user for the receive-only NWC code (then the swap URI), one question
|
|
39
|
+
per message, and store each pasted code in the project's env file yourself.
|
|
40
|
+
Never print the value; never invent a placeholder.
|
|
40
41
|
|
|
41
42
|
Install, per adapter — Express: `npm install @openreceive/express @openreceive/react`;
|
|
42
43
|
Fastify: `npm install @openreceive/fastify @openreceive/react`; Next.js:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (BTCPay Server)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.12.
|
|
4
4
|
|
|
5
5
|
Connect a BTCPay Server store to a receive-only NWC wallet with the OpenReceive
|
|
6
6
|
plugin, and optionally let payers pay BTCPay invoices with USDT, USDC, ETH or
|
|
@@ -35,10 +35,12 @@ refund path on the same checkout screen.
|
|
|
35
35
|
1. Confirm the BTCPay Server version is 2.4.4 or later (Server Settings →
|
|
36
36
|
About, or `GET /api/v1/server/info`). The plugin declares that minimum and
|
|
37
37
|
BTCPay refuses to load it below.
|
|
38
|
-
2. Check whether the plugin is installed (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
2. Check whether the plugin is installed (the Plugins menu — the plug icon in
|
|
39
|
+
the top-right corner — under Installed Plugins, or the store navigation
|
|
40
|
+
shows an "OpenReceive" entry). If not, install it from the BTCPay plugin
|
|
41
|
+
directory (the same Plugins menu → Plugin Directory, search "openreceive",
|
|
42
|
+
then Install and Restart now), as the quickstart says; do not invent an
|
|
43
|
+
installer command.
|
|
42
44
|
3. Check whether the store already has an OpenReceive connection:
|
|
43
45
|
`GET /api/v1/stores/{storeId}/openreceive/settings` returns
|
|
44
46
|
`lightningNodeIsOpenReceive`. If true, the wallet step is done — go to
|
|
@@ -119,6 +121,8 @@ enough; drop the `.md` for the same page a person would read.
|
|
|
119
121
|
Questions, or a problem with the plugin itself:
|
|
120
122
|
https://openreceive.org/contact
|
|
121
123
|
|
|
124
|
+
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
125
|
+
|
|
122
126
|
---
|
|
123
127
|
|
|
124
128
|
## The quickstart, in full
|
|
@@ -131,15 +135,15 @@ passes. The page it comes from is https://openreceive.org/guides/quickstart-btcp
|
|
|
131
135
|
Requires BTCPay Server ≥ 2.4.4.
|
|
132
136
|
|
|
133
137
|
The OpenReceive plugin makes a receive-only NWC wallet the Lightning node of a
|
|
134
|
-
BTCPay store. BTCPay
|
|
135
|
-
payments
|
|
136
|
-
BTCPay invoice with USDT, USDC, ETH or SOL through a Lightning Swap Connect
|
|
137
|
-
provider
|
|
138
|
+
BTCPay store. BTCPay creates every Lightning invoice in that wallet. It records
|
|
139
|
+
payments the same way it records any other payment. You can also let payers pay
|
|
140
|
+
a BTCPay invoice with USDT, USDC, ETH or SOL through a Lightning Swap Connect
|
|
141
|
+
provider. The swap pays into the same wallet. The store's internal node is
|
|
138
142
|
never used.
|
|
139
143
|
|
|
140
144
|
This is not the Node or Rails library. There are no hooks, no
|
|
141
|
-
`openreceive_payments` table and no OpenReceive HTTP routes
|
|
142
|
-
invoices, checkout, webhooks and Greenfield API
|
|
145
|
+
`openreceive_payments` table and no OpenReceive HTTP routes. BTCPay's own
|
|
146
|
+
invoices, checkout, webhooks and Greenfield API do that work.
|
|
143
147
|
|
|
144
148
|
### 1. Prerequisites
|
|
145
149
|
|
|
@@ -155,39 +159,66 @@ invoices, checkout, webhooks and Greenfield API are the host.
|
|
|
155
159
|
|
|
156
160
|
### 2. Install the plugin
|
|
157
161
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
Sign in as a **server administrator**. If someone else hosts your server, ask
|
|
163
|
+
them to install the plugin for you.
|
|
164
|
+
|
|
165
|
+
**1. Open the Plugins menu.** It is the plug icon in the top-right corner.
|
|
166
|
+
|
|
167
|
+
**2. Click Plugin Directory.**
|
|
168
|
+
|
|
169
|
+
**3. Search for `openreceive`** and click the **OpenReceive** result.
|
|
170
|
+
|
|
171
|
+
**4. Click Install in BTCPay Server.** Confirm when prompted, then click
|
|
172
|
+
**Restart now** and wait for BTCPay to come back.
|
|
173
|
+
|
|
174
|
+
At startup, BTCPay creates the plugin's two tables in its own Postgres
|
|
175
|
+
database: `openreceive_invoices` and `openreceive_swaps`, in the schema
|
|
176
|
+
`BTCPayServer.Plugins.OpenReceive`. Nothing else is created.
|
|
163
177
|
|
|
164
178
|
To build the plugin from source instead, follow
|
|
165
179
|
[the .NET workspace README](https://github.com/OpenReceive/openreceive/blob/master/packages/dotnet/README.md).
|
|
166
180
|
|
|
167
181
|
### 3. Connect the wallet
|
|
168
182
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
node.
|
|
183
|
+
1. Select your store and open **OpenReceive** in its sidebar, under Wallets.
|
|
184
|
+
2. Paste your receive-only NWC code. To see what the wallet supports first,
|
|
185
|
+
click **Test connection**.
|
|
186
|
+
3. Click **Save NWC Code**.
|
|
187
|
+
4. To turn swaps on, paste a Lightning Swap Connect code and click **Save swap
|
|
188
|
+
settings**.
|
|
176
189
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
190
|
+
The page then shows **Wallet connected**. If you set up a provider, it also
|
|
191
|
+
shows **Swaps on**. There is nothing else to configure. You never open BTCPay's
|
|
192
|
+
Lightning node screen, and the plugin never reads the internal node.
|
|
193
|
+
|
|
194
|
+
Screenshots for each of those steps, and for creating a first test invoice,
|
|
195
|
+
are in the plugin's
|
|
196
|
+
[README](https://github.com/OpenReceive/openreceive/blob/master/packages/dotnet/BTCPayServer.Plugins.OpenReceive/README.md).
|
|
197
|
+
|
|
198
|
+
The plugin refuses to save a code whose wallet advertises a spend method such
|
|
199
|
+
as `pay_invoice`. Create a receive-only code instead. If your wallet cannot
|
|
200
|
+
make one, there is an override, but using it is a deliberate choice and the
|
|
201
|
+
plugin logs it.
|
|
202
|
+
|
|
203
|
+
Turning swaps on raises the store's invoice expiration to 60 minutes if it is
|
|
204
|
+
shorter. A swap needs the invoice to stay open for at least 45 minutes.
|
|
182
205
|
|
|
183
206
|
### 4. Check it
|
|
184
207
|
|
|
185
|
-
**Run a health check** on the OpenReceive page runs every
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
208
|
+
Click **Run a health check** on the OpenReceive page. It runs every check
|
|
209
|
+
right there:
|
|
210
|
+
|
|
211
|
+
- the connection
|
|
212
|
+
- the wallet preflight
|
|
213
|
+
- payment notifications
|
|
214
|
+
- the last wallet scan
|
|
215
|
+
- the swap provider and its assets
|
|
216
|
+
- the invoice expiration
|
|
217
|
+
- swaps that need a human
|
|
218
|
+
|
|
219
|
+
Each failing check comes with a link to the fix.
|
|
189
220
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
`nostr+walletconnect://` string in BTCPay's Lightning node screen.
|
|
221
|
+
The [BTCPay plugin reference](https://openreceive.org/guides/btcpay-reference.md) lists every setting,
|
|
222
|
+
Greenfield route, swap state, log event and check. It also lists what the
|
|
223
|
+
plugin does not support by design: every send-side feature, top-up invoices,
|
|
224
|
+
and a bare `nostr+walletconnect://` string in BTCPay's Lightning node screen.
|