@swype-org/react-sdk 0.1.64 → 0.1.68
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.cjs +240 -221
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +240 -221
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -657,6 +657,24 @@ function normalizeSignature(sig) {
|
|
|
657
657
|
);
|
|
658
658
|
}
|
|
659
659
|
|
|
660
|
+
// src/transferPolling.ts
|
|
661
|
+
async function pollTransferTick(params) {
|
|
662
|
+
const fetchTransfer2 = params.fetchTransfer ?? fetchTransfer;
|
|
663
|
+
const token = await params.getAccessToken();
|
|
664
|
+
if (!token) {
|
|
665
|
+
return { kind: "retry" };
|
|
666
|
+
}
|
|
667
|
+
try {
|
|
668
|
+
const transfer = await fetchTransfer2(params.apiBaseUrl, token, params.transferId);
|
|
669
|
+
return { kind: "success", transfer };
|
|
670
|
+
} catch (err) {
|
|
671
|
+
return {
|
|
672
|
+
kind: "error",
|
|
673
|
+
message: err instanceof Error ? err.message : "Polling error"
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
660
678
|
// src/passkey-delegation.ts
|
|
661
679
|
var PasskeyIframeBlockedError = class extends Error {
|
|
662
680
|
constructor(message = "Passkey creation is not supported in this browser context.") {
|
|
@@ -959,20 +977,22 @@ function useTransferPolling(intervalMs = 3e3) {
|
|
|
959
977
|
}, []);
|
|
960
978
|
const poll = react.useCallback(async () => {
|
|
961
979
|
if (!transferIdRef.current) return;
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
}
|
|
975
|
-
|
|
980
|
+
const result = await pollTransferTick({
|
|
981
|
+
apiBaseUrl,
|
|
982
|
+
transferId: transferIdRef.current,
|
|
983
|
+
getAccessToken
|
|
984
|
+
});
|
|
985
|
+
if (result.kind === "retry") {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
if (result.kind === "error") {
|
|
989
|
+
setError(result.message);
|
|
990
|
+
stopPolling();
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
setError(null);
|
|
994
|
+
setTransfer(result.transfer);
|
|
995
|
+
if (result.transfer.status === "COMPLETED" || result.transfer.status === "FAILED") {
|
|
976
996
|
stopPolling();
|
|
977
997
|
}
|
|
978
998
|
}, [apiBaseUrl, getAccessToken, stopPolling]);
|
|
@@ -1583,6 +1603,41 @@ function isMobileUserAgent(userAgent) {
|
|
|
1583
1603
|
function shouldUseWalletConnector(options) {
|
|
1584
1604
|
return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
|
|
1585
1605
|
}
|
|
1606
|
+
|
|
1607
|
+
// src/mobileFlow.ts
|
|
1608
|
+
function hasActiveWallet(accounts) {
|
|
1609
|
+
return accounts.some((account) => account.wallets.some((wallet) => wallet.status === "ACTIVE"));
|
|
1610
|
+
}
|
|
1611
|
+
function resolvePostAuthStep(state) {
|
|
1612
|
+
if (!state.hasPasskey) {
|
|
1613
|
+
return { step: "create-passkey", clearPersistedFlow: false };
|
|
1614
|
+
}
|
|
1615
|
+
if (state.persistedMobileFlow) {
|
|
1616
|
+
if (state.persistedMobileFlow.isSetup && hasActiveWallet(state.accounts)) {
|
|
1617
|
+
return { step: "deposit", clearPersistedFlow: true };
|
|
1618
|
+
}
|
|
1619
|
+
return { step: "open-wallet", clearPersistedFlow: false };
|
|
1620
|
+
}
|
|
1621
|
+
if ((state.accounts.length === 0 || !hasActiveWallet(state.accounts)) && !state.connectingNewAccount) {
|
|
1622
|
+
return { step: "wallet-picker", clearPersistedFlow: false };
|
|
1623
|
+
}
|
|
1624
|
+
return { step: "deposit", clearPersistedFlow: false };
|
|
1625
|
+
}
|
|
1626
|
+
function resolveRestoredMobileFlow(transferStatus, isSetup) {
|
|
1627
|
+
if (transferStatus === "AUTHORIZED") {
|
|
1628
|
+
return isSetup ? { kind: "resume-setup-deposit", step: "deposit", clearPersistedFlow: true } : { kind: "resume-confirm-sign", step: "confirm-sign", clearPersistedFlow: true };
|
|
1629
|
+
}
|
|
1630
|
+
if (transferStatus === "COMPLETED") {
|
|
1631
|
+
return { kind: "resume-success", step: "success", clearPersistedFlow: true };
|
|
1632
|
+
}
|
|
1633
|
+
if (transferStatus === "FAILED") {
|
|
1634
|
+
return { kind: "resume-failed", step: "success", clearPersistedFlow: true };
|
|
1635
|
+
}
|
|
1636
|
+
if (isSetup) {
|
|
1637
|
+
return { kind: "resume-stale-setup", step: "wallet-picker", clearPersistedFlow: true };
|
|
1638
|
+
}
|
|
1639
|
+
return { kind: "resume-open-wallet", step: "open-wallet", clearPersistedFlow: false };
|
|
1640
|
+
}
|
|
1586
1641
|
var FOOTER_CSS = `
|
|
1587
1642
|
.swype-screen-footer {
|
|
1588
1643
|
padding-bottom: max(24px, env(safe-area-inset-bottom, 24px));
|
|
@@ -1911,137 +1966,6 @@ var inputStyle = (tokens, filled) => ({
|
|
|
1911
1966
|
caretColor: tokens.borderFocus,
|
|
1912
1967
|
transition: "border-color 0.15s ease"
|
|
1913
1968
|
});
|
|
1914
|
-
function LimitSlider({
|
|
1915
|
-
value,
|
|
1916
|
-
min,
|
|
1917
|
-
max,
|
|
1918
|
-
step = 1,
|
|
1919
|
-
onChange,
|
|
1920
|
-
ticks,
|
|
1921
|
-
disabled
|
|
1922
|
-
}) {
|
|
1923
|
-
const { tokens } = useSwypeConfig();
|
|
1924
|
-
const pct = (value - min) / (max - min) * 100;
|
|
1925
|
-
const handleChange = react.useCallback(
|
|
1926
|
-
(e) => onChange(Number(e.target.value)),
|
|
1927
|
-
[onChange]
|
|
1928
|
-
);
|
|
1929
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "swype-slider-wrap", style: wrapperStyle, children: [
|
|
1930
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: trackContainerStyle, children: [
|
|
1931
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: trackBgStyle(tokens.border) }),
|
|
1932
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: trackFillStyle(tokens.accent, pct) }),
|
|
1933
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1934
|
-
"input",
|
|
1935
|
-
{
|
|
1936
|
-
type: "range",
|
|
1937
|
-
min,
|
|
1938
|
-
max,
|
|
1939
|
-
step,
|
|
1940
|
-
value,
|
|
1941
|
-
onChange: handleChange,
|
|
1942
|
-
disabled,
|
|
1943
|
-
style: rangeInputStyle
|
|
1944
|
-
}
|
|
1945
|
-
)
|
|
1946
|
-
] }),
|
|
1947
|
-
ticks && ticks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: ticksStyle, children: ticks.map((tick, i) => {
|
|
1948
|
-
const pctPos = (tick - min) / (max - min) * 100;
|
|
1949
|
-
const isFirst = i === 0;
|
|
1950
|
-
const isLast = i === ticks.length - 1;
|
|
1951
|
-
const label = tick % 1 === 0 ? `$${tick}` : `$${tick.toFixed(2)}`;
|
|
1952
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1953
|
-
"span",
|
|
1954
|
-
{
|
|
1955
|
-
style: tickLabelStyle(tokens.textMuted, pctPos, isFirst, isLast),
|
|
1956
|
-
children: label
|
|
1957
|
-
},
|
|
1958
|
-
tick
|
|
1959
|
-
);
|
|
1960
|
-
}) }),
|
|
1961
|
-
/* @__PURE__ */ jsxRuntime.jsx("style", { children: sliderThumbCss(tokens.accent) })
|
|
1962
|
-
] });
|
|
1963
|
-
}
|
|
1964
|
-
var wrapperStyle = { width: "100%" };
|
|
1965
|
-
var trackContainerStyle = {
|
|
1966
|
-
position: "relative",
|
|
1967
|
-
height: 28,
|
|
1968
|
-
display: "flex",
|
|
1969
|
-
alignItems: "center"
|
|
1970
|
-
};
|
|
1971
|
-
var trackBgStyle = (color) => ({
|
|
1972
|
-
position: "absolute",
|
|
1973
|
-
left: 0,
|
|
1974
|
-
right: 0,
|
|
1975
|
-
height: 4,
|
|
1976
|
-
borderRadius: 2,
|
|
1977
|
-
background: color
|
|
1978
|
-
});
|
|
1979
|
-
var trackFillStyle = (color, pct) => ({
|
|
1980
|
-
position: "absolute",
|
|
1981
|
-
left: 0,
|
|
1982
|
-
width: `${pct}%`,
|
|
1983
|
-
height: 4,
|
|
1984
|
-
borderRadius: 2,
|
|
1985
|
-
background: color
|
|
1986
|
-
});
|
|
1987
|
-
var rangeInputStyle = {
|
|
1988
|
-
position: "absolute",
|
|
1989
|
-
left: 0,
|
|
1990
|
-
right: 0,
|
|
1991
|
-
width: "100%",
|
|
1992
|
-
height: 28,
|
|
1993
|
-
margin: 0,
|
|
1994
|
-
cursor: "pointer",
|
|
1995
|
-
zIndex: 2,
|
|
1996
|
-
WebkitAppearance: "none",
|
|
1997
|
-
appearance: "none",
|
|
1998
|
-
background: "transparent"
|
|
1999
|
-
};
|
|
2000
|
-
var ticksStyle = {
|
|
2001
|
-
position: "relative",
|
|
2002
|
-
height: 18,
|
|
2003
|
-
marginTop: 6
|
|
2004
|
-
};
|
|
2005
|
-
var tickLabelStyle = (color, pct, isFirst, isLast) => ({
|
|
2006
|
-
position: "absolute",
|
|
2007
|
-
left: `${pct}%`,
|
|
2008
|
-
transform: isFirst ? "none" : isLast ? "translateX(-100%)" : "translateX(-50%)",
|
|
2009
|
-
fontSize: "0.72rem",
|
|
2010
|
-
fontWeight: 500,
|
|
2011
|
-
color,
|
|
2012
|
-
whiteSpace: "nowrap"
|
|
2013
|
-
});
|
|
2014
|
-
var sliderThumbCss = (accent) => `
|
|
2015
|
-
.swype-slider-wrap input[type="range"]::-webkit-slider-runnable-track {
|
|
2016
|
-
height: 4px;
|
|
2017
|
-
background: transparent;
|
|
2018
|
-
}
|
|
2019
|
-
.swype-slider-wrap input[type="range"]::-webkit-slider-thumb {
|
|
2020
|
-
-webkit-appearance: none;
|
|
2021
|
-
width: 20px;
|
|
2022
|
-
height: 20px;
|
|
2023
|
-
border-radius: 50%;
|
|
2024
|
-
background: ${accent};
|
|
2025
|
-
border: 3px solid #fff;
|
|
2026
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
|
2027
|
-
cursor: pointer;
|
|
2028
|
-
margin-top: -8px;
|
|
2029
|
-
}
|
|
2030
|
-
.swype-slider-wrap input[type="range"]::-moz-range-track {
|
|
2031
|
-
height: 4px;
|
|
2032
|
-
background: transparent;
|
|
2033
|
-
border: none;
|
|
2034
|
-
}
|
|
2035
|
-
.swype-slider-wrap input[type="range"]::-moz-range-thumb {
|
|
2036
|
-
width: 14px;
|
|
2037
|
-
height: 14px;
|
|
2038
|
-
border-radius: 50%;
|
|
2039
|
-
background: ${accent};
|
|
2040
|
-
border: 3px solid #fff;
|
|
2041
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
|
2042
|
-
cursor: pointer;
|
|
2043
|
-
}
|
|
2044
|
-
`;
|
|
2045
1969
|
|
|
2046
1970
|
// src/assets/logos.ts
|
|
2047
1971
|
function svgToDataUri(svg) {
|
|
@@ -3003,18 +2927,6 @@ var dividerTextStyle = (color) => ({
|
|
|
3003
2927
|
});
|
|
3004
2928
|
var DEFAULT_MAX = 500;
|
|
3005
2929
|
var ABSOLUTE_MIN = 1;
|
|
3006
|
-
function buildTicks(min, max) {
|
|
3007
|
-
if (max <= min) return [min];
|
|
3008
|
-
const range = max - min;
|
|
3009
|
-
const candidates = [1, 2, 5, 10, 25, 50, 100, 250];
|
|
3010
|
-
const step = candidates.find((s) => range / s <= 5) ?? Math.ceil(range / 4);
|
|
3011
|
-
const ticks = [];
|
|
3012
|
-
for (let v = min; v <= max; v += step) {
|
|
3013
|
-
ticks.push(Math.round(v * 100) / 100);
|
|
3014
|
-
}
|
|
3015
|
-
if (ticks[ticks.length - 1] !== max) ticks.push(max);
|
|
3016
|
-
return ticks;
|
|
3017
|
-
}
|
|
3018
2930
|
function SetupScreen({
|
|
3019
2931
|
availableBalance,
|
|
3020
2932
|
tokenCount,
|
|
@@ -3030,9 +2942,22 @@ function SetupScreen({
|
|
|
3030
2942
|
const { tokens } = useSwypeConfig();
|
|
3031
2943
|
const effectiveMax = Math.floor(Math.min(DEFAULT_MAX, availableBalance > 0 ? availableBalance : DEFAULT_MAX) * 100) / 100;
|
|
3032
2944
|
const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
|
|
3033
|
-
const
|
|
3034
|
-
const
|
|
3035
|
-
const [
|
|
2945
|
+
const [limit, setLimit] = react.useState(() => effectiveMax);
|
|
2946
|
+
const [editing, setEditing] = react.useState(false);
|
|
2947
|
+
const [inputValue, setInputValue] = react.useState("");
|
|
2948
|
+
const inputRef = react.useRef(null);
|
|
2949
|
+
const startEditing = react.useCallback(() => {
|
|
2950
|
+
setInputValue(limit.toFixed(2));
|
|
2951
|
+
setEditing(true);
|
|
2952
|
+
requestAnimationFrame(() => inputRef.current?.select());
|
|
2953
|
+
}, [limit]);
|
|
2954
|
+
const commitEdit = react.useCallback(() => {
|
|
2955
|
+
const parsed = parseFloat(inputValue);
|
|
2956
|
+
if (!isNaN(parsed)) {
|
|
2957
|
+
setLimit(Math.min(effectiveMax, Math.max(effectiveMin, Math.round(parsed * 100) / 100)));
|
|
2958
|
+
}
|
|
2959
|
+
setEditing(false);
|
|
2960
|
+
}, [inputValue, effectiveMax, effectiveMin]);
|
|
3036
2961
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3037
2962
|
ScreenLayout,
|
|
3038
2963
|
{
|
|
@@ -3088,19 +3013,33 @@ function SetupScreen({
|
|
|
3088
3013
|
] }),
|
|
3089
3014
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitSectionStyle, children: [
|
|
3090
3015
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: limitLabelStyle(tokens.textMuted), children: "Your One-Tap limit" }),
|
|
3091
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitValueStyle(tokens.text), children: [
|
|
3016
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitValueStyle(tokens.text), children: [
|
|
3092
3017
|
"$",
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3018
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3019
|
+
"input",
|
|
3020
|
+
{
|
|
3021
|
+
ref: inputRef,
|
|
3022
|
+
type: "text",
|
|
3023
|
+
inputMode: "decimal",
|
|
3024
|
+
pattern: "[0-9]*",
|
|
3025
|
+
value: inputValue,
|
|
3026
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
3027
|
+
onBlur: commitEdit,
|
|
3028
|
+
onKeyDown: (e) => {
|
|
3029
|
+
if (e.key === "Enter") commitEdit();
|
|
3030
|
+
},
|
|
3031
|
+
style: limitInputStyle(tokens.text)
|
|
3032
|
+
}
|
|
3033
|
+
)
|
|
3034
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3035
|
+
"div",
|
|
3097
3036
|
{
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3037
|
+
style: { ...limitValueStyle(tokens.text), cursor: "pointer" },
|
|
3038
|
+
onClick: startEditing,
|
|
3039
|
+
children: [
|
|
3040
|
+
"$",
|
|
3041
|
+
limit.toFixed(2)
|
|
3042
|
+
]
|
|
3104
3043
|
}
|
|
3105
3044
|
)
|
|
3106
3045
|
] }),
|
|
@@ -3207,6 +3146,19 @@ var limitValueStyle = (color) => ({
|
|
|
3207
3146
|
color,
|
|
3208
3147
|
marginBottom: 12
|
|
3209
3148
|
});
|
|
3149
|
+
var limitInputStyle = (color) => ({
|
|
3150
|
+
fontSize: "2.2rem",
|
|
3151
|
+
fontWeight: 700,
|
|
3152
|
+
color,
|
|
3153
|
+
background: "transparent",
|
|
3154
|
+
border: "none",
|
|
3155
|
+
borderBottom: "2px solid currentColor",
|
|
3156
|
+
outline: "none",
|
|
3157
|
+
textAlign: "center",
|
|
3158
|
+
width: "5ch",
|
|
3159
|
+
fontFamily: "inherit",
|
|
3160
|
+
padding: 0
|
|
3161
|
+
});
|
|
3210
3162
|
var bannerWrapStyle = { marginBottom: 16 };
|
|
3211
3163
|
var linkStyle = (color) => ({
|
|
3212
3164
|
background: "transparent",
|
|
@@ -4112,6 +4064,8 @@ function OpenWalletScreen({
|
|
|
4112
4064
|
walletName,
|
|
4113
4065
|
deeplinkUri,
|
|
4114
4066
|
loading,
|
|
4067
|
+
error,
|
|
4068
|
+
onRetryStatus,
|
|
4115
4069
|
onLogout
|
|
4116
4070
|
}) {
|
|
4117
4071
|
const { tokens } = useSwypeConfig();
|
|
@@ -4132,12 +4086,14 @@ function OpenWalletScreen({
|
|
|
4132
4086
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4133
4087
|
ScreenLayout,
|
|
4134
4088
|
{
|
|
4135
|
-
footer: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4089
|
+
footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: footerContentStyle, children: [
|
|
4090
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: error }),
|
|
4136
4091
|
!loading && /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: handleOpen, children: [
|
|
4137
4092
|
"Open ",
|
|
4138
4093
|
displayName
|
|
4139
4094
|
] }),
|
|
4140
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4095
|
+
error && onRetryStatus && /* @__PURE__ */ jsxRuntime.jsx(OutlineButton, { onClick: onRetryStatus, children: "Retry status check" }),
|
|
4096
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: hintStyle3(tokens.textMuted), children: loading ? "Preparing authorization..." : error ? "Retry the status check after returning to the browser, or reopen your wallet if needed." : "If your wallet didn't open automatically, tap the button above" })
|
|
4141
4097
|
] }),
|
|
4142
4098
|
children: [
|
|
4143
4099
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
|
|
@@ -4163,6 +4119,11 @@ var contentStyle6 = {
|
|
|
4163
4119
|
textAlign: "center",
|
|
4164
4120
|
padding: "0 24px"
|
|
4165
4121
|
};
|
|
4122
|
+
var footerContentStyle = {
|
|
4123
|
+
display: "flex",
|
|
4124
|
+
flexDirection: "column",
|
|
4125
|
+
gap: 12
|
|
4126
|
+
};
|
|
4166
4127
|
var logoStyle = {
|
|
4167
4128
|
width: 56,
|
|
4168
4129
|
height: 56,
|
|
@@ -4452,24 +4413,6 @@ function buildSelectSourceChoices(options) {
|
|
|
4452
4413
|
}
|
|
4453
4414
|
return chainChoices;
|
|
4454
4415
|
}
|
|
4455
|
-
function resolvePostAuthStep(state) {
|
|
4456
|
-
if (!state.hasPasskey) {
|
|
4457
|
-
return { step: "create-passkey", clearPersistedFlow: false };
|
|
4458
|
-
}
|
|
4459
|
-
const hasActiveWallet = state.accounts.some(
|
|
4460
|
-
(a) => a.wallets.some((w) => w.status === "ACTIVE")
|
|
4461
|
-
);
|
|
4462
|
-
if (state.persistedMobileFlow) {
|
|
4463
|
-
if (hasActiveWallet && !state.mobileSetupInProgress) {
|
|
4464
|
-
return { step: "deposit", clearPersistedFlow: true };
|
|
4465
|
-
}
|
|
4466
|
-
return { step: "open-wallet", clearPersistedFlow: false };
|
|
4467
|
-
}
|
|
4468
|
-
if ((state.accounts.length === 0 || !hasActiveWallet) && !state.connectingNewAccount) {
|
|
4469
|
-
return { step: "wallet-picker", clearPersistedFlow: false };
|
|
4470
|
-
}
|
|
4471
|
-
return { step: "deposit", clearPersistedFlow: false };
|
|
4472
|
-
}
|
|
4473
4416
|
function SwypePayment(props) {
|
|
4474
4417
|
const resetKey = react.useRef(0);
|
|
4475
4418
|
const handleBoundaryReset = react.useCallback(() => {
|
|
@@ -4559,6 +4502,55 @@ function SwypePaymentInner({
|
|
|
4559
4502
|
setConnectingNewAccount(false);
|
|
4560
4503
|
}
|
|
4561
4504
|
}, [getAccessToken, activeCredentialId, apiBaseUrl, depositAmount]);
|
|
4505
|
+
const enterPersistedMobileFlow = react.useCallback((persisted, errorMessage) => {
|
|
4506
|
+
setMobileFlow(true);
|
|
4507
|
+
setDeeplinkUri(persisted.deeplinkUri);
|
|
4508
|
+
setSelectedProviderId(persisted.providerId);
|
|
4509
|
+
pollingTransferIdRef.current = persisted.transferId;
|
|
4510
|
+
mobileSetupFlowRef.current = persisted.isSetup;
|
|
4511
|
+
setError(errorMessage ?? null);
|
|
4512
|
+
setStep("open-wallet");
|
|
4513
|
+
polling.startPolling(persisted.transferId);
|
|
4514
|
+
}, [polling]);
|
|
4515
|
+
const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
|
|
4516
|
+
setTransfer(authorizedTransfer);
|
|
4517
|
+
polling.stopPolling();
|
|
4518
|
+
if (isSetup) {
|
|
4519
|
+
mobileSetupFlowRef.current = false;
|
|
4520
|
+
clearMobileFlowState();
|
|
4521
|
+
try {
|
|
4522
|
+
await reloadAccounts();
|
|
4523
|
+
setError(null);
|
|
4524
|
+
setDeeplinkUri(null);
|
|
4525
|
+
setMobileFlow(false);
|
|
4526
|
+
setStep("deposit");
|
|
4527
|
+
} catch (err) {
|
|
4528
|
+
setError(
|
|
4529
|
+
err instanceof Error ? err.message : "Wallet authorized, but we could not refresh your account yet."
|
|
4530
|
+
);
|
|
4531
|
+
setStep("open-wallet");
|
|
4532
|
+
}
|
|
4533
|
+
return;
|
|
4534
|
+
}
|
|
4535
|
+
mobileSetupFlowRef.current = false;
|
|
4536
|
+
clearMobileFlowState();
|
|
4537
|
+
setError(null);
|
|
4538
|
+
setDeeplinkUri(null);
|
|
4539
|
+
setMobileFlow(false);
|
|
4540
|
+
setStep("confirm-sign");
|
|
4541
|
+
}, [polling.stopPolling, reloadAccounts]);
|
|
4542
|
+
const handleRetryMobileStatus = react.useCallback(() => {
|
|
4543
|
+
setError(null);
|
|
4544
|
+
const currentTransfer = polling.transfer ?? transfer;
|
|
4545
|
+
if (currentTransfer?.status === "AUTHORIZED") {
|
|
4546
|
+
void handleAuthorizedMobileReturn(currentTransfer, mobileSetupFlowRef.current);
|
|
4547
|
+
return;
|
|
4548
|
+
}
|
|
4549
|
+
const transferIdToResume = pollingTransferIdRef.current ?? currentTransfer?.id;
|
|
4550
|
+
if (transferIdToResume) {
|
|
4551
|
+
polling.startPolling(transferIdToResume);
|
|
4552
|
+
}
|
|
4553
|
+
}, [handleAuthorizedMobileReturn, polling, transfer]);
|
|
4562
4554
|
react.useEffect(() => {
|
|
4563
4555
|
if (depositAmount != null) {
|
|
4564
4556
|
setAmount(depositAmount.toString());
|
|
@@ -4656,7 +4648,6 @@ function SwypePaymentInner({
|
|
|
4656
4648
|
hasPasskey: true,
|
|
4657
4649
|
accounts: accts,
|
|
4658
4650
|
persistedMobileFlow: persisted,
|
|
4659
|
-
mobileSetupInProgress: false,
|
|
4660
4651
|
connectingNewAccount: false
|
|
4661
4652
|
});
|
|
4662
4653
|
if (resolved.clearPersistedFlow) {
|
|
@@ -4666,23 +4657,52 @@ function SwypePaymentInner({
|
|
|
4666
4657
|
try {
|
|
4667
4658
|
const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
|
|
4668
4659
|
if (cancelled) return;
|
|
4669
|
-
const
|
|
4670
|
-
|
|
4660
|
+
const mobileResolution = resolveRestoredMobileFlow(
|
|
4661
|
+
existingTransfer.status,
|
|
4662
|
+
persisted.isSetup
|
|
4663
|
+
);
|
|
4664
|
+
if (mobileResolution.kind === "resume-setup-deposit") {
|
|
4665
|
+
await handleAuthorizedMobileReturn(existingTransfer, true);
|
|
4666
|
+
return;
|
|
4667
|
+
}
|
|
4668
|
+
if (mobileResolution.kind === "resume-confirm-sign") {
|
|
4669
|
+
await handleAuthorizedMobileReturn(existingTransfer, false);
|
|
4670
|
+
return;
|
|
4671
|
+
}
|
|
4672
|
+
if (mobileResolution.kind === "resume-success") {
|
|
4671
4673
|
clearMobileFlowState();
|
|
4672
|
-
|
|
4674
|
+
setMobileFlow(false);
|
|
4675
|
+
setDeeplinkUri(null);
|
|
4676
|
+
setTransfer(existingTransfer);
|
|
4677
|
+
setError(null);
|
|
4678
|
+
setStep("success");
|
|
4679
|
+
onComplete?.(existingTransfer);
|
|
4673
4680
|
return;
|
|
4674
4681
|
}
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4682
|
+
if (mobileResolution.kind === "resume-failed") {
|
|
4683
|
+
clearMobileFlowState();
|
|
4684
|
+
setMobileFlow(false);
|
|
4685
|
+
setDeeplinkUri(null);
|
|
4686
|
+
setTransfer(existingTransfer);
|
|
4687
|
+
setError("Transfer failed.");
|
|
4688
|
+
setStep("success");
|
|
4689
|
+
return;
|
|
4690
|
+
}
|
|
4691
|
+
if (mobileResolution.kind === "resume-stale-setup") {
|
|
4692
|
+
clearMobileFlowState();
|
|
4693
|
+
if (!cancelled) setStep("wallet-picker");
|
|
4694
|
+
return;
|
|
4695
|
+
}
|
|
4696
|
+
} catch (err) {
|
|
4697
|
+
if (cancelled) return;
|
|
4698
|
+
enterPersistedMobileFlow(
|
|
4699
|
+
persisted,
|
|
4700
|
+
err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
|
|
4701
|
+
);
|
|
4678
4702
|
return;
|
|
4679
4703
|
}
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
setSelectedProviderId(persisted.providerId);
|
|
4683
|
-
pollingTransferIdRef.current = persisted.transferId;
|
|
4684
|
-
mobileSetupFlowRef.current = persisted.isSetup;
|
|
4685
|
-
polling.startPolling(persisted.transferId);
|
|
4704
|
+
enterPersistedMobileFlow(persisted);
|
|
4705
|
+
return;
|
|
4686
4706
|
}
|
|
4687
4707
|
setStep(resolved.step);
|
|
4688
4708
|
};
|
|
@@ -4723,7 +4743,18 @@ function SwypePaymentInner({
|
|
|
4723
4743
|
return () => {
|
|
4724
4744
|
cancelled = true;
|
|
4725
4745
|
};
|
|
4726
|
-
}, [
|
|
4746
|
+
}, [
|
|
4747
|
+
ready,
|
|
4748
|
+
authenticated,
|
|
4749
|
+
step,
|
|
4750
|
+
apiBaseUrl,
|
|
4751
|
+
getAccessToken,
|
|
4752
|
+
activeCredentialId,
|
|
4753
|
+
resetHeadlessLogin,
|
|
4754
|
+
enterPersistedMobileFlow,
|
|
4755
|
+
handleAuthorizedMobileReturn,
|
|
4756
|
+
onComplete
|
|
4757
|
+
]);
|
|
4727
4758
|
const loadingDataRef = react.useRef(false);
|
|
4728
4759
|
react.useEffect(() => {
|
|
4729
4760
|
if (!authenticated) return;
|
|
@@ -4833,22 +4864,8 @@ function SwypePaymentInner({
|
|
|
4833
4864
|
if (!mobileFlow) return;
|
|
4834
4865
|
const polledTransfer = polling.transfer;
|
|
4835
4866
|
if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
clearMobileFlowState();
|
|
4839
|
-
setDeeplinkUri(null);
|
|
4840
|
-
polling.stopPolling();
|
|
4841
|
-
setTransfer(polledTransfer);
|
|
4842
|
-
reloadAccounts().catch(() => {
|
|
4843
|
-
}).then(() => {
|
|
4844
|
-
setMobileFlow(false);
|
|
4845
|
-
setStep("deposit");
|
|
4846
|
-
});
|
|
4847
|
-
return;
|
|
4848
|
-
}
|
|
4849
|
-
setTransfer(polledTransfer);
|
|
4850
|
-
setStep("confirm-sign");
|
|
4851
|
-
}, [mobileFlow, polling.transfer, polling.stopPolling, transferSigning, onError, reloadAccounts]);
|
|
4867
|
+
void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
|
|
4868
|
+
}, [mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
|
|
4852
4869
|
react.useEffect(() => {
|
|
4853
4870
|
if (!mobileFlow) return;
|
|
4854
4871
|
const transferIdToResume = pollingTransferIdRef.current ?? transfer?.id;
|
|
@@ -5290,6 +5307,8 @@ function SwypePaymentInner({
|
|
|
5290
5307
|
walletName: providerName,
|
|
5291
5308
|
deeplinkUri: deeplinkUri ?? "",
|
|
5292
5309
|
loading: creatingTransfer || !deeplinkUri,
|
|
5310
|
+
error: error || polling.error,
|
|
5311
|
+
onRetryStatus: handleRetryMobileStatus,
|
|
5293
5312
|
onLogout: handleLogout
|
|
5294
5313
|
}
|
|
5295
5314
|
);
|