@openreceive/react 0.3.0 → 0.3.1
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/index.d.ts +10 -0
- package/dist/index.js +73 -52
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -244,6 +244,14 @@ interface PaymentWizardProps {
|
|
|
244
244
|
* back to posting the refund itself and carrying the staging locally.
|
|
245
245
|
*/
|
|
246
246
|
readonly swapRefund?: SwapRefundStaging;
|
|
247
|
+
/**
|
|
248
|
+
* Whether this checkout has a URL the payer can come BACK to — `<Checkout
|
|
249
|
+
* syncUrl>`, or a host route of its own that carries the order. It decides
|
|
250
|
+
* which of the two refund-return warnings the deposit panel shows; see
|
|
251
|
+
* `SwapDisplayModel.refundReturnLabel`. Defaults to false, so a payer is
|
|
252
|
+
* never told to bookmark a page that will not bring them back.
|
|
253
|
+
*/
|
|
254
|
+
readonly resumable?: boolean;
|
|
247
255
|
readonly onError?: (error: unknown) => void;
|
|
248
256
|
/**
|
|
249
257
|
* Called when the payer enters or leaves the focused swap flow (a pay-in coin is
|
|
@@ -322,6 +330,8 @@ declare function renderSwapDepositPanel(options: {
|
|
|
322
330
|
readonly onError?: (error: unknown) => void;
|
|
323
331
|
readonly onRefund: (attemptId: string, refundAddress: string, confirm: boolean) => Promise<void>;
|
|
324
332
|
readonly onBackToLightning: () => void;
|
|
333
|
+
/** Does this checkout have a URL to return to? See `refundReturnLabel`. */
|
|
334
|
+
readonly resumable?: boolean;
|
|
325
335
|
}): React.ReactElement | null;
|
|
326
336
|
|
|
327
337
|
declare function useTheme(options?: UseThemeOptions): UseThemeResult;
|
package/dist/index.js
CHANGED
|
@@ -30,16 +30,23 @@ function useCheckoutSession(options) {
|
|
|
30
30
|
reference: () => optionsRef.current.reference(),
|
|
31
31
|
requestCheckout: (reference) => optionsRef.current.requestCheckout?.(reference),
|
|
32
32
|
onSnapshot: (snapshot) => optionsRef.current.onSnapshot?.(snapshot),
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
// The inner `swap` is always present because the session is built once,
|
|
34
|
+
// on the first render, and the host may only gain swap options later.
|
|
35
|
+
// Every accessor reads through `optionsRef`, so a host with no `swap`
|
|
36
|
+
// makes `prefix()` answer undefined and the session reports the missing
|
|
37
|
+
// wiring instead of silently doing nothing.
|
|
38
|
+
swap: {
|
|
39
|
+
selection: {
|
|
40
|
+
started: () => optionsRef.current.swap?.selection.started(),
|
|
41
|
+
setStarted: (invoice) => optionsRef.current.swap?.selection.setStarted(invoice),
|
|
42
|
+
dismissedInvoiceId: () => optionsRef.current.swap?.selection.dismissedInvoiceId() ?? null,
|
|
43
|
+
setDismissedInvoiceId: (invoiceId) => optionsRef.current.swap?.selection.setDismissedInvoiceId(invoiceId),
|
|
44
|
+
setSelectedAsset: (payInAsset) => optionsRef.current.swap?.selection.setSelectedAsset(payInAsset)
|
|
45
|
+
},
|
|
46
|
+
prefix: () => optionsRef.current.swap?.prefix(),
|
|
47
|
+
fetch: () => optionsRef.current.swap?.fetch(),
|
|
48
|
+
onStarted: (invoice) => optionsRef.current.swap?.onStarted?.(invoice)
|
|
41
49
|
},
|
|
42
|
-
onSwapStarted: (invoice) => optionsRef.current.onSwapStarted?.(invoice),
|
|
43
50
|
get logger() {
|
|
44
51
|
return optionsRef.current.logger;
|
|
45
52
|
},
|
|
@@ -56,7 +63,7 @@ import {
|
|
|
56
63
|
OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES,
|
|
57
64
|
copyInvoice as copyInvoiceHelper,
|
|
58
65
|
createCheckoutStatusModel,
|
|
59
|
-
|
|
66
|
+
createQrSvgController,
|
|
60
67
|
formatAmountCaption,
|
|
61
68
|
checkoutLabels,
|
|
62
69
|
openWallet as openWalletHelper,
|
|
@@ -185,14 +192,15 @@ function QRCode(props) {
|
|
|
185
192
|
const onErrorRef = React3.useRef(onError);
|
|
186
193
|
onErrorRef.current = onError;
|
|
187
194
|
React3.useEffect(() => {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
195
|
+
const controller = createQrSvgController({
|
|
196
|
+
onValue: setSvg,
|
|
197
|
+
onError: (error) => onErrorRef.current?.(error),
|
|
198
|
+
...encoder === void 0 ? {} : { encoder },
|
|
199
|
+
width
|
|
193
200
|
});
|
|
201
|
+
controller.show(invoice);
|
|
194
202
|
return () => {
|
|
195
|
-
|
|
203
|
+
controller.stop();
|
|
196
204
|
};
|
|
197
205
|
}, [invoice, encoder, width]);
|
|
198
206
|
return React3.createElement("div", {
|
|
@@ -1194,7 +1202,7 @@ import {
|
|
|
1194
1202
|
createDetailExternalLink,
|
|
1195
1203
|
createSwapDisplayModel,
|
|
1196
1204
|
createTransactionDetails,
|
|
1197
|
-
|
|
1205
|
+
createQrSvgController as createQrSvgController2,
|
|
1198
1206
|
getSwapRefundFormError,
|
|
1199
1207
|
checkoutLabels as checkoutLabels4,
|
|
1200
1208
|
createSwapUnavailableModel,
|
|
@@ -1301,10 +1309,10 @@ function renderSwapUnavailable(quote, checkout) {
|
|
|
1301
1309
|
);
|
|
1302
1310
|
}
|
|
1303
1311
|
function renderSwapDepositPanel(options) {
|
|
1304
|
-
const display = createSwapDisplayModel(
|
|
1305
|
-
options.
|
|
1306
|
-
options.
|
|
1307
|
-
);
|
|
1312
|
+
const display = createSwapDisplayModel(options.invoice, {
|
|
1313
|
+
...options.now === void 0 ? {} : { now: options.now },
|
|
1314
|
+
...options.resumable === void 0 ? {} : { resumable: options.resumable }
|
|
1315
|
+
});
|
|
1308
1316
|
if (display === void 0) return null;
|
|
1309
1317
|
const backButton = React8.createElement(
|
|
1310
1318
|
"button",
|
|
@@ -1454,7 +1462,7 @@ function renderSwapDepositPanel(options) {
|
|
|
1454
1462
|
onError: options.onError
|
|
1455
1463
|
}),
|
|
1456
1464
|
renderSwapSupportDetails(display, options),
|
|
1457
|
-
renderSwapRefundReturnWarning()
|
|
1465
|
+
renderSwapRefundReturnWarning(display)
|
|
1458
1466
|
);
|
|
1459
1467
|
}
|
|
1460
1468
|
if (display.state === "refund_pending" || display.state === "refunded") {
|
|
@@ -1482,7 +1490,7 @@ function renderSwapDepositPanel(options) {
|
|
|
1482
1490
|
})
|
|
1483
1491
|
),
|
|
1484
1492
|
renderSwapSupportDetails(display, options),
|
|
1485
|
-
renderSwapRefundReturnWarning()
|
|
1493
|
+
renderSwapRefundReturnWarning(display)
|
|
1486
1494
|
);
|
|
1487
1495
|
}
|
|
1488
1496
|
if (display.state === "deposit") {
|
|
@@ -1742,13 +1750,13 @@ function renderSwapSupportDetails(display, options) {
|
|
|
1742
1750
|
)
|
|
1743
1751
|
);
|
|
1744
1752
|
}
|
|
1745
|
-
function renderSwapRefundReturnWarning() {
|
|
1753
|
+
function renderSwapRefundReturnWarning(display) {
|
|
1746
1754
|
return React8.createElement(
|
|
1747
1755
|
"p",
|
|
1748
1756
|
{
|
|
1749
1757
|
className: orClasses5.swapWarning
|
|
1750
1758
|
},
|
|
1751
|
-
|
|
1759
|
+
display.refundReturnLabel
|
|
1752
1760
|
);
|
|
1753
1761
|
}
|
|
1754
1762
|
var REFUND_ADDRESS_DRAFT_LIMIT = 8;
|
|
@@ -1845,17 +1853,19 @@ function SwapPayloadQRCode(props) {
|
|
|
1845
1853
|
const [svg, setSvg] = React8.useState("");
|
|
1846
1854
|
const onErrorRef = React8.useRef(props.onError);
|
|
1847
1855
|
onErrorRef.current = props.onError;
|
|
1856
|
+
const { payload, encoder } = props;
|
|
1848
1857
|
React8.useEffect(() => {
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1858
|
+
const controller = createQrSvgController2({
|
|
1859
|
+
onValue: setSvg,
|
|
1860
|
+
onError: (error) => onErrorRef.current?.(error),
|
|
1861
|
+
...encoder === void 0 ? {} : { encoder },
|
|
1862
|
+
width: 220
|
|
1854
1863
|
});
|
|
1864
|
+
controller.showPayload(payload);
|
|
1855
1865
|
return () => {
|
|
1856
|
-
|
|
1866
|
+
controller.stop();
|
|
1857
1867
|
};
|
|
1858
|
-
}, [
|
|
1868
|
+
}, [payload, encoder]);
|
|
1859
1869
|
const imageSource = svg.length === 0 ? void 0 : `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
1860
1870
|
return React8.createElement("img", {
|
|
1861
1871
|
alt: "",
|
|
@@ -1873,9 +1883,7 @@ function PaymentWizard(props) {
|
|
|
1873
1883
|
const [startedSwapInvoice, setStartedSwapInvoice] = React9.useState(null);
|
|
1874
1884
|
const [dismissedSwapInvoiceId, setDismissedSwapInvoiceId] = React9.useState(null);
|
|
1875
1885
|
const [selectedSwapAsset, setSelectedSwapAsset] = React9.useState(null);
|
|
1876
|
-
const [
|
|
1877
|
-
{}
|
|
1878
|
-
);
|
|
1886
|
+
const [selectedSwapAssetByGroup, setSelectedSwapAssetByGroup] = React9.useState({});
|
|
1879
1887
|
const [selectedPickerKey, setSelectedPickerKey] = React9.useState(null);
|
|
1880
1888
|
const autoSwapAttemptedRef = React9.useRef(/* @__PURE__ */ new Set());
|
|
1881
1889
|
const fetcher = props.fetch ?? globalThis.fetch;
|
|
@@ -1884,16 +1892,18 @@ function PaymentWizard(props) {
|
|
|
1884
1892
|
const session = useCheckoutSession({
|
|
1885
1893
|
snapshot: () => checkout,
|
|
1886
1894
|
reference: () => reference,
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
+
swap: {
|
|
1896
|
+
selection: {
|
|
1897
|
+
started: () => startedSwapInvoice ?? void 0,
|
|
1898
|
+
setStarted: setStartedSwapInvoice,
|
|
1899
|
+
dismissedInvoiceId: () => dismissedSwapInvoiceId,
|
|
1900
|
+
setDismissedInvoiceId: setDismissedSwapInvoiceId,
|
|
1901
|
+
setSelectedAsset: setSelectedSwapAsset
|
|
1902
|
+
},
|
|
1903
|
+
prefix: () => props.prefix,
|
|
1904
|
+
fetch: () => fetcher,
|
|
1905
|
+
onStarted: (invoice) => props.onSwapStarted?.(invoice)
|
|
1895
1906
|
},
|
|
1896
|
-
onSwapStarted: (invoice) => props.onSwapStarted?.(invoice),
|
|
1897
1907
|
...props.logger === void 0 ? {} : { logger: props.logger },
|
|
1898
1908
|
onError: (error) => props.onError?.(error)
|
|
1899
1909
|
});
|
|
@@ -1901,7 +1911,7 @@ function PaymentWizard(props) {
|
|
|
1901
1911
|
const clearSwapFocus = React9.useCallback(() => {
|
|
1902
1912
|
setSelectedSwapAsset(null);
|
|
1903
1913
|
setSelectedPickerKey(null);
|
|
1904
|
-
|
|
1914
|
+
setSelectedSwapAssetByGroup({});
|
|
1905
1915
|
session.clearSwapStartError();
|
|
1906
1916
|
props.swapRefund?.clearSwapRefundStaging();
|
|
1907
1917
|
}, [session, props.swapRefund]);
|
|
@@ -2038,6 +2048,7 @@ function PaymentWizard(props) {
|
|
|
2038
2048
|
logger: props.logger,
|
|
2039
2049
|
onError: props.onError,
|
|
2040
2050
|
onRefund: refundSwap,
|
|
2051
|
+
...props.resumable === void 0 ? {} : { resumable: props.resumable },
|
|
2041
2052
|
onBackToLightning: () => {
|
|
2042
2053
|
setDismissedSwapInvoiceId(activeSwapForAsset.invoice_id);
|
|
2043
2054
|
clearSwapFocus();
|
|
@@ -2061,7 +2072,7 @@ function PaymentWizard(props) {
|
|
|
2061
2072
|
checkout: checkout ?? void 0,
|
|
2062
2073
|
selectedPickerKey,
|
|
2063
2074
|
startingAsset: swapStartingAsset,
|
|
2064
|
-
|
|
2075
|
+
selectedSwapAssetByGroup,
|
|
2065
2076
|
// One resolver decides what a tile click MEANS, so the "ask the
|
|
2066
2077
|
// network question only when it is a real question" rule is not
|
|
2067
2078
|
// re-derived here: a single-network group comes back as start_swap
|
|
@@ -2071,7 +2082,7 @@ function PaymentWizard(props) {
|
|
|
2071
2082
|
pickerKey: key,
|
|
2072
2083
|
previousKey,
|
|
2073
2084
|
entries: buildMethodGridEntries(paymentMethods, swapAssetOptions),
|
|
2074
|
-
|
|
2085
|
+
selectedAssetByGroup: selectedSwapAssetByGroup
|
|
2075
2086
|
});
|
|
2076
2087
|
if (resolved.kind === "none") return;
|
|
2077
2088
|
if (resolved.kind === "select_method") {
|
|
@@ -2088,10 +2099,10 @@ function PaymentWizard(props) {
|
|
|
2088
2099
|
return;
|
|
2089
2100
|
}
|
|
2090
2101
|
setSelectedPickerKey(key);
|
|
2091
|
-
|
|
2102
|
+
setSelectedSwapAssetByGroup(resolved.selectedAssetByGroup);
|
|
2092
2103
|
},
|
|
2093
2104
|
onSelectNetwork: (groupKey, payInAsset) => {
|
|
2094
|
-
|
|
2105
|
+
setSelectedSwapAssetByGroup((current) => ({
|
|
2095
2106
|
...current,
|
|
2096
2107
|
[groupKey]: payInAsset
|
|
2097
2108
|
}));
|
|
@@ -2174,6 +2185,7 @@ function PaymentWizard(props) {
|
|
|
2174
2185
|
logger: props.logger,
|
|
2175
2186
|
onError: props.onError,
|
|
2176
2187
|
onRefund: refundSwap,
|
|
2188
|
+
...props.resumable === void 0 ? {} : { resumable: props.resumable },
|
|
2177
2189
|
onBackToLightning: () => {
|
|
2178
2190
|
setDismissedSwapInvoiceId(activeSwapForRoute.invoice_id);
|
|
2179
2191
|
clearSwapFocus();
|
|
@@ -2275,7 +2287,7 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2275
2287
|
const display = createMethodGridDisplay({
|
|
2276
2288
|
entries: buildMethodGridEntries(paymentMethods, options.swapAssetOptions),
|
|
2277
2289
|
selectedPickerKey: options.selectedPickerKey,
|
|
2278
|
-
|
|
2290
|
+
selectedAssetByGroup: options.selectedSwapAssetByGroup,
|
|
2279
2291
|
startingAsset: options.startingAsset,
|
|
2280
2292
|
...options.checkout === void 0 ? {} : { checkout: options.checkout }
|
|
2281
2293
|
});
|
|
@@ -2890,9 +2902,13 @@ function CheckoutView(props) {
|
|
|
2890
2902
|
prefix = OPENRECEIVE_DEFAULT_PREFIX,
|
|
2891
2903
|
metadata: _metadata,
|
|
2892
2904
|
createFetch: _createFetch,
|
|
2893
|
-
|
|
2905
|
+
// Not `_`-prefixed like its neighbours: the view reads it, to infer
|
|
2906
|
+
// `resumable` for the refund screen. Still destructured out so it never
|
|
2907
|
+
// reaches the rendered <section>.
|
|
2908
|
+
syncUrl,
|
|
2894
2909
|
resumePathPrefix: _resumePathPrefix,
|
|
2895
|
-
routeReference
|
|
2910
|
+
routeReference,
|
|
2911
|
+
resumable,
|
|
2896
2912
|
onRequestLightning,
|
|
2897
2913
|
onSwapStarted,
|
|
2898
2914
|
mintingLightning = false,
|
|
@@ -3175,6 +3191,11 @@ function CheckoutView(props) {
|
|
|
3175
3191
|
onSwapStarted,
|
|
3176
3192
|
resolveAssetUrl,
|
|
3177
3193
|
assetBaseUrl,
|
|
3194
|
+
// Whether a payer who closes the tab has a URL to come back
|
|
3195
|
+
// to. Explicit wins — only the host knows about a per-order
|
|
3196
|
+
// route of its own; otherwise infer it from the two props that
|
|
3197
|
+
// put the reference in the URL.
|
|
3198
|
+
resumable: resumable ?? (syncUrl === true || routeReference !== void 0),
|
|
3178
3199
|
// The engine's staged refund address rides the controller this
|
|
3179
3200
|
// model owns, so a poll cannot wipe a review in progress.
|
|
3180
3201
|
swapRefund: checkoutModel
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openreceive/react",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "React checkout components and hooks for OpenReceive (<Checkout>, useCheckout, PaymentWizard).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bitcoin",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"main": "./dist/index.js",
|
|
20
20
|
"types": "./dist/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@openreceive/browser": "0.3.
|
|
23
|
-
"@openreceive/core": "0.3.
|
|
22
|
+
"@openreceive/browser": "0.3.1",
|
|
23
|
+
"@openreceive/core": "0.3.1"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"react": ">=18.0.0"
|