@unifold/ui-react 0.1.69 → 0.1.70
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.mts +52 -17
- package/dist/index.d.ts +52 -17
- package/dist/index.js +880 -357
- package/dist/index.mjs +839 -315
- package/dist/styles-base.css +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -114,6 +114,7 @@ __export(index_exports, {
|
|
|
114
114
|
useDepositPolling: () => useDepositPolling,
|
|
115
115
|
useDepositQuote: () => useDepositQuote,
|
|
116
116
|
usePaymentIntent: () => usePaymentIntent,
|
|
117
|
+
usePublicIncident: () => usePublicIncident,
|
|
117
118
|
useSourceTokenValidation: () => useSourceTokenValidation,
|
|
118
119
|
useSupportedDepositTokens: () => useSupportedDepositTokens,
|
|
119
120
|
useSupportedDestinationTokens: () => useSupportedDestinationTokens,
|
|
@@ -750,7 +751,13 @@ function useDepositAddress(params) {
|
|
|
750
751
|
// 24 hours in cache
|
|
751
752
|
refetchOnMount: false,
|
|
752
753
|
refetchOnWindowFocus: false,
|
|
753
|
-
retry
|
|
754
|
+
// Don't retry recipient-address validation errors — they're deterministic
|
|
755
|
+
// (a 400 won't succeed on retry) and we want to surface the invalid-address
|
|
756
|
+
// screen immediately rather than after 3 backoff attempts.
|
|
757
|
+
retry: (failureCount, error) => {
|
|
758
|
+
if ((0, import_core.isDepositAddressValidationError)(error)) return false;
|
|
759
|
+
return failureCount < 3;
|
|
760
|
+
},
|
|
754
761
|
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
|
|
755
762
|
// 1s, 2s, 4s (max 10s)
|
|
756
763
|
});
|
|
@@ -975,7 +982,8 @@ function DepositHeader({
|
|
|
975
982
|
balanceChainId,
|
|
976
983
|
balanceTokenAddress,
|
|
977
984
|
projectName,
|
|
978
|
-
publishableKey
|
|
985
|
+
publishableKey,
|
|
986
|
+
incident
|
|
979
987
|
}) {
|
|
980
988
|
const { colors: colors2, fonts, components } = useTheme();
|
|
981
989
|
const [balance, setBalance] = (0, import_react2.useState)(null);
|
|
@@ -1073,19 +1081,64 @@ function DepositHeader({
|
|
|
1073
1081
|
balanceTokenAddress,
|
|
1074
1082
|
publishableKey
|
|
1075
1083
|
]);
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1084
|
+
const incidentMessages = incident?.messages ?? [];
|
|
1085
|
+
const showIncident = incident?.enabled && incidentMessages.length > 0;
|
|
1086
|
+
const incidentSeverity = incident?.severity ?? "degraded";
|
|
1087
|
+
const incidentSeverityLabel = incidentSeverity === "outage" ? "Outage" : incidentSeverity === "info" ? "Info" : "Degraded service";
|
|
1088
|
+
const incidentStyles = incidentSeverity === "outage" ? {
|
|
1089
|
+
bg: "rgba(239, 68, 68, 0.12)",
|
|
1090
|
+
border: "rgba(239, 68, 68, 0.35)",
|
|
1091
|
+
text: "#fca5a5",
|
|
1092
|
+
link: "#fca5a5"
|
|
1093
|
+
} : incidentSeverity === "info" ? {
|
|
1094
|
+
bg: "rgba(59, 130, 246, 0.12)",
|
|
1095
|
+
border: "rgba(59, 130, 246, 0.35)",
|
|
1096
|
+
text: "#93c5fd",
|
|
1097
|
+
link: "#93c5fd"
|
|
1098
|
+
} : {
|
|
1099
|
+
bg: "rgba(245, 158, 11, 0.12)",
|
|
1100
|
+
border: "rgba(245, 158, 11, 0.35)",
|
|
1101
|
+
text: "#fcd34d",
|
|
1102
|
+
link: "#fcd34d"
|
|
1103
|
+
};
|
|
1104
|
+
const IncidentIcon = incidentSeverity === "info" ? import_lucide_react3.Info : import_lucide_react3.AlertTriangle;
|
|
1105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
|
|
1107
|
+
showBack ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1108
|
+
"button",
|
|
1109
|
+
{
|
|
1110
|
+
onClick: onBack,
|
|
1111
|
+
className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
|
|
1112
|
+
style: { color: components.header.buttonColor },
|
|
1113
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ArrowLeft, { className: "uf-w-5 uf-h-5" })
|
|
1114
|
+
}
|
|
1115
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
|
|
1117
|
+
badge ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1119
|
+
DialogTitle,
|
|
1120
|
+
{
|
|
1121
|
+
className: "uf-text-center uf-text-base",
|
|
1122
|
+
style: {
|
|
1123
|
+
color: components.header.titleColor,
|
|
1124
|
+
fontFamily: fonts.medium
|
|
1125
|
+
},
|
|
1126
|
+
children: title
|
|
1127
|
+
}
|
|
1128
|
+
),
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1130
|
+
"div",
|
|
1131
|
+
{
|
|
1132
|
+
className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
|
|
1133
|
+
style: {
|
|
1134
|
+
backgroundColor: colors2.card,
|
|
1135
|
+
color: colors2.foregroundMuted,
|
|
1136
|
+
fontFamily: fonts.regular
|
|
1137
|
+
},
|
|
1138
|
+
children: badge.count
|
|
1139
|
+
}
|
|
1140
|
+
)
|
|
1141
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1089
1142
|
DialogTitle,
|
|
1090
1143
|
{
|
|
1091
1144
|
className: "uf-text-center uf-text-base",
|
|
@@ -1096,61 +1149,91 @@ function DepositHeader({
|
|
|
1096
1149
|
children: title
|
|
1097
1150
|
}
|
|
1098
1151
|
),
|
|
1099
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1152
|
+
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1100
1153
|
"div",
|
|
1101
1154
|
{
|
|
1102
|
-
className: "uf-
|
|
1155
|
+
className: "uf-text-xs uf-mt-1",
|
|
1103
1156
|
style: {
|
|
1104
|
-
backgroundColor: colors2.card,
|
|
1105
1157
|
color: colors2.foregroundMuted,
|
|
1106
1158
|
fontFamily: fonts.regular
|
|
1107
1159
|
},
|
|
1108
|
-
children:
|
|
1160
|
+
children: subtitle
|
|
1109
1161
|
}
|
|
1110
|
-
)
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
),
|
|
1122
|
-
|
|
1123
|
-
"
|
|
1124
|
-
{
|
|
1125
|
-
className: "uf-text-xs uf-mt-1",
|
|
1126
|
-
style: {
|
|
1127
|
-
color: colors2.foregroundMuted,
|
|
1128
|
-
fontFamily: fonts.regular
|
|
1129
|
-
},
|
|
1130
|
-
children: subtitle
|
|
1131
|
-
}
|
|
1132
|
-
) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-1" }) : balance ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1133
|
-
"div",
|
|
1162
|
+
) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-1" }) : balance ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1163
|
+
"div",
|
|
1164
|
+
{
|
|
1165
|
+
className: "uf-text-xs uf-mt-1",
|
|
1166
|
+
style: {
|
|
1167
|
+
color: colors2.foregroundMuted,
|
|
1168
|
+
fontFamily: fonts.regular
|
|
1169
|
+
},
|
|
1170
|
+
children: formatBalanceDisplay(balance, projectName)
|
|
1171
|
+
}
|
|
1172
|
+
) : null : null
|
|
1173
|
+
] }),
|
|
1174
|
+
showClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1175
|
+
"button",
|
|
1134
1176
|
{
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
},
|
|
1140
|
-
children: formatBalanceDisplay(balance, projectName)
|
|
1177
|
+
onClick: onClose,
|
|
1178
|
+
className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
|
|
1179
|
+
style: { color: components.header.buttonColor },
|
|
1180
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.X, { className: "uf-w-5 uf-h-5" })
|
|
1141
1181
|
}
|
|
1142
|
-
) :
|
|
1182
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
|
|
1143
1183
|
] }),
|
|
1144
|
-
|
|
1145
|
-
"
|
|
1184
|
+
showIncident && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1185
|
+
"div",
|
|
1146
1186
|
{
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1187
|
+
className: "uf-rounded-lg uf-px-3 uf-py-2.5 uf-mb-4",
|
|
1188
|
+
style: {
|
|
1189
|
+
backgroundColor: incidentStyles.bg,
|
|
1190
|
+
border: `1px solid ${incidentStyles.border}`
|
|
1191
|
+
},
|
|
1192
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-flex uf-items-start uf-gap-2.5", children: [
|
|
1193
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1194
|
+
IncidentIcon,
|
|
1195
|
+
{
|
|
1196
|
+
className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
|
|
1197
|
+
style: { color: incidentStyles.text }
|
|
1198
|
+
}
|
|
1199
|
+
),
|
|
1200
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "uf-min-w-0 uf-flex-1", children: [
|
|
1201
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1202
|
+
"span",
|
|
1203
|
+
{
|
|
1204
|
+
className: "uf-text-[11px] uf-leading-none uf-px-1.5 uf-py-1 uf-rounded-md",
|
|
1205
|
+
style: {
|
|
1206
|
+
color: incidentStyles.text,
|
|
1207
|
+
border: `1px solid ${incidentStyles.border}`,
|
|
1208
|
+
fontFamily: fonts.medium
|
|
1209
|
+
},
|
|
1210
|
+
children: incidentSeverityLabel
|
|
1211
|
+
}
|
|
1212
|
+
) }),
|
|
1213
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1214
|
+
"div",
|
|
1215
|
+
{
|
|
1216
|
+
className: "uf-space-y-1",
|
|
1217
|
+
style: { color: incidentStyles.text, fontFamily: fonts.regular },
|
|
1218
|
+
children: incidentMessages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "uf-text-xs uf-leading-relaxed", children: message }, `${message}-${index}`))
|
|
1219
|
+
}
|
|
1220
|
+
),
|
|
1221
|
+
incident.statusPageUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1222
|
+
"a",
|
|
1223
|
+
{
|
|
1224
|
+
href: incident.statusPageUrl,
|
|
1225
|
+
target: "_blank",
|
|
1226
|
+
rel: "noreferrer",
|
|
1227
|
+
className: "uf-inline-block uf-mt-1.5 uf-text-xs uf-underline uf-underline-offset-2",
|
|
1228
|
+
style: { color: incidentStyles.link, fontFamily: fonts.medium },
|
|
1229
|
+
children: "View status"
|
|
1230
|
+
}
|
|
1231
|
+
)
|
|
1232
|
+
] })
|
|
1233
|
+
] })
|
|
1151
1234
|
}
|
|
1152
|
-
)
|
|
1153
|
-
] })
|
|
1235
|
+
)
|
|
1236
|
+
] });
|
|
1154
1237
|
}
|
|
1155
1238
|
|
|
1156
1239
|
// src/components/currency/CurrencyListItem.tsx
|
|
@@ -1488,7 +1571,8 @@ var en_default = {
|
|
|
1488
1571
|
},
|
|
1489
1572
|
stripeLink: {
|
|
1490
1573
|
title: "Pay with Link",
|
|
1491
|
-
subtitle: "Buy with card or bank"
|
|
1574
|
+
subtitle: "Buy with card or bank",
|
|
1575
|
+
unavailableInRegionMessage: "Pay with Link is currently unavailable in your region."
|
|
1492
1576
|
},
|
|
1493
1577
|
browserWallet: {
|
|
1494
1578
|
title: "Connect Wallet",
|
|
@@ -6618,7 +6702,7 @@ function BankTransfer({
|
|
|
6618
6702
|
subdivision_code: userIpInfo?.subdivisionCode || void 0,
|
|
6619
6703
|
// A provider may advertise multiple rails; default to the first.
|
|
6620
6704
|
// UIs that want per-rail rows would need to render one entry per element.
|
|
6621
|
-
|
|
6705
|
+
payment_method_type: provider.payment_methods[0]
|
|
6622
6706
|
});
|
|
6623
6707
|
setActiveProvider(provider);
|
|
6624
6708
|
const convertedPrefilled = await resolvePrefilledSourceAmount(provider.source_currency);
|
|
@@ -7949,7 +8033,7 @@ function AppleLogo({ className, style }) {
|
|
|
7949
8033
|
}
|
|
7950
8034
|
);
|
|
7951
8035
|
}
|
|
7952
|
-
function ApplePayButton({ onClick, title, subtitle }) {
|
|
8036
|
+
function ApplePayButton({ onClick, title, subtitle, iconUrl }) {
|
|
7953
8037
|
const { colors: colors2, fonts, components } = useTheme();
|
|
7954
8038
|
const [isHovered, setIsHovered] = React14.useState(false);
|
|
7955
8039
|
const [isTouchDevice, setIsTouchDevice] = React14.useState(false);
|
|
@@ -7971,7 +8055,14 @@ function ApplePayButton({ onClick, title, subtitle }) {
|
|
|
7971
8055
|
},
|
|
7972
8056
|
children: [
|
|
7973
8057
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
|
|
7974
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "uf-rounded-lg uf-
|
|
8058
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "uf-rounded-lg uf-overflow-hidden uf-w-9 uf-h-9 uf-flex uf-items-center uf-justify-center", children: iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("img", { src: iconUrl, alt: "Apple Pay", width: 36, height: 36, className: "uf-rounded-lg" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
8059
|
+
"div",
|
|
8060
|
+
{
|
|
8061
|
+
className: "uf-w-9 uf-h-9 uf-rounded-lg uf-flex uf-items-center uf-justify-center",
|
|
8062
|
+
style: { backgroundColor: "#000" },
|
|
8063
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AppleLogo, { className: "uf-w-5 uf-h-5", style: { color: "#fff" } })
|
|
8064
|
+
}
|
|
8065
|
+
) }),
|
|
7975
8066
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "uf-text-left", children: [
|
|
7976
8067
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
7977
8068
|
"div",
|
|
@@ -8205,13 +8296,6 @@ function solanaCandidate(provider, type, name, icon) {
|
|
|
8205
8296
|
if (provider.isConnected && provider.publicKey) {
|
|
8206
8297
|
return { type, name, address: provider.publicKey.toString(), icon };
|
|
8207
8298
|
}
|
|
8208
|
-
try {
|
|
8209
|
-
const resp = await provider.connect({ onlyIfTrusted: true });
|
|
8210
|
-
if (resp.publicKey) {
|
|
8211
|
-
return { type, name, address: resp.publicKey.toString(), icon };
|
|
8212
|
-
}
|
|
8213
|
-
} catch {
|
|
8214
|
-
}
|
|
8215
8299
|
return null;
|
|
8216
8300
|
}
|
|
8217
8301
|
};
|
|
@@ -8440,6 +8524,180 @@ async function disconnectInjectedBrowserWallet(wallet) {
|
|
|
8440
8524
|
);
|
|
8441
8525
|
}
|
|
8442
8526
|
|
|
8527
|
+
// src/components/deposits/browser-wallets/providerResolvers.ts
|
|
8528
|
+
var STORED_TYPE_TO_EIP6963_WALLET_ID = {
|
|
8529
|
+
metamask: "metamask",
|
|
8530
|
+
"phantom-ethereum": "phantom",
|
|
8531
|
+
coinbase: "coinbase",
|
|
8532
|
+
trust: "trust",
|
|
8533
|
+
rainbow: "rainbow",
|
|
8534
|
+
rabby: "rabby",
|
|
8535
|
+
okx: "okx"
|
|
8536
|
+
};
|
|
8537
|
+
var EIP6963_WALLET_ID_TO_INFO = {
|
|
8538
|
+
metamask: { walletType: "metamask", name: "MetaMask", icon: "metamask" },
|
|
8539
|
+
phantom: { walletType: "phantom-ethereum", name: "Phantom", icon: "phantom" },
|
|
8540
|
+
coinbase: { walletType: "coinbase", name: "Coinbase Wallet", icon: "coinbase" },
|
|
8541
|
+
trust: { walletType: "trust", name: "Trust Wallet", icon: "trust" },
|
|
8542
|
+
rainbow: { walletType: "rainbow", name: "Rainbow", icon: "rainbow" },
|
|
8543
|
+
rabby: { walletType: "rabby", name: "Rabby", icon: "rabby" },
|
|
8544
|
+
okx: { walletType: "okx", name: "OKX Wallet", icon: "okx" }
|
|
8545
|
+
};
|
|
8546
|
+
var WALLET_ID_TO_WALLET_TYPE = {
|
|
8547
|
+
phantom: "phantom-ethereum",
|
|
8548
|
+
coinbase: "coinbase",
|
|
8549
|
+
trust: "trust",
|
|
8550
|
+
rainbow: "rainbow",
|
|
8551
|
+
rabby: "rabby",
|
|
8552
|
+
okx: "okx",
|
|
8553
|
+
metamask: "metamask"
|
|
8554
|
+
};
|
|
8555
|
+
var WALLET_TYPE_TO_WALLET_ID = {
|
|
8556
|
+
"phantom-ethereum": "phantom",
|
|
8557
|
+
coinbase: "coinbase",
|
|
8558
|
+
trust: "trust",
|
|
8559
|
+
okx: "okx",
|
|
8560
|
+
rainbow: "rainbow",
|
|
8561
|
+
rabby: "rabby",
|
|
8562
|
+
metamask: "metamask"
|
|
8563
|
+
};
|
|
8564
|
+
function isWalletType(value) {
|
|
8565
|
+
return value === "phantom-solana" || value === "phantom-ethereum" || value === "metamask" || value === "coinbase" || value === "solflare" || value === "backpack" || value === "glow" || value === "trust" || value === "rainbow" || value === "rabby" || value === "okx";
|
|
8566
|
+
}
|
|
8567
|
+
function walletIdToWalletType(walletId) {
|
|
8568
|
+
return WALLET_ID_TO_WALLET_TYPE[walletId] || "metamask";
|
|
8569
|
+
}
|
|
8570
|
+
function walletTypeToWalletId(walletType) {
|
|
8571
|
+
return WALLET_TYPE_TO_WALLET_ID[walletType] || walletType;
|
|
8572
|
+
}
|
|
8573
|
+
function getLegacyEvmProviders(win) {
|
|
8574
|
+
if (!win) return {};
|
|
8575
|
+
const anyWin = win;
|
|
8576
|
+
return {
|
|
8577
|
+
ethereum: anyWin.ethereum,
|
|
8578
|
+
phantomEthereum: anyWin.phantom?.ethereum,
|
|
8579
|
+
coinbaseEthereum: anyWin.coinbaseWalletExtension,
|
|
8580
|
+
trustEthereum: anyWin.trustwallet?.ethereum,
|
|
8581
|
+
okxEthereum: anyWin.okxwallet
|
|
8582
|
+
};
|
|
8583
|
+
}
|
|
8584
|
+
function getInjectedSolanaProviders(win) {
|
|
8585
|
+
if (!win) return {};
|
|
8586
|
+
const anyWin = win;
|
|
8587
|
+
return {
|
|
8588
|
+
phantomSolana: anyWin.phantom?.solana,
|
|
8589
|
+
solflare: anyWin.solflare,
|
|
8590
|
+
backpack: anyWin.backpack,
|
|
8591
|
+
glow: anyWin.glow,
|
|
8592
|
+
coinbaseSolana: anyWin.coinbaseSolana || anyWin.coinbaseWalletExtension?.solana,
|
|
8593
|
+
trustSolana: anyWin.trustwallet?.solana
|
|
8594
|
+
};
|
|
8595
|
+
}
|
|
8596
|
+
function describeEip6963Provider(wp) {
|
|
8597
|
+
const mapped = EIP6963_WALLET_ID_TO_INFO[wp.walletId];
|
|
8598
|
+
return {
|
|
8599
|
+
provider: wp.provider,
|
|
8600
|
+
walletType: mapped?.walletType ?? "metamask",
|
|
8601
|
+
name: mapped?.name ?? wp.info.name,
|
|
8602
|
+
icon: mapped?.icon ?? wp.info.icon
|
|
8603
|
+
};
|
|
8604
|
+
}
|
|
8605
|
+
function resolveQuickConnectEvmProvider(win) {
|
|
8606
|
+
const eip6963Providers = getEip6963Providers();
|
|
8607
|
+
if (eip6963Providers.length > 0) {
|
|
8608
|
+
const stored = getStoredWalletState();
|
|
8609
|
+
const preferredWalletId = stored?.walletType && isWalletType(stored.walletType) ? STORED_TYPE_TO_EIP6963_WALLET_ID[stored.walletType] : void 0;
|
|
8610
|
+
if (preferredWalletId) {
|
|
8611
|
+
const preferred = findProviderByWalletId(preferredWalletId);
|
|
8612
|
+
if (preferred) return describeEip6963Provider(preferred);
|
|
8613
|
+
}
|
|
8614
|
+
if (eip6963Providers.length === 1) {
|
|
8615
|
+
return describeEip6963Provider(eip6963Providers[0]);
|
|
8616
|
+
}
|
|
8617
|
+
return void 0;
|
|
8618
|
+
}
|
|
8619
|
+
const anyWin = win;
|
|
8620
|
+
const legacy = anyWin.phantom?.ethereum || anyWin.ethereum;
|
|
8621
|
+
if (!legacy) return void 0;
|
|
8622
|
+
const isPhantom = legacy.isPhantom;
|
|
8623
|
+
return {
|
|
8624
|
+
provider: legacy,
|
|
8625
|
+
walletType: isPhantom ? "phantom-ethereum" : "metamask",
|
|
8626
|
+
name: isPhantom ? "Phantom" : "MetaMask",
|
|
8627
|
+
icon: isPhantom ? "phantom" : "metamask"
|
|
8628
|
+
};
|
|
8629
|
+
}
|
|
8630
|
+
function resolveSolanaPublicKey(provider, response) {
|
|
8631
|
+
if (response?.publicKey) return { publicKey: response.publicKey };
|
|
8632
|
+
if (provider.publicKey) return { publicKey: provider.publicKey };
|
|
8633
|
+
return null;
|
|
8634
|
+
}
|
|
8635
|
+
function isUserRejectedSolanaConnectError(error) {
|
|
8636
|
+
if (!error || typeof error !== "object") return false;
|
|
8637
|
+
const maybeCode = "code" in error ? error.code : void 0;
|
|
8638
|
+
if (maybeCode === 4001) return true;
|
|
8639
|
+
const msg = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
|
|
8640
|
+
return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("rejected the request") || msg.includes("declined");
|
|
8641
|
+
}
|
|
8642
|
+
function isSolanaConnectTimeoutError(error) {
|
|
8643
|
+
return error instanceof Error && error.message.toLowerCase().includes("did not respond to the connection request");
|
|
8644
|
+
}
|
|
8645
|
+
async function connectSolanaProviderWithRecovery(provider, walletId, walletName) {
|
|
8646
|
+
if (provider.isConnected && provider.publicKey) {
|
|
8647
|
+
return { publicKey: provider.publicKey };
|
|
8648
|
+
}
|
|
8649
|
+
const connectOnce = () => provider.connect(walletId === "solflare" ? { onlyIfTrusted: false } : void 0);
|
|
8650
|
+
const withTimeout = async (ms = 2e4) => await Promise.race([
|
|
8651
|
+
connectOnce(),
|
|
8652
|
+
new Promise(
|
|
8653
|
+
(resolve, reject) => setTimeout(() => {
|
|
8654
|
+
const connected = resolveSolanaPublicKey(provider);
|
|
8655
|
+
if (connected) {
|
|
8656
|
+
resolve(connected);
|
|
8657
|
+
return;
|
|
8658
|
+
}
|
|
8659
|
+
reject(
|
|
8660
|
+
new Error(
|
|
8661
|
+
`${walletName} did not respond to the connection request. Please unlock the wallet and try again.`
|
|
8662
|
+
)
|
|
8663
|
+
);
|
|
8664
|
+
}, ms)
|
|
8665
|
+
)
|
|
8666
|
+
]);
|
|
8667
|
+
if (walletId === "solflare") {
|
|
8668
|
+
await provider.disconnect?.().catch(() => {
|
|
8669
|
+
});
|
|
8670
|
+
}
|
|
8671
|
+
const connectAndResolve = async () => {
|
|
8672
|
+
try {
|
|
8673
|
+
const response = await withTimeout();
|
|
8674
|
+
const resolved = resolveSolanaPublicKey(provider, response);
|
|
8675
|
+
if (resolved) return resolved;
|
|
8676
|
+
await new Promise((resolve) => setTimeout(resolve, 120));
|
|
8677
|
+
const delayedResolved = resolveSolanaPublicKey(provider);
|
|
8678
|
+
if (delayedResolved) return delayedResolved;
|
|
8679
|
+
throw new Error(`${walletName} connected but did not expose a public key.`);
|
|
8680
|
+
} catch (error) {
|
|
8681
|
+
const connected = resolveSolanaPublicKey(provider);
|
|
8682
|
+
if (connected) return connected;
|
|
8683
|
+
throw error;
|
|
8684
|
+
}
|
|
8685
|
+
};
|
|
8686
|
+
try {
|
|
8687
|
+
return await connectAndResolve();
|
|
8688
|
+
} catch (err) {
|
|
8689
|
+
if (isUserRejectedSolanaConnectError(err)) throw err;
|
|
8690
|
+
if (isSolanaConnectTimeoutError(err)) throw err;
|
|
8691
|
+
if (walletId === "solflare") {
|
|
8692
|
+
await provider.disconnect?.().catch(() => {
|
|
8693
|
+
});
|
|
8694
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
8695
|
+
return await connectAndResolve();
|
|
8696
|
+
}
|
|
8697
|
+
throw err;
|
|
8698
|
+
}
|
|
8699
|
+
}
|
|
8700
|
+
|
|
8443
8701
|
// src/resources/icons/MetamaskIcon.tsx
|
|
8444
8702
|
var React17 = __toESM(require("react"));
|
|
8445
8703
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
@@ -10244,7 +10502,11 @@ function WalletIconWithNetwork({
|
|
|
10244
10502
|
}
|
|
10245
10503
|
|
|
10246
10504
|
// src/components/deposits/buttons/BrowserWalletButton.tsx
|
|
10247
|
-
var import_jsx_runtime41 =
|
|
10505
|
+
var import_jsx_runtime41 = (
|
|
10506
|
+
// Wallet announced via EIP-6963 with no internal icon component: render its
|
|
10507
|
+
// own advertised icon (`info.icon`) rather than a generic placeholder.
|
|
10508
|
+
require("react/jsx-runtime")
|
|
10509
|
+
);
|
|
10248
10510
|
var WALLET_ICON_COMPONENTS = {
|
|
10249
10511
|
metamask: MetamaskIcon,
|
|
10250
10512
|
phantom: PhantomIcon,
|
|
@@ -10352,21 +10614,19 @@ function BrowserWalletButton({
|
|
|
10352
10614
|
}
|
|
10353
10615
|
}
|
|
10354
10616
|
if (!chainType || chainType === "ethereum") {
|
|
10355
|
-
const
|
|
10356
|
-
if (
|
|
10357
|
-
const accounts = await
|
|
10617
|
+
const resolved = resolveQuickConnectEvmProvider(window);
|
|
10618
|
+
if (resolved) {
|
|
10619
|
+
const accounts = await resolved.provider.request({
|
|
10358
10620
|
method: "eth_requestAccounts"
|
|
10359
10621
|
});
|
|
10360
10622
|
if (accounts && accounts.length > 0) {
|
|
10361
10623
|
setUserDisconnectedWallet(false);
|
|
10362
|
-
|
|
10363
|
-
const walletType = isPhantom ? "phantom-ethereum" : "metamask";
|
|
10364
|
-
setStoredWalletState(walletType);
|
|
10624
|
+
setStoredWalletState(resolved.walletType);
|
|
10365
10625
|
setWallet({
|
|
10366
|
-
type: walletType,
|
|
10367
|
-
name:
|
|
10626
|
+
type: resolved.walletType,
|
|
10627
|
+
name: resolved.name,
|
|
10368
10628
|
address: accounts[0],
|
|
10369
|
-
icon:
|
|
10629
|
+
icon: resolved.icon
|
|
10370
10630
|
});
|
|
10371
10631
|
}
|
|
10372
10632
|
}
|
|
@@ -10400,7 +10660,10 @@ function BrowserWalletButton({
|
|
|
10400
10660
|
if (isLoading) {
|
|
10401
10661
|
return null;
|
|
10402
10662
|
}
|
|
10403
|
-
const
|
|
10663
|
+
const eip6963EvmProviderCount = getEip6963Providers().length;
|
|
10664
|
+
const legacyEvmProviders = getLegacyEvmProviders(window);
|
|
10665
|
+
const hasLegacyEvmProvider = eip6963EvmProviderCount === 0 && !!(legacyEvmProviders.ethereum || legacyEvmProviders.phantomEthereum || legacyEvmProviders.coinbaseEthereum || legacyEvmProviders.trustEthereum || legacyEvmProviders.okxEthereum);
|
|
10666
|
+
const hasWalletExtension = (!chainType || chainType === "ethereum") && eip6963EvmProviderCount > 0 || (!chainType || chainType === "solana") && (window.phantom?.solana?.isPhantom || window.solana?.isPhantom) || (!chainType || chainType === "ethereum") && hasLegacyEvmProvider;
|
|
10404
10667
|
if (!onConnectClick && !wallet && !hasWalletExtension) {
|
|
10405
10668
|
return null;
|
|
10406
10669
|
}
|
|
@@ -10410,11 +10673,21 @@ function BrowserWalletButton({
|
|
|
10410
10673
|
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
10411
10674
|
};
|
|
10412
10675
|
const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
|
|
10676
|
+
const isImageIcon = !!wallet && (wallet.icon.startsWith("data:") || wallet.icon.startsWith("http"));
|
|
10413
10677
|
const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React29.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
|
|
10414
10678
|
size: 36,
|
|
10415
10679
|
className: "uf-rounded-lg",
|
|
10416
10680
|
variant: "color"
|
|
10417
|
-
}) :
|
|
10681
|
+
}) : isImageIcon ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
10682
|
+
"img",
|
|
10683
|
+
{
|
|
10684
|
+
src: wallet.icon,
|
|
10685
|
+
alt: wallet.name,
|
|
10686
|
+
width: 36,
|
|
10687
|
+
height: 36,
|
|
10688
|
+
className: "uf-rounded-lg uf-w-9 uf-h-9"
|
|
10689
|
+
}
|
|
10690
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-lg uf-bg-gray-500" }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-rounded-lg uf-p-2", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react22.Wallet, { className: "uf-w-5 uf-h-5", style: { color: components.card.iconColor } }) });
|
|
10418
10691
|
const titleSubtitleBlock = /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "uf-text-left uf-min-w-0", children: [
|
|
10419
10692
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
10420
10693
|
"div",
|
|
@@ -10984,6 +11257,13 @@ function setStoredSelectedToken(customerId, token) {
|
|
|
10984
11257
|
} catch {
|
|
10985
11258
|
}
|
|
10986
11259
|
}
|
|
11260
|
+
function clearStoredSelectedToken(customerId) {
|
|
11261
|
+
try {
|
|
11262
|
+
if (typeof window === "undefined" || !customerId) return;
|
|
11263
|
+
localStorage.removeItem(selectedTokenKey(customerId));
|
|
11264
|
+
} catch {
|
|
11265
|
+
}
|
|
11266
|
+
}
|
|
10987
11267
|
|
|
10988
11268
|
// src/components/deposits/stripe-link/PayWithStripeLink.tsx
|
|
10989
11269
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
@@ -11001,6 +11281,31 @@ var STRIPE_SESSION_STATUS = {
|
|
|
11001
11281
|
EXPIRED: "expired"
|
|
11002
11282
|
};
|
|
11003
11283
|
var STRIPE_SESSION_POLL_INTERVAL_MS = 3e3;
|
|
11284
|
+
var STRIPE_CONSUMED_PAYMENT_METHOD_CODE = "payment_method_unexpected_state";
|
|
11285
|
+
function isConsumedPaymentMethodError(err) {
|
|
11286
|
+
return err instanceof import_core21.StripeApiResponseError && (err.errorType === "stripe_onramp_payment_method_consumed" || err.stripeCode === STRIPE_CONSUMED_PAYMENT_METHOD_CODE);
|
|
11287
|
+
}
|
|
11288
|
+
var STRIPE_PAYMENT_FAILURE_MESSAGES = {
|
|
11289
|
+
card_declined: "Your card was declined. Try again or use a different payment method.",
|
|
11290
|
+
insufficient_funds: "Your card has insufficient funds. Try a different payment method.",
|
|
11291
|
+
expired_card: "Your card has expired. Use a different payment method.",
|
|
11292
|
+
incorrect_cvc: "Your card\u2019s security code is incorrect. Try again or use a different card.",
|
|
11293
|
+
incorrect_number: "Your card number is incorrect. Try again or use a different card.",
|
|
11294
|
+
card_not_supported: "This card isn\u2019t supported for this purchase. Try a different payment method.",
|
|
11295
|
+
processing_error: "We couldn\u2019t process your card. Please try again in a moment.",
|
|
11296
|
+
authentication_required: "Your bank requires authentication for this payment. Please try again.",
|
|
11297
|
+
payment_intent_authentication_failure: "Card authentication failed. Try again or use a different card.",
|
|
11298
|
+
payment_method_provider_decline: "Your payment provider declined the charge. Try a different payment method.",
|
|
11299
|
+
payment_failed: "Your payment didn\u2019t go through. Try again or use a different payment method."
|
|
11300
|
+
};
|
|
11301
|
+
function describeStripePaymentFailure(reason) {
|
|
11302
|
+
if (!reason) return null;
|
|
11303
|
+
return STRIPE_PAYMENT_FAILURE_MESSAGES[reason] ?? null;
|
|
11304
|
+
}
|
|
11305
|
+
var PAYMENT_FAILED_LEAD = "We couldn\u2019t complete your payment.";
|
|
11306
|
+
function unmappedPaymentFailureMessage(stripeMessage) {
|
|
11307
|
+
return stripeMessage ? `${PAYMENT_FAILED_LEAD} ${stripeMessage}` : `${PAYMENT_FAILED_LEAD} Please try again.`;
|
|
11308
|
+
}
|
|
11004
11309
|
var NO_AUTOFILL = {
|
|
11005
11310
|
autoComplete: "off",
|
|
11006
11311
|
"data-lpignore": "true",
|
|
@@ -11102,7 +11407,11 @@ function PayWithStripeLink({
|
|
|
11102
11407
|
}, [controlledStep]);
|
|
11103
11408
|
(0, import_react17.useEffect)(() => {
|
|
11104
11409
|
setLoading(false);
|
|
11105
|
-
|
|
11410
|
+
if (preserveErrorOnNextStepRef.current) {
|
|
11411
|
+
preserveErrorOnNextStepRef.current = false;
|
|
11412
|
+
} else {
|
|
11413
|
+
setError(null);
|
|
11414
|
+
}
|
|
11106
11415
|
setKycPendingMessage(null);
|
|
11107
11416
|
setQuoteLoading(false);
|
|
11108
11417
|
if (step !== "checkout") {
|
|
@@ -11191,7 +11500,10 @@ function PayWithStripeLink({
|
|
|
11191
11500
|
const pendingAddPaymentRef = (0, import_react17.useRef)(false);
|
|
11192
11501
|
const autoOpenedAddPaymentRef = (0, import_react17.useRef)(false);
|
|
11193
11502
|
const checkoutGenRef = (0, import_react17.useRef)(0);
|
|
11503
|
+
const preserveErrorOnNextStepRef = (0, import_react17.useRef)(false);
|
|
11504
|
+
const spentSessionIdsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
|
|
11194
11505
|
const [stripePaymentUIReady, setStripePaymentUIReady] = (0, import_react17.useState)(false);
|
|
11506
|
+
const [addPaymentHovered, setAddPaymentHovered] = (0, import_react17.useState)(false);
|
|
11195
11507
|
const [oauthToken, setOauthToken] = (0, import_react17.useState)(null);
|
|
11196
11508
|
const [refreshTokenValue, setRefreshTokenValue] = (0, import_react17.useState)(null);
|
|
11197
11509
|
const [customerId, setCustomerId] = (0, import_react17.useState)(null);
|
|
@@ -11340,7 +11652,7 @@ function PayWithStripeLink({
|
|
|
11340
11652
|
const merged = [
|
|
11341
11653
|
...pmResult.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
11342
11654
|
...persistedNotInApi ? [persisted] : []
|
|
11343
|
-
];
|
|
11655
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
11344
11656
|
if (merged.length > 0) {
|
|
11345
11657
|
const preferred = persisted && merged.find((m) => m.id === persisted.id) || merged[0];
|
|
11346
11658
|
selectPaymentToken(preferred);
|
|
@@ -11405,6 +11717,7 @@ function PayWithStripeLink({
|
|
|
11405
11717
|
const [selectedPaymentToken, setSelectedPaymentToken] = (0, import_react17.useState)(null);
|
|
11406
11718
|
const [paymentDisplay, setPaymentDisplay] = (0, import_react17.useState)(null);
|
|
11407
11719
|
const selectedTokenSingleUseRef = (0, import_react17.useRef)(false);
|
|
11720
|
+
const deadPaymentTokenIdsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
|
|
11408
11721
|
const selectPaymentToken = (0, import_react17.useCallback)(
|
|
11409
11722
|
(token) => {
|
|
11410
11723
|
selectedTokenSingleUseRef.current = !!token.singleUse;
|
|
@@ -11432,9 +11745,25 @@ function PayWithStripeLink({
|
|
|
11432
11745
|
setStoredSelectedTokenState(null);
|
|
11433
11746
|
}
|
|
11434
11747
|
}, [customerId]);
|
|
11748
|
+
const forgetSelectedPaymentToken = (0, import_react17.useCallback)(
|
|
11749
|
+
(tokenId) => {
|
|
11750
|
+
selectedTokenSingleUseRef.current = false;
|
|
11751
|
+
if (customerId) {
|
|
11752
|
+
const persisted = getStoredSelectedToken(customerId);
|
|
11753
|
+
if (!tokenId || persisted?.id === tokenId) {
|
|
11754
|
+
clearStoredSelectedToken(customerId);
|
|
11755
|
+
}
|
|
11756
|
+
}
|
|
11757
|
+
setSelectedPaymentToken((prev) => !tokenId || prev === tokenId ? null : prev);
|
|
11758
|
+
setPaymentDisplay((prev) => !tokenId || !prev ? null : prev);
|
|
11759
|
+
setStoredSelectedTokenState((prev) => !tokenId || prev?.id === tokenId ? null : prev);
|
|
11760
|
+
},
|
|
11761
|
+
[customerId]
|
|
11762
|
+
);
|
|
11435
11763
|
const displayPaymentTokens = (() => {
|
|
11436
|
-
const
|
|
11437
|
-
|
|
11764
|
+
const isDead = (id) => deadPaymentTokenIdsRef.current.has(id);
|
|
11765
|
+
const apiDisplay = paymentTokens.filter((t13) => !isDead(t13.id)).map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
|
|
11766
|
+
if (storedSelectedToken && !isDead(storedSelectedToken.id) && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
|
|
11438
11767
|
return [...apiDisplay, storedSelectedToken];
|
|
11439
11768
|
}
|
|
11440
11769
|
return apiDisplay;
|
|
@@ -12083,7 +12412,7 @@ function PayWithStripeLink({
|
|
|
12083
12412
|
const merged = [
|
|
12084
12413
|
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
12085
12414
|
...storedNotInApi ? [stored] : []
|
|
12086
|
-
];
|
|
12415
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
12087
12416
|
if (merged.length === 0) {
|
|
12088
12417
|
if (!autoOpenedAddPaymentRef.current) {
|
|
12089
12418
|
autoOpenedAddPaymentRef.current = true;
|
|
@@ -12125,6 +12454,9 @@ function PayWithStripeLink({
|
|
|
12125
12454
|
paymentInnerRef.current.replaceChildren();
|
|
12126
12455
|
};
|
|
12127
12456
|
}, [step, oauthToken, customerId, publishableKey, coordinator]);
|
|
12457
|
+
(0, import_react17.useEffect)(() => {
|
|
12458
|
+
if (step !== "payment") setAddPaymentHovered(false);
|
|
12459
|
+
}, [step]);
|
|
12128
12460
|
(0, import_react17.useEffect)(() => {
|
|
12129
12461
|
if (step !== "add_payment") return;
|
|
12130
12462
|
if (!isCustomerVerified(customer)) {
|
|
@@ -12275,6 +12607,17 @@ function PayWithStripeLink({
|
|
|
12275
12607
|
}
|
|
12276
12608
|
if (message) onDepositError?.({ message, error: err });
|
|
12277
12609
|
};
|
|
12610
|
+
const isRetriablePaymentToken = (id) => !!id && paymentTokens.some((t13) => t13.id === id);
|
|
12611
|
+
const dropConsumedToken = (message, cause) => {
|
|
12612
|
+
if (selectedPaymentToken) deadPaymentTokenIdsRef.current.add(selectedPaymentToken);
|
|
12613
|
+
setSessionForCheckout(null);
|
|
12614
|
+
forgetSelectedPaymentToken(selectedPaymentToken);
|
|
12615
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12616
|
+
setError(message);
|
|
12617
|
+
setStep("amount");
|
|
12618
|
+
onDepositError?.({ message, error: cause });
|
|
12619
|
+
};
|
|
12620
|
+
const CONSUMED_TOKEN_MESSAGE = "That payment method can\u2019t be used. Please choose another.";
|
|
12278
12621
|
if (!sessionForCheckout || sessionForCheckout.amount !== amount || sessionForCheckout.paymentToken !== selectedPaymentToken) {
|
|
12279
12622
|
return;
|
|
12280
12623
|
}
|
|
@@ -12282,19 +12625,29 @@ function PayWithStripeLink({
|
|
|
12282
12625
|
setLoading(true);
|
|
12283
12626
|
setError(null);
|
|
12284
12627
|
setStep("checkout");
|
|
12628
|
+
let lastConfirmError = null;
|
|
12285
12629
|
try {
|
|
12286
|
-
const runCheckout = (sid) =>
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12292
|
-
|
|
12293
|
-
|
|
12294
|
-
|
|
12295
|
-
|
|
12296
|
-
|
|
12297
|
-
|
|
12630
|
+
const runCheckout = (sid) => {
|
|
12631
|
+
spentSessionIdsRef.current.add(sid);
|
|
12632
|
+
return coordinator.performCheckout(sid, async (onrampSessionId) => {
|
|
12633
|
+
try {
|
|
12634
|
+
await withTokenRefresh(
|
|
12635
|
+
(tok) => (0, import_core21.stripeRefreshQuote)(onrampSessionId, tok, publishableKey)
|
|
12636
|
+
);
|
|
12637
|
+
} catch {
|
|
12638
|
+
}
|
|
12639
|
+
try {
|
|
12640
|
+
const confirmResponse = await withTokenRefresh(
|
|
12641
|
+
(tok) => (0, import_core21.stripeConfirmSession)(onrampSessionId, tok, {}, publishableKey)
|
|
12642
|
+
);
|
|
12643
|
+
lastConfirmError = null;
|
|
12644
|
+
return confirmResponse.client_secret ?? "";
|
|
12645
|
+
} catch (confirmErr) {
|
|
12646
|
+
lastConfirmError = confirmErr;
|
|
12647
|
+
throw confirmErr;
|
|
12648
|
+
}
|
|
12649
|
+
});
|
|
12650
|
+
};
|
|
12298
12651
|
const lastErrorFor = async (sid) => {
|
|
12299
12652
|
const sessionState = await withTokenRefresh(
|
|
12300
12653
|
(tok) => (0, import_core21.stripeGetSession)(sid, tok, publishableKey)
|
|
@@ -12354,8 +12707,9 @@ function PayWithStripeLink({
|
|
|
12354
12707
|
setStep("success");
|
|
12355
12708
|
} else if (lastError === "quote_rate_drifted" || lastError === "charged_with_expired_quote") {
|
|
12356
12709
|
setSessionForCheckout(null);
|
|
12357
|
-
|
|
12710
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12358
12711
|
setError("Pricing updated. Please try again.");
|
|
12712
|
+
setStep("amount");
|
|
12359
12713
|
} else if (lastError === "missing_document_verification") {
|
|
12360
12714
|
surfaceStepUpOnAmount(void 0, void 0, "l2");
|
|
12361
12715
|
} else if (lastError === "transaction_limit_reached") {
|
|
@@ -12366,28 +12720,52 @@ function PayWithStripeLink({
|
|
|
12366
12720
|
} else if (lastError === "missing_consumer_wallet") {
|
|
12367
12721
|
setStep("wallet");
|
|
12368
12722
|
setError(null);
|
|
12723
|
+
} else if (isConsumedPaymentMethodError(lastConfirmError)) {
|
|
12724
|
+
dropConsumedToken(CONSUMED_TOKEN_MESSAGE, lastConfirmError);
|
|
12369
12725
|
} else {
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12726
|
+
const confirmErr = lastConfirmError instanceof import_core21.StripeApiResponseError ? lastConfirmError : void 0;
|
|
12727
|
+
const reason = describeStripePaymentFailure(lastError) ?? describeStripePaymentFailure(confirmErr?.stripeCode) ?? unmappedPaymentFailureMessage(confirmErr?.stripeMessage);
|
|
12728
|
+
if (!isRetriablePaymentToken(selectedPaymentToken)) {
|
|
12729
|
+
dropConsumedToken(reason, lastConfirmError ?? void 0);
|
|
12730
|
+
} else {
|
|
12731
|
+
setSessionForCheckout(null);
|
|
12732
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12733
|
+
setError(reason);
|
|
12734
|
+
setStep("amount");
|
|
12735
|
+
onDepositError?.({
|
|
12736
|
+
message: lastError ?? confirmErr?.stripeCode ?? "checkout_failed",
|
|
12737
|
+
error: lastConfirmError ?? void 0
|
|
12738
|
+
});
|
|
12739
|
+
}
|
|
12373
12740
|
}
|
|
12374
12741
|
} catch (err) {
|
|
12375
12742
|
if (isStale()) return;
|
|
12376
|
-
const
|
|
12377
|
-
const
|
|
12378
|
-
|
|
12743
|
+
const stripeErr = lastConfirmError instanceof import_core21.StripeApiResponseError ? lastConfirmError : err instanceof import_core21.StripeApiResponseError ? err : void 0;
|
|
12744
|
+
const effectiveError = stripeErr ?? err;
|
|
12745
|
+
const msg = stripeErr?.message ?? (err instanceof Error ? err.message : "Checkout failed");
|
|
12746
|
+
const errorType = stripeErr?.errorType;
|
|
12747
|
+
if (isConsumedPaymentMethodError(effectiveError)) {
|
|
12748
|
+
dropConsumedToken(CONSUMED_TOKEN_MESSAGE, effectiveError);
|
|
12749
|
+
} else if (errorType === "stripe_onramp_missing_minimum_identity_verification") {
|
|
12379
12750
|
setStep("kyc");
|
|
12380
12751
|
setError(null);
|
|
12381
12752
|
} else if (errorType === "stripe_onramp_missing_identity_verification") {
|
|
12382
|
-
surfaceStepUpOnAmount(
|
|
12753
|
+
surfaceStepUpOnAmount(effectiveError, msg, "l1");
|
|
12383
12754
|
} else if (errorType === "stripe_onramp_missing_document_verification") {
|
|
12384
|
-
surfaceStepUpOnAmount(
|
|
12755
|
+
surfaceStepUpOnAmount(effectiveError, msg, "l2");
|
|
12385
12756
|
} else if (errorType === "stripe_onramp_purchase_limit_reached") {
|
|
12386
|
-
surfaceStepUpOnAmount(
|
|
12757
|
+
surfaceStepUpOnAmount(effectiveError, msg, null);
|
|
12387
12758
|
} else {
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12759
|
+
const reason = describeStripePaymentFailure(stripeErr?.stripeCode) ?? (stripeErr?.stripeMessage ? unmappedPaymentFailureMessage(stripeErr.stripeMessage) : msg || unmappedPaymentFailureMessage());
|
|
12760
|
+
if (!isRetriablePaymentToken(selectedPaymentToken)) {
|
|
12761
|
+
dropConsumedToken(reason, effectiveError);
|
|
12762
|
+
} else {
|
|
12763
|
+
setSessionForCheckout(null);
|
|
12764
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12765
|
+
setError(reason);
|
|
12766
|
+
setStep("amount");
|
|
12767
|
+
onDepositError?.({ message: msg || "checkout_failed", error: effectiveError });
|
|
12768
|
+
}
|
|
12391
12769
|
}
|
|
12392
12770
|
} finally {
|
|
12393
12771
|
setLoading(false);
|
|
@@ -12413,7 +12791,7 @@ function PayWithStripeLink({
|
|
|
12413
12791
|
const merged = [
|
|
12414
12792
|
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
12415
12793
|
...stored && !existing.data.some((t13) => t13.id === stored.id) ? [stored] : []
|
|
12416
|
-
];
|
|
12794
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
12417
12795
|
if (merged.length > 0) {
|
|
12418
12796
|
const preferred = stored && merged.find((m) => m.id === stored.id) || merged[0];
|
|
12419
12797
|
selectPaymentToken(preferred);
|
|
@@ -12492,7 +12870,7 @@ function PayWithStripeLink({
|
|
|
12492
12870
|
(0, import_react17.useEffect)(() => {
|
|
12493
12871
|
if (step === "review") {
|
|
12494
12872
|
const existing = sessionForCheckoutRef.current;
|
|
12495
|
-
const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken);
|
|
12873
|
+
const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(existing.id));
|
|
12496
12874
|
if (quoteNonce === quoteNonceAtReviewRef.current && hasFreshSession) return;
|
|
12497
12875
|
quoteNonceAtReviewRef.current = quoteNonce;
|
|
12498
12876
|
} else if (step !== "amount") {
|
|
@@ -12516,7 +12894,9 @@ function PayWithStripeLink({
|
|
|
12516
12894
|
const hasPaymentMethod = !!(isAuthenticated && selectedPaymentToken && onrampWalletAddress && isOnrampWalletRegistered);
|
|
12517
12895
|
if (hasPaymentMethod) {
|
|
12518
12896
|
const existing = sessionForCheckoutRef.current;
|
|
12519
|
-
const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken
|
|
12897
|
+
const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken && // Never refresh (and thereby reuse) a session already checked out —
|
|
12898
|
+
// its PaymentIntent is spent. Build a fresh one instead.
|
|
12899
|
+
!spentSessionIdsRef.current.has(existing.id);
|
|
12520
12900
|
const session = canRefreshExisting ? await withTokenRefresh((tok) => (0, import_core21.stripeRefreshQuote)(existing.id, tok, publishableKey)) : await withTokenRefresh(
|
|
12521
12901
|
(tok) => (0, import_core21.stripeCreateSession)(
|
|
12522
12902
|
{
|
|
@@ -12644,7 +13024,7 @@ function PayWithStripeLink({
|
|
|
12644
13024
|
const exceedsReachedLimit = limitReachedAmount !== null && hasInput && amountNum >= limitReachedAmount;
|
|
12645
13025
|
const exceedsLimit = exceedsKnownLimit || exceedsReachedLimit || requiredStepUp !== null;
|
|
12646
13026
|
const isValidAmount = hasInput && amountNum >= 5 && !exceedsLimit;
|
|
12647
|
-
const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken);
|
|
13027
|
+
const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(sessionForCheckout.id));
|
|
12648
13028
|
const canCheckoutDirectly = !!(oauthToken && customerId && selectedPaymentToken && isOnrampWalletRegistered);
|
|
12649
13029
|
const isPreparingSession = canCheckoutDirectly && isValidAmount && !quoteError && (quoteLoading || !hasValidSession);
|
|
12650
13030
|
const custTiers = customer?.kyc_tiers ?? [];
|
|
@@ -13161,7 +13541,7 @@ function PayWithStripeLink({
|
|
|
13161
13541
|
{
|
|
13162
13542
|
onClick: kycFormMode === "name" ? handleNameNext : handleKycSubmit,
|
|
13163
13543
|
disabled: loading || (kycFormMode === "name" ? !kycForm.givenName || !kycForm.surname : kycFormMode === "address" ? !kycForm.addressLine1 || !kycForm.addressCity || !kycForm.addressState || !kycForm.addressPostalCode : !kycForm.ssn || !kycForm.dob.day || !kycForm.dob.month || !kycForm.dob.year),
|
|
13164
|
-
className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
13544
|
+
className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13165
13545
|
style: {
|
|
13166
13546
|
backgroundColor: components.button.primaryBackground,
|
|
13167
13547
|
fontFamily: fonts.medium,
|
|
@@ -13220,7 +13600,17 @@ function PayWithStripeLink({
|
|
|
13220
13600
|
className: "uf-w-full uf-flex-1 uf-overflow-y-auto uf-overflow-x-hidden"
|
|
13221
13601
|
}
|
|
13222
13602
|
),
|
|
13223
|
-
!stripePaymentUIReady && /* @__PURE__ */ (0, import_jsx_runtime44.
|
|
13603
|
+
!stripePaymentUIReady && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-gap-3 uf-py-10", children: [
|
|
13604
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react25.Loader2, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }),
|
|
13605
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
13606
|
+
"p",
|
|
13607
|
+
{
|
|
13608
|
+
className: "uf-text-sm uf-text-center",
|
|
13609
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
13610
|
+
children: "Setting up secure payment\u2026"
|
|
13611
|
+
}
|
|
13612
|
+
)
|
|
13613
|
+
] }),
|
|
13224
13614
|
error && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
13225
13615
|
"div",
|
|
13226
13616
|
{
|
|
@@ -13327,35 +13717,14 @@ function PayWithStripeLink({
|
|
|
13327
13717
|
isCustomerVerified(customer) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "uf-px-1", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
13328
13718
|
"button",
|
|
13329
13719
|
{
|
|
13330
|
-
onClick:
|
|
13331
|
-
|
|
13332
|
-
setStep("add_payment");
|
|
13333
|
-
return;
|
|
13334
|
-
}
|
|
13335
|
-
pendingAddPaymentRef.current = true;
|
|
13336
|
-
if (accessTokenRef.current && email) {
|
|
13337
|
-
setLoading(true);
|
|
13338
|
-
try {
|
|
13339
|
-
await withTokenRefresh(
|
|
13340
|
-
(tok) => (0, import_core21.stripeGetCustomer)(customerId, tok, publishableKey)
|
|
13341
|
-
);
|
|
13342
|
-
const sdk = await initialize();
|
|
13343
|
-
if (!sdk) throw new Error("SDK failed to load");
|
|
13344
|
-
const authResult = await (0, import_core21.stripeCreateAuthIntent)(email, publishableKey);
|
|
13345
|
-
setAuthIntentId(authResult.auth_intent_id);
|
|
13346
|
-
setStep("auth");
|
|
13347
|
-
} catch {
|
|
13348
|
-
setStep("email");
|
|
13349
|
-
} finally {
|
|
13350
|
-
setLoading(false);
|
|
13351
|
-
}
|
|
13352
|
-
return;
|
|
13353
|
-
}
|
|
13354
|
-
setStep("email");
|
|
13720
|
+
onClick: () => {
|
|
13721
|
+
setStep("add_payment");
|
|
13355
13722
|
},
|
|
13723
|
+
onMouseEnter: () => setAddPaymentHovered(true),
|
|
13724
|
+
onMouseLeave: () => setAddPaymentHovered(false),
|
|
13356
13725
|
className: "uf-w-full uf-p-3 uf-flex uf-items-center uf-gap-3 uf-transition-colors",
|
|
13357
13726
|
style: {
|
|
13358
|
-
backgroundColor: components.card.backgroundColor,
|
|
13727
|
+
backgroundColor: addPaymentHovered ? colors2.cardHover : components.card.backgroundColor,
|
|
13359
13728
|
borderRadius: components.card.borderRadius,
|
|
13360
13729
|
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
13361
13730
|
},
|
|
@@ -13470,7 +13839,7 @@ function PayWithStripeLink({
|
|
|
13470
13839
|
{
|
|
13471
13840
|
onClick: () => handleEmailSubmit(),
|
|
13472
13841
|
disabled: loading || !email.trim(),
|
|
13473
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
13842
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13474
13843
|
style: {
|
|
13475
13844
|
backgroundColor: components.button.primaryBackground,
|
|
13476
13845
|
fontFamily: fonts.medium,
|
|
@@ -13699,7 +14068,7 @@ function PayWithStripeLink({
|
|
|
13699
14068
|
{
|
|
13700
14069
|
onClick: handleRegisterSubmit,
|
|
13701
14070
|
disabled: loading || phone.length !== 10,
|
|
13702
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14071
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13703
14072
|
style: {
|
|
13704
14073
|
backgroundColor: components.button.primaryBackground,
|
|
13705
14074
|
fontFamily: fonts.medium,
|
|
@@ -13833,7 +14202,9 @@ function PayWithStripeLink({
|
|
|
13833
14202
|
);
|
|
13834
14203
|
}
|
|
13835
14204
|
if (step === "amount") {
|
|
13836
|
-
const
|
|
14205
|
+
const canSelectPaymentMethod = !!(oauthToken && customerId && isCustomerVerified(customer));
|
|
14206
|
+
const needsPaymentMethodSelection = canSelectPaymentMethod && !selectedPaymentToken;
|
|
14207
|
+
const paymentSelector = canSelectPaymentMethod ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
13837
14208
|
"button",
|
|
13838
14209
|
{
|
|
13839
14210
|
onClick: () => setStep("payment"),
|
|
@@ -13907,6 +14278,35 @@ function PayWithStripeLink({
|
|
|
13907
14278
|
style: { backgroundColor: colors2.background },
|
|
13908
14279
|
children: [
|
|
13909
14280
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-mb-6 uf-pt-2", children: [
|
|
14281
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
14282
|
+
"div",
|
|
14283
|
+
{
|
|
14284
|
+
className: "uf-flex uf-items-start uf-gap-2 uf-mx-1 uf-mb-4 uf-px-3 uf-py-2.5",
|
|
14285
|
+
role: "alert",
|
|
14286
|
+
style: {
|
|
14287
|
+
backgroundColor: `${colors2.error}14`,
|
|
14288
|
+
border: `1px solid ${colors2.error}40`,
|
|
14289
|
+
borderRadius: components.card.borderRadius
|
|
14290
|
+
},
|
|
14291
|
+
children: [
|
|
14292
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
14293
|
+
import_lucide_react25.AlertTriangle,
|
|
14294
|
+
{
|
|
14295
|
+
className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
|
|
14296
|
+
style: { color: colors2.error }
|
|
14297
|
+
}
|
|
14298
|
+
),
|
|
14299
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
14300
|
+
"span",
|
|
14301
|
+
{
|
|
14302
|
+
className: "uf-text-xs uf-text-left",
|
|
14303
|
+
style: { color: colors2.error, fontFamily: fonts.regular },
|
|
14304
|
+
children: error
|
|
14305
|
+
}
|
|
14306
|
+
)
|
|
14307
|
+
]
|
|
14308
|
+
}
|
|
14309
|
+
),
|
|
13910
14310
|
paymentSelector,
|
|
13911
14311
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-text-center uf-mb-4", children: [
|
|
13912
14312
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
@@ -13943,7 +14343,7 @@ function PayWithStripeLink({
|
|
|
13943
14343
|
children: amount && amountNum < 5 && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: "Minimum amount is $5" }) : exceedsLimit && canRaiseLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { style: { color: colors2.foregroundMuted }, children: [
|
|
13944
14344
|
purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 ` : "Limit reached \xB7 ",
|
|
13945
14345
|
"Verify to raise"
|
|
13946
|
-
] }) : exceedsLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) :
|
|
14346
|
+
] }) : exceedsLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) : quoteError ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: quoteError }) : quoteLoading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
13947
14347
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
13948
14348
|
import_lucide_react25.Loader2,
|
|
13949
14349
|
{
|
|
@@ -14033,7 +14433,7 @@ function PayWithStripeLink({
|
|
|
14033
14433
|
{
|
|
14034
14434
|
onClick: startLimitStepUp,
|
|
14035
14435
|
disabled: loading,
|
|
14036
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14436
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14037
14437
|
style: {
|
|
14038
14438
|
backgroundColor: components.button.primaryBackground,
|
|
14039
14439
|
fontFamily: fonts.medium,
|
|
@@ -14045,8 +14445,8 @@ function PayWithStripeLink({
|
|
|
14045
14445
|
"button",
|
|
14046
14446
|
{
|
|
14047
14447
|
onClick: handleAmountContinue,
|
|
14048
|
-
disabled: loading || !isValidAmount || !quote || isPreparingSession,
|
|
14049
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14448
|
+
disabled: loading || !isValidAmount || !quote || isPreparingSession || needsPaymentMethodSelection,
|
|
14449
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14050
14450
|
style: {
|
|
14051
14451
|
backgroundColor: components.button.primaryBackground,
|
|
14052
14452
|
fontFamily: fonts.medium,
|
|
@@ -14176,7 +14576,7 @@ function PayWithStripeLink({
|
|
|
14176
14576
|
{
|
|
14177
14577
|
onClick: isBuyNow ? handleCheckout : handleReviewContinue,
|
|
14178
14578
|
disabled: loading || !quote || isBuyNow && !hasValidSession,
|
|
14179
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14579
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14180
14580
|
style: {
|
|
14181
14581
|
backgroundColor: components.button.primaryBackground,
|
|
14182
14582
|
fontFamily: fonts.medium,
|
|
@@ -16423,16 +16823,38 @@ function useExchanges({
|
|
|
16423
16823
|
return { exchanges, isLoading };
|
|
16424
16824
|
}
|
|
16425
16825
|
|
|
16426
|
-
// src/hooks/use-
|
|
16826
|
+
// src/hooks/use-public-incident.ts
|
|
16427
16827
|
var import_react_query13 = require("@tanstack/react-query");
|
|
16428
16828
|
var import_core27 = require("@unifold/core");
|
|
16829
|
+
function usePublicIncident({
|
|
16830
|
+
publishableKey,
|
|
16831
|
+
enabled = true
|
|
16832
|
+
}) {
|
|
16833
|
+
const {
|
|
16834
|
+
data: incident,
|
|
16835
|
+
isLoading,
|
|
16836
|
+
error
|
|
16837
|
+
} = (0, import_react_query13.useQuery)({
|
|
16838
|
+
queryKey: ["unifold", "publicIncident", publishableKey],
|
|
16839
|
+
queryFn: () => (0, import_core27.getPublicIncident)(publishableKey),
|
|
16840
|
+
enabled,
|
|
16841
|
+
staleTime: 1e3 * 30,
|
|
16842
|
+
refetchInterval: 1e3 * 30,
|
|
16843
|
+
refetchOnWindowFocus: true
|
|
16844
|
+
});
|
|
16845
|
+
return { incident, isLoading, error: error ?? null };
|
|
16846
|
+
}
|
|
16847
|
+
|
|
16848
|
+
// src/hooks/use-apple-pay-providers.ts
|
|
16849
|
+
var import_react_query14 = require("@tanstack/react-query");
|
|
16850
|
+
var import_core28 = require("@unifold/core");
|
|
16429
16851
|
function useApplePayProviders({
|
|
16430
16852
|
publishableKey,
|
|
16431
16853
|
enabled = true
|
|
16432
16854
|
}) {
|
|
16433
|
-
const { data: providers, isLoading } = (0,
|
|
16855
|
+
const { data: providers, isLoading } = (0, import_react_query14.useQuery)({
|
|
16434
16856
|
queryKey: ["unifold", "applePayProviders", publishableKey],
|
|
16435
|
-
queryFn: () => (0,
|
|
16857
|
+
queryFn: () => (0, import_core28.getApplePayProviders)(publishableKey),
|
|
16436
16858
|
enabled,
|
|
16437
16859
|
staleTime: 1e3 * 60 * 30,
|
|
16438
16860
|
refetchOnMount: true,
|
|
@@ -16442,7 +16864,7 @@ function useApplePayProviders({
|
|
|
16442
16864
|
}
|
|
16443
16865
|
|
|
16444
16866
|
// src/components/deposits/DepositModal.tsx
|
|
16445
|
-
var
|
|
16867
|
+
var import_core38 = require("@unifold/core");
|
|
16446
16868
|
|
|
16447
16869
|
// src/hooks/use-allowed-country.ts
|
|
16448
16870
|
function useAllowedCountry(publishableKey) {
|
|
@@ -16487,8 +16909,8 @@ function useAllowedCountry(publishableKey) {
|
|
|
16487
16909
|
}
|
|
16488
16910
|
|
|
16489
16911
|
// src/hooks/use-address-validation.ts
|
|
16490
|
-
var
|
|
16491
|
-
var
|
|
16912
|
+
var import_react_query15 = require("@tanstack/react-query");
|
|
16913
|
+
var import_core29 = require("@unifold/core");
|
|
16492
16914
|
function useAddressValidation({
|
|
16493
16915
|
recipientAddress,
|
|
16494
16916
|
destinationChainType,
|
|
@@ -16499,7 +16921,7 @@ function useAddressValidation({
|
|
|
16499
16921
|
refetchOnMount = false
|
|
16500
16922
|
}) {
|
|
16501
16923
|
const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
|
|
16502
|
-
const { data, isLoading, error } = (0,
|
|
16924
|
+
const { data, isLoading, error } = (0, import_react_query15.useQuery)({
|
|
16503
16925
|
queryKey: [
|
|
16504
16926
|
"unifold",
|
|
16505
16927
|
"addressValidation",
|
|
@@ -16508,7 +16930,7 @@ function useAddressValidation({
|
|
|
16508
16930
|
destinationChainId,
|
|
16509
16931
|
destinationTokenAddress
|
|
16510
16932
|
],
|
|
16511
|
-
queryFn: () => (0,
|
|
16933
|
+
queryFn: () => (0, import_core29.verifyRecipientAddress)(
|
|
16512
16934
|
{
|
|
16513
16935
|
chain_type: destinationChainType,
|
|
16514
16936
|
chain_id: destinationChainId,
|
|
@@ -16530,6 +16952,7 @@ function useAddressValidation({
|
|
|
16530
16952
|
return {
|
|
16531
16953
|
isValid: null,
|
|
16532
16954
|
failureCode: null,
|
|
16955
|
+
message: null,
|
|
16533
16956
|
metadata: null,
|
|
16534
16957
|
isLoading: false,
|
|
16535
16958
|
error: null
|
|
@@ -16538,6 +16961,7 @@ function useAddressValidation({
|
|
|
16538
16961
|
return {
|
|
16539
16962
|
isValid: data?.valid ?? null,
|
|
16540
16963
|
failureCode: data?.failure_code ?? null,
|
|
16964
|
+
message: data?.message ?? null,
|
|
16541
16965
|
metadata: data?.metadata ?? null,
|
|
16542
16966
|
isLoading,
|
|
16543
16967
|
error: error ?? null
|
|
@@ -16789,7 +17213,7 @@ function PoweredByUnifold({
|
|
|
16789
17213
|
}
|
|
16790
17214
|
|
|
16791
17215
|
// src/components/deposits/DepositsModal.tsx
|
|
16792
|
-
var
|
|
17216
|
+
var import_core30 = require("@unifold/core");
|
|
16793
17217
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
16794
17218
|
function DepositsModal({
|
|
16795
17219
|
open,
|
|
@@ -16807,7 +17231,7 @@ function DepositsModal({
|
|
|
16807
17231
|
if (!open || !userId) return;
|
|
16808
17232
|
const fetchExecutions = async () => {
|
|
16809
17233
|
try {
|
|
16810
|
-
const response = await (0,
|
|
17234
|
+
const response = await (0, import_core30.queryExecutions)(userId, publishableKey, import_core30.ActionType.Deposit);
|
|
16811
17235
|
const sorted = [...response.data].sort((a, b) => {
|
|
16812
17236
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
16813
17237
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -17390,6 +17814,37 @@ var import_react21 = require("react");
|
|
|
17390
17814
|
var getChainKey = (chainId, chainType) => {
|
|
17391
17815
|
return `${chainType}:${chainId}`;
|
|
17392
17816
|
};
|
|
17817
|
+
function getStoredSelection(key) {
|
|
17818
|
+
if (typeof window === "undefined") return null;
|
|
17819
|
+
try {
|
|
17820
|
+
const raw = localStorage.getItem(key);
|
|
17821
|
+
if (!raw) return null;
|
|
17822
|
+
const parsed = JSON.parse(raw);
|
|
17823
|
+
if (parsed && typeof parsed.symbol === "string" && typeof parsed.chainType === "string" && typeof parsed.chainId === "string") {
|
|
17824
|
+
return parsed;
|
|
17825
|
+
}
|
|
17826
|
+
} catch {
|
|
17827
|
+
}
|
|
17828
|
+
return null;
|
|
17829
|
+
}
|
|
17830
|
+
function saveStoredSelection(key, symbol, chainType, chainId) {
|
|
17831
|
+
if (typeof window === "undefined") return;
|
|
17832
|
+
try {
|
|
17833
|
+
localStorage.setItem(key, JSON.stringify({ symbol, chainType, chainId }));
|
|
17834
|
+
} catch {
|
|
17835
|
+
}
|
|
17836
|
+
}
|
|
17837
|
+
function resolveFromStorage(tokens, stored) {
|
|
17838
|
+
for (const t13 of tokens) {
|
|
17839
|
+
if (t13.symbol !== stored.symbol) continue;
|
|
17840
|
+
const matchedChain = t13.chains.find(
|
|
17841
|
+
(c) => c.chain_type === stored.chainType && c.chain_id === stored.chainId
|
|
17842
|
+
);
|
|
17843
|
+
if (matchedChain) return { token: t13, chain: matchedChain };
|
|
17844
|
+
if (t13.chains.length > 0) return { token: t13, chain: t13.chains[0] };
|
|
17845
|
+
}
|
|
17846
|
+
return null;
|
|
17847
|
+
}
|
|
17393
17848
|
function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
|
|
17394
17849
|
if (!tokens.length) return null;
|
|
17395
17850
|
let selectedToken;
|
|
@@ -17439,27 +17894,73 @@ function useDefaultToken({
|
|
|
17439
17894
|
defaultChainType,
|
|
17440
17895
|
defaultChainId,
|
|
17441
17896
|
defaultTokenAddress,
|
|
17442
|
-
defaultSymbol
|
|
17897
|
+
defaultSymbol,
|
|
17898
|
+
storageKey: storageKey2
|
|
17443
17899
|
}) {
|
|
17444
|
-
const [token,
|
|
17445
|
-
const [chain,
|
|
17900
|
+
const [token, setTokenState] = (0, import_react21.useState)(null);
|
|
17901
|
+
const [chain, setChainState] = (0, import_react21.useState)(null);
|
|
17446
17902
|
const [initialSelectionDone, setInitialSelectionDone] = (0, import_react21.useState)(false);
|
|
17447
17903
|
const appliedDefaultsRef = (0, import_react21.useRef)("");
|
|
17904
|
+
const tokenRef = (0, import_react21.useRef)(null);
|
|
17905
|
+
const chainRef = (0, import_react21.useRef)(null);
|
|
17906
|
+
tokenRef.current = token;
|
|
17907
|
+
chainRef.current = chain;
|
|
17908
|
+
const setToken = (0, import_react21.useCallback)(
|
|
17909
|
+
(newToken) => {
|
|
17910
|
+
tokenRef.current = newToken;
|
|
17911
|
+
setTokenState(newToken);
|
|
17912
|
+
if (storageKey2 && chainRef.current) {
|
|
17913
|
+
const [chainType, chainId] = chainRef.current.split(":");
|
|
17914
|
+
saveStoredSelection(storageKey2, newToken, chainType, chainId);
|
|
17915
|
+
}
|
|
17916
|
+
},
|
|
17917
|
+
[storageKey2]
|
|
17918
|
+
);
|
|
17919
|
+
const setChain = (0, import_react21.useCallback)(
|
|
17920
|
+
(newChain) => {
|
|
17921
|
+
chainRef.current = newChain;
|
|
17922
|
+
setChainState(newChain);
|
|
17923
|
+
if (storageKey2 && tokenRef.current) {
|
|
17924
|
+
const [chainType, chainId] = newChain.split(":");
|
|
17925
|
+
saveStoredSelection(storageKey2, tokenRef.current, chainType, chainId);
|
|
17926
|
+
}
|
|
17927
|
+
},
|
|
17928
|
+
[storageKey2]
|
|
17929
|
+
);
|
|
17448
17930
|
(0, import_react21.useEffect)(() => {
|
|
17449
17931
|
if (!tokens.length) return;
|
|
17450
17932
|
const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
|
|
17451
17933
|
const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
|
|
17452
17934
|
if (initialSelectionDone && !defaultsChanged) return;
|
|
17453
|
-
const
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
|
|
17935
|
+
const hasExplicitDefaults = defaultTokenAddress && defaultChainType && defaultChainId || defaultSymbol && defaultChainType && defaultChainId;
|
|
17936
|
+
let result = null;
|
|
17937
|
+
if (hasExplicitDefaults) {
|
|
17938
|
+
result = resolveToken(
|
|
17939
|
+
tokens,
|
|
17940
|
+
defaultChainType,
|
|
17941
|
+
defaultChainId,
|
|
17942
|
+
defaultTokenAddress,
|
|
17943
|
+
defaultSymbol
|
|
17944
|
+
);
|
|
17945
|
+
if (result) {
|
|
17946
|
+
const matched = defaultTokenAddress && result.chain.token_address.toLowerCase() === defaultTokenAddress.toLowerCase() && result.chain.chain_type === defaultChainType && result.chain.chain_id === defaultChainId || defaultSymbol && result.token.symbol === defaultSymbol && result.chain.chain_type === defaultChainType && result.chain.chain_id === defaultChainId;
|
|
17947
|
+
if (!matched) {
|
|
17948
|
+
result = null;
|
|
17949
|
+
}
|
|
17950
|
+
}
|
|
17951
|
+
}
|
|
17952
|
+
if (!result && storageKey2) {
|
|
17953
|
+
const stored = getStoredSelection(storageKey2);
|
|
17954
|
+
if (stored) {
|
|
17955
|
+
result = resolveFromStorage(tokens, stored);
|
|
17956
|
+
}
|
|
17957
|
+
}
|
|
17958
|
+
if (!result) {
|
|
17959
|
+
result = resolveToken(tokens);
|
|
17960
|
+
}
|
|
17460
17961
|
if (result) {
|
|
17461
|
-
|
|
17462
|
-
|
|
17962
|
+
setTokenState(result.token.symbol);
|
|
17963
|
+
setChainState(getChainKey(result.chain.chain_id, result.chain.chain_type));
|
|
17463
17964
|
appliedDefaultsRef.current = defaultsKey;
|
|
17464
17965
|
setInitialSelectionDone(true);
|
|
17465
17966
|
}
|
|
@@ -17469,7 +17970,8 @@ function useDefaultToken({
|
|
|
17469
17970
|
defaultSymbol,
|
|
17470
17971
|
defaultChainType,
|
|
17471
17972
|
defaultChainId,
|
|
17472
|
-
initialSelectionDone
|
|
17973
|
+
initialSelectionDone,
|
|
17974
|
+
storageKey2
|
|
17473
17975
|
]);
|
|
17474
17976
|
(0, import_react21.useEffect)(() => {
|
|
17475
17977
|
if (!tokens.length || !token) return;
|
|
@@ -17480,13 +17982,14 @@ function useDefaultToken({
|
|
|
17480
17982
|
});
|
|
17481
17983
|
if (!isChainAvailable) {
|
|
17482
17984
|
const firstChain = currentToken.chains[0];
|
|
17483
|
-
|
|
17985
|
+
setChainState(getChainKey(firstChain.chain_id, firstChain.chain_type));
|
|
17484
17986
|
}
|
|
17485
17987
|
}, [token, tokens, chain]);
|
|
17486
17988
|
return { token, chain, setToken, setChain, initialSelectionDone };
|
|
17487
17989
|
}
|
|
17488
17990
|
|
|
17489
17991
|
// src/hooks/use-default-source-token.ts
|
|
17992
|
+
var STORAGE_KEY2 = "unifold_last_deposit_from_token";
|
|
17490
17993
|
function useDefaultSourceToken({
|
|
17491
17994
|
supportedTokens,
|
|
17492
17995
|
defaultSourceChainType,
|
|
@@ -17499,7 +18002,8 @@ function useDefaultSourceToken({
|
|
|
17499
18002
|
defaultChainType: defaultSourceChainType,
|
|
17500
18003
|
defaultChainId: defaultSourceChainId,
|
|
17501
18004
|
defaultTokenAddress: defaultSourceTokenAddress,
|
|
17502
|
-
defaultSymbol: defaultSourceSymbol
|
|
18005
|
+
defaultSymbol: defaultSourceSymbol,
|
|
18006
|
+
storageKey: STORAGE_KEY2
|
|
17503
18007
|
});
|
|
17504
18008
|
}
|
|
17505
18009
|
|
|
@@ -17844,11 +18348,11 @@ var TooltipContent = React33.forwardRef(({ className, sideOffset = 4, ...props }
|
|
|
17844
18348
|
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
17845
18349
|
|
|
17846
18350
|
// src/components/deposits/TransferCryptoSingleInput.tsx
|
|
17847
|
-
var
|
|
18351
|
+
var import_core32 = require("@unifold/core");
|
|
17848
18352
|
|
|
17849
18353
|
// src/hooks/use-hypercore-activation.ts
|
|
17850
|
-
var
|
|
17851
|
-
var
|
|
18354
|
+
var import_react_query16 = require("@tanstack/react-query");
|
|
18355
|
+
var import_core31 = require("@unifold/core");
|
|
17852
18356
|
|
|
17853
18357
|
// src/lib/constants.ts
|
|
17854
18358
|
var HYPERCORE_CHAIN_ID = "1337";
|
|
@@ -17866,9 +18370,9 @@ function useHypercoreActivation(params) {
|
|
|
17866
18370
|
const recipient = recipientAddress?.trim() ?? "";
|
|
17867
18371
|
const source = sourceAddress?.trim() ?? "";
|
|
17868
18372
|
const hasAddresses = !!recipient && !!source;
|
|
17869
|
-
const { data, isLoading } = (0,
|
|
18373
|
+
const { data, isLoading } = (0, import_react_query16.useQuery)({
|
|
17870
18374
|
queryKey: ["unifold", "hypercoreActivation", source, recipient, publishableKey],
|
|
17871
|
-
queryFn: () => (0,
|
|
18375
|
+
queryFn: () => (0, import_core31.checkHypercoreActivation)(
|
|
17872
18376
|
{
|
|
17873
18377
|
source_address: source,
|
|
17874
18378
|
recipient_address: recipient
|
|
@@ -18017,7 +18521,7 @@ function TransferCryptoSingleInput({
|
|
|
18017
18521
|
(c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
|
|
18018
18522
|
) : void 0;
|
|
18019
18523
|
const currentChainType = currentChainData?.chain_type || "ethereum";
|
|
18020
|
-
const currentWallet = (0,
|
|
18524
|
+
const currentWallet = (0, import_core32.getWalletByChainType)(wallets, currentChainType);
|
|
18021
18525
|
const depositAddress = currentWallet?.address || "";
|
|
18022
18526
|
const {
|
|
18023
18527
|
executions: depositExecutions,
|
|
@@ -18262,7 +18766,7 @@ function TransferCryptoSingleInput({
|
|
|
18262
18766
|
className: "uf-text-sm uf-font-semibold",
|
|
18263
18767
|
style: { color: components.card.titleColor, fontFamily: fonts.semibold },
|
|
18264
18768
|
children: [
|
|
18265
|
-
checkoutQuote.isStablecoin ? (0,
|
|
18769
|
+
checkoutQuote.isStablecoin ? (0, import_core32.formatStablecoinAmount)(
|
|
18266
18770
|
checkoutQuote.sourceAmount,
|
|
18267
18771
|
checkoutQuote.sourceTokenDecimals
|
|
18268
18772
|
) : (Number(checkoutQuote.sourceAmount) / 10 ** checkoutQuote.sourceTokenDecimals).toFixed(Math.min(checkoutQuote.sourceTokenDecimals, 6)),
|
|
@@ -18747,7 +19251,7 @@ var SelectSeparator = React34.forwardRef(({ className, ...props }, ref) => /* @_
|
|
|
18747
19251
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
18748
19252
|
|
|
18749
19253
|
// src/components/deposits/TransferCryptoDoubleInput.tsx
|
|
18750
|
-
var
|
|
19254
|
+
var import_core33 = require("@unifold/core");
|
|
18751
19255
|
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
18752
19256
|
var t7 = i18n.transferCrypto;
|
|
18753
19257
|
var getChainKey3 = (chainId, chainType) => {
|
|
@@ -18832,7 +19336,7 @@ function TransferCryptoDoubleInput({
|
|
|
18832
19336
|
(c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
|
|
18833
19337
|
) : void 0;
|
|
18834
19338
|
const currentChainType = currentChainData?.chain_type || "ethereum";
|
|
18835
|
-
const currentWallet = (0,
|
|
19339
|
+
const currentWallet = (0, import_core33.getWalletByChainType)(wallets, currentChainType);
|
|
18836
19340
|
const depositAddress = currentWallet?.address || "";
|
|
18837
19341
|
const {
|
|
18838
19342
|
executions: depositExecutions,
|
|
@@ -19402,10 +19906,10 @@ function TransferCryptoDoubleInput({
|
|
|
19402
19906
|
// src/components/deposits/WalletConnect.tsx
|
|
19403
19907
|
var React35 = __toESM(require("react"));
|
|
19404
19908
|
var import_lucide_react36 = require("lucide-react");
|
|
19405
|
-
var
|
|
19909
|
+
var import_core37 = require("@unifold/core");
|
|
19406
19910
|
|
|
19407
19911
|
// src/lib/send-hypercore.ts
|
|
19408
|
-
var
|
|
19912
|
+
var import_core34 = require("@unifold/core");
|
|
19409
19913
|
function isHypercoreChain(chainId) {
|
|
19410
19914
|
return chainId === HYPERCORE_CHAIN_ID;
|
|
19411
19915
|
}
|
|
@@ -19416,7 +19920,7 @@ async function sendHypercoreEvmTransfer(params) {
|
|
|
19416
19920
|
params: []
|
|
19417
19921
|
});
|
|
19418
19922
|
const activeChainId = String(parseInt(currentChainHex, 16));
|
|
19419
|
-
const buildResult = await (0,
|
|
19923
|
+
const buildResult = await (0, import_core34.buildHypercoreTransaction)(
|
|
19420
19924
|
{
|
|
19421
19925
|
signature_chain_id: activeChainId,
|
|
19422
19926
|
recipient_address: recipientAddress,
|
|
@@ -19429,7 +19933,7 @@ async function sendHypercoreEvmTransfer(params) {
|
|
|
19429
19933
|
method: "eth_signTypedData_v4",
|
|
19430
19934
|
params: [fromAddress, JSON.stringify(buildResult.typed_data)]
|
|
19431
19935
|
});
|
|
19432
|
-
await (0,
|
|
19936
|
+
await (0, import_core34.sendHypercoreTransaction)(
|
|
19433
19937
|
{
|
|
19434
19938
|
action_payload: buildResult.action_payload,
|
|
19435
19939
|
signature,
|
|
@@ -19441,8 +19945,8 @@ async function sendHypercoreEvmTransfer(params) {
|
|
|
19441
19945
|
}
|
|
19442
19946
|
|
|
19443
19947
|
// src/hooks/use-deposit-quote.ts
|
|
19444
|
-
var
|
|
19445
|
-
var
|
|
19948
|
+
var import_react_query17 = require("@tanstack/react-query");
|
|
19949
|
+
var import_core35 = require("@unifold/core");
|
|
19446
19950
|
function useDepositQuote(params) {
|
|
19447
19951
|
const {
|
|
19448
19952
|
publishableKey,
|
|
@@ -19468,7 +19972,7 @@ function useDepositQuote(params) {
|
|
|
19468
19972
|
...adjustForSlippage ? { adjust_for_slippage: true } : {},
|
|
19469
19973
|
...stablecoinParity ? { stablecoin_parity: true } : {}
|
|
19470
19974
|
};
|
|
19471
|
-
return (0,
|
|
19975
|
+
return (0, import_react_query17.useQuery)({
|
|
19472
19976
|
queryKey: [
|
|
19473
19977
|
"unifold",
|
|
19474
19978
|
"depositQuote",
|
|
@@ -19483,7 +19987,7 @@ function useDepositQuote(params) {
|
|
|
19483
19987
|
stablecoinParity,
|
|
19484
19988
|
publishableKey
|
|
19485
19989
|
],
|
|
19486
|
-
queryFn: () => (0,
|
|
19990
|
+
queryFn: () => (0, import_core35.getDepositQuote)(request, publishableKey),
|
|
19487
19991
|
enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
|
|
19488
19992
|
staleTime: 3e4,
|
|
19489
19993
|
gcTime: 5 * 6e4,
|
|
@@ -19496,15 +20000,15 @@ function useDepositQuote(params) {
|
|
|
19496
20000
|
}
|
|
19497
20001
|
|
|
19498
20002
|
// src/hooks/use-external-wallets.ts
|
|
19499
|
-
var
|
|
19500
|
-
var
|
|
20003
|
+
var import_react_query18 = require("@tanstack/react-query");
|
|
20004
|
+
var import_core36 = require("@unifold/core");
|
|
19501
20005
|
function useExternalWallets({
|
|
19502
20006
|
publishableKey,
|
|
19503
20007
|
enabled = true
|
|
19504
20008
|
}) {
|
|
19505
|
-
const { data: wallets = [], isLoading } = (0,
|
|
20009
|
+
const { data: wallets = [], isLoading } = (0, import_react_query18.useQuery)({
|
|
19506
20010
|
queryKey: ["unifold", "external-wallets", publishableKey],
|
|
19507
|
-
queryFn: () => (0,
|
|
20011
|
+
queryFn: () => (0, import_core36.getExternalWallets)(publishableKey).then((res) => res.data),
|
|
19508
20012
|
enabled: enabled && !!publishableKey,
|
|
19509
20013
|
staleTime: 1e3 * 60 * 30,
|
|
19510
20014
|
refetchOnMount: false,
|
|
@@ -20613,33 +21117,11 @@ function balancesRepresentSameToken(a, b) {
|
|
|
20613
21117
|
if (!tokenA || !tokenB) return false;
|
|
20614
21118
|
return tokenA.chain_type === tokenB.chain_type && tokenA.chain_id === tokenB.chain_id && normalizeTokenAddress(tokenA.token_address) === normalizeTokenAddress(tokenB.token_address);
|
|
20615
21119
|
}
|
|
20616
|
-
function getSolanaProviders() {
|
|
20617
|
-
if (typeof window === "undefined") return {};
|
|
20618
|
-
const win = window;
|
|
20619
|
-
return {
|
|
20620
|
-
phantomSolana: win.phantom?.solana,
|
|
20621
|
-
solflare: win.solflare,
|
|
20622
|
-
backpack: win.backpack,
|
|
20623
|
-
glow: win.glow,
|
|
20624
|
-
coinbaseSolana: win.coinbaseSolana || win.coinbaseWalletExtension?.solana
|
|
20625
|
-
};
|
|
20626
|
-
}
|
|
20627
|
-
function getLegacyEvmProviders() {
|
|
20628
|
-
if (typeof window === "undefined") return {};
|
|
20629
|
-
const win = window;
|
|
20630
|
-
return {
|
|
20631
|
-
ethereum: win.ethereum,
|
|
20632
|
-
phantomEthereum: win.phantom?.ethereum,
|
|
20633
|
-
coinbaseEthereum: win.coinbaseWalletExtension,
|
|
20634
|
-
trustEthereum: win.trustwallet?.ethereum,
|
|
20635
|
-
okxEthereum: win.okxwallet
|
|
20636
|
-
};
|
|
20637
|
-
}
|
|
20638
21120
|
function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
|
|
20639
|
-
const solProviders = getSolanaProviders();
|
|
20640
|
-
const legacyEvm = getLegacyEvmProviders();
|
|
20641
|
-
const eip6963List = getEip6963Providers();
|
|
20642
21121
|
const win = typeof window !== "undefined" ? window : null;
|
|
21122
|
+
const solProviders = getInjectedSolanaProviders(win);
|
|
21123
|
+
const legacyEvm = getLegacyEvmProviders(win);
|
|
21124
|
+
const eip6963List = getEip6963Providers();
|
|
20643
21125
|
const hasEip6963 = (walletId) => eip6963List.some((d) => {
|
|
20644
21126
|
const rdns = d.info?.rdns || "";
|
|
20645
21127
|
switch (walletId) {
|
|
@@ -20891,7 +21373,7 @@ function WalletConnect({
|
|
|
20891
21373
|
const chainType = activeDepositWallet?.chain_type ?? "ethereum";
|
|
20892
21374
|
const recipientAddress = activeDepositWallet?.address ?? "";
|
|
20893
21375
|
const isCheckoutMode = !!checkoutAmountUsd;
|
|
20894
|
-
const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
|
|
21376
|
+
const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" || chainType === "tron" ? "ethereum" : chainType;
|
|
20895
21377
|
const transitionTo = React35.useCallback((nextView) => {
|
|
20896
21378
|
if (nextView === viewRef.current) return;
|
|
20897
21379
|
setIsTransitioning(true);
|
|
@@ -20908,10 +21390,13 @@ function WalletConnect({
|
|
|
20908
21390
|
};
|
|
20909
21391
|
const openMobileWalletBrowse = async (wallet, depositAddresses) => {
|
|
20910
21392
|
try {
|
|
20911
|
-
const
|
|
21393
|
+
const cleanedAmountUsd = amountUsd?.replace(/[^0-9.]/g, "") ?? "";
|
|
21394
|
+
const forwardedAmountUsd = parseFloat(cleanedAmountUsd) > 0 ? cleanedAmountUsd : void 0;
|
|
21395
|
+
const res = await (0, import_core37.getWalletMobileDeepLink)(
|
|
20912
21396
|
wallet.id,
|
|
20913
21397
|
depositAddresses,
|
|
20914
|
-
publishableKey
|
|
21398
|
+
publishableKey,
|
|
21399
|
+
forwardedAmountUsd
|
|
20915
21400
|
);
|
|
20916
21401
|
if (res.deeplink) {
|
|
20917
21402
|
setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
|
|
@@ -21000,7 +21485,7 @@ function WalletConnect({
|
|
|
21000
21485
|
const eip6963Match = findProviderByWalletId(wallet.id);
|
|
21001
21486
|
let provider = eip6963Match?.provider;
|
|
21002
21487
|
if (!provider) {
|
|
21003
|
-
const legacyEvm = getLegacyEvmProviders();
|
|
21488
|
+
const legacyEvm = getLegacyEvmProviders(win);
|
|
21004
21489
|
switch (wallet.id) {
|
|
21005
21490
|
case "metamask":
|
|
21006
21491
|
if (legacyEvm.ethereum?.isMetaMask && !legacyEvm.ethereum?.isPhantom)
|
|
@@ -21032,16 +21517,7 @@ function WalletConnect({
|
|
|
21032
21517
|
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
21033
21518
|
if (!accounts?.length) throw new Error("No accounts returned from wallet");
|
|
21034
21519
|
setUserDisconnectedWallet(false);
|
|
21035
|
-
const
|
|
21036
|
-
phantom: "phantom-ethereum",
|
|
21037
|
-
coinbase: "coinbase",
|
|
21038
|
-
trust: "trust",
|
|
21039
|
-
rainbow: "rainbow",
|
|
21040
|
-
rabby: "rabby",
|
|
21041
|
-
okx: "okx",
|
|
21042
|
-
metamask: "metamask"
|
|
21043
|
-
};
|
|
21044
|
-
const walletType = walletIdToType[wallet.id] || "metamask";
|
|
21520
|
+
const walletType = walletIdToWalletType(wallet.id);
|
|
21045
21521
|
setStoredWalletState(walletType);
|
|
21046
21522
|
connectedInfo = {
|
|
21047
21523
|
type: walletType,
|
|
@@ -21050,7 +21526,7 @@ function WalletConnect({
|
|
|
21050
21526
|
icon: wallet.id
|
|
21051
21527
|
};
|
|
21052
21528
|
} else {
|
|
21053
|
-
const solProviders =
|
|
21529
|
+
const solProviders = getInjectedSolanaProviders(win);
|
|
21054
21530
|
let provider;
|
|
21055
21531
|
switch (wallet.id) {
|
|
21056
21532
|
case "phantom":
|
|
@@ -21069,11 +21545,11 @@ function WalletConnect({
|
|
|
21069
21545
|
provider = solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana;
|
|
21070
21546
|
break;
|
|
21071
21547
|
case "trust":
|
|
21072
|
-
provider =
|
|
21548
|
+
provider = solProviders.trustSolana;
|
|
21073
21549
|
break;
|
|
21074
21550
|
}
|
|
21075
21551
|
if (!provider) throw new Error(`${wallet.name} Solana wallet not found.`);
|
|
21076
|
-
const response = await provider.
|
|
21552
|
+
const response = await connectSolanaProviderWithRecovery(provider, wallet.id, wallet.name);
|
|
21077
21553
|
setUserDisconnectedWallet(false);
|
|
21078
21554
|
const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
|
|
21079
21555
|
setStoredWalletState(walletType);
|
|
@@ -21219,7 +21695,7 @@ function WalletConnect({
|
|
|
21219
21695
|
destination_chain_type: activeDepositWallet.destination_chain_type,
|
|
21220
21696
|
...productType ? { product_type: productType } : {}
|
|
21221
21697
|
};
|
|
21222
|
-
const response = await (0,
|
|
21698
|
+
const response = await (0, import_core37.getSupportedDepositTokens)(publishableKey, options);
|
|
21223
21699
|
if (cancelled) return;
|
|
21224
21700
|
const supportedToken = response.data.find(
|
|
21225
21701
|
(t13) => t13.symbol.toLowerCase() === token.symbol.toLowerCase()
|
|
@@ -21246,8 +21722,8 @@ function WalletConnect({
|
|
|
21246
21722
|
let cancelled = false;
|
|
21247
21723
|
setIsLoading(true);
|
|
21248
21724
|
setError(null);
|
|
21249
|
-
const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" ? "ethereum" : activeDepositWallet.chain_type;
|
|
21250
|
-
(0,
|
|
21725
|
+
const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" || activeDepositWallet.chain_type === "tron" ? "ethereum" : activeDepositWallet.chain_type;
|
|
21726
|
+
(0, import_core37.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
|
|
21251
21727
|
if (cancelled) return;
|
|
21252
21728
|
const nonZero = response.balances.filter((b) => b.amount !== "0");
|
|
21253
21729
|
const defaultSource = {
|
|
@@ -21424,16 +21900,7 @@ function WalletConnect({
|
|
|
21424
21900
|
return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
|
|
21425
21901
|
};
|
|
21426
21902
|
const resolveEvmProvider = () => {
|
|
21427
|
-
const
|
|
21428
|
-
"phantom-ethereum": "phantom",
|
|
21429
|
-
coinbase: "coinbase",
|
|
21430
|
-
trust: "trust",
|
|
21431
|
-
okx: "okx",
|
|
21432
|
-
rainbow: "rainbow",
|
|
21433
|
-
rabby: "rabby",
|
|
21434
|
-
metamask: "metamask"
|
|
21435
|
-
};
|
|
21436
|
-
const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
|
|
21903
|
+
const lookupId = walletTypeToWalletId(walletInfo.type);
|
|
21437
21904
|
const eip6963Match = findProviderByWalletId(lookupId);
|
|
21438
21905
|
let provider = eip6963Match?.provider;
|
|
21439
21906
|
if (!provider) {
|
|
@@ -21523,7 +21990,7 @@ function WalletConnect({
|
|
|
21523
21990
|
if (!provider.publicKey) await provider.connect();
|
|
21524
21991
|
const isNative = token.token_address === "native" || token.token_address === "So11111111111111111111111111111111111111112" || token.token_address === "";
|
|
21525
21992
|
const smallestUnit = isNative ? decimalToSmallestUnit(amountStr, 9) : decimalToSmallestUnit(amountStr, token.decimals);
|
|
21526
|
-
const buildResp = await (0,
|
|
21993
|
+
const buildResp = await (0, import_core37.buildSolanaTransaction)(
|
|
21527
21994
|
{
|
|
21528
21995
|
chain_id: "mainnet",
|
|
21529
21996
|
token_address: token.token_address === "" ? "native" : token.token_address,
|
|
@@ -21545,7 +22012,7 @@ function WalletConnect({
|
|
|
21545
22012
|
const ser = signed.serialize();
|
|
21546
22013
|
let bs = "";
|
|
21547
22014
|
for (let i = 0; i < ser.length; i++) bs += String.fromCharCode(ser[i]);
|
|
21548
|
-
const resp = await (0,
|
|
22015
|
+
const resp = await (0, import_core37.sendSolanaTransaction)(
|
|
21549
22016
|
{ chain_id: "mainnet", signed_transaction: btoa(bs) },
|
|
21550
22017
|
publishableKey
|
|
21551
22018
|
);
|
|
@@ -21591,7 +22058,7 @@ function WalletConnect({
|
|
|
21591
22058
|
} else if (isHypercoreToken) {
|
|
21592
22059
|
let sendAmount = tokenAmount;
|
|
21593
22060
|
try {
|
|
21594
|
-
const activation = await (0,
|
|
22061
|
+
const activation = await (0, import_core37.checkHypercoreActivation)(
|
|
21595
22062
|
{ source_address: walletInfo.address, recipient_address: recipientAddress },
|
|
21596
22063
|
publishableKey
|
|
21597
22064
|
);
|
|
@@ -21968,8 +22435,8 @@ function WalletConnect({
|
|
|
21968
22435
|
] }) });
|
|
21969
22436
|
}
|
|
21970
22437
|
if (view === "mobile_deposit_status" && latestDepositExecution) {
|
|
21971
|
-
const isComplete = latestDepositExecution.status ===
|
|
21972
|
-
const isFailed = latestDepositExecution.status ===
|
|
22438
|
+
const isComplete = latestDepositExecution.status === import_core37.ExecutionStatus.SUCCEEDED;
|
|
22439
|
+
const isFailed = latestDepositExecution.status === import_core37.ExecutionStatus.FAILED;
|
|
21973
22440
|
const title = isComplete ? "Payment Complete" : isFailed ? "Payment Failed" : "Payment Processing";
|
|
21974
22441
|
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { style: viewTransitionStyle, children: [
|
|
21975
22442
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
@@ -22165,6 +22632,7 @@ function DepositModal({
|
|
|
22165
22632
|
applePayTitle = "Pay with Apple Pay",
|
|
22166
22633
|
applePaySubTitle = "Instant",
|
|
22167
22634
|
enableBankTransfer,
|
|
22635
|
+
enableIncidentBanner = false,
|
|
22168
22636
|
// No default: left undefined so the backend `stripe_link.enabled` can govern
|
|
22169
22637
|
// (via the `??` chain in showStripeLink) once a dashboard toggle exists.
|
|
22170
22638
|
enableStripeLink,
|
|
@@ -22210,7 +22678,7 @@ function DepositModal({
|
|
|
22210
22678
|
const s = initialScreen ?? "main";
|
|
22211
22679
|
if (s === "tracker" && hideDepositTracker === true) return "main";
|
|
22212
22680
|
if (s === "cashapp" && enableCashApp === false) return "main";
|
|
22213
|
-
if (s === "stripe_link" &&
|
|
22681
|
+
if (s === "stripe_link" && enableStripeLink === false) return "main";
|
|
22214
22682
|
if (s === "apple_pay" && enableApplePay === false) return "main";
|
|
22215
22683
|
if (s === "card" && enableFiatOnramp === false) return "main";
|
|
22216
22684
|
if (s === "pay_with_exchange") return enablePayWithExchange === false ? "main" : "exchange";
|
|
@@ -22269,21 +22737,31 @@ function DepositModal({
|
|
|
22269
22737
|
const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
|
|
22270
22738
|
const showBankTransfer = enableBankTransfer ?? projectConfig?.bank_transfer?.enabled ?? true;
|
|
22271
22739
|
const showDepositTracker = hideDepositTracker ? false : projectConfig?.deposit_tracker?.enabled ?? true;
|
|
22740
|
+
const { incident: publicIncident } = usePublicIncident({
|
|
22741
|
+
publishableKey,
|
|
22742
|
+
enabled: open && enableIncidentBanner
|
|
22743
|
+
});
|
|
22744
|
+
const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
|
|
22745
|
+
enabled: true,
|
|
22746
|
+
messages: publicIncident.messages,
|
|
22747
|
+
severity: publicIncident.severity,
|
|
22748
|
+
statusPageUrl: publicIncident.status_page_url
|
|
22749
|
+
} : void 0;
|
|
22272
22750
|
const [integrationExchanges, setIntegrationExchanges] = (0, import_react26.useState)([]);
|
|
22273
22751
|
(0, import_react26.useEffect)(() => {
|
|
22274
22752
|
if (!showConnectExchange || !open) return;
|
|
22275
|
-
(0,
|
|
22753
|
+
(0, import_core38.getIntegrationExchanges)(publishableKey).then((res) => setIntegrationExchanges(res.data)).catch(() => {
|
|
22276
22754
|
});
|
|
22277
22755
|
}, [showConnectExchange, open, publishableKey]);
|
|
22278
22756
|
const [connectedExchange, setConnectedExchange] = (0, import_react26.useState)(() => {
|
|
22279
22757
|
if (!showConnectExchange) return null;
|
|
22280
|
-
const stored = getStoredIntegrationToken(
|
|
22758
|
+
const stored = getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
|
|
22281
22759
|
if (!stored) return null;
|
|
22282
22760
|
return { name: "Coinbase", iconUrl: void 0, balanceUsd: null, isLoading: true };
|
|
22283
22761
|
});
|
|
22284
22762
|
(0, import_react26.useEffect)(() => {
|
|
22285
22763
|
if (!showConnectExchange || !open || view !== "main") return;
|
|
22286
|
-
const stored = getStoredIntegrationToken(
|
|
22764
|
+
const stored = getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
|
|
22287
22765
|
if (!stored) {
|
|
22288
22766
|
setConnectedExchange(null);
|
|
22289
22767
|
return;
|
|
@@ -22303,24 +22781,24 @@ function DepositModal({
|
|
|
22303
22781
|
}) : null;
|
|
22304
22782
|
setConnectedExchange((prev) => prev ? { ...prev, balanceUsd, isLoading: false } : null);
|
|
22305
22783
|
};
|
|
22306
|
-
(0,
|
|
22784
|
+
(0, import_core38.getIntegrationHoldings)(import_core38.IntegrationProvider.COINBASE, stored.access_token, publishableKey).then(processHoldings).catch(async () => {
|
|
22307
22785
|
try {
|
|
22308
|
-
const refreshResult = await (0,
|
|
22309
|
-
if (!getStoredIntegrationToken(
|
|
22786
|
+
const refreshResult = await (0, import_core38.refreshIntegrationToken)(stored.access_token, publishableKey);
|
|
22787
|
+
if (!getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE)) return;
|
|
22310
22788
|
setStoredIntegrationToken({
|
|
22311
|
-
integration_provider:
|
|
22789
|
+
integration_provider: import_core38.IntegrationProvider.COINBASE,
|
|
22312
22790
|
access_token: refreshResult.access_token,
|
|
22313
22791
|
expires_at: refreshResult.expires_at
|
|
22314
22792
|
});
|
|
22315
|
-
const retryResult = await (0,
|
|
22316
|
-
|
|
22793
|
+
const retryResult = await (0, import_core38.getIntegrationHoldings)(
|
|
22794
|
+
import_core38.IntegrationProvider.COINBASE,
|
|
22317
22795
|
refreshResult.access_token,
|
|
22318
22796
|
publishableKey
|
|
22319
22797
|
);
|
|
22320
22798
|
processHoldings(retryResult);
|
|
22321
22799
|
} catch {
|
|
22322
|
-
if (!getStoredIntegrationToken(
|
|
22323
|
-
clearStoredIntegrationToken(
|
|
22800
|
+
if (!getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE)) return;
|
|
22801
|
+
clearStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
|
|
22324
22802
|
setConnectedExchange(null);
|
|
22325
22803
|
}
|
|
22326
22804
|
});
|
|
@@ -22328,14 +22806,18 @@ function DepositModal({
|
|
|
22328
22806
|
(0, import_react26.useEffect)(() => {
|
|
22329
22807
|
if (!connectedExchange || integrationExchanges.length === 0) return;
|
|
22330
22808
|
const cbExchange = integrationExchanges.find(
|
|
22331
|
-
(e) => e.service_provider ===
|
|
22809
|
+
(e) => e.service_provider === import_core38.IntegrationProvider.COINBASE
|
|
22332
22810
|
);
|
|
22333
22811
|
const iconUrl = cbExchange?.icon_urls?.find((u) => u.format === "svg")?.url || cbExchange?.icon_urls?.find((u) => u.format === "png")?.url || cbExchange?.icon_url;
|
|
22334
22812
|
if (iconUrl && iconUrl !== connectedExchange.iconUrl) {
|
|
22335
22813
|
setConnectedExchange((prev) => prev ? { ...prev, iconUrl } : prev);
|
|
22336
22814
|
}
|
|
22337
22815
|
}, [integrationExchanges, connectedExchange]);
|
|
22338
|
-
const {
|
|
22816
|
+
const {
|
|
22817
|
+
data: depositAddressResponse,
|
|
22818
|
+
isLoading: walletsLoading,
|
|
22819
|
+
error: walletsError
|
|
22820
|
+
} = useDepositAddress({
|
|
22339
22821
|
userId,
|
|
22340
22822
|
publishableKey,
|
|
22341
22823
|
recipientAddress,
|
|
@@ -22433,7 +22915,7 @@ function DepositModal({
|
|
|
22433
22915
|
if (view !== "tracker" || !userId) return;
|
|
22434
22916
|
const fetchExecutions = async () => {
|
|
22435
22917
|
try {
|
|
22436
|
-
const response = await (0,
|
|
22918
|
+
const response = await (0, import_core38.queryExecutions)(userId, publishableKey, import_core38.ActionType.Deposit);
|
|
22437
22919
|
const sorted = [...response.data].sort((a, b) => {
|
|
22438
22920
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
22439
22921
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -22468,6 +22950,7 @@ function DepositModal({
|
|
|
22468
22950
|
const {
|
|
22469
22951
|
isValid: isAddressValid,
|
|
22470
22952
|
failureCode: addressFailureCode,
|
|
22953
|
+
message: addressFailureMessage,
|
|
22471
22954
|
metadata: addressFailureMetadata,
|
|
22472
22955
|
isLoading: isAddressValidationLoading
|
|
22473
22956
|
} = useAddressValidation({
|
|
@@ -22481,17 +22964,31 @@ function DepositModal({
|
|
|
22481
22964
|
refetchOnMount: "always"
|
|
22482
22965
|
});
|
|
22483
22966
|
const addressValidationMessages = i18n.transferCrypto.addressValidation;
|
|
22484
|
-
const getAddressValidationErrorMessage = (code, metadata) => {
|
|
22967
|
+
const getAddressValidationErrorMessage = (message, code, metadata) => {
|
|
22968
|
+
if (message && message.trim().length > 0) return message;
|
|
22485
22969
|
if (!code) return addressValidationMessages.defaultError;
|
|
22486
22970
|
const errors = addressValidationMessages.errors;
|
|
22487
22971
|
const template = errors[code] ?? addressValidationMessages.defaultError;
|
|
22488
22972
|
return interpolate(template, metadata);
|
|
22489
22973
|
};
|
|
22974
|
+
const walletsRecipientError = (0, import_core38.isDepositAddressValidationError)(walletsError) ? walletsError.message : null;
|
|
22975
|
+
const isRecipientAddressInvalid = isAddressValid === false || walletsRecipientError !== null;
|
|
22976
|
+
const recipientInvalidMessage = getAddressValidationErrorMessage(
|
|
22977
|
+
addressFailureMessage ?? walletsRecipientError,
|
|
22978
|
+
addressFailureCode,
|
|
22979
|
+
addressFailureMetadata
|
|
22980
|
+
);
|
|
22490
22981
|
const openingScreen = effectiveInitialScreen;
|
|
22491
22982
|
const sessionOpenedFromMenu = openingScreen === "main";
|
|
22492
22983
|
const standaloneNeedsDepositPrereq = openingScreen !== "main" && (view === "transfer" || view === "card");
|
|
22493
22984
|
let depositPrerequisiteBody;
|
|
22494
|
-
if (
|
|
22985
|
+
if (isRecipientAddressInvalid) {
|
|
22986
|
+
depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
22987
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_lucide_react37.AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
22988
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
|
|
22989
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: recipientInvalidMessage })
|
|
22990
|
+
] });
|
|
22991
|
+
} else if (isCountryLoading || isAddressValidationLoading || tokensLoading || walletsLoading || !projectConfig || // Bank-transfer row visibility depends on the country-gated providers
|
|
22495
22992
|
// fetch — block the menu on it so the row never flashes in or out.
|
|
22496
22993
|
showBankTransfer && bankTransferProvidersLoading || // Same for Apple Pay: row visibility depends on the geo/platform-gated
|
|
22497
22994
|
// providers fetch — block the menu so the row doesn't pop in or out.
|
|
@@ -22513,12 +23010,6 @@ function DepositModal({
|
|
|
22513
23010
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
|
|
22514
23011
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: "There are no supported tokens available from your current location." })
|
|
22515
23012
|
] });
|
|
22516
|
-
} else if (isAddressValid === false) {
|
|
22517
|
-
depositPrerequisiteBody = /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
22518
|
-
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_lucide_react37.AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
22519
|
-
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
|
|
22520
|
-
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(addressFailureCode, addressFailureMetadata) })
|
|
22521
|
-
] });
|
|
22522
23013
|
} else {
|
|
22523
23014
|
depositPrerequisiteBody = null;
|
|
22524
23015
|
}
|
|
@@ -22535,11 +23026,11 @@ function DepositModal({
|
|
|
22535
23026
|
if (view === "wallet_connect" && sessionOpenedFromMenu) setView("main");
|
|
22536
23027
|
};
|
|
22537
23028
|
const handleExchangeDisconnect = () => {
|
|
22538
|
-
const stored = getStoredIntegrationToken(
|
|
23029
|
+
const stored = getStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
|
|
22539
23030
|
if (stored) {
|
|
22540
|
-
(0,
|
|
23031
|
+
(0, import_core38.revokeIntegrationToken)(stored.access_token, publishableKey);
|
|
22541
23032
|
}
|
|
22542
|
-
clearStoredIntegrationToken(
|
|
23033
|
+
clearStoredIntegrationToken(import_core38.IntegrationProvider.COINBASE);
|
|
22543
23034
|
setConnectedExchange(null);
|
|
22544
23035
|
if (view === "coinbase_connect" && sessionOpenedFromMenu) setView("main");
|
|
22545
23036
|
};
|
|
@@ -23012,6 +23503,7 @@ function DepositModal({
|
|
|
23012
23503
|
title: modalTitle || "Deposit",
|
|
23013
23504
|
showClose: !hideOverlay,
|
|
23014
23505
|
onClose: handleClose,
|
|
23506
|
+
incident: activeIncident,
|
|
23015
23507
|
showBalance: showBalanceHeader,
|
|
23016
23508
|
balanceAddress: recipientAddress,
|
|
23017
23509
|
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
|
|
@@ -23031,6 +23523,7 @@ function DepositModal({
|
|
|
23031
23523
|
showBack: showBackTransfer,
|
|
23032
23524
|
onBack: handleBack,
|
|
23033
23525
|
onClose: handleClose,
|
|
23526
|
+
incident: activeIncident,
|
|
23034
23527
|
showBalance: showBalanceHeader,
|
|
23035
23528
|
balanceAddress: recipientAddress,
|
|
23036
23529
|
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
|
|
@@ -23091,7 +23584,8 @@ function DepositModal({
|
|
|
23091
23584
|
title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
|
|
23092
23585
|
showBack: showBackTracker,
|
|
23093
23586
|
onBack: handleBack,
|
|
23094
|
-
onClose: handleClose
|
|
23587
|
+
onClose: handleClose,
|
|
23588
|
+
incident: activeIncident
|
|
23095
23589
|
}
|
|
23096
23590
|
),
|
|
23097
23591
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
@@ -23123,6 +23617,7 @@ function DepositModal({
|
|
|
23123
23617
|
showBack: showBackCard,
|
|
23124
23618
|
onBack: handleBack,
|
|
23125
23619
|
onClose: handleClose,
|
|
23620
|
+
incident: activeIncident,
|
|
23126
23621
|
badge: cardView === "quotes" ? { count: quotesCount } : void 0,
|
|
23127
23622
|
showBalance: showBalanceHeader,
|
|
23128
23623
|
balanceAddress: recipientAddress,
|
|
@@ -23172,7 +23667,8 @@ function DepositModal({
|
|
|
23172
23667
|
title: payWithExchangeTitle,
|
|
23173
23668
|
showBack: exchangeView === "pending" || sessionOpenedFromMenu,
|
|
23174
23669
|
onBack: handleBack,
|
|
23175
|
-
onClose: handleClose
|
|
23670
|
+
onClose: handleClose,
|
|
23671
|
+
incident: activeIncident
|
|
23176
23672
|
}
|
|
23177
23673
|
),
|
|
23178
23674
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
@@ -23286,7 +23782,8 @@ function DepositModal({
|
|
|
23286
23782
|
title: t8.bankTransfer.title,
|
|
23287
23783
|
showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
|
|
23288
23784
|
onBack: handleBack,
|
|
23289
|
-
onClose: handleClose
|
|
23785
|
+
onClose: handleClose,
|
|
23786
|
+
incident: activeIncident
|
|
23290
23787
|
}
|
|
23291
23788
|
),
|
|
23292
23789
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
@@ -23320,26 +23817,24 @@ function DepositModal({
|
|
|
23320
23817
|
title: "Deposit with Link",
|
|
23321
23818
|
showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
|
|
23322
23819
|
onBack: handleBack,
|
|
23820
|
+
incident: activeIncident,
|
|
23323
23821
|
showClose: stripeLinkStep !== "checkout" && stripeLinkStep !== "auth",
|
|
23324
23822
|
onClose: handleClose
|
|
23325
23823
|
}
|
|
23326
23824
|
),
|
|
23327
23825
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
23328
23826
|
isLoadingIp ? (
|
|
23329
|
-
//
|
|
23330
|
-
// PayWithStripeLink (which kicks off config/OAuth work) for a
|
|
23331
|
-
// deep-link user who turns out to be outside the US.
|
|
23827
|
+
// Wait for location so the first config fetch is region-aware.
|
|
23332
23828
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(SkeletonButton, { variant: "with-icons" })
|
|
23333
23829
|
) : !showStripeLink ? (
|
|
23334
|
-
//
|
|
23335
|
-
//
|
|
23336
|
-
//
|
|
23337
|
-
// the Link UI.
|
|
23830
|
+
// Direct opens (initialScreen="stripe_link") have no menu row
|
|
23831
|
+
// to fall back to, so render an unavailable state when backend
|
|
23832
|
+
// config resolves Stripe Link disabled/hidden.
|
|
23338
23833
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
23339
23834
|
GeoRestrictionScreen,
|
|
23340
23835
|
{
|
|
23341
23836
|
methodName: t8.stripeLink.title,
|
|
23342
|
-
message:
|
|
23837
|
+
message: t8.stripeLink.unavailableInRegionMessage
|
|
23343
23838
|
}
|
|
23344
23839
|
)
|
|
23345
23840
|
) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
@@ -23372,7 +23867,8 @@ function DepositModal({
|
|
|
23372
23867
|
title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
|
|
23373
23868
|
showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
|
|
23374
23869
|
onBack: handleBack,
|
|
23375
|
-
onClose: handleClose
|
|
23870
|
+
onClose: handleClose,
|
|
23871
|
+
incident: activeIncident
|
|
23376
23872
|
}
|
|
23377
23873
|
),
|
|
23378
23874
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
@@ -23408,7 +23904,8 @@ function DepositModal({
|
|
|
23408
23904
|
const handled = applePayHandleRef.current?.requestBack() ?? false;
|
|
23409
23905
|
if (!handled) handleBack();
|
|
23410
23906
|
},
|
|
23411
|
-
onClose: handleClose
|
|
23907
|
+
onClose: handleClose,
|
|
23908
|
+
incident: activeIncident
|
|
23412
23909
|
}
|
|
23413
23910
|
),
|
|
23414
23911
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
@@ -23454,14 +23951,14 @@ var import_react27 = require("react");
|
|
|
23454
23951
|
var import_lucide_react38 = require("lucide-react");
|
|
23455
23952
|
|
|
23456
23953
|
// src/hooks/use-payment-intent.ts
|
|
23457
|
-
var
|
|
23458
|
-
var
|
|
23954
|
+
var import_react_query19 = require("@tanstack/react-query");
|
|
23955
|
+
var import_core39 = require("@unifold/core");
|
|
23459
23956
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "expired", "refunded", "canceled"]);
|
|
23460
23957
|
function usePaymentIntent(params) {
|
|
23461
23958
|
const { clientSecret, publishableKey, enabled = true, pollingInterval = 3e3 } = params;
|
|
23462
|
-
return (0,
|
|
23959
|
+
return (0, import_react_query19.useQuery)({
|
|
23463
23960
|
queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
|
|
23464
|
-
queryFn: () => (0,
|
|
23961
|
+
queryFn: () => (0, import_core39.retrievePaymentIntent)(clientSecret, publishableKey),
|
|
23465
23962
|
enabled: enabled && !!clientSecret && !!publishableKey,
|
|
23466
23963
|
staleTime: 0,
|
|
23467
23964
|
refetchInterval: (query) => {
|
|
@@ -23477,7 +23974,7 @@ function usePaymentIntent(params) {
|
|
|
23477
23974
|
}
|
|
23478
23975
|
|
|
23479
23976
|
// src/components/checkout/CheckoutModal.tsx
|
|
23480
|
-
var
|
|
23977
|
+
var import_core40 = require("@unifold/core");
|
|
23481
23978
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
23482
23979
|
function mapToCheckoutPaymentIntent(pi) {
|
|
23483
23980
|
return {
|
|
@@ -23535,6 +24032,7 @@ function CheckoutModal({
|
|
|
23535
24032
|
modalTitle,
|
|
23536
24033
|
enableTransferCrypto,
|
|
23537
24034
|
enableConnectWallet,
|
|
24035
|
+
enableIncidentBanner = false,
|
|
23538
24036
|
defaultSourceChainType,
|
|
23539
24037
|
defaultSourceChainId,
|
|
23540
24038
|
defaultSourceTokenAddress,
|
|
@@ -23563,8 +24061,8 @@ function CheckoutModal({
|
|
|
23563
24061
|
if (isSucceeded && richIntent) {
|
|
23564
24062
|
const createdSec = data.paymentIntent?.updated_at ? Math.floor(new Date(data.paymentIntent.updated_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3);
|
|
23565
24063
|
onEvent?.({
|
|
23566
|
-
id: (0,
|
|
23567
|
-
type:
|
|
24064
|
+
id: (0, import_core40.generatePrefixedKSUID)("sevt"),
|
|
24065
|
+
type: import_core40.CheckoutEventType.PAYMENT_INTENT_SUCCEEDED,
|
|
23568
24066
|
created: createdSec,
|
|
23569
24067
|
method,
|
|
23570
24068
|
data: { object: richIntent }
|
|
@@ -23606,6 +24104,16 @@ function CheckoutModal({
|
|
|
23606
24104
|
});
|
|
23607
24105
|
const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
|
|
23608
24106
|
const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
|
|
24107
|
+
const { incident: publicIncident } = usePublicIncident({
|
|
24108
|
+
publishableKey,
|
|
24109
|
+
enabled: open && enableIncidentBanner
|
|
24110
|
+
});
|
|
24111
|
+
const activeIncident = enableIncidentBanner && publicIncident?.enabled && (publicIncident.messages?.length ?? 0) > 0 ? {
|
|
24112
|
+
enabled: true,
|
|
24113
|
+
messages: publicIncident.messages,
|
|
24114
|
+
severity: publicIncident.severity,
|
|
24115
|
+
statusPageUrl: publicIncident.status_page_url
|
|
24116
|
+
} : void 0;
|
|
23609
24117
|
(0, import_react27.useEffect)(() => {
|
|
23610
24118
|
if (view === "transfer" && !showTransferCrypto) {
|
|
23611
24119
|
setView("main");
|
|
@@ -23907,7 +24415,15 @@ function CheckoutModal({
|
|
|
23907
24415
|
{
|
|
23908
24416
|
className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
|
|
23909
24417
|
children: view === "main" ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
|
|
23910
|
-
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
24418
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
24419
|
+
DepositHeader,
|
|
24420
|
+
{
|
|
24421
|
+
title: modalTitle || "Checkout",
|
|
24422
|
+
showClose: true,
|
|
24423
|
+
onClose: handleClose,
|
|
24424
|
+
incident: activeIncident
|
|
24425
|
+
}
|
|
24426
|
+
),
|
|
23911
24427
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
23912
24428
|
piLoading ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uf-space-y-3", children: [
|
|
23913
24429
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
@@ -24005,7 +24521,8 @@ function CheckoutModal({
|
|
|
24005
24521
|
title: modalTitle || "Checkout",
|
|
24006
24522
|
showBack: true,
|
|
24007
24523
|
onBack: handleBack,
|
|
24008
|
-
onClose: handleClose
|
|
24524
|
+
onClose: handleClose,
|
|
24525
|
+
incident: activeIncident
|
|
24009
24526
|
}
|
|
24010
24527
|
),
|
|
24011
24528
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
@@ -24170,12 +24687,12 @@ var import_react32 = require("react");
|
|
|
24170
24687
|
var import_lucide_react41 = require("lucide-react");
|
|
24171
24688
|
|
|
24172
24689
|
// src/hooks/use-supported-destination-tokens.ts
|
|
24173
|
-
var
|
|
24174
|
-
var
|
|
24690
|
+
var import_react_query20 = require("@tanstack/react-query");
|
|
24691
|
+
var import_core41 = require("@unifold/core");
|
|
24175
24692
|
function useSupportedDestinationTokens(publishableKey, enabled = true) {
|
|
24176
|
-
return (0,
|
|
24693
|
+
return (0, import_react_query20.useQuery)({
|
|
24177
24694
|
queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
|
|
24178
|
-
queryFn: () => (0,
|
|
24695
|
+
queryFn: () => (0, import_core41.getSupportedDestinationTokens)(publishableKey),
|
|
24179
24696
|
staleTime: 1e3 * 60 * 5,
|
|
24180
24697
|
gcTime: 1e3 * 60 * 30,
|
|
24181
24698
|
refetchOnMount: false,
|
|
@@ -24185,6 +24702,7 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
|
|
|
24185
24702
|
}
|
|
24186
24703
|
|
|
24187
24704
|
// src/hooks/use-default-destination-token.ts
|
|
24705
|
+
var STORAGE_KEY3 = "unifold_last_withdraw_to_token";
|
|
24188
24706
|
function useDefaultDestinationToken({
|
|
24189
24707
|
destinationTokens,
|
|
24190
24708
|
defaultDestinationChainType,
|
|
@@ -24197,13 +24715,14 @@ function useDefaultDestinationToken({
|
|
|
24197
24715
|
defaultChainType: defaultDestinationChainType,
|
|
24198
24716
|
defaultChainId: defaultDestinationChainId,
|
|
24199
24717
|
defaultTokenAddress: defaultDestinationTokenAddress,
|
|
24200
|
-
defaultSymbol: defaultDestinationSymbol
|
|
24718
|
+
defaultSymbol: defaultDestinationSymbol,
|
|
24719
|
+
storageKey: STORAGE_KEY3
|
|
24201
24720
|
});
|
|
24202
24721
|
}
|
|
24203
24722
|
|
|
24204
24723
|
// src/hooks/use-source-token-validation.ts
|
|
24205
|
-
var
|
|
24206
|
-
var
|
|
24724
|
+
var import_react_query21 = require("@tanstack/react-query");
|
|
24725
|
+
var import_core42 = require("@unifold/core");
|
|
24207
24726
|
function useSourceTokenValidation(params) {
|
|
24208
24727
|
const {
|
|
24209
24728
|
sourceChainType,
|
|
@@ -24214,7 +24733,7 @@ function useSourceTokenValidation(params) {
|
|
|
24214
24733
|
enabled = true
|
|
24215
24734
|
} = params;
|
|
24216
24735
|
const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
|
|
24217
|
-
return (0,
|
|
24736
|
+
return (0, import_react_query21.useQuery)({
|
|
24218
24737
|
queryKey: [
|
|
24219
24738
|
"unifold",
|
|
24220
24739
|
"sourceTokenValidation",
|
|
@@ -24224,7 +24743,7 @@ function useSourceTokenValidation(params) {
|
|
|
24224
24743
|
publishableKey
|
|
24225
24744
|
],
|
|
24226
24745
|
queryFn: async () => {
|
|
24227
|
-
const res = await (0,
|
|
24746
|
+
const res = await (0, import_core42.getSupportedDepositTokens)(publishableKey);
|
|
24228
24747
|
let matchedMinUsd = null;
|
|
24229
24748
|
let matchedProcessingTime = null;
|
|
24230
24749
|
let matchedSlippage = null;
|
|
@@ -24262,12 +24781,12 @@ function useSourceTokenValidation(params) {
|
|
|
24262
24781
|
}
|
|
24263
24782
|
|
|
24264
24783
|
// src/hooks/use-address-balance.ts
|
|
24265
|
-
var
|
|
24266
|
-
var
|
|
24784
|
+
var import_react_query22 = require("@tanstack/react-query");
|
|
24785
|
+
var import_core43 = require("@unifold/core");
|
|
24267
24786
|
function useAddressBalance(params) {
|
|
24268
24787
|
const { address, chainType, chainId, tokenAddress, publishableKey, enabled = true } = params;
|
|
24269
24788
|
const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
|
|
24270
|
-
return (0,
|
|
24789
|
+
return (0, import_react_query22.useQuery)({
|
|
24271
24790
|
queryKey: [
|
|
24272
24791
|
"unifold",
|
|
24273
24792
|
"addressBalance",
|
|
@@ -24278,7 +24797,7 @@ function useAddressBalance(params) {
|
|
|
24278
24797
|
publishableKey
|
|
24279
24798
|
],
|
|
24280
24799
|
queryFn: async () => {
|
|
24281
|
-
const res = await (0,
|
|
24800
|
+
const res = await (0, import_core43.getAddressBalance)(
|
|
24282
24801
|
address,
|
|
24283
24802
|
chainType,
|
|
24284
24803
|
chainId,
|
|
@@ -24323,13 +24842,13 @@ function useAddressBalance(params) {
|
|
|
24323
24842
|
}
|
|
24324
24843
|
|
|
24325
24844
|
// src/hooks/use-executions.ts
|
|
24326
|
-
var
|
|
24327
|
-
var
|
|
24845
|
+
var import_react_query23 = require("@tanstack/react-query");
|
|
24846
|
+
var import_core44 = require("@unifold/core");
|
|
24328
24847
|
function useExecutions(userId, publishableKey, options) {
|
|
24329
|
-
const actionType = options?.actionType ??
|
|
24330
|
-
return (0,
|
|
24848
|
+
const actionType = options?.actionType ?? import_core44.ActionType.Deposit;
|
|
24849
|
+
return (0, import_react_query23.useQuery)({
|
|
24331
24850
|
queryKey: ["unifold", "executions", actionType, userId, publishableKey],
|
|
24332
|
-
queryFn: () => (0,
|
|
24851
|
+
queryFn: () => (0, import_core44.queryExecutions)(userId, publishableKey, actionType),
|
|
24333
24852
|
enabled: (options?.enabled ?? true) && !!userId,
|
|
24334
24853
|
refetchInterval: options?.refetchInterval ?? 3e3,
|
|
24335
24854
|
staleTime: 0,
|
|
@@ -24340,7 +24859,7 @@ function useExecutions(userId, publishableKey, options) {
|
|
|
24340
24859
|
|
|
24341
24860
|
// src/hooks/use-withdraw-polling.ts
|
|
24342
24861
|
var import_react28 = require("react");
|
|
24343
|
-
var
|
|
24862
|
+
var import_core45 = require("@unifold/core");
|
|
24344
24863
|
var POLL_INTERVAL_MS3 = 2500;
|
|
24345
24864
|
var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
|
|
24346
24865
|
var CUTOFF_BUFFER_MS2 = 6e4;
|
|
@@ -24353,8 +24872,8 @@ function useWithdrawPolling({
|
|
|
24353
24872
|
onWithdrawError
|
|
24354
24873
|
}) {
|
|
24355
24874
|
const createExecutionSuccessEvent = (execution) => ({
|
|
24356
|
-
id: (0,
|
|
24357
|
-
type:
|
|
24875
|
+
id: (0, import_core45.generatePrefixedKSUID)("sevt"),
|
|
24876
|
+
type: import_core45.WithdrawEventType.DIRECT_EXECUTION_SUCCEEDED,
|
|
24358
24877
|
created: execution.updated_at ? Math.floor(new Date(execution.updated_at).getTime() / 1e3) : execution.created_at ? Math.floor(new Date(execution.created_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3),
|
|
24359
24878
|
data: { object: mapToDirectExecution(execution) }
|
|
24360
24879
|
});
|
|
@@ -24405,7 +24924,7 @@ function useWithdrawPolling({
|
|
|
24405
24924
|
const enabledAt = enabledAtRef.current;
|
|
24406
24925
|
const poll = async () => {
|
|
24407
24926
|
try {
|
|
24408
|
-
const response = await (0,
|
|
24927
|
+
const response = await (0, import_core45.queryExecutions)(userId, publishableKey, import_core45.ActionType.Withdraw);
|
|
24409
24928
|
const cutoff = new Date(enabledAt.getTime() - CUTOFF_BUFFER_MS2);
|
|
24410
24929
|
const sorted = [...response.data].sort((a, b) => {
|
|
24411
24930
|
const tA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
@@ -24413,11 +24932,11 @@ function useWithdrawPolling({
|
|
|
24413
24932
|
return tB - tA;
|
|
24414
24933
|
});
|
|
24415
24934
|
const inProgress = [
|
|
24416
|
-
|
|
24417
|
-
|
|
24418
|
-
|
|
24935
|
+
import_core45.ExecutionStatus.PENDING,
|
|
24936
|
+
import_core45.ExecutionStatus.WAITING,
|
|
24937
|
+
import_core45.ExecutionStatus.DELAYED
|
|
24419
24938
|
];
|
|
24420
|
-
const terminal = [
|
|
24939
|
+
const terminal = [import_core45.ExecutionStatus.SUCCEEDED, import_core45.ExecutionStatus.FAILED];
|
|
24421
24940
|
let target = null;
|
|
24422
24941
|
for (const ex of sorted) {
|
|
24423
24942
|
const t13 = ex.created_at ? new Date(ex.created_at) : null;
|
|
@@ -24447,7 +24966,7 @@ function useWithdrawPolling({
|
|
|
24447
24966
|
}
|
|
24448
24967
|
return [...list, ex];
|
|
24449
24968
|
});
|
|
24450
|
-
if (ex.status ===
|
|
24969
|
+
if (ex.status === import_core45.ExecutionStatus.SUCCEEDED && (!prev || inProgress.includes(prev))) {
|
|
24451
24970
|
onSuccessRef.current?.({
|
|
24452
24971
|
message: "Withdrawal completed successfully",
|
|
24453
24972
|
executionId: ex.id,
|
|
@@ -24455,7 +24974,7 @@ function useWithdrawPolling({
|
|
|
24455
24974
|
transaction: ex,
|
|
24456
24975
|
execution: createExecutionSuccessEvent(ex)
|
|
24457
24976
|
});
|
|
24458
|
-
} else if (ex.status ===
|
|
24977
|
+
} else if (ex.status === import_core45.ExecutionStatus.FAILED && prev !== import_core45.ExecutionStatus.FAILED) {
|
|
24459
24978
|
onErrorRef.current?.({
|
|
24460
24979
|
message: "Withdrawal failed",
|
|
24461
24980
|
code: "WITHDRAW_FAILED",
|
|
@@ -24484,7 +25003,7 @@ function useWithdrawPolling({
|
|
|
24484
25003
|
if (!enabled || !depositWalletId) return;
|
|
24485
25004
|
const trigger = async () => {
|
|
24486
25005
|
try {
|
|
24487
|
-
await (0,
|
|
25006
|
+
await (0, import_core45.pollDirectExecutions)({ deposit_wallet_id: depositWalletId }, publishableKey);
|
|
24488
25007
|
} catch {
|
|
24489
25008
|
}
|
|
24490
25009
|
};
|
|
@@ -24653,11 +25172,11 @@ function WithdrawDoubleInput({
|
|
|
24653
25172
|
// src/components/withdrawals/WithdrawForm.tsx
|
|
24654
25173
|
var import_react30 = require("react");
|
|
24655
25174
|
var import_lucide_react39 = require("lucide-react");
|
|
24656
|
-
var
|
|
25175
|
+
var import_core50 = require("@unifold/core");
|
|
24657
25176
|
|
|
24658
25177
|
// src/hooks/use-verify-recipient-address.ts
|
|
24659
|
-
var
|
|
24660
|
-
var
|
|
25178
|
+
var import_react_query24 = require("@tanstack/react-query");
|
|
25179
|
+
var import_core46 = require("@unifold/core");
|
|
24661
25180
|
function useVerifyRecipientAddress(params) {
|
|
24662
25181
|
const {
|
|
24663
25182
|
chainType,
|
|
@@ -24669,7 +25188,7 @@ function useVerifyRecipientAddress(params) {
|
|
|
24669
25188
|
} = params;
|
|
24670
25189
|
const trimmedAddress = recipientAddress?.trim() || "";
|
|
24671
25190
|
const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
|
|
24672
|
-
return (0,
|
|
25191
|
+
return (0, import_react_query24.useQuery)({
|
|
24673
25192
|
queryKey: [
|
|
24674
25193
|
"unifold",
|
|
24675
25194
|
"verifyRecipientAddress",
|
|
@@ -24679,7 +25198,7 @@ function useVerifyRecipientAddress(params) {
|
|
|
24679
25198
|
trimmedAddress,
|
|
24680
25199
|
publishableKey
|
|
24681
25200
|
],
|
|
24682
|
-
queryFn: () => (0,
|
|
25201
|
+
queryFn: () => (0, import_core46.verifyRecipientAddress)(
|
|
24683
25202
|
{
|
|
24684
25203
|
chain_type: chainType,
|
|
24685
25204
|
chain_id: chainId,
|
|
@@ -24698,7 +25217,7 @@ function useVerifyRecipientAddress(params) {
|
|
|
24698
25217
|
}
|
|
24699
25218
|
|
|
24700
25219
|
// src/components/withdrawals/send-withdraw.ts
|
|
24701
|
-
var
|
|
25220
|
+
var import_core47 = require("@unifold/core");
|
|
24702
25221
|
async function sendEvmWithdraw(params) {
|
|
24703
25222
|
const {
|
|
24704
25223
|
provider,
|
|
@@ -24787,7 +25306,7 @@ async function sendSolanaWithdraw(params) {
|
|
|
24787
25306
|
if (!provider.publicKey) {
|
|
24788
25307
|
await provider.connect();
|
|
24789
25308
|
}
|
|
24790
|
-
const buildResponse = await (0,
|
|
25309
|
+
const buildResponse = await (0, import_core47.buildSolanaTransaction)(
|
|
24791
25310
|
{
|
|
24792
25311
|
chain_id: "mainnet",
|
|
24793
25312
|
token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
|
|
@@ -24813,7 +25332,7 @@ async function sendSolanaWithdraw(params) {
|
|
|
24813
25332
|
for (let i = 0; i < serialized.length; i++) {
|
|
24814
25333
|
binaryStr += String.fromCharCode(serialized[i]);
|
|
24815
25334
|
}
|
|
24816
|
-
const sendResponse = await (0,
|
|
25335
|
+
const sendResponse = await (0, import_core47.sendSolanaTransaction)(
|
|
24817
25336
|
{ chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
|
|
24818
25337
|
publishableKey
|
|
24819
25338
|
);
|
|
@@ -24914,11 +25433,11 @@ async function detectBrowserWallet(chainType, senderAddress) {
|
|
|
24914
25433
|
|
|
24915
25434
|
// src/hooks/use-hypercore-withdraw-activation.ts
|
|
24916
25435
|
var import_react29 = require("react");
|
|
24917
|
-
var
|
|
25436
|
+
var import_core49 = require("@unifold/core");
|
|
24918
25437
|
|
|
24919
25438
|
// src/hooks/use-get-deposit-address.ts
|
|
24920
|
-
var
|
|
24921
|
-
var
|
|
25439
|
+
var import_react_query25 = require("@tanstack/react-query");
|
|
25440
|
+
var import_core48 = require("@unifold/core");
|
|
24922
25441
|
function useGetDepositAddress(params) {
|
|
24923
25442
|
const {
|
|
24924
25443
|
userId,
|
|
@@ -24931,7 +25450,7 @@ function useGetDepositAddress(params) {
|
|
|
24931
25450
|
enabled = true
|
|
24932
25451
|
} = params;
|
|
24933
25452
|
const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
|
|
24934
|
-
return (0,
|
|
25453
|
+
return (0, import_react_query25.useQuery)({
|
|
24935
25454
|
queryKey: [
|
|
24936
25455
|
"unifold",
|
|
24937
25456
|
"getDepositAddress",
|
|
@@ -24943,7 +25462,7 @@ function useGetDepositAddress(params) {
|
|
|
24943
25462
|
actionType ?? null,
|
|
24944
25463
|
publishableKey
|
|
24945
25464
|
],
|
|
24946
|
-
queryFn: () => (0,
|
|
25465
|
+
queryFn: () => (0, import_core48.getDepositAddress)(
|
|
24947
25466
|
{
|
|
24948
25467
|
external_user_id: userId,
|
|
24949
25468
|
recipient_address: recipientAddress,
|
|
@@ -24997,7 +25516,7 @@ function useHypercoreWithdrawActivation(params) {
|
|
|
24997
25516
|
destinationChainType,
|
|
24998
25517
|
destinationChainId,
|
|
24999
25518
|
destinationTokenAddress,
|
|
25000
|
-
actionType:
|
|
25519
|
+
actionType: import_core49.ActionType.Withdraw,
|
|
25001
25520
|
enabled: enabled && isHypercore(sourceChainId)
|
|
25002
25521
|
});
|
|
25003
25522
|
const depositWalletAddress = (0, import_react29.useMemo)(() => {
|
|
@@ -25127,6 +25646,9 @@ function WithdrawForm({
|
|
|
25127
25646
|
if (isDebouncing || isVerifyingAddress) return null;
|
|
25128
25647
|
if (verifyError) return t10.invalidAddress;
|
|
25129
25648
|
if (addressVerification && !addressVerification.valid) {
|
|
25649
|
+
if (addressVerification.message && addressVerification.message.trim().length > 0) {
|
|
25650
|
+
return addressVerification.message;
|
|
25651
|
+
}
|
|
25130
25652
|
if (addressVerification.failure_code === "account_not_found")
|
|
25131
25653
|
return `Account not found on ${selectedChain?.chain_name}`;
|
|
25132
25654
|
if (addressVerification.failure_code === "not_opted_in")
|
|
@@ -25288,7 +25810,7 @@ function WithdrawForm({
|
|
|
25288
25810
|
let humanAmount = isMaxed ? balanceData.balanceHuman : toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
|
|
25289
25811
|
if (isHypercoreChain(sourceChainId)) {
|
|
25290
25812
|
try {
|
|
25291
|
-
const check = await (0,
|
|
25813
|
+
const check = await (0, import_core50.checkHypercoreActivation)(
|
|
25292
25814
|
{
|
|
25293
25815
|
source_address: senderAddress,
|
|
25294
25816
|
recipient_address: depositWallet.address
|
|
@@ -25737,11 +26259,11 @@ function WithdrawForm({
|
|
|
25737
26259
|
|
|
25738
26260
|
// src/components/withdrawals/WithdrawExecutionItem.tsx
|
|
25739
26261
|
var import_lucide_react40 = require("lucide-react");
|
|
25740
|
-
var
|
|
26262
|
+
var import_core51 = require("@unifold/core");
|
|
25741
26263
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
25742
26264
|
function WithdrawExecutionItem({ execution, onClick }) {
|
|
25743
26265
|
const { colors: colors2, fonts, components } = useTheme();
|
|
25744
|
-
const isPending = execution.status ===
|
|
26266
|
+
const isPending = execution.status === import_core51.ExecutionStatus.PENDING || execution.status === import_core51.ExecutionStatus.WAITING || execution.status === import_core51.ExecutionStatus.DELAYED;
|
|
25745
26267
|
const formatDateTime = (timestamp) => {
|
|
25746
26268
|
try {
|
|
25747
26269
|
const date = new Date(timestamp);
|
|
@@ -25788,7 +26310,7 @@ function WithdrawExecutionItem({ execution, onClick }) {
|
|
|
25788
26310
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
25789
26311
|
"img",
|
|
25790
26312
|
{
|
|
25791
|
-
src: execution.destination_token_metadata?.icon_url || (0,
|
|
26313
|
+
src: execution.destination_token_metadata?.icon_url || (0, import_core51.getIconUrl)("/icons/tokens/svg/usdc.svg"),
|
|
25792
26314
|
alt: "Token",
|
|
25793
26315
|
width: 36,
|
|
25794
26316
|
height: 36,
|
|
@@ -26024,7 +26546,7 @@ function WithdrawConfirmingView({
|
|
|
26024
26546
|
}
|
|
26025
26547
|
|
|
26026
26548
|
// src/components/withdrawals/WithdrawModal.tsx
|
|
26027
|
-
var
|
|
26549
|
+
var import_core52 = require("@unifold/core");
|
|
26028
26550
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
26029
26551
|
var t11 = i18n.withdrawModal;
|
|
26030
26552
|
var getChainKey5 = (chainId, chainType) => `${chainType}:${chainId}`;
|
|
@@ -26130,26 +26652,26 @@ function WithdrawModal({
|
|
|
26130
26652
|
onWithdrawError
|
|
26131
26653
|
});
|
|
26132
26654
|
const { data: allWithdrawalsData } = useExecutions(externalUserId, publishableKey, {
|
|
26133
|
-
actionType:
|
|
26655
|
+
actionType: import_core52.ActionType.Withdraw,
|
|
26134
26656
|
enabled: open,
|
|
26135
26657
|
refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
|
|
26136
26658
|
});
|
|
26137
26659
|
const allWithdrawals = allWithdrawalsData?.data ?? [];
|
|
26138
26660
|
const handleDepositWalletCreation = (0, import_react32.useCallback)(
|
|
26139
26661
|
async (params) => {
|
|
26140
|
-
const { data: wallets } = await (0,
|
|
26662
|
+
const { data: wallets } = await (0, import_core52.createDepositAddress)(
|
|
26141
26663
|
{
|
|
26142
26664
|
external_user_id: externalUserId,
|
|
26143
26665
|
destination_chain_type: params.destinationChainType,
|
|
26144
26666
|
destination_chain_id: params.destinationChainId,
|
|
26145
26667
|
destination_token_address: params.destinationTokenAddress,
|
|
26146
26668
|
recipient_address: params.recipientAddress,
|
|
26147
|
-
action_type:
|
|
26669
|
+
action_type: import_core52.ActionType.Withdraw,
|
|
26148
26670
|
source_chain_type: sourceChainType
|
|
26149
26671
|
},
|
|
26150
26672
|
publishableKey
|
|
26151
26673
|
);
|
|
26152
|
-
const depositWallet = (0,
|
|
26674
|
+
const depositWallet = (0, import_core52.getWalletByChainType)(wallets, sourceChainType);
|
|
26153
26675
|
if (!depositWallet) {
|
|
26154
26676
|
throw new Error(`No deposit wallet available for ${sourceChainType}`);
|
|
26155
26677
|
}
|
|
@@ -26674,6 +27196,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
|
|
|
26674
27196
|
useDepositPolling,
|
|
26675
27197
|
useDepositQuote,
|
|
26676
27198
|
usePaymentIntent,
|
|
27199
|
+
usePublicIncident,
|
|
26677
27200
|
useSourceTokenValidation,
|
|
26678
27201
|
useSupportedDepositTokens,
|
|
26679
27202
|
useSupportedDestinationTokens,
|