@openreceive/browser 0.4.14 → 0.4.17
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/README.md +11 -0
- package/dist/{chunk-FBM57URY.js → chunk-LFX45HHQ.js} +17 -3
- package/dist/headless.d.ts +13 -4
- package/dist/headless.js +8 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{status-Q1CJqaYo.d.ts → status-BC2Rl8KA.d.ts} +2 -0
- package/package.json +3 -4
- package/skills/debug-openreceive-payment/SKILL.md +0 -97
- package/skills/integrate-openreceive/SKILL.md +0 -139
- package/skills/integrate-openreceive/references/btcpay.md +0 -224
- package/skills/integrate-openreceive/references/django.md +0 -745
- package/skills/integrate-openreceive/references/fastapi.md +0 -619
- package/skills/integrate-openreceive/references/fastify.md +0 -615
- package/skills/integrate-openreceive/references/laravel.md +0 -749
- package/skills/integrate-openreceive/references/next.md +0 -660
- package/skills/integrate-openreceive/references/node.md +0 -588
- package/skills/integrate-openreceive/references/php.md +0 -682
- package/skills/integrate-openreceive/references/rails.md +0 -698
- package/skills/integrate-openreceive/references/woocommerce.md +0 -193
package/README.md
CHANGED
|
@@ -68,3 +68,14 @@ Content-Security-Policy has a strict `img-src`, allow `data:`.
|
|
|
68
68
|
`@openreceive/provider-data`; `/headless` re-exports
|
|
69
69
|
`loadPayTutorialImages` / `payTutorialImage` for the lazy tutorial chunk.
|
|
70
70
|
See [docs/guides/provider-registry.md](https://github.com/OpenReceive/openreceive/blob/master/docs/guides/provider-registry.md#assets).
|
|
71
|
+
|
|
72
|
+
## Agent skills
|
|
73
|
+
|
|
74
|
+
Run `npx openreceive skills install` from your application after installing an
|
|
75
|
+
OpenReceive server adapter. The offline copy ships in `@openreceive/node`, a
|
|
76
|
+
server-adapter dependency. For a frontend-only project, use
|
|
77
|
+
`npx skills add OpenReceive/openreceive`.
|
|
78
|
+
See [agent setup](https://openreceive.org/agents). The bundled installers write
|
|
79
|
+
to `.agents/skills/`; use `--dir .claude/skills` for Claude Code. They replace
|
|
80
|
+
only `integrate-openreceive` and `debug-openreceive-payment`, preserving
|
|
81
|
+
unrelated skills.
|
|
@@ -170,6 +170,7 @@ var OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES = {
|
|
|
170
170
|
* grid. A hash the server will not serve is ignored.
|
|
171
171
|
*/
|
|
172
172
|
resumePaymentHash: "resume-payment-hash",
|
|
173
|
+
resumePaymentRail: "resume-payment-rail",
|
|
173
174
|
/**
|
|
174
175
|
* Does a payer who closes this tab have a URL that brings them back to this
|
|
175
176
|
* checkout? Only the refund screen's copy depends on it — see
|
|
@@ -805,7 +806,7 @@ function formatSwapLimit(checkout, limitMsats, rounding = "ceil") {
|
|
|
805
806
|
}
|
|
806
807
|
}
|
|
807
808
|
const sats = rounding === "floor" ? Math.floor(limitMsats / 1e3) : Math.ceil(limitMsats / 1e3);
|
|
808
|
-
return `${sats} ${sats === 1 ? "sat" : "sats"}`;
|
|
809
|
+
return `${sats.toLocaleString("en-US")} ${sats === 1 ? "sat" : "sats"}`;
|
|
809
810
|
}
|
|
810
811
|
function scaleFiatLimitExact(input) {
|
|
811
812
|
const fiat = parseDecimal(input.fiatValue);
|
|
@@ -2475,7 +2476,8 @@ function mergeMintedCheckout(checkout, previous) {
|
|
|
2475
2476
|
payment_methods: previous.payment_methods ?? checkout.payment_methods,
|
|
2476
2477
|
// Prepare answered with it and create echoes it, but a host that only
|
|
2477
2478
|
// returns it from one of the two must not lose it at the mint.
|
|
2478
|
-
description: checkout.description ?? previous.description
|
|
2479
|
+
description: checkout.description ?? previous.description,
|
|
2480
|
+
fiat: checkout.fiat ?? previous.fiat
|
|
2479
2481
|
});
|
|
2480
2482
|
}
|
|
2481
2483
|
|
|
@@ -2798,7 +2800,13 @@ function checkoutSnapshot(checkout) {
|
|
|
2798
2800
|
status: "open",
|
|
2799
2801
|
amount_msats: amountMsats,
|
|
2800
2802
|
active: invoice,
|
|
2801
|
-
invoices: [invoice]
|
|
2803
|
+
invoices: [invoice],
|
|
2804
|
+
...invoice.fiat_quote?.fiat === void 0 ? {} : {
|
|
2805
|
+
fiat: {
|
|
2806
|
+
currency: requiredString(invoice.fiat_quote.fiat.currency, "fiat.currency"),
|
|
2807
|
+
value: requiredString(invoice.fiat_quote.fiat.value, "fiat.value")
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2802
2810
|
};
|
|
2803
2811
|
}
|
|
2804
2812
|
function normalizePaymentMethods(value) {
|
|
@@ -3051,6 +3059,11 @@ async function resumeSwapAttempt(options) {
|
|
|
3051
3059
|
return options.snapshot;
|
|
3052
3060
|
}
|
|
3053
3061
|
}
|
|
3062
|
+
async function resumeCheckoutAttempt(options) {
|
|
3063
|
+
if (options.rail !== "lightning") return resumeSwapAttempt(options);
|
|
3064
|
+
if (options.paymentHash.length === 0) return options.snapshot;
|
|
3065
|
+
return requestCheckout({ ...options, previous: options.snapshot });
|
|
3066
|
+
}
|
|
3054
3067
|
async function requestSwapRefund(options) {
|
|
3055
3068
|
const body = await postJson({
|
|
3056
3069
|
fetch: options.fetch,
|
|
@@ -3847,6 +3860,7 @@ export {
|
|
|
3847
3860
|
startSwapRequest,
|
|
3848
3861
|
requestSwapStatus,
|
|
3849
3862
|
resumeSwapAttempt,
|
|
3863
|
+
resumeCheckoutAttempt,
|
|
3850
3864
|
requestSwapRefund,
|
|
3851
3865
|
createCheckoutController,
|
|
3852
3866
|
deriveStatus,
|
package/dist/headless.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AssetIndexEntry, PaymentWizardRoute } from '@openreceive/provider-data';
|
|
2
2
|
export { PaymentWizardRoute, PaymentWizardRouteRequest, getPaymentWizardRoutes, loadPayTutorialImages, payTutorialImage } from '@openreceive/provider-data';
|
|
3
|
-
import { P as PaymentIconId, a as ParseOpenReceiveOptionalIntegerOptions, b as PaymentMethod, R as ResolvedTheme, T as ThemePreference, c as PaymentMethodOption, d as TickingValueOptions, e as TickingValueController, f as TransientFeedbackOptions, g as TransientFeedbackController, C as CheckoutInvoiceSnapshot, U as UnixSeconds, S as SwapDisplayModel, h as CheckoutSnapshot, i as SwapDepositRisk, j as CheckoutState, k as TransactionDetailsInput, l as TransactionDetailRow, m as CreateCheckoutStateOptions, n as CheckoutStatusModelInput, o as CheckoutStatusModel, p as CheckoutPaymentMethod, B as BrowserLoggerOption, q as ThemeAttributeTarget, r as CheckoutElementAttributes, s as CheckoutElementAttributeOptions, t as CheckoutElementEventHandlers, u as CheckoutElementListeners, v as CreateCheckoutShellOptions, w as CheckoutShellElements, x as CheckoutShellOptions, y as CheckoutShellModel, z as CreateOpenReceiveThemeToggleElementOptions, A as ThemeToggleElementAttributeOptions, D as ThemeToggleElementAttributes, E as StoredThemeModelOptions, F as ThemeModel, G as ThemeModelOptions, H as ReadThemePreferenceOptions, I as ThemeControlTargets, J as ThemeStorageOptions, K as PaymentWizardControllerOptions, L as PaymentWizardController, M as PaymentWizardSelection, N as PaymentWizardModel, W as WizardRouteAssetDisplay, O as WizardRouteDisplay, Q as PaymentWizardSelectionAction } from './status-
|
|
4
|
-
export { V as BrowserLogContext, X as BrowserLogger, Y as BrowserRequestError, Z as CheckoutController, _ as CheckoutControllerOptions, $ as CheckoutPhase, a0 as CheckoutShellRootAttributes, a1 as CheckoutStatusRefresh, a2 as OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES, a3 as OPENRECEIVE_CHECKOUT_DATA_SELECTORS, a4 as OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES, a5 as OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS, a6 as OPENRECEIVE_CHECKOUT_ELEMENT_PARTS, a7 as OPENRECEIVE_CHECKOUT_ELEMENT_PART_SELECTORS, a8 as OPENRECEIVE_CHECKOUT_ELEMENT_SLOTS, a9 as OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME, aa as OPENRECEIVE_COPY_FEEDBACK_MS, ab as OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS, ac as OPENRECEIVE_DEFAULT_PREFIX, ad as OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES, ae as OPENRECEIVE_PAYMENT_WIZARD_SELECTORS, af as OPENRECEIVE_PROVIDER_PREVIEW_LIMIT, ag as OPENRECEIVE_STYLE_ROOT_ATTRIBUTE, ah as OPENRECEIVE_STYLE_ROOT_SELECTOR, ai as OPENRECEIVE_THEME_STORAGE_KEY, aj as OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES, ak as OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS, al as OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS, am as OPENRECEIVE_THEME_TOGGLE_ELEMENT_PART_SELECTORS, an as OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME, ao as QrEncoder, ap as QrSvgController, aq as QrSvgControllerOptions, ar as Status, as as SwapCopyRow, at as SwapRefundStaging, au as WizardProviderDisplay, av as assertDisplayInvoice, aw as copyInvoice, ax as createCheckoutActionEvent, ay as createCheckoutController, az as createCheckoutErrorEvent, aA as createCheckoutProviderCopyEvent, aB as createCheckoutStateEvent, aC as createQrPayloadSvg, aD as createQrSvg, aE as createQrSvgController, aF as createStatusFetcher, aG as createThemeChangeEvent, aH as currentCheckoutUrl, aI as deriveCheckoutStateLabels, aJ as deriveStatus, aK as enterCheckoutResumePath, aL as escapeHtml, aM as formatAmountCaption, aN as formatDepositAmount, aO as formatFiatAmount, aP as formatMsats, aQ as formatSwapLimit, aR as formatUnixTime, aS as openWallet, aT as paymentIconSvgs, aU as prepareCheckout, aV as requestCheckout } from './status-
|
|
3
|
+
import { P as PaymentIconId, a as ParseOpenReceiveOptionalIntegerOptions, b as PaymentMethod, R as ResolvedTheme, T as ThemePreference, c as PaymentMethodOption, d as TickingValueOptions, e as TickingValueController, f as TransientFeedbackOptions, g as TransientFeedbackController, C as CheckoutInvoiceSnapshot, U as UnixSeconds, S as SwapDisplayModel, h as CheckoutSnapshot, i as SwapDepositRisk, j as CheckoutState, k as TransactionDetailsInput, l as TransactionDetailRow, m as CreateCheckoutStateOptions, n as CheckoutStatusModelInput, o as CheckoutStatusModel, p as CheckoutPaymentMethod, B as BrowserLoggerOption, q as ThemeAttributeTarget, r as CheckoutElementAttributes, s as CheckoutElementAttributeOptions, t as CheckoutElementEventHandlers, u as CheckoutElementListeners, v as CreateCheckoutShellOptions, w as CheckoutShellElements, x as CheckoutShellOptions, y as CheckoutShellModel, z as CreateOpenReceiveThemeToggleElementOptions, A as ThemeToggleElementAttributeOptions, D as ThemeToggleElementAttributes, E as StoredThemeModelOptions, F as ThemeModel, G as ThemeModelOptions, H as ReadThemePreferenceOptions, I as ThemeControlTargets, J as ThemeStorageOptions, K as PaymentWizardControllerOptions, L as PaymentWizardController, M as PaymentWizardSelection, N as PaymentWizardModel, W as WizardRouteAssetDisplay, O as WizardRouteDisplay, Q as PaymentWizardSelectionAction } from './status-BC2Rl8KA.js';
|
|
4
|
+
export { V as BrowserLogContext, X as BrowserLogger, Y as BrowserRequestError, Z as CheckoutController, _ as CheckoutControllerOptions, $ as CheckoutPhase, a0 as CheckoutShellRootAttributes, a1 as CheckoutStatusRefresh, a2 as OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES, a3 as OPENRECEIVE_CHECKOUT_DATA_SELECTORS, a4 as OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES, a5 as OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS, a6 as OPENRECEIVE_CHECKOUT_ELEMENT_PARTS, a7 as OPENRECEIVE_CHECKOUT_ELEMENT_PART_SELECTORS, a8 as OPENRECEIVE_CHECKOUT_ELEMENT_SLOTS, a9 as OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME, aa as OPENRECEIVE_COPY_FEEDBACK_MS, ab as OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS, ac as OPENRECEIVE_DEFAULT_PREFIX, ad as OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES, ae as OPENRECEIVE_PAYMENT_WIZARD_SELECTORS, af as OPENRECEIVE_PROVIDER_PREVIEW_LIMIT, ag as OPENRECEIVE_STYLE_ROOT_ATTRIBUTE, ah as OPENRECEIVE_STYLE_ROOT_SELECTOR, ai as OPENRECEIVE_THEME_STORAGE_KEY, aj as OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES, ak as OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS, al as OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS, am as OPENRECEIVE_THEME_TOGGLE_ELEMENT_PART_SELECTORS, an as OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME, ao as QrEncoder, ap as QrSvgController, aq as QrSvgControllerOptions, ar as Status, as as SwapCopyRow, at as SwapRefundStaging, au as WizardProviderDisplay, av as assertDisplayInvoice, aw as copyInvoice, ax as createCheckoutActionEvent, ay as createCheckoutController, az as createCheckoutErrorEvent, aA as createCheckoutProviderCopyEvent, aB as createCheckoutStateEvent, aC as createQrPayloadSvg, aD as createQrSvg, aE as createQrSvgController, aF as createStatusFetcher, aG as createThemeChangeEvent, aH as currentCheckoutUrl, aI as deriveCheckoutStateLabels, aJ as deriveStatus, aK as enterCheckoutResumePath, aL as escapeHtml, aM as formatAmountCaption, aN as formatDepositAmount, aO as formatFiatAmount, aP as formatMsats, aQ as formatSwapLimit, aR as formatUnixTime, aS as openWallet, aT as paymentIconSvgs, aU as prepareCheckout, aV as requestCheckout } from './status-BC2Rl8KA.js';
|
|
5
5
|
import '@openreceive/core';
|
|
6
6
|
|
|
7
7
|
/** Each packaged payment icon as a `data:image/svg+xml` URI, keyed by id. */
|
|
@@ -662,6 +662,8 @@ interface CheckoutComponentProps {
|
|
|
662
662
|
* attempt only until it expires. See docs/guides/swap-refunds.md.
|
|
663
663
|
*/
|
|
664
664
|
readonly resumePaymentHash?: string;
|
|
665
|
+
/** Rail of the remembered attempt; defaults to swap for existing integrations. */
|
|
666
|
+
readonly resumePaymentRail?: "lightning" | "swap";
|
|
665
667
|
/**
|
|
666
668
|
* Does a payer who closes this tab have a URL that brings them back to this
|
|
667
669
|
* checkout? It decides ONE thing: which of the two refund-return warnings the
|
|
@@ -676,7 +678,7 @@ interface CheckoutComponentProps {
|
|
|
676
678
|
readonly resumable?: boolean;
|
|
677
679
|
}
|
|
678
680
|
/** Which props only do something in create mode (no `checkout` snapshot). */
|
|
679
|
-
declare const CREATE_MODE_ONLY_PROPS: readonly ["metadata", "syncUrl", "resumePathPrefix", "routeReference", "resumePaymentHash"];
|
|
681
|
+
declare const CREATE_MODE_ONLY_PROPS: readonly ["metadata", "syncUrl", "resumePathPrefix", "routeReference", "resumePaymentHash", "resumePaymentRail"];
|
|
680
682
|
type CreateModeOnlyProp = (typeof CREATE_MODE_ONLY_PROPS)[number];
|
|
681
683
|
/**
|
|
682
684
|
* What the check reads: the two mode props plus the create-only ones, derived
|
|
@@ -910,6 +912,13 @@ declare function resumeSwapAttempt(options: SwapRequestOptions & {
|
|
|
910
912
|
readonly paymentHash: string;
|
|
911
913
|
readonly snapshot: CheckoutSnapshot;
|
|
912
914
|
}): Promise<CheckoutSnapshot>;
|
|
915
|
+
/** Resume the host-selected rail; old callers continue to use swap recovery. */
|
|
916
|
+
declare function resumeCheckoutAttempt(options: SwapRequestOptions & {
|
|
917
|
+
readonly reference: string;
|
|
918
|
+
readonly paymentHash: string;
|
|
919
|
+
readonly rail?: "lightning" | "swap";
|
|
920
|
+
readonly snapshot: CheckoutSnapshot;
|
|
921
|
+
}): Promise<CheckoutSnapshot>;
|
|
913
922
|
/**
|
|
914
923
|
* Review-or-confirm a swap refund for one attempt, and return the normalized
|
|
915
924
|
* swap invoice — carrying the staged refund address on review.
|
|
@@ -1249,4 +1258,4 @@ declare function createPaymentWizardModel(selection: PaymentWizardSelection): Pa
|
|
|
1249
1258
|
declare function updatePaymentWizardSelection(selection: PaymentWizardSelection, action: PaymentWizardSelectionAction): PaymentWizardSelection;
|
|
1250
1259
|
declare function createPaymentWizardController(options?: PaymentWizardControllerOptions): PaymentWizardController;
|
|
1251
1260
|
|
|
1252
|
-
export { BrowserLoggerOption, type CheckoutComponentProps, CheckoutElementAttributeOptions, CheckoutElementAttributes, CheckoutElementEventHandlers, CheckoutElementListeners, CheckoutInvoiceSnapshot, CheckoutPaymentMethod, type CheckoutPropsValidation, type CheckoutSession, type CheckoutSessionOptions, CheckoutShellElements, CheckoutShellModel, CheckoutShellOptions, CheckoutSnapshot, CheckoutState, CheckoutStatusModel, type CheckoutSwapOptions, CreateCheckoutShellOptions, type DetailLinkKind, type MethodGridContinueDisplay, type MethodGridDisplay, type MethodGridDisplayEntry, type MethodGridEntry, type MethodGridGroupDisplay, PaymentIconId, PaymentMethod, PaymentWizardController, PaymentWizardModel, PaymentWizardSelection, ResolvedTheme, StoredThemeModelOptions, SwapDepositRisk, SwapDisplayModel, type SwapLimitContext, type SwapMethodGroup, type SwapSelection, type SwapUnavailableModel, ThemeModel, ThemeModelOptions, ThemePreference, ThemeToggleElementAttributeOptions, ThemeToggleElementAttributes, TransactionDetailRow, TransactionDetailsInput, type TransactionDetailsSource, TransientFeedbackController, UnixSeconds, WizardRouteAssetDisplay, WizardRouteDisplay, type WizardSelection, applyCheckoutElementAttributes, assetButtonClasses, buildMethodGridEntries, checkoutElementStyles, checkoutLabels, createBlockExplorerUrl, createCheckoutElementAttributes, createCheckoutElementListeners, createCheckoutSession, createCheckoutShell, createCheckoutShellModel, createCheckoutSnapshotFromInvoice, createCheckoutState, createCheckoutStatusModel, createDetailExternalLink, createLightningInvoiceDecodeUrl, createMethodGridDisplay, createPaymentWizardController, createPaymentWizardModel, createPaymentWizardSelection, createStoredThemeModel, createSwapDisplayModel, createSwapUnavailableModel, createThemeModel, createThemeToggleElement, createThemeToggleElementAttributes, createTickingValueController, createTransactionDetails, createTransactionDetailsFromState, createTransientFeedbackController, createWizardRouteAssetDisplays, createWizardRouteDisplays, formatMethodNetworkDetail, formatNetworkSummary, getExplorerNetwork, getNetworkIcon, getNetworkIconId, getPaymentMethodIcon, getPaymentMethodIconId, getRouteNetworkLabel, getSwapOptionIcon, getSwapOptionIconId, getSwapRefundFormError, getWizardEmptyMessage, isReusableLightningInvoice, mergeAttemptIntoCheckout, mergeAttemptIntoSnapshot, networkButtonClasses, networkCheckClasses, networkMobileRevealClasses, networkSummaryIconClasses, normalizeSwapStartInvoice, orClasses, parseBooleanAttribute, parseMethodPickerKey, parseOptionalInteger, parsePaymentMethod, parseResolvedTheme, parseThemePreference, paymentAccentId, paymentIconUrls, paymentMethods, postJson, readThemePreference, requestSwapRefund, requestSwapStatus, resolveTransactionDetailRows, resolveWizardSelection, resumeSwapAttempt, selectCheckoutDisplayInvoice, selectCurrentSwapInvoice, startSwapRequest, swapAssetMatchesRoute, swapDepositRisk, swapOptionLimitMessage, swapOptionLimitSentence, swapPickerKey, syncStoredThemeControls, toggleStoredThemeControls, updatePaymentWizardSelection, validateCheckoutProps, writeThemePreference };
|
|
1261
|
+
export { BrowserLoggerOption, type CheckoutComponentProps, CheckoutElementAttributeOptions, CheckoutElementAttributes, CheckoutElementEventHandlers, CheckoutElementListeners, CheckoutInvoiceSnapshot, CheckoutPaymentMethod, type CheckoutPropsValidation, type CheckoutSession, type CheckoutSessionOptions, CheckoutShellElements, CheckoutShellModel, CheckoutShellOptions, CheckoutSnapshot, CheckoutState, CheckoutStatusModel, type CheckoutSwapOptions, CreateCheckoutShellOptions, type DetailLinkKind, type MethodGridContinueDisplay, type MethodGridDisplay, type MethodGridDisplayEntry, type MethodGridEntry, type MethodGridGroupDisplay, PaymentIconId, PaymentMethod, PaymentWizardController, PaymentWizardModel, PaymentWizardSelection, ResolvedTheme, StoredThemeModelOptions, SwapDepositRisk, SwapDisplayModel, type SwapLimitContext, type SwapMethodGroup, type SwapSelection, type SwapUnavailableModel, ThemeModel, ThemeModelOptions, ThemePreference, ThemeToggleElementAttributeOptions, ThemeToggleElementAttributes, TransactionDetailRow, TransactionDetailsInput, type TransactionDetailsSource, TransientFeedbackController, UnixSeconds, WizardRouteAssetDisplay, WizardRouteDisplay, type WizardSelection, applyCheckoutElementAttributes, assetButtonClasses, buildMethodGridEntries, checkoutElementStyles, checkoutLabels, createBlockExplorerUrl, createCheckoutElementAttributes, createCheckoutElementListeners, createCheckoutSession, createCheckoutShell, createCheckoutShellModel, createCheckoutSnapshotFromInvoice, createCheckoutState, createCheckoutStatusModel, createDetailExternalLink, createLightningInvoiceDecodeUrl, createMethodGridDisplay, createPaymentWizardController, createPaymentWizardModel, createPaymentWizardSelection, createStoredThemeModel, createSwapDisplayModel, createSwapUnavailableModel, createThemeModel, createThemeToggleElement, createThemeToggleElementAttributes, createTickingValueController, createTransactionDetails, createTransactionDetailsFromState, createTransientFeedbackController, createWizardRouteAssetDisplays, createWizardRouteDisplays, formatMethodNetworkDetail, formatNetworkSummary, getExplorerNetwork, getNetworkIcon, getNetworkIconId, getPaymentMethodIcon, getPaymentMethodIconId, getRouteNetworkLabel, getSwapOptionIcon, getSwapOptionIconId, getSwapRefundFormError, getWizardEmptyMessage, isReusableLightningInvoice, mergeAttemptIntoCheckout, mergeAttemptIntoSnapshot, networkButtonClasses, networkCheckClasses, networkMobileRevealClasses, networkSummaryIconClasses, normalizeSwapStartInvoice, orClasses, parseBooleanAttribute, parseMethodPickerKey, parseOptionalInteger, parsePaymentMethod, parseResolvedTheme, parseThemePreference, paymentAccentId, paymentIconUrls, paymentMethods, postJson, readThemePreference, requestSwapRefund, requestSwapStatus, resolveTransactionDetailRows, resolveWizardSelection, resumeCheckoutAttempt, resumeSwapAttempt, selectCheckoutDisplayInvoice, selectCurrentSwapInvoice, startSwapRequest, swapAssetMatchesRoute, swapDepositRisk, swapOptionLimitMessage, swapOptionLimitSentence, swapPickerKey, syncStoredThemeControls, toggleStoredThemeControls, updatePaymentWizardSelection, validateCheckoutProps, writeThemePreference };
|
package/dist/headless.js
CHANGED
|
@@ -109,6 +109,7 @@ import {
|
|
|
109
109
|
requestSwapStatus,
|
|
110
110
|
resolveTransactionDetailRows,
|
|
111
111
|
resolveWizardSelection,
|
|
112
|
+
resumeCheckoutAttempt,
|
|
112
113
|
resumeSwapAttempt,
|
|
113
114
|
selectCheckoutDisplayInvoice,
|
|
114
115
|
selectCurrentSwapInvoice,
|
|
@@ -119,7 +120,7 @@ import {
|
|
|
119
120
|
swapOptionLimitSentence,
|
|
120
121
|
swapPickerKey,
|
|
121
122
|
updatePaymentWizardSelection
|
|
122
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-LFX45HHQ.js";
|
|
123
124
|
|
|
124
125
|
// src/headless.ts
|
|
125
126
|
import {
|
|
@@ -134,7 +135,8 @@ var CREATE_MODE_ONLY_PROPS = [
|
|
|
134
135
|
"syncUrl",
|
|
135
136
|
"resumePathPrefix",
|
|
136
137
|
"routeReference",
|
|
137
|
-
"resumePaymentHash"
|
|
138
|
+
"resumePaymentHash",
|
|
139
|
+
"resumePaymentRail"
|
|
138
140
|
];
|
|
139
141
|
var warnedSnapshotModeProps = /* @__PURE__ */ new Set();
|
|
140
142
|
function validateCheckoutProps(props) {
|
|
@@ -496,6 +498,9 @@ function createModeAttributes(options) {
|
|
|
496
498
|
if (options.resumePaymentHash !== void 0) {
|
|
497
499
|
attributes[OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES.resumePaymentHash] = options.resumePaymentHash;
|
|
498
500
|
}
|
|
501
|
+
if (options.resumePaymentRail !== void 0) {
|
|
502
|
+
attributes[OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES.resumePaymentRail] = options.resumePaymentRail;
|
|
503
|
+
}
|
|
499
504
|
return attributes;
|
|
500
505
|
}
|
|
501
506
|
function sharedElementAttributes(options) {
|
|
@@ -806,6 +811,7 @@ export {
|
|
|
806
811
|
requestSwapStatus,
|
|
807
812
|
resolveTransactionDetailRows,
|
|
808
813
|
resolveWizardSelection,
|
|
814
|
+
resumeCheckoutAttempt,
|
|
809
815
|
resumeSwapAttempt,
|
|
810
816
|
selectCheckoutDisplayInvoice,
|
|
811
817
|
selectCurrentSwapInvoice,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { aW as BrowserLogLevel } from './status-
|
|
2
|
-
export { aX as BrowserLogEntry, X as BrowserLogger, B as BrowserLoggerOption, Y as BrowserRequestError, Z as CheckoutController, _ as CheckoutControllerOptions, h as CheckoutSnapshot, j as CheckoutState, aY as CopyInvoiceOptions, aZ as GuestCheckoutResumeController, a_ as GuestCheckoutResumeOptions, a$ as OpenWalletOptions, b0 as PrepareCheckoutOptions, b1 as QrOptions, b2 as RequestCheckoutOptions, ar as Status, b3 as StatusInvoiceLike, U as UnixSeconds, aw as copyInvoice, ay as createCheckoutController, b4 as createGuestCheckoutResume, b5 as createGuestOrderFetcher, b6 as createLightningUri, b7 as createQrPngDataUrl, aD as createQrSvg, aJ as deriveStatus, aK as enterCheckoutResumePath, aS as openWallet, aU as prepareCheckout, aV as requestCheckout } from './status-
|
|
1
|
+
import { aW as BrowserLogLevel } from './status-BC2Rl8KA.js';
|
|
2
|
+
export { aX as BrowserLogEntry, X as BrowserLogger, B as BrowserLoggerOption, Y as BrowserRequestError, Z as CheckoutController, _ as CheckoutControllerOptions, h as CheckoutSnapshot, j as CheckoutState, aY as CopyInvoiceOptions, aZ as GuestCheckoutResumeController, a_ as GuestCheckoutResumeOptions, a$ as OpenWalletOptions, b0 as PrepareCheckoutOptions, b1 as QrOptions, b2 as RequestCheckoutOptions, ar as Status, b3 as StatusInvoiceLike, U as UnixSeconds, aw as copyInvoice, ay as createCheckoutController, b4 as createGuestCheckoutResume, b5 as createGuestOrderFetcher, b6 as createLightningUri, b7 as createQrPngDataUrl, aD as createQrSvg, aJ as deriveStatus, aK as enterCheckoutResumePath, aS as openWallet, aU as prepareCheckout, aV as requestCheckout } from './status-BC2Rl8KA.js';
|
|
3
3
|
import '@openreceive/provider-data';
|
|
4
4
|
import '@openreceive/core';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -286,6 +286,7 @@ declare const OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES: {
|
|
|
286
286
|
* grid. A hash the server will not serve is ignored.
|
|
287
287
|
*/
|
|
288
288
|
readonly resumePaymentHash: "resume-payment-hash";
|
|
289
|
+
readonly resumePaymentRail: "resume-payment-rail";
|
|
289
290
|
/**
|
|
290
291
|
* Does a payer who closes this tab have a URL that brings them back to this
|
|
291
292
|
* checkout? Only the refund screen's copy depends on it — see
|
|
@@ -680,6 +681,7 @@ interface CheckoutElementAttributeOptions {
|
|
|
680
681
|
* the server will not serve is ignored.
|
|
681
682
|
*/
|
|
682
683
|
readonly resumePaymentHash?: string;
|
|
684
|
+
readonly resumePaymentRail?: "lightning" | "swap";
|
|
683
685
|
/**
|
|
684
686
|
* Does a payer who closes this tab have a URL that brings them back? Emitted
|
|
685
687
|
* in every mode, because the refund screen it governs shows in every mode.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openreceive/browser",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.17",
|
|
4
4
|
"description": "Browser helpers and a headless UI engine for Bitcoin Lightning checkout and optional USDT, USDC, SOL and ETH swaps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bitcoin",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"./styles.css": "./dist/styles.css"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@openreceive/core": "0.4.
|
|
34
|
-
"@openreceive/provider-data": "0.4.
|
|
33
|
+
"@openreceive/core": "0.4.17",
|
|
34
|
+
"@openreceive/provider-data": "0.4.17",
|
|
35
35
|
"qrcode": "^1.5.4"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
43
43
|
"dist",
|
|
44
|
-
"skills",
|
|
45
44
|
"README.md",
|
|
46
45
|
"LICENSE"
|
|
47
46
|
],
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: debug-openreceive-payment
|
|
3
|
-
description: >
|
|
4
|
-
Diagnose a failing OpenReceive integration. Use when an OpenReceive-powered
|
|
5
|
-
checkout misbehaves: the server refuses to boot, checkout routes return 403,
|
|
6
|
-
404, 409, or 5xx, a paid invoice never settles, a swap refund seems
|
|
7
|
-
unreachable, or the checkout UI renders nothing.
|
|
8
|
-
license: MIT
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Debug an OpenReceive payment
|
|
12
|
-
|
|
13
|
-
Work top-down: configuration, then the request, then settlement. Every guide
|
|
14
|
-
URL below is raw markdown — fetch it when the step needs it.
|
|
15
|
-
|
|
16
|
-
## 1. Run the doctor first
|
|
17
|
-
|
|
18
|
-
```sh
|
|
19
|
-
npx openreceive doctor # Node version, NWC_URI, swap config, wallet probe
|
|
20
|
-
npx openreceive doctor --db <db> # + are openreceive_payments/openreceive_meta migrated?
|
|
21
|
-
npx openreceive doctor --url http://localhost:3000 # + are the routes actually mounted?
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Each failing line states its own fix. `npx openreceive debug-report` prints the
|
|
25
|
-
same diagnostics redacted, always exit 0 — safe to share.
|
|
26
|
-
|
|
27
|
-
## 2. Boot failures
|
|
28
|
-
|
|
29
|
-
| Symptom | Cause and fix |
|
|
30
|
-
| --- | --- |
|
|
31
|
-
| `MISSING_NWC` / "needs a receive-only NWC code" | `NWC_URI` is not in the server process env. A `.env` file alone is not enough — something must load it (`dotenv/config`, Next auto-load). Get a code: https://openreceive.org/get_a_nwc_code_to_receive_payments |
|
|
32
|
-
| `INVALID_NWC` / "not a valid NWC code" | The value is malformed (must be `nostr+walletconnect://` with 64-hex pubkey and secret, ≥1 `wss` relay). Re-copy it from the wallet. |
|
|
33
|
-
| "NOT receive-only" / spend methods advertised | The wallet minted a spend-capable code; OpenReceive fails closed because a leak would drain the wallet. Mint a receive-only code. Overriding (`allowSpendCapableWallet` / `OPENRECEIVE_ALLOW_SPEND_CAPABLE_NWC`) is a last resort. |
|
|
34
|
-
| Wallet preflight failed (methods/encryption) | The wallet must advertise `make_invoice` + `list_transactions` and NIP-04 or NIP-44 v2. Use a compatible wallet. |
|
|
35
|
-
| "The openreceive_meta table does not exist" / raw `no such table: openreceive_payments` | The migration was never applied. Node: `npx openreceive scaffold payments --orm <yours>`, then run the emitted migration through the app's normal workflow. Rails: `bin/rails generate openreceive:install`, then `bin/rails db:migrate`. https://openreceive.org/guides/storage.md |
|
|
36
|
-
| "requires amountFor / onPaid / authorize / host" | The factory is missing a required hook — see the host contract in https://openreceive.org/guides/api-reference.md |
|
|
37
|
-
|
|
38
|
-
## 3. Request-time errors from the routes
|
|
39
|
-
|
|
40
|
-
| Status | Meaning | Where to look |
|
|
41
|
-
| --- | --- | --- |
|
|
42
|
-
| 403 FORBIDDEN | Your own `authorize` hook denied it, or the request looked cross-site. Check the session/cookie actually reaches the checkout routes. https://openreceive.org/guides/authorization.md |
|
|
43
|
-
| Never 403s — any visitor can mint, poll, or refund for any reference | The opposite failure: on Rails the generated `config.authorize = OpenReceive::ALLOW_ALL_AUTHORIZE` placeholder is still installed (the engine warns at boot; `bin/rails openreceive:doctor` reports it). Replace it with the app's real ownership check. https://openreceive.org/guides/authorization.md |
|
|
44
|
-
| 404 NOT_FOUND | `amountFor` returned `null` (unknown reference), or the `payment_hash` does not belong to that reference. |
|
|
45
|
-
| 409 CONFLICT | **Normal state, not a bug**: the reference already settled, or an unpaid checkout for that method is already live. Show it as order state; never retry-loop. |
|
|
46
|
-
| 503 retryable | The host hook failed while persisting the attempt (instructions withheld), or the wallet is unavailable. Read the server log for the underlying error. |
|
|
47
|
-
| Framework 404 / HTML error page | The router is not mounted, or mounted at a different prefix than the UI's `prefix` prop. `doctor --url` distinguishes these. |
|
|
48
|
-
|
|
49
|
-
## 4. Paid but never settles
|
|
50
|
-
|
|
51
|
-
- Settlement is opportunistic: any OpenReceive request runs one reconcile pass
|
|
52
|
-
through a durable gate (min 3s between wallet scans, stretched by invoice
|
|
53
|
-
age). A quiet server settles on the next request — or run the optional
|
|
54
|
-
notification worker. No timer is missing; that is the design.
|
|
55
|
-
- An unpaid attempt closes only after a successful wallet scan at/after expiry
|
|
56
|
-
plus a 900s grace constant — a local clock alone never closes one. `expired`
|
|
57
|
-
arriving "late" is correct.
|
|
58
|
-
- `onPaid` runs once per reference, first settled attempt only, inside the
|
|
59
|
-
settlement transaction. If your fulfillment did not run, check whether the
|
|
60
|
-
guarded `UPDATE … WHERE` matched zero rows (already transitioned).
|
|
61
|
-
https://openreceive.org/guides/storage.md
|
|
62
|
-
|
|
63
|
-
## 5. Swaps and refunds
|
|
64
|
-
|
|
65
|
-
- A deposit that arrives short or late becomes `refund_required`; the payer
|
|
66
|
-
claims it on a second visit. That needs a per-order URL you serve
|
|
67
|
-
(`/checkout/:reference`, `syncUrl` on the drop-ins). Keep the
|
|
68
|
-
`payment_hash`: `POST /swaps/status` reopens the attempt with no expiry
|
|
69
|
-
window, while re-picking the coin mints a new deposit after ~30 minutes.
|
|
70
|
-
- Refunds exist only for swap deposits from `refund_required`. There is **no
|
|
71
|
-
Lightning refund** — the wallet cannot spend. Do not chase one.
|
|
72
|
-
https://openreceive.org/guides/swap-refunds.md
|
|
73
|
-
- "Payer reports two different amounts on a stablecoin checkout" (50.05 or
|
|
74
|
-
50.03?): the deposit amount is a token quantity, `fee.pay_in_fiat` is its
|
|
75
|
-
fiat valuation. Only `swap.deposit_amount` is an instruction. From 0.4.10 the
|
|
76
|
-
packaged checkout renders a USD stablecoin's breakdown in the token and never
|
|
77
|
-
shows `pay_in_fiat`; on an older bundle, upgrade `@openreceive/*`. To verify,
|
|
78
|
-
read the row's `deposit_amount` and `fee` and confirm the UI shows only the
|
|
79
|
-
deposit amount. A custom UI must call `createSwapFeeBreakdown(fee, swap)`
|
|
80
|
-
with the swap, not the fee alone.
|
|
81
|
-
|
|
82
|
-
## 6. Checkout UI shows nothing
|
|
83
|
-
|
|
84
|
-
- The components require `prefix` — the exact base path the routes are mounted
|
|
85
|
-
at (`"/openreceive"` unless you changed it).
|
|
86
|
-
- Import the stylesheet (`@openreceive/react/styles.css` or the elements
|
|
87
|
-
sheet).
|
|
88
|
-
- "invoice must not be an NWC connection string" means a server secret leaked
|
|
89
|
-
into a browser payload — stop and fix the server response; never render it.
|
|
90
|
-
https://openreceive.org/guides/frontend-checkout.md
|
|
91
|
-
|
|
92
|
-
## Still stuck
|
|
93
|
-
|
|
94
|
-
The full route/option/error reference:
|
|
95
|
-
https://openreceive.org/guides/api-reference.md · machine-readable contract:
|
|
96
|
-
https://openreceive.org/openapi.yaml · library bug reports:
|
|
97
|
-
https://openreceive.org/contact
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: integrate-openreceive
|
|
3
|
-
description: >
|
|
4
|
-
Integrate OpenReceive inbound Bitcoin Lightning payments into an application.
|
|
5
|
-
Use when adding Bitcoin, Lightning, or crypto checkout to a Node.js, Express,
|
|
6
|
-
Fastify, Next.js, Rails, React, Vue, Svelte, Angular, or plain-HTML
|
|
7
|
-
application with OpenReceive (the @openreceive/* npm packages or the
|
|
8
|
-
openreceive-rails gem), or when connecting a BTCPay Server store to a
|
|
9
|
-
receive-only NWC wallet with the OpenReceive plugin.
|
|
10
|
-
license: MIT
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Integrate OpenReceive
|
|
14
|
-
|
|
15
|
-
OpenReceive is a payment library that runs inside the application you are
|
|
16
|
-
editing. It mounts HTTP routes there, issues Lightning invoices against a
|
|
17
|
-
wallet the merchant already controls, and calls back into your code when one
|
|
18
|
-
settles. There is no OpenReceive account and no API key; funds land directly in
|
|
19
|
-
the merchant's wallet. The one required credential is a **receive-only NWC
|
|
20
|
-
code** (`NWC_URI`).
|
|
21
|
-
|
|
22
|
-
## Pick the stack, then follow its directions
|
|
23
|
-
|
|
24
|
-
1. Identify the server stack of the application you are in.
|
|
25
|
-
2. Open the matching reference — it is complete (quickstart inlined) and needs
|
|
26
|
-
no network access:
|
|
27
|
-
- Node, Express: [references/node.md](references/node.md)
|
|
28
|
-
- Node, Fastify: [references/fastify.md](references/fastify.md)
|
|
29
|
-
- Node, Next.js App Router: [references/next.md](references/next.md)
|
|
30
|
-
- Rails: [references/rails.md](references/rails.md)
|
|
31
|
-
- Django: [references/django.md](references/django.md)
|
|
32
|
-
- Laravel: [references/laravel.md](references/laravel.md)
|
|
33
|
-
- WordPress + WooCommerce: [references/woocommerce.md](references/woocommerce.md) — the packaged gateway and merchant settings.
|
|
34
|
-
- BTCPay Server: [references/btcpay.md](references/btcpay.md) — a plugin,
|
|
35
|
-
configured in BTCPay's store UI or Greenfield API; no application code,
|
|
36
|
-
no npm packages, no gem. The rest of this file is about the library.
|
|
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.
|
|
41
|
-
|
|
42
|
-
Install, per adapter — Express: `npm install @openreceive/express @openreceive/react`;
|
|
43
|
-
Fastify: `npm install @openreceive/fastify @openreceive/react`; Next.js:
|
|
44
|
-
`npm install @openreceive/next @openreceive/react`. Swap the UI package (`vue`,
|
|
45
|
-
`svelte`, `angular`, `elements`) for the frontend the app already has. Install
|
|
46
|
-
(Rails): `bundle add openreceive-rails`.
|
|
47
|
-
|
|
48
|
-
## The three server objects
|
|
49
|
-
|
|
50
|
-
| Object | Built with | Talks to |
|
|
51
|
-
| --- | --- | --- |
|
|
52
|
-
| Wallet client | `createOpenReceive()` | the merchant's wallet — mints invoices, reads settlement, holds the NWC code |
|
|
53
|
-
| Host | `createHost()` | your database — your hooks plus the `openreceive_payments` table |
|
|
54
|
-
| HTTP routes | `openReceiveExpress()` / `openReceiveFastify()` / `openReceiveNext()` / the Rails engine | the browser — mounted at `/openreceive` by default |
|
|
55
|
-
|
|
56
|
-
The quickstart's one-factory form (`openReceiveExpress({ wallet, storage,
|
|
57
|
-
amountFor, authorize })`) builds all three; compose them separately only for a
|
|
58
|
-
shared wallet client or a custom repository. The checkout UI
|
|
59
|
-
(`<Checkout reference={...} prefix="/openreceive" />`) is the optional fourth
|
|
60
|
-
piece.
|
|
61
|
-
|
|
62
|
-
## The host contract: authorize, amountFor, onPaid
|
|
63
|
-
|
|
64
|
-
Your application keeps orders, users, prices, and fulfillment. Three hooks are
|
|
65
|
-
the entire bridge — wire them to the models this app already has, never to
|
|
66
|
-
copied demo models:
|
|
67
|
-
|
|
68
|
-
- `amountFor(reference)` — the authoritative price, read from your own data.
|
|
69
|
-
Return `{ currency, value, description }` with `value` a **decimal string**
|
|
70
|
-
(never a float, never payer input), or `null` when there is nothing to pay
|
|
71
|
-
for. The `reference` is your order id: one per thing you fulfill, created
|
|
72
|
-
before checkout, kept across retries, never reused.
|
|
73
|
-
- `authorize({ action, request, resource })` — your own access check, run on
|
|
74
|
-
every request. `resource.reference` is a claim the payer made, not proof;
|
|
75
|
-
read a real session.
|
|
76
|
-
- `onPaid({ reference, paidAt, query })` — fulfillment, run once per reference
|
|
77
|
-
inside the settlement transaction, only for the first settled attempt. Use
|
|
78
|
-
the provided `query`, not your ORM's other connection, and guard the
|
|
79
|
-
transition (`UPDATE … WHERE state = 'awaiting_payment'`).
|
|
80
|
-
|
|
81
|
-
## 409 is a state, not a failure
|
|
82
|
-
|
|
83
|
-
The library serializes attempts per reference. A create that returns **409
|
|
84
|
-
CONFLICT** is normal checkout flow: the reference already settled, or an unpaid
|
|
85
|
-
checkout for that payment method is already in progress. Surface it as order
|
|
86
|
-
state; do not retry-loop it, and do not build an idempotency store around it —
|
|
87
|
-
that serialization is the library's job. (A hook failure while persisting an
|
|
88
|
-
attempt is a **503 retryable**, deliberately distinct.)
|
|
89
|
-
|
|
90
|
-
## Amounts on the deposit panel
|
|
91
|
-
|
|
92
|
-
`swap.deposit_amount` is the ONLY amount a payer is ever told to send, in the
|
|
93
|
-
pay-in token. `swap.fee.pay_in_fiat` / `payout_fiat` are fiat valuations that
|
|
94
|
-
explain the spread (why the deposit exceeds the cart total); they are not
|
|
95
|
-
instructions. For a stablecoin pegged to the fee currency (USDT, USDC) the
|
|
96
|
-
packaged checkout expresses the breakdown in the token and never renders
|
|
97
|
-
`pay_in_fiat` — "$50.03" under "50.05 USDC" reads as the same number with a
|
|
98
|
-
typo. A custom UI gets the same rule from `createSwapFeeBreakdown(fee, swap)`;
|
|
99
|
-
pass the swap, not just the fee.
|
|
100
|
-
|
|
101
|
-
## Secrets
|
|
102
|
-
|
|
103
|
-
`NWC_URI` and `LSC_URI_*` are server-only. Never put them in browser code,
|
|
104
|
-
logs, assets, or tests. Boot fails closed if the NWC code advertises spend
|
|
105
|
-
methods such as `pay_invoice` — mint a receive-only code
|
|
106
|
-
(https://openreceive.org/get_a_nwc_code_to_receive_payments) instead of
|
|
107
|
-
overriding.
|
|
108
|
-
|
|
109
|
-
## Database tables
|
|
110
|
-
|
|
111
|
-
```sh
|
|
112
|
-
npx openreceive scaffold payments --orm prisma # or drizzle | typeorm | sequelize | knex
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
emits the `openreceive_payments` + `openreceive_meta` migration for THIS app's
|
|
116
|
-
database (Rails: `bin/rails generate openreceive:install`); run it through the
|
|
117
|
-
app's normal migration workflow. The tables sit beside your models — no
|
|
118
|
-
relations to them, no separate database, no Redis.
|
|
119
|
-
|
|
120
|
-
## Verify, and test without a real wallet
|
|
121
|
-
|
|
122
|
-
`npx openreceive doctor` checks the configuration and says what to fix.
|
|
123
|
-
|
|
124
|
-
For tests, inject a fake wallet at the stable seams — `client` on
|
|
125
|
-
`createOpenReceive` (any object with `preflight`, `makeInvoice`,
|
|
126
|
-
`listTransactions`) or `config.nwc_client` in Rails — plus
|
|
127
|
-
`StaticPriceProvider` for fiat pricing without a network. Your routes,
|
|
128
|
-
persistence, reconcile, and `onPaid` then run the production code paths.
|
|
129
|
-
Details: https://openreceive.org/guides/host-testing.md
|
|
130
|
-
|
|
131
|
-
## Deeper documentation
|
|
132
|
-
|
|
133
|
-
Fetch on demand — each URL is raw markdown:
|
|
134
|
-
https://openreceive.org/guides/authorization.md ·
|
|
135
|
-
https://openreceive.org/guides/storage.md ·
|
|
136
|
-
https://openreceive.org/guides/api-reference.md ·
|
|
137
|
-
https://openreceive.org/guides/security.md ·
|
|
138
|
-
https://openreceive.org/openapi.yaml (the normative HTTP contract) ·
|
|
139
|
-
https://openreceive.org/llms.txt (the full index)
|