@openreceive/browser 0.4.9 → 0.4.10
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-CPVYEWVM.js → chunk-FIAYCDZO.js} +50 -25
- package/dist/headless.d.ts +2 -2
- package/dist/headless.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{status-Doh8Wz4D.d.ts → status-Cnx1Vv-w.d.ts} +6 -3
- package/package.json +3 -3
- package/skills/debug-openreceive-payment/SKILL.md +8 -0
- package/skills/integrate-openreceive/SKILL.md +11 -0
- package/skills/integrate-openreceive/references/btcpay.md +4 -4
- package/skills/integrate-openreceive/references/django.md +8 -1
- package/skills/integrate-openreceive/references/fastapi.md +8 -1
- package/skills/integrate-openreceive/references/fastify.md +8 -1
- package/skills/integrate-openreceive/references/laravel.md +8 -1
- package/skills/integrate-openreceive/references/next.md +8 -1
- package/skills/integrate-openreceive/references/node.md +8 -1
- package/skills/integrate-openreceive/references/php.md +8 -1
- package/skills/integrate-openreceive/references/rails.md +8 -1
- package/skills/integrate-openreceive/references/woocommerce.md +1 -1
|
@@ -864,7 +864,8 @@ import {
|
|
|
864
864
|
formatDecimal as formatDecimal2,
|
|
865
865
|
parseDecimal as parseDecimal2,
|
|
866
866
|
payInAssetNetwork,
|
|
867
|
-
swapAddressNetworkForPayInAsset
|
|
867
|
+
swapAddressNetworkForPayInAsset,
|
|
868
|
+
swapPayInAssetPeggedTo
|
|
868
869
|
} from "@openreceive/core";
|
|
869
870
|
|
|
870
871
|
// src/internal/unix-seconds.ts
|
|
@@ -881,34 +882,56 @@ function resolveNow(now) {
|
|
|
881
882
|
}
|
|
882
883
|
|
|
883
884
|
// src/internal/checkout-swap-view.ts
|
|
884
|
-
function
|
|
885
|
+
function swapFeeInTokenUnits(fee, payInAsset) {
|
|
886
|
+
return swapPayInAssetPeggedTo(payInAsset) === fee.currency;
|
|
887
|
+
}
|
|
888
|
+
function createSwapFeeBreakdown(fee, swap) {
|
|
885
889
|
if (fee === void 0) return void 0;
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
payIn = parseDecimal2(fee.pay_in_fiat);
|
|
890
|
-
payout = parseDecimal2(fee.payout_fiat);
|
|
891
|
-
} catch {
|
|
892
|
-
return void 0;
|
|
893
|
-
}
|
|
894
|
-
if (payout.units <= 0n) return void 0;
|
|
895
|
-
const scale = Math.max(payIn.scale, payout.scale);
|
|
896
|
-
const payInUnits = payIn.units * 10n ** BigInt(scale - payIn.scale);
|
|
897
|
-
const payoutUnits = payout.units * 10n ** BigInt(scale - payout.scale);
|
|
898
|
-
const feeUnits = payInUnits > payoutUnits ? payInUnits - payoutUnits : 0n;
|
|
899
|
-
const format = (units) => {
|
|
890
|
+
const payout = parseFeeDecimal(fee.payout_fiat);
|
|
891
|
+
if (payout === void 0 || payout.units <= 0n) return void 0;
|
|
892
|
+
const fiat = (units, scale) => {
|
|
900
893
|
const value = formatDecimal2(rescaleHalfUp(units, scale, 2), 2);
|
|
901
894
|
return formatFiatAmount({ currency: fee.currency, value }) ?? `${value} ${fee.currency}`;
|
|
902
895
|
};
|
|
903
|
-
|
|
904
|
-
|
|
896
|
+
if (swap !== void 0 && swapFeeInTokenUnits(fee, swap.pay_in_asset)) {
|
|
897
|
+
const deposit = parseFeeDecimal(swap.deposit_amount);
|
|
898
|
+
if (deposit === void 0) return void 0;
|
|
899
|
+
const { assetLabel } = getSwapAssetDisplay(swap.pay_in_asset);
|
|
900
|
+
const gap2 = decimalGap(deposit, payout);
|
|
901
|
+
return {
|
|
902
|
+
cartTotal: fiat(gap2.base, gap2.scale),
|
|
903
|
+
youSend: `${formatDepositAmount(swap.deposit_amount)} ${assetLabel}`,
|
|
904
|
+
fee: `${formatDecimal2(rescaleHalfUp(gap2.fee, gap2.scale, 2), 2)} ${assetLabel}`,
|
|
905
|
+
feePercent: percentOf(gap2.fee, gap2.base)
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
const payIn = parseFeeDecimal(fee.pay_in_fiat);
|
|
909
|
+
if (payIn === void 0) return void 0;
|
|
910
|
+
const gap = decimalGap(payIn, payout);
|
|
905
911
|
return {
|
|
906
|
-
cartTotal:
|
|
907
|
-
youSend:
|
|
908
|
-
fee:
|
|
909
|
-
feePercent
|
|
912
|
+
cartTotal: fiat(gap.base, gap.scale),
|
|
913
|
+
youSend: fiat(gap.base + gap.fee, gap.scale),
|
|
914
|
+
fee: fiat(gap.fee, gap.scale),
|
|
915
|
+
feePercent: percentOf(gap.fee, gap.base)
|
|
910
916
|
};
|
|
911
917
|
}
|
|
918
|
+
function parseFeeDecimal(value) {
|
|
919
|
+
try {
|
|
920
|
+
return parseDecimal2(value);
|
|
921
|
+
} catch {
|
|
922
|
+
return void 0;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function decimalGap(paid, base) {
|
|
926
|
+
const scale = Math.max(paid.scale, base.scale);
|
|
927
|
+
const paidUnits = paid.units * 10n ** BigInt(scale - paid.scale);
|
|
928
|
+
const baseUnits = base.units * 10n ** BigInt(scale - base.scale);
|
|
929
|
+
return { fee: paidUnits > baseUnits ? paidUnits - baseUnits : 0n, base: baseUnits, scale };
|
|
930
|
+
}
|
|
931
|
+
function percentOf(fee, base) {
|
|
932
|
+
const tenths = roundedDiv(fee * 1000n, base);
|
|
933
|
+
return `${(tenths / 10n).toString()}.${(tenths % 10n).toString()}%`;
|
|
934
|
+
}
|
|
912
935
|
function swapDepositRisk(payInAsset) {
|
|
913
936
|
const network = swapAddressNetworkForPayInAsset(payInAsset);
|
|
914
937
|
if (network === void 0 || network === "ETH") return "chain_ambiguous";
|
|
@@ -929,7 +952,7 @@ function createSwapDisplayModel(invoice, options = {}) {
|
|
|
929
952
|
const depositRisk = swapDepositRisk(swap.pay_in_asset);
|
|
930
953
|
const doubleSpendWarning = `Pay with one method only \u2014 if you already sent ${asset.assetLabel}, do not also pay the Lightning invoice.`;
|
|
931
954
|
const settled = invoice.transaction_state === "settled";
|
|
932
|
-
const feeBreakdown = createSwapFeeBreakdown(swap.fee);
|
|
955
|
+
const feeBreakdown = createSwapFeeBreakdown(swap.fee, swap);
|
|
933
956
|
return {
|
|
934
957
|
provider: swap.provider,
|
|
935
958
|
attemptId: swap.attempt_id ?? invoice.invoice_id,
|
|
@@ -1291,7 +1314,7 @@ function createTransactionDetails(input) {
|
|
|
1291
1314
|
push("Lightning payout", swap.payout_tx_id);
|
|
1292
1315
|
push("Refund address", swap.refund_address, void 0, "address");
|
|
1293
1316
|
push("Refund transaction", swap.refund_tx_id, void 0, "tx");
|
|
1294
|
-
const feeBreakdown = createSwapFeeBreakdown(swap.fee);
|
|
1317
|
+
const feeBreakdown = createSwapFeeBreakdown(swap.fee, swap);
|
|
1295
1318
|
if (feeBreakdown !== void 0) {
|
|
1296
1319
|
push("Cart total", feeBreakdown.cartTotal);
|
|
1297
1320
|
push("You send", feeBreakdown.youSend);
|
|
@@ -1301,7 +1324,9 @@ function createTransactionDetails(input) {
|
|
|
1301
1324
|
);
|
|
1302
1325
|
} else if (swap.fee !== void 0) {
|
|
1303
1326
|
push("Fee currency", swap.fee.currency);
|
|
1304
|
-
|
|
1327
|
+
if (!swapFeeInTokenUnits(swap.fee, swap.pay_in_asset)) {
|
|
1328
|
+
push("Pay-in fiat", swap.fee.pay_in_fiat);
|
|
1329
|
+
}
|
|
1305
1330
|
push("Payout fiat", swap.fee.payout_fiat);
|
|
1306
1331
|
}
|
|
1307
1332
|
}
|
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-Cnx1Vv-w.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-Cnx1Vv-w.js';
|
|
5
5
|
import '@openreceive/core';
|
|
6
6
|
|
|
7
7
|
/** Each packaged payment icon as a `data:image/svg+xml` URI, keyed by id. */
|
package/dist/headless.js
CHANGED
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-Cnx1Vv-w.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-Cnx1Vv-w.js';
|
|
3
3
|
import '@openreceive/provider-data';
|
|
4
4
|
import '@openreceive/core';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -431,14 +431,17 @@ interface CheckoutInvoiceSwapSnapshot {
|
|
|
431
431
|
}
|
|
432
432
|
/**
|
|
433
433
|
* Formatted fee breakout for the deposit panel, explaining why the payer sends more
|
|
434
|
-
* than the cart total. All figures are display-ready
|
|
434
|
+
* than the cart total. All figures are display-ready strings. `cartTotal` is
|
|
435
|
+
* always fiat; `youSend` and `fee` are fiat for a floating asset and token
|
|
436
|
+
* amounts ("50.05 USDC") for a stablecoin pegged to the fee currency, where a
|
|
437
|
+
* fiat valuation would read as the deposit amount with a typo.
|
|
435
438
|
*/
|
|
436
439
|
interface SwapFeeBreakdown {
|
|
437
440
|
/** Cart total delivered to the merchant, e.g. "$10.00". */
|
|
438
441
|
readonly cartTotal: string;
|
|
439
|
-
/**
|
|
442
|
+
/** What the payer sends: its fiat value ("$10.59") or, for a pegged stablecoin, the deposit amount itself ("10.59 USDC"). */
|
|
440
443
|
readonly youSend: string;
|
|
441
|
-
/** The swap fee absorbed by the payer (exchange spread + network fees), e.g. "$0.59". */
|
|
444
|
+
/** The swap fee absorbed by the payer (exchange spread + network fees), e.g. "$0.59" or "0.59 USDC". */
|
|
442
445
|
readonly fee: string;
|
|
443
446
|
/** The fee as a percentage of the cart total, e.g. "5.9%", when computable. */
|
|
444
447
|
readonly feePercent?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openreceive/browser",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
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.10",
|
|
34
|
+
"@openreceive/provider-data": "0.4.10",
|
|
35
35
|
"qrcode": "^1.5.4"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
@@ -70,6 +70,14 @@ same diagnostics redacted, always exit 0 — safe to share.
|
|
|
70
70
|
- Refunds exist only for swap deposits from `refund_required`. There is **no
|
|
71
71
|
Lightning refund** — the wallet cannot spend. Do not chase one.
|
|
72
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.
|
|
73
81
|
|
|
74
82
|
## 6. Checkout UI shows nothing
|
|
75
83
|
|
|
@@ -86,6 +86,17 @@ state; do not retry-loop it, and do not build an idempotency store around it —
|
|
|
86
86
|
that serialization is the library's job. (A hook failure while persisting an
|
|
87
87
|
attempt is a **503 retryable**, deliberately distinct.)
|
|
88
88
|
|
|
89
|
+
## Amounts on the deposit panel
|
|
90
|
+
|
|
91
|
+
`swap.deposit_amount` is the ONLY amount a payer is ever told to send, in the
|
|
92
|
+
pay-in token. `swap.fee.pay_in_fiat` / `payout_fiat` are fiat valuations that
|
|
93
|
+
explain the spread (why the deposit exceeds the cart total); they are not
|
|
94
|
+
instructions. For a stablecoin pegged to the fee currency (USDT, USDC) the
|
|
95
|
+
packaged checkout expresses the breakdown in the token and never renders
|
|
96
|
+
`pay_in_fiat` — "$50.03" under "50.05 USDC" reads as the same number with a
|
|
97
|
+
typo. A custom UI gets the same rule from `createSwapFeeBreakdown(fee, swap)`;
|
|
98
|
+
pass the swap, not just the fee.
|
|
99
|
+
|
|
89
100
|
## Secrets
|
|
90
101
|
|
|
91
102
|
`NWC_URI` and `LSC_URI_*` are server-only. Never put them in browser code,
|
|
@@ -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.10.
|
|
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
|
|
@@ -32,7 +32,7 @@ refund path on the same checkout screen.
|
|
|
32
32
|
|
|
33
33
|
## Step 0 — check the deployment before you change anything
|
|
34
34
|
|
|
35
|
-
1. Confirm the BTCPay Server version is 2.4.
|
|
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
38
|
2. Check whether the plugin is installed (Server Settings → Plugins, or the
|
|
@@ -128,7 +128,7 @@ passes. The page it comes from is https://openreceive.org/guides/quickstart-btcp
|
|
|
128
128
|
|
|
129
129
|
## BTCPay Server quickstart
|
|
130
130
|
|
|
131
|
-
Requires BTCPay Server ≥ 2.4.
|
|
131
|
+
Requires BTCPay Server ≥ 2.4.4.
|
|
132
132
|
|
|
133
133
|
The OpenReceive plugin makes a receive-only NWC wallet the Lightning node of a
|
|
134
134
|
BTCPay store. BTCPay mints every Lightning invoice in that wallet and records
|
|
@@ -143,7 +143,7 @@ invoices, checkout, webhooks and Greenfield API are the host.
|
|
|
143
143
|
|
|
144
144
|
### 1. Prerequisites
|
|
145
145
|
|
|
146
|
-
- A BTCPay Server, version 2.4.
|
|
146
|
+
- A BTCPay Server, version 2.4.4 or later, on any network (mainnet, testnet,
|
|
147
147
|
signet, regtest). The wallet must be on the same network.
|
|
148
148
|
- A receive-only NWC code for the wallet you want to receive into
|
|
149
149
|
([get one here](https://openreceive.org/get_a_nwc_code_to_receive_payments)).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (Django)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a Django project — the app you are already working in. You
|
|
6
6
|
do not need a copy of the OpenReceive source: the Python package is on PyPI
|
|
@@ -231,6 +231,13 @@ built on `@openreceive/browser/headless`. Read that before writing components.
|
|
|
231
231
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
232
232
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
233
233
|
the model gives it.
|
|
234
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
235
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
236
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
237
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
238
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
239
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
240
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
234
241
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
235
242
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
236
243
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (FastAPI)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a FastAPI application — the app you are already working in.
|
|
6
6
|
You do not need a copy of the OpenReceive source: the engine is on PyPI
|
|
@@ -228,6 +228,13 @@ components.
|
|
|
228
228
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
229
229
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
230
230
|
the model gives it.
|
|
231
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
232
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
233
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
234
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
235
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
236
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
237
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
231
238
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
232
239
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
233
240
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (Fastify)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a Fastify application — the app you are already working in.
|
|
6
6
|
You do not need a copy of the OpenReceive source: the packages are on npm, and
|
|
@@ -211,6 +211,13 @@ components.
|
|
|
211
211
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
212
212
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
213
213
|
the model gives it.
|
|
214
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
215
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
216
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
217
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
218
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
219
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
220
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
214
221
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
215
222
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
216
223
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (Laravel)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a Laravel application — the app you are already working in.
|
|
6
6
|
You do not need a copy of the OpenReceive source: the package is on Packagist
|
|
@@ -216,6 +216,13 @@ built on `@openreceive/browser/headless`. Read that before writing components.
|
|
|
216
216
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
217
217
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
218
218
|
the model gives it.
|
|
219
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
220
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
221
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
222
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
223
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
224
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
225
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
219
226
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
220
227
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
221
228
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (Next.js)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a Next.js App Router application — the app you are already
|
|
6
6
|
working in. You do not need a copy of the OpenReceive source: the packages are
|
|
@@ -217,6 +217,13 @@ components.
|
|
|
217
217
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
218
218
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
219
219
|
the model gives it.
|
|
220
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
221
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
222
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
223
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
224
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
225
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
226
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
220
227
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
221
228
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
222
229
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (Node.js)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a Node application — the app you are already working in. You
|
|
6
6
|
do not need a copy of the OpenReceive source: the packages are on npm, and the
|
|
@@ -203,6 +203,13 @@ components.
|
|
|
203
203
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
204
204
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
205
205
|
the model gives it.
|
|
206
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
207
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
208
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
209
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
210
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
211
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
212
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
206
213
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
207
214
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
208
215
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (PHP)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a PHP application — the app you are already working in. You
|
|
6
6
|
do not need a copy of the OpenReceive source: the engine is on Packagist
|
|
@@ -229,6 +229,13 @@ of https://openreceive.org/guides/checkout-ux.md, for a UI built on
|
|
|
229
229
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
230
230
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
231
231
|
the model gives it.
|
|
232
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
233
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
234
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
235
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
236
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
237
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
238
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
232
239
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
233
240
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
234
241
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (Rails)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Add OpenReceive to a Rails application — the app you are already working in. You
|
|
6
6
|
do not need a copy of the OpenReceive source: the gem is on RubyGems, the
|
|
@@ -210,6 +210,13 @@ built on `@openreceive/browser/headless`. Read that before writing components.
|
|
|
210
210
|
- `createSwapDisplayModel` → `display.copyRows` for deposits: address, memo,
|
|
211
211
|
and the bare amount each get a copy row. Render `swap.networkWarning*` as
|
|
212
212
|
the model gives it.
|
|
213
|
+
- `swap.deposit_amount` is the only amount a payer is told to send. Never put
|
|
214
|
+
a fiat valuation of it (`swap.fee.pay_in_fiat`) next to a stablecoin amount:
|
|
215
|
+
"$50.03" under "50.05 USDC" reads as a typo, and the payer asks which one to
|
|
216
|
+
send. The one fiat figure on a USDT/USDC deposit panel is the cart total
|
|
217
|
+
(`payout_fiat`); express "you send" and the fee in the token. Use
|
|
218
|
+
`createSwapFeeBreakdown(fee, swap)` — with the swap, not the fee alone — and
|
|
219
|
+
it applies this for you; SOL and ETH keep a fiat breakdown.
|
|
213
220
|
- `createCheckoutSession` owns mint and swap start. To start swaps, pass its
|
|
214
221
|
`swap` option (`selection`, `prefix`, `fetch`) together. Without it
|
|
215
222
|
`startSwap` reports through `onError`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenReceive agent directions (WordPress + WooCommerce)
|
|
2
2
|
|
|
3
|
-
These directions describe OpenReceive 0.4.
|
|
3
|
+
These directions describe OpenReceive 0.4.10.
|
|
4
4
|
|
|
5
5
|
Install and configure the OpenReceive gateway in the existing WooCommerce
|
|
6
6
|
store. Preserve its theme, checkout, customer accounts, order model and prices.
|