@swype-org/react-sdk 0.1.64 → 0.1.67
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 +229 -221
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +229 -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,35 @@ 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
|
+
return { step: "open-wallet", clearPersistedFlow: false };
|
|
1617
|
+
}
|
|
1618
|
+
if ((state.accounts.length === 0 || !hasActiveWallet(state.accounts)) && !state.connectingNewAccount) {
|
|
1619
|
+
return { step: "wallet-picker", clearPersistedFlow: false };
|
|
1620
|
+
}
|
|
1621
|
+
return { step: "deposit", clearPersistedFlow: false };
|
|
1622
|
+
}
|
|
1623
|
+
function resolveRestoredMobileFlow(transferStatus, isSetup) {
|
|
1624
|
+
if (transferStatus === "AUTHORIZED") {
|
|
1625
|
+
return isSetup ? { kind: "resume-setup-deposit", step: "deposit", clearPersistedFlow: true } : { kind: "resume-confirm-sign", step: "confirm-sign", clearPersistedFlow: true };
|
|
1626
|
+
}
|
|
1627
|
+
if (transferStatus === "COMPLETED") {
|
|
1628
|
+
return { kind: "resume-success", step: "success", clearPersistedFlow: true };
|
|
1629
|
+
}
|
|
1630
|
+
if (transferStatus === "FAILED") {
|
|
1631
|
+
return { kind: "resume-failed", step: "success", clearPersistedFlow: true };
|
|
1632
|
+
}
|
|
1633
|
+
return { kind: "resume-open-wallet", step: "open-wallet", clearPersistedFlow: false };
|
|
1634
|
+
}
|
|
1586
1635
|
var FOOTER_CSS = `
|
|
1587
1636
|
.swype-screen-footer {
|
|
1588
1637
|
padding-bottom: max(24px, env(safe-area-inset-bottom, 24px));
|
|
@@ -1911,137 +1960,6 @@ var inputStyle = (tokens, filled) => ({
|
|
|
1911
1960
|
caretColor: tokens.borderFocus,
|
|
1912
1961
|
transition: "border-color 0.15s ease"
|
|
1913
1962
|
});
|
|
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
1963
|
|
|
2046
1964
|
// src/assets/logos.ts
|
|
2047
1965
|
function svgToDataUri(svg) {
|
|
@@ -3003,18 +2921,6 @@ var dividerTextStyle = (color) => ({
|
|
|
3003
2921
|
});
|
|
3004
2922
|
var DEFAULT_MAX = 500;
|
|
3005
2923
|
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
2924
|
function SetupScreen({
|
|
3019
2925
|
availableBalance,
|
|
3020
2926
|
tokenCount,
|
|
@@ -3030,9 +2936,22 @@ function SetupScreen({
|
|
|
3030
2936
|
const { tokens } = useSwypeConfig();
|
|
3031
2937
|
const effectiveMax = Math.floor(Math.min(DEFAULT_MAX, availableBalance > 0 ? availableBalance : DEFAULT_MAX) * 100) / 100;
|
|
3032
2938
|
const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
|
|
3033
|
-
const
|
|
3034
|
-
const
|
|
3035
|
-
const [
|
|
2939
|
+
const [limit, setLimit] = react.useState(() => effectiveMax);
|
|
2940
|
+
const [editing, setEditing] = react.useState(false);
|
|
2941
|
+
const [inputValue, setInputValue] = react.useState("");
|
|
2942
|
+
const inputRef = react.useRef(null);
|
|
2943
|
+
const startEditing = react.useCallback(() => {
|
|
2944
|
+
setInputValue(limit.toFixed(2));
|
|
2945
|
+
setEditing(true);
|
|
2946
|
+
requestAnimationFrame(() => inputRef.current?.select());
|
|
2947
|
+
}, [limit]);
|
|
2948
|
+
const commitEdit = react.useCallback(() => {
|
|
2949
|
+
const parsed = parseFloat(inputValue);
|
|
2950
|
+
if (!isNaN(parsed)) {
|
|
2951
|
+
setLimit(Math.min(effectiveMax, Math.max(effectiveMin, Math.round(parsed * 100) / 100)));
|
|
2952
|
+
}
|
|
2953
|
+
setEditing(false);
|
|
2954
|
+
}, [inputValue, effectiveMax, effectiveMin]);
|
|
3036
2955
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3037
2956
|
ScreenLayout,
|
|
3038
2957
|
{
|
|
@@ -3088,19 +3007,33 @@ function SetupScreen({
|
|
|
3088
3007
|
] }),
|
|
3089
3008
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitSectionStyle, children: [
|
|
3090
3009
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: limitLabelStyle(tokens.textMuted), children: "Your One-Tap limit" }),
|
|
3091
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitValueStyle(tokens.text), children: [
|
|
3010
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitValueStyle(tokens.text), children: [
|
|
3092
3011
|
"$",
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3012
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3013
|
+
"input",
|
|
3014
|
+
{
|
|
3015
|
+
ref: inputRef,
|
|
3016
|
+
type: "text",
|
|
3017
|
+
inputMode: "decimal",
|
|
3018
|
+
pattern: "[0-9]*",
|
|
3019
|
+
value: inputValue,
|
|
3020
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
3021
|
+
onBlur: commitEdit,
|
|
3022
|
+
onKeyDown: (e) => {
|
|
3023
|
+
if (e.key === "Enter") commitEdit();
|
|
3024
|
+
},
|
|
3025
|
+
style: limitInputStyle(tokens.text)
|
|
3026
|
+
}
|
|
3027
|
+
)
|
|
3028
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3029
|
+
"div",
|
|
3097
3030
|
{
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3031
|
+
style: { ...limitValueStyle(tokens.text), cursor: "pointer" },
|
|
3032
|
+
onClick: startEditing,
|
|
3033
|
+
children: [
|
|
3034
|
+
"$",
|
|
3035
|
+
limit.toFixed(2)
|
|
3036
|
+
]
|
|
3104
3037
|
}
|
|
3105
3038
|
)
|
|
3106
3039
|
] }),
|
|
@@ -3207,6 +3140,19 @@ var limitValueStyle = (color) => ({
|
|
|
3207
3140
|
color,
|
|
3208
3141
|
marginBottom: 12
|
|
3209
3142
|
});
|
|
3143
|
+
var limitInputStyle = (color) => ({
|
|
3144
|
+
fontSize: "2.2rem",
|
|
3145
|
+
fontWeight: 700,
|
|
3146
|
+
color,
|
|
3147
|
+
background: "transparent",
|
|
3148
|
+
border: "none",
|
|
3149
|
+
borderBottom: "2px solid currentColor",
|
|
3150
|
+
outline: "none",
|
|
3151
|
+
textAlign: "center",
|
|
3152
|
+
width: "5ch",
|
|
3153
|
+
fontFamily: "inherit",
|
|
3154
|
+
padding: 0
|
|
3155
|
+
});
|
|
3210
3156
|
var bannerWrapStyle = { marginBottom: 16 };
|
|
3211
3157
|
var linkStyle = (color) => ({
|
|
3212
3158
|
background: "transparent",
|
|
@@ -4112,6 +4058,8 @@ function OpenWalletScreen({
|
|
|
4112
4058
|
walletName,
|
|
4113
4059
|
deeplinkUri,
|
|
4114
4060
|
loading,
|
|
4061
|
+
error,
|
|
4062
|
+
onRetryStatus,
|
|
4115
4063
|
onLogout
|
|
4116
4064
|
}) {
|
|
4117
4065
|
const { tokens } = useSwypeConfig();
|
|
@@ -4132,12 +4080,14 @@ function OpenWalletScreen({
|
|
|
4132
4080
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4133
4081
|
ScreenLayout,
|
|
4134
4082
|
{
|
|
4135
|
-
footer: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4083
|
+
footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: footerContentStyle, children: [
|
|
4084
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: error }),
|
|
4136
4085
|
!loading && /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: handleOpen, children: [
|
|
4137
4086
|
"Open ",
|
|
4138
4087
|
displayName
|
|
4139
4088
|
] }),
|
|
4140
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4089
|
+
error && onRetryStatus && /* @__PURE__ */ jsxRuntime.jsx(OutlineButton, { onClick: onRetryStatus, children: "Retry status check" }),
|
|
4090
|
+
/* @__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
4091
|
] }),
|
|
4142
4092
|
children: [
|
|
4143
4093
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
|
|
@@ -4163,6 +4113,11 @@ var contentStyle6 = {
|
|
|
4163
4113
|
textAlign: "center",
|
|
4164
4114
|
padding: "0 24px"
|
|
4165
4115
|
};
|
|
4116
|
+
var footerContentStyle = {
|
|
4117
|
+
display: "flex",
|
|
4118
|
+
flexDirection: "column",
|
|
4119
|
+
gap: 12
|
|
4120
|
+
};
|
|
4166
4121
|
var logoStyle = {
|
|
4167
4122
|
width: 56,
|
|
4168
4123
|
height: 56,
|
|
@@ -4452,24 +4407,6 @@ function buildSelectSourceChoices(options) {
|
|
|
4452
4407
|
}
|
|
4453
4408
|
return chainChoices;
|
|
4454
4409
|
}
|
|
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
4410
|
function SwypePayment(props) {
|
|
4474
4411
|
const resetKey = react.useRef(0);
|
|
4475
4412
|
const handleBoundaryReset = react.useCallback(() => {
|
|
@@ -4559,6 +4496,55 @@ function SwypePaymentInner({
|
|
|
4559
4496
|
setConnectingNewAccount(false);
|
|
4560
4497
|
}
|
|
4561
4498
|
}, [getAccessToken, activeCredentialId, apiBaseUrl, depositAmount]);
|
|
4499
|
+
const enterPersistedMobileFlow = react.useCallback((persisted, errorMessage) => {
|
|
4500
|
+
setMobileFlow(true);
|
|
4501
|
+
setDeeplinkUri(persisted.deeplinkUri);
|
|
4502
|
+
setSelectedProviderId(persisted.providerId);
|
|
4503
|
+
pollingTransferIdRef.current = persisted.transferId;
|
|
4504
|
+
mobileSetupFlowRef.current = persisted.isSetup;
|
|
4505
|
+
setError(errorMessage ?? null);
|
|
4506
|
+
setStep("open-wallet");
|
|
4507
|
+
polling.startPolling(persisted.transferId);
|
|
4508
|
+
}, [polling]);
|
|
4509
|
+
const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
|
|
4510
|
+
setTransfer(authorizedTransfer);
|
|
4511
|
+
polling.stopPolling();
|
|
4512
|
+
if (isSetup) {
|
|
4513
|
+
mobileSetupFlowRef.current = false;
|
|
4514
|
+
clearMobileFlowState();
|
|
4515
|
+
try {
|
|
4516
|
+
await reloadAccounts();
|
|
4517
|
+
setError(null);
|
|
4518
|
+
setDeeplinkUri(null);
|
|
4519
|
+
setMobileFlow(false);
|
|
4520
|
+
setStep("deposit");
|
|
4521
|
+
} catch (err) {
|
|
4522
|
+
setError(
|
|
4523
|
+
err instanceof Error ? err.message : "Wallet authorized, but we could not refresh your account yet."
|
|
4524
|
+
);
|
|
4525
|
+
setStep("open-wallet");
|
|
4526
|
+
}
|
|
4527
|
+
return;
|
|
4528
|
+
}
|
|
4529
|
+
mobileSetupFlowRef.current = false;
|
|
4530
|
+
clearMobileFlowState();
|
|
4531
|
+
setError(null);
|
|
4532
|
+
setDeeplinkUri(null);
|
|
4533
|
+
setMobileFlow(false);
|
|
4534
|
+
setStep("confirm-sign");
|
|
4535
|
+
}, [polling.stopPolling, reloadAccounts]);
|
|
4536
|
+
const handleRetryMobileStatus = react.useCallback(() => {
|
|
4537
|
+
setError(null);
|
|
4538
|
+
const currentTransfer = polling.transfer ?? transfer;
|
|
4539
|
+
if (currentTransfer?.status === "AUTHORIZED") {
|
|
4540
|
+
void handleAuthorizedMobileReturn(currentTransfer, mobileSetupFlowRef.current);
|
|
4541
|
+
return;
|
|
4542
|
+
}
|
|
4543
|
+
const transferIdToResume = pollingTransferIdRef.current ?? currentTransfer?.id;
|
|
4544
|
+
if (transferIdToResume) {
|
|
4545
|
+
polling.startPolling(transferIdToResume);
|
|
4546
|
+
}
|
|
4547
|
+
}, [handleAuthorizedMobileReturn, polling, transfer]);
|
|
4562
4548
|
react.useEffect(() => {
|
|
4563
4549
|
if (depositAmount != null) {
|
|
4564
4550
|
setAmount(depositAmount.toString());
|
|
@@ -4656,7 +4642,6 @@ function SwypePaymentInner({
|
|
|
4656
4642
|
hasPasskey: true,
|
|
4657
4643
|
accounts: accts,
|
|
4658
4644
|
persistedMobileFlow: persisted,
|
|
4659
|
-
mobileSetupInProgress: false,
|
|
4660
4645
|
connectingNewAccount: false
|
|
4661
4646
|
});
|
|
4662
4647
|
if (resolved.clearPersistedFlow) {
|
|
@@ -4666,23 +4651,47 @@ function SwypePaymentInner({
|
|
|
4666
4651
|
try {
|
|
4667
4652
|
const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
|
|
4668
4653
|
if (cancelled) return;
|
|
4669
|
-
const
|
|
4670
|
-
|
|
4654
|
+
const mobileResolution = resolveRestoredMobileFlow(
|
|
4655
|
+
existingTransfer.status,
|
|
4656
|
+
persisted.isSetup
|
|
4657
|
+
);
|
|
4658
|
+
if (mobileResolution.kind === "resume-setup-deposit") {
|
|
4659
|
+
await handleAuthorizedMobileReturn(existingTransfer, true);
|
|
4660
|
+
return;
|
|
4661
|
+
}
|
|
4662
|
+
if (mobileResolution.kind === "resume-confirm-sign") {
|
|
4663
|
+
await handleAuthorizedMobileReturn(existingTransfer, false);
|
|
4664
|
+
return;
|
|
4665
|
+
}
|
|
4666
|
+
if (mobileResolution.kind === "resume-success") {
|
|
4671
4667
|
clearMobileFlowState();
|
|
4672
|
-
|
|
4668
|
+
setMobileFlow(false);
|
|
4669
|
+
setDeeplinkUri(null);
|
|
4670
|
+
setTransfer(existingTransfer);
|
|
4671
|
+
setError(null);
|
|
4672
|
+
setStep("success");
|
|
4673
|
+
onComplete?.(existingTransfer);
|
|
4673
4674
|
return;
|
|
4674
4675
|
}
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4676
|
+
if (mobileResolution.kind === "resume-failed") {
|
|
4677
|
+
clearMobileFlowState();
|
|
4678
|
+
setMobileFlow(false);
|
|
4679
|
+
setDeeplinkUri(null);
|
|
4680
|
+
setTransfer(existingTransfer);
|
|
4681
|
+
setError("Transfer failed.");
|
|
4682
|
+
setStep("success");
|
|
4683
|
+
return;
|
|
4684
|
+
}
|
|
4685
|
+
} catch (err) {
|
|
4686
|
+
if (cancelled) return;
|
|
4687
|
+
enterPersistedMobileFlow(
|
|
4688
|
+
persisted,
|
|
4689
|
+
err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
|
|
4690
|
+
);
|
|
4678
4691
|
return;
|
|
4679
4692
|
}
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
setSelectedProviderId(persisted.providerId);
|
|
4683
|
-
pollingTransferIdRef.current = persisted.transferId;
|
|
4684
|
-
mobileSetupFlowRef.current = persisted.isSetup;
|
|
4685
|
-
polling.startPolling(persisted.transferId);
|
|
4693
|
+
enterPersistedMobileFlow(persisted);
|
|
4694
|
+
return;
|
|
4686
4695
|
}
|
|
4687
4696
|
setStep(resolved.step);
|
|
4688
4697
|
};
|
|
@@ -4723,7 +4732,18 @@ function SwypePaymentInner({
|
|
|
4723
4732
|
return () => {
|
|
4724
4733
|
cancelled = true;
|
|
4725
4734
|
};
|
|
4726
|
-
}, [
|
|
4735
|
+
}, [
|
|
4736
|
+
ready,
|
|
4737
|
+
authenticated,
|
|
4738
|
+
step,
|
|
4739
|
+
apiBaseUrl,
|
|
4740
|
+
getAccessToken,
|
|
4741
|
+
activeCredentialId,
|
|
4742
|
+
resetHeadlessLogin,
|
|
4743
|
+
enterPersistedMobileFlow,
|
|
4744
|
+
handleAuthorizedMobileReturn,
|
|
4745
|
+
onComplete
|
|
4746
|
+
]);
|
|
4727
4747
|
const loadingDataRef = react.useRef(false);
|
|
4728
4748
|
react.useEffect(() => {
|
|
4729
4749
|
if (!authenticated) return;
|
|
@@ -4833,22 +4853,8 @@ function SwypePaymentInner({
|
|
|
4833
4853
|
if (!mobileFlow) return;
|
|
4834
4854
|
const polledTransfer = polling.transfer;
|
|
4835
4855
|
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]);
|
|
4856
|
+
void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
|
|
4857
|
+
}, [mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
|
|
4852
4858
|
react.useEffect(() => {
|
|
4853
4859
|
if (!mobileFlow) return;
|
|
4854
4860
|
const transferIdToResume = pollingTransferIdRef.current ?? transfer?.id;
|
|
@@ -5290,6 +5296,8 @@ function SwypePaymentInner({
|
|
|
5290
5296
|
walletName: providerName,
|
|
5291
5297
|
deeplinkUri: deeplinkUri ?? "",
|
|
5292
5298
|
loading: creatingTransfer || !deeplinkUri,
|
|
5299
|
+
error: error || polling.error,
|
|
5300
|
+
onRetryStatus: handleRetryMobileStatus,
|
|
5293
5301
|
onLogout: handleLogout
|
|
5294
5302
|
}
|
|
5295
5303
|
);
|