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