@unifold/ui-react 0.1.77 → 0.1.78
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 +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +341 -139
- package/dist/index.mjs +288 -86
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -420,6 +420,9 @@ var en_default = {
|
|
|
420
420
|
transactionBreakdown: "Transaction breakdown",
|
|
421
421
|
networkFee: "Network fee",
|
|
422
422
|
confirmOrder: "Confirm Order",
|
|
423
|
+
mfaEnrollmentTitle: "Enable SMS or Authy 2FA",
|
|
424
|
+
mfaEnrollmentMessage: "Please make sure you enable SMS or Authy 2FA in your Coinbase account. Press Continue after you enable it.",
|
|
425
|
+
mfaEnrollmentSettingsLink: "Open Coinbase security settings",
|
|
423
426
|
termsNoticePrefix: "By clicking on Confirm Order, you agree to our ",
|
|
424
427
|
termsNoticeLink: "terms",
|
|
425
428
|
termsNoticeSuffix: "."
|
|
@@ -550,7 +553,12 @@ var en_default = {
|
|
|
550
553
|
prefix: "By continuing, you agree to Coinbase's ",
|
|
551
554
|
separator: ", ",
|
|
552
555
|
lastSeparator: ", and ",
|
|
553
|
-
suffix: ".
|
|
556
|
+
suffix: ".",
|
|
557
|
+
agreements: {
|
|
558
|
+
guest_checkout_terms: "Terms of Service",
|
|
559
|
+
user_agreement: "User Agreement",
|
|
560
|
+
privacy_policy: "Privacy Policy"
|
|
561
|
+
}
|
|
554
562
|
},
|
|
555
563
|
errors: {
|
|
556
564
|
rateLimited: "Too many attempts. Please wait a few minutes and try again.",
|
|
@@ -1211,6 +1219,9 @@ var zh_default = {
|
|
|
1211
1219
|
transactionBreakdown: "\u4EA4\u6613\u660E\u7EC6",
|
|
1212
1220
|
networkFee: "\u7F51\u7EDC\u624B\u7EED\u8D39",
|
|
1213
1221
|
confirmOrder: "\u786E\u8BA4\u8BA2\u5355",
|
|
1222
|
+
mfaEnrollmentTitle: "\u8BF7\u542F\u7528\u77ED\u4FE1\u6216 Authy \u53CC\u91CD\u9A8C\u8BC1",
|
|
1223
|
+
mfaEnrollmentMessage: "\u8BF7\u786E\u8BA4\u60A8\u5DF2\u5728 Coinbase \u8D26\u6237\u4E2D\u542F\u7528\u77ED\u4FE1\u6216 Authy \u53CC\u91CD\u9A8C\u8BC1\u3002\u542F\u7528\u540E\u8BF7\u6309\u7EE7\u7EED\u3002",
|
|
1224
|
+
mfaEnrollmentSettingsLink: "\u6253\u5F00 Coinbase \u5B89\u5168\u8BBE\u7F6E",
|
|
1214
1225
|
termsNoticePrefix: "\u70B9\u51FB\u201C\u786E\u8BA4\u8BA2\u5355\u201D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u4EEC\u7684",
|
|
1215
1226
|
termsNoticeLink: "\u6761\u6B3E",
|
|
1216
1227
|
termsNoticeSuffix: "\u3002"
|
|
@@ -1341,7 +1352,12 @@ var zh_default = {
|
|
|
1341
1352
|
prefix: "\u7EE7\u7EED\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
|
|
1342
1353
|
separator: "\u3001",
|
|
1343
1354
|
lastSeparator: "\u548C",
|
|
1344
|
-
suffix: "\
|
|
1355
|
+
suffix: "\u3002",
|
|
1356
|
+
agreements: {
|
|
1357
|
+
guest_checkout_terms: "\u670D\u52A1\u6761\u6B3E",
|
|
1358
|
+
user_agreement: "\u7528\u6237\u534F\u8BAE",
|
|
1359
|
+
privacy_policy: "\u9690\u79C1\u653F\u7B56"
|
|
1360
|
+
}
|
|
1345
1361
|
},
|
|
1346
1362
|
errors: {
|
|
1347
1363
|
rateLimited: "\u5C1D\u8BD5\u6B21\u6570\u8FC7\u591A\u3002\u8BF7\u7A0D\u7B49\u51E0\u5206\u949F\u540E\u91CD\u8BD5\u3002",
|
|
@@ -2002,6 +2018,9 @@ var zh_TW_default = {
|
|
|
2002
2018
|
transactionBreakdown: "\u4EA4\u6613\u660E\u7D30",
|
|
2003
2019
|
networkFee: "\u7DB2\u8DEF\u624B\u7E8C\u8CBB",
|
|
2004
2020
|
confirmOrder: "\u78BA\u8A8D\u8A02\u55AE",
|
|
2021
|
+
mfaEnrollmentTitle: "\u8ACB\u555F\u7528\u7C21\u8A0A\u6216 Authy \u96D9\u91CD\u9A57\u8B49",
|
|
2022
|
+
mfaEnrollmentMessage: "\u8ACB\u78BA\u8A8D\u60A8\u5DF2\u5728 Coinbase \u5E33\u6236\u4E2D\u555F\u7528\u7C21\u8A0A\u6216 Authy \u96D9\u91CD\u9A57\u8B49\u3002\u555F\u7528\u5F8C\u8ACB\u6309\u7E7C\u7E8C\u3002",
|
|
2023
|
+
mfaEnrollmentSettingsLink: "\u958B\u555F Coinbase \u5B89\u5168\u8A2D\u5B9A",
|
|
2005
2024
|
termsNoticePrefix: "\u9EDE\u64CA\u300C\u78BA\u8A8D\u8A02\u55AE\u300D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u5011\u7684",
|
|
2006
2025
|
termsNoticeLink: "\u689D\u6B3E",
|
|
2007
2026
|
termsNoticeSuffix: "\u3002"
|
|
@@ -2132,7 +2151,12 @@ var zh_TW_default = {
|
|
|
2132
2151
|
prefix: "\u7E7C\u7E8C\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
|
|
2133
2152
|
separator: "\u3001",
|
|
2134
2153
|
lastSeparator: "\u548C",
|
|
2135
|
-
suffix: "\
|
|
2154
|
+
suffix: "\u3002",
|
|
2155
|
+
agreements: {
|
|
2156
|
+
guest_checkout_terms: "\u670D\u52D9\u689D\u6B3E",
|
|
2157
|
+
user_agreement: "\u4F7F\u7528\u8005\u5354\u8B70",
|
|
2158
|
+
privacy_policy: "\u96B1\u79C1\u6B0A\u653F\u7B56"
|
|
2159
|
+
}
|
|
2136
2160
|
},
|
|
2137
2161
|
errors: {
|
|
2138
2162
|
rateLimited: "\u5617\u8A66\u6B21\u6578\u904E\u591A\u3002\u8ACB\u7A0D\u7B49\u5E7E\u5206\u9418\u5F8C\u91CD\u8A66\u3002",
|
|
@@ -3071,13 +3095,15 @@ import {
|
|
|
3071
3095
|
} from "@unifold/core";
|
|
3072
3096
|
|
|
3073
3097
|
// src/hooks/use-deposit-address.ts
|
|
3074
|
-
import { useEffect as useEffect3 } from "react";
|
|
3075
3098
|
import { useQuery } from "@tanstack/react-query";
|
|
3076
3099
|
import {
|
|
3077
3100
|
createDepositAddress,
|
|
3078
3101
|
isDepositAddressValidationError
|
|
3079
3102
|
} from "@unifold/core";
|
|
3080
3103
|
|
|
3104
|
+
// src/hooks/use-internal-user-id.ts
|
|
3105
|
+
import { useEffect as useEffect3 } from "react";
|
|
3106
|
+
|
|
3081
3107
|
// src/context/AnalyticsContext.tsx
|
|
3082
3108
|
import * as React5 from "react";
|
|
3083
3109
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
@@ -3109,6 +3135,15 @@ function useAnalytics() {
|
|
|
3109
3135
|
return { track, startSession, endSession, getSessionId, setUserId, subscribe };
|
|
3110
3136
|
}
|
|
3111
3137
|
|
|
3138
|
+
// src/hooks/use-internal-user-id.ts
|
|
3139
|
+
function useStampInternalUserId({ internalUserId }) {
|
|
3140
|
+
const { setUserId } = useAnalytics();
|
|
3141
|
+
useEffect3(() => {
|
|
3142
|
+
if (!internalUserId) return;
|
|
3143
|
+
setUserId(internalUserId);
|
|
3144
|
+
}, [internalUserId, setUserId]);
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3112
3147
|
// src/hooks/use-deposit-address.ts
|
|
3113
3148
|
function useDepositAddress(params) {
|
|
3114
3149
|
const {
|
|
@@ -3122,7 +3157,6 @@ function useDepositAddress(params) {
|
|
|
3122
3157
|
contractCalls,
|
|
3123
3158
|
enabled = true
|
|
3124
3159
|
} = params;
|
|
3125
|
-
const { setUserId } = useAnalytics();
|
|
3126
3160
|
const query = useQuery({
|
|
3127
3161
|
queryKey: [
|
|
3128
3162
|
"unifold",
|
|
@@ -3165,11 +3199,7 @@ function useDepositAddress(params) {
|
|
|
3165
3199
|
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
|
|
3166
3200
|
// 1s, 2s, 4s (max 10s)
|
|
3167
3201
|
});
|
|
3168
|
-
|
|
3169
|
-
if (query.data?.user_id) {
|
|
3170
|
-
setUserId(query.data.user_id);
|
|
3171
|
-
}
|
|
3172
|
-
}, [query.data?.user_id, setUserId]);
|
|
3202
|
+
useStampInternalUserId({ internalUserId: query.data?.user_id });
|
|
3173
3203
|
return query;
|
|
3174
3204
|
}
|
|
3175
3205
|
|
|
@@ -5475,7 +5505,11 @@ function BuyWithCard({
|
|
|
5475
5505
|
method: "card",
|
|
5476
5506
|
flow_type: "deposit",
|
|
5477
5507
|
provider: selectedProvider.service_provider,
|
|
5478
|
-
amount_usd: amount
|
|
5508
|
+
amount_usd: amount,
|
|
5509
|
+
// The execution only exists once the provider's payout lands on this
|
|
5510
|
+
// wallet, and it carries this id — so it's the join key for a purchase
|
|
5511
|
+
// that starts here and never reaches flow_completed.
|
|
5512
|
+
deposit_wallet_id: depositWalletId
|
|
5479
5513
|
});
|
|
5480
5514
|
onEvent?.({
|
|
5481
5515
|
id: generatePrefixedKSUID2("sevt"),
|
|
@@ -6987,6 +7021,8 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
6987
7021
|
const [limitUpgradeError, setLimitUpgradeError] = useState15(null);
|
|
6988
7022
|
const [upgradeSubmitting, setUpgradeSubmitting] = useState15(false);
|
|
6989
7023
|
const upgradeFlowAbortRef = useRef6(null);
|
|
7024
|
+
const applyLimitRoutingRef = useRef6(() => {
|
|
7025
|
+
});
|
|
6990
7026
|
const [amount, setAmount] = useState15(amountUsd ?? "");
|
|
6991
7027
|
const [preparedOrder, setPreparedOrder] = useState15(null);
|
|
6992
7028
|
const sessionAbortRef = useRef6(null);
|
|
@@ -7121,6 +7157,14 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7121
7157
|
},
|
|
7122
7158
|
[email, normalizedPhone, userId]
|
|
7123
7159
|
);
|
|
7160
|
+
const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
|
|
7161
|
+
userId,
|
|
7162
|
+
publishableKey,
|
|
7163
|
+
normalizedPhone,
|
|
7164
|
+
userEmail,
|
|
7165
|
+
sessionPhoneVerified: verificationSession?.phone?.status === "verified",
|
|
7166
|
+
isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
|
|
7167
|
+
});
|
|
7124
7168
|
const createSessionAndSendOtp = useCallback4(async () => {
|
|
7125
7169
|
setView("submitting_session");
|
|
7126
7170
|
setErrorMessage("");
|
|
@@ -7130,7 +7174,12 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7130
7174
|
email,
|
|
7131
7175
|
phone: normalizedPhone,
|
|
7132
7176
|
terms_accepted: true,
|
|
7133
|
-
|
|
7177
|
+
// TODO: when the API honors `false`, this will trigger email OTP.
|
|
7178
|
+
// Today `false` still skips email (we don't verify it) and JWT ev
|
|
7179
|
+
// is null. Don't send `true` — that was a fake attest.
|
|
7180
|
+
email_already_verified: false
|
|
7181
|
+
// Coinbase stays Redis-only + JWT until bank-transfer identity
|
|
7182
|
+
// is live. Do not persist from this path yet.
|
|
7134
7183
|
},
|
|
7135
7184
|
publishableKey
|
|
7136
7185
|
);
|
|
@@ -7140,6 +7189,34 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7140
7189
|
}
|
|
7141
7190
|
setClientSecret(session.client_secret);
|
|
7142
7191
|
storeWalletPaySession();
|
|
7192
|
+
if (session.status === "verified") {
|
|
7193
|
+
const tokenRes = await exchangeOnrampVerificationToken(
|
|
7194
|
+
session.id,
|
|
7195
|
+
session.client_secret,
|
|
7196
|
+
publishableKey
|
|
7197
|
+
);
|
|
7198
|
+
setOnrampToken(tokenRes);
|
|
7199
|
+
storeWalletPaySession({
|
|
7200
|
+
emailVerifiedAt: session.email.verified_at,
|
|
7201
|
+
phoneVerifiedAt: session.phone.verified_at,
|
|
7202
|
+
onrampToken: tokenRes.token,
|
|
7203
|
+
onrampTokenExpiresAtMs: Date.now() + tokenRes.expires_in * 1e3
|
|
7204
|
+
});
|
|
7205
|
+
if (amountUsd) setAmount(amountUsd);
|
|
7206
|
+
try {
|
|
7207
|
+
const result = await refetchWalletPayLimits();
|
|
7208
|
+
if (result.data) {
|
|
7209
|
+
const nextView = getViewForLimitStatus(result.data);
|
|
7210
|
+
if (nextView) {
|
|
7211
|
+
applyLimitRoutingRef.current(nextView, result.data.upgrade_status);
|
|
7212
|
+
return;
|
|
7213
|
+
}
|
|
7214
|
+
}
|
|
7215
|
+
} catch {
|
|
7216
|
+
}
|
|
7217
|
+
setView("amount");
|
|
7218
|
+
return;
|
|
7219
|
+
}
|
|
7143
7220
|
await sendOnrampVerificationOtp(session.id, "phone", session.client_secret, publishableKey);
|
|
7144
7221
|
setResendCooldown(30);
|
|
7145
7222
|
setView("phone_otp");
|
|
@@ -7148,19 +7225,19 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7148
7225
|
setErrorMessage(prettifyVerificationError(raw));
|
|
7149
7226
|
setView("phone_input");
|
|
7150
7227
|
}
|
|
7151
|
-
}, [
|
|
7228
|
+
}, [
|
|
7229
|
+
email,
|
|
7230
|
+
normalizedPhone,
|
|
7231
|
+
publishableKey,
|
|
7232
|
+
storeWalletPaySession,
|
|
7233
|
+
userId,
|
|
7234
|
+
amountUsd,
|
|
7235
|
+
refetchWalletPayLimits
|
|
7236
|
+
]);
|
|
7152
7237
|
const clearUpgradeFields = useCallback4(() => {
|
|
7153
7238
|
setSsnLast4("");
|
|
7154
7239
|
setDobInput("");
|
|
7155
7240
|
}, []);
|
|
7156
|
-
const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
|
|
7157
|
-
userId,
|
|
7158
|
-
publishableKey,
|
|
7159
|
-
normalizedPhone,
|
|
7160
|
-
userEmail,
|
|
7161
|
-
sessionPhoneVerified: verificationSession?.phone?.status === "verified",
|
|
7162
|
-
isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
|
|
7163
|
-
});
|
|
7164
7241
|
const pollLimitUpgradeStatus = useCallback4(
|
|
7165
7242
|
async (signal) => {
|
|
7166
7243
|
const POLL_INTERVAL_MS5 = 1500;
|
|
@@ -7271,6 +7348,7 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7271
7348
|
},
|
|
7272
7349
|
[startUpgradePolling]
|
|
7273
7350
|
);
|
|
7351
|
+
applyLimitRoutingRef.current = applyLimitRouting;
|
|
7274
7352
|
const hasInitializedRef = useRef6(false);
|
|
7275
7353
|
useEffect12(() => {
|
|
7276
7354
|
if (hasInitializedRef.current) return;
|
|
@@ -7500,7 +7578,10 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7500
7578
|
track("flow_started", {
|
|
7501
7579
|
method,
|
|
7502
7580
|
flow_type: "deposit",
|
|
7503
|
-
amount_usd: walletPayAmountUsd
|
|
7581
|
+
amount_usd: walletPayAmountUsd,
|
|
7582
|
+
// No execution yet — one appears when the payout lands on this
|
|
7583
|
+
// wallet, carrying the same id.
|
|
7584
|
+
deposit_wallet_id: depositWalletId
|
|
7504
7585
|
});
|
|
7505
7586
|
onEvent?.({
|
|
7506
7587
|
id: generatePrefixedKSUID3("sevt"),
|
|
@@ -7550,6 +7631,7 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7550
7631
|
defaultTokenLoading,
|
|
7551
7632
|
defaultTokenError,
|
|
7552
7633
|
depositWallet?.address,
|
|
7634
|
+
depositWalletId,
|
|
7553
7635
|
userEmail,
|
|
7554
7636
|
publishableKey,
|
|
7555
7637
|
onEvent,
|
|
@@ -8524,7 +8606,7 @@ var FALLBACK_AGREEMENTS = [
|
|
|
8524
8606
|
{
|
|
8525
8607
|
key: "guest_checkout_terms",
|
|
8526
8608
|
name: "Guest Checkout Terms of Service",
|
|
8527
|
-
url: "https://www.coinbase.com/legal/
|
|
8609
|
+
url: "https://www.coinbase.com/legal/guest-checkout/us"
|
|
8528
8610
|
},
|
|
8529
8611
|
{
|
|
8530
8612
|
key: "user_agreement",
|
|
@@ -8544,22 +8626,24 @@ function LegalDisclaimer({ legalAgreements, loading }) {
|
|
|
8544
8626
|
return /* @__PURE__ */ jsxs14(
|
|
8545
8627
|
"div",
|
|
8546
8628
|
{
|
|
8547
|
-
className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse",
|
|
8629
|
+
className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse uf-opacity-50",
|
|
8548
8630
|
"aria-hidden": true,
|
|
8549
8631
|
"aria-busy": "true",
|
|
8550
8632
|
children: [
|
|
8551
|
-
/* @__PURE__ */ jsx18("div", { className: "uf-h-2
|
|
8552
|
-
/* @__PURE__ */ jsx18("div", { className: "uf-h-2
|
|
8553
|
-
/* @__PURE__ */ jsx18("div", { className: "uf-h-2
|
|
8633
|
+
/* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-full", style: { backgroundColor: colors2.card } }),
|
|
8634
|
+
/* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-11/12", style: { backgroundColor: colors2.card } }),
|
|
8635
|
+
/* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-3/4", style: { backgroundColor: colors2.card } })
|
|
8554
8636
|
]
|
|
8555
8637
|
}
|
|
8556
8638
|
);
|
|
8557
8639
|
}
|
|
8558
8640
|
const agreements = legalAgreements?.agreements ?? FALLBACK_AGREEMENTS;
|
|
8641
|
+
const shortLabels = t.agreements;
|
|
8642
|
+
const lastSeparator = t.lastSeparator.replace(/\s+$/, "\xA0");
|
|
8559
8643
|
return /* @__PURE__ */ jsxs14(
|
|
8560
8644
|
"p",
|
|
8561
8645
|
{
|
|
8562
|
-
className: "uf-text-[
|
|
8646
|
+
className: "uf-text-[10px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-opacity-60 uf-text-center",
|
|
8563
8647
|
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
8564
8648
|
children: [
|
|
8565
8649
|
t.prefix,
|
|
@@ -8570,12 +8654,12 @@ function LegalDisclaimer({ legalAgreements, loading }) {
|
|
|
8570
8654
|
href: a.url,
|
|
8571
8655
|
target: "_blank",
|
|
8572
8656
|
rel: "noopener noreferrer",
|
|
8573
|
-
className: "uf-underline",
|
|
8574
|
-
style: { color:
|
|
8575
|
-
children: a.name
|
|
8657
|
+
className: "uf-no-underline",
|
|
8658
|
+
style: { color: "inherit", textDecoration: "none", whiteSpace: "nowrap" },
|
|
8659
|
+
children: shortLabels[a.key] ?? a.name
|
|
8576
8660
|
}
|
|
8577
8661
|
),
|
|
8578
|
-
idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ?
|
|
8662
|
+
idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? lastSeparator : ""
|
|
8579
8663
|
] }, a.key)),
|
|
8580
8664
|
t.suffix
|
|
8581
8665
|
]
|
|
@@ -9259,6 +9343,7 @@ function PayWithCashApp({
|
|
|
9259
9343
|
destinationChainType,
|
|
9260
9344
|
destinationChainId,
|
|
9261
9345
|
destinationTokenAddress,
|
|
9346
|
+
contractCalls,
|
|
9262
9347
|
cashAppIconUrl,
|
|
9263
9348
|
view: controlledView,
|
|
9264
9349
|
onViewChange,
|
|
@@ -9351,7 +9436,8 @@ function PayWithCashApp({
|
|
|
9351
9436
|
destination_token_address: destinationTokenAddress,
|
|
9352
9437
|
recipient_address: recipientAddress,
|
|
9353
9438
|
source_amount: amount,
|
|
9354
|
-
external_id: externalId
|
|
9439
|
+
external_id: externalId,
|
|
9440
|
+
...contractCalls?.length ? { contract_calls: contractCalls } : {}
|
|
9355
9441
|
},
|
|
9356
9442
|
publishableKey
|
|
9357
9443
|
);
|
|
@@ -9364,7 +9450,10 @@ function PayWithCashApp({
|
|
|
9364
9450
|
track("flow_started", {
|
|
9365
9451
|
method: "cashapp",
|
|
9366
9452
|
flow_type: "deposit",
|
|
9367
|
-
amount_usd: amount
|
|
9453
|
+
amount_usd: amount,
|
|
9454
|
+
// No execution yet — one appears when the payout lands on this
|
|
9455
|
+
// wallet, carrying the same id.
|
|
9456
|
+
deposit_wallet_id: depositWalletId
|
|
9368
9457
|
});
|
|
9369
9458
|
onEvent?.({
|
|
9370
9459
|
id: generatePrefixedKSUID5("sevt"),
|
|
@@ -9389,6 +9478,8 @@ function PayWithCashApp({
|
|
|
9389
9478
|
destinationChainType,
|
|
9390
9479
|
destinationChainId,
|
|
9391
9480
|
destinationTokenAddress,
|
|
9481
|
+
contractCalls,
|
|
9482
|
+
depositWalletId,
|
|
9392
9483
|
onEvent,
|
|
9393
9484
|
onDepositError,
|
|
9394
9485
|
track,
|
|
@@ -10009,7 +10100,10 @@ function BankTransfer({
|
|
|
10009
10100
|
method: "bank_transfer",
|
|
10010
10101
|
flow_type: "deposit",
|
|
10011
10102
|
provider: request.service_provider,
|
|
10012
|
-
amount_usd: request.source_amount
|
|
10103
|
+
amount_usd: request.source_amount,
|
|
10104
|
+
// No execution yet — one appears when the provider's payout lands on
|
|
10105
|
+
// this wallet, carrying the same id.
|
|
10106
|
+
deposit_wallet_id: pollingWalletId
|
|
10013
10107
|
});
|
|
10014
10108
|
onEvent?.({
|
|
10015
10109
|
id: generatePrefixedKSUID6("sevt"),
|
|
@@ -16274,7 +16368,11 @@ function PayWithStripeLink({
|
|
|
16274
16368
|
if (checkoutResult.successful) {
|
|
16275
16369
|
handledTerminalSessionRef.current = null;
|
|
16276
16370
|
executionReconciledSessionRef.current = null;
|
|
16277
|
-
track("flow_started", {
|
|
16371
|
+
track("flow_started", {
|
|
16372
|
+
method: "stripe_link",
|
|
16373
|
+
flow_type: "deposit",
|
|
16374
|
+
deposit_wallet_id: depositWalletId
|
|
16375
|
+
});
|
|
16278
16376
|
setConfirmedSessionId(activeSessionId);
|
|
16279
16377
|
setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
|
|
16280
16378
|
if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
|
|
@@ -17771,7 +17869,14 @@ function PayWithStripeLink({
|
|
|
17771
17869
|
]
|
|
17772
17870
|
}
|
|
17773
17871
|
),
|
|
17774
|
-
/* @__PURE__ */ jsx50(
|
|
17872
|
+
/* @__PURE__ */ jsx50(
|
|
17873
|
+
"div",
|
|
17874
|
+
{
|
|
17875
|
+
ref: authMountRef,
|
|
17876
|
+
className: "uf-w-full uf-min-h-[200px]",
|
|
17877
|
+
style: { colorScheme: "only light" }
|
|
17878
|
+
}
|
|
17879
|
+
)
|
|
17775
17880
|
]
|
|
17776
17881
|
}
|
|
17777
17882
|
);
|
|
@@ -19079,6 +19184,9 @@ function CoinbaseConnect({
|
|
|
19079
19184
|
flow_type: "deposit",
|
|
19080
19185
|
method: "exchange_connect",
|
|
19081
19186
|
provider: IntegrationProvider.COINBASE,
|
|
19187
|
+
// No execution yet — one appears when the exchange's transfer lands on
|
|
19188
|
+
// this wallet, carrying the same id.
|
|
19189
|
+
deposit_wallet_id: transferDepositWalletId,
|
|
19082
19190
|
amount_usd: sendAmount || void 0,
|
|
19083
19191
|
currency: selectedAsset?.currency.toLowerCase().replace(/[^a-z0-9]+/g, "_"),
|
|
19084
19192
|
chain: sourceChain?.chain_id,
|
|
@@ -19086,6 +19194,34 @@ function CoinbaseConnect({
|
|
|
19086
19194
|
network: sourceChain?.network
|
|
19087
19195
|
});
|
|
19088
19196
|
};
|
|
19197
|
+
const applyConfirmResult = (result) => {
|
|
19198
|
+
if (result.status === "mfa_required") {
|
|
19199
|
+
track("verification_started", {
|
|
19200
|
+
flow_type: "deposit",
|
|
19201
|
+
method: "exchange_connect",
|
|
19202
|
+
provider: IntegrationProvider.COINBASE,
|
|
19203
|
+
verification_type: "mfa",
|
|
19204
|
+
verification_status: result.status
|
|
19205
|
+
});
|
|
19206
|
+
transitionTo("mfa");
|
|
19207
|
+
setMfaCode("");
|
|
19208
|
+
setMfaError(false);
|
|
19209
|
+
} else if (result.status === "mfa_enrollment_required") {
|
|
19210
|
+
transitionTo("mfa_enrollment");
|
|
19211
|
+
} else if (result.status === "completed") {
|
|
19212
|
+
trackTransferStarted();
|
|
19213
|
+
setConfirmResult(result);
|
|
19214
|
+
transitionTo("success");
|
|
19215
|
+
onTransferSuccess?.(result);
|
|
19216
|
+
} else {
|
|
19217
|
+
setErrorMessage(result.message || t.errors.transferFailed);
|
|
19218
|
+
transitionTo("error");
|
|
19219
|
+
onTransferError?.({
|
|
19220
|
+
message: result.message || t.errors.transferFailed,
|
|
19221
|
+
code: result.status
|
|
19222
|
+
});
|
|
19223
|
+
}
|
|
19224
|
+
};
|
|
19089
19225
|
const handleConfirmTransfer = async () => {
|
|
19090
19226
|
if (!transferIntent || !accessToken) return;
|
|
19091
19227
|
setIsLoading(true);
|
|
@@ -19120,30 +19256,7 @@ function CoinbaseConnect({
|
|
|
19120
19256
|
});
|
|
19121
19257
|
throw err;
|
|
19122
19258
|
});
|
|
19123
|
-
|
|
19124
|
-
track("verification_started", {
|
|
19125
|
-
flow_type: "deposit",
|
|
19126
|
-
method: "exchange_connect",
|
|
19127
|
-
provider: IntegrationProvider.COINBASE,
|
|
19128
|
-
verification_type: "mfa",
|
|
19129
|
-
verification_status: result.status
|
|
19130
|
-
});
|
|
19131
|
-
transitionTo("mfa");
|
|
19132
|
-
setMfaCode("");
|
|
19133
|
-
setMfaError(false);
|
|
19134
|
-
} else if (result.status === "completed") {
|
|
19135
|
-
trackTransferStarted();
|
|
19136
|
-
setConfirmResult(result);
|
|
19137
|
-
transitionTo("success");
|
|
19138
|
-
onTransferSuccess?.(result);
|
|
19139
|
-
} else {
|
|
19140
|
-
setErrorMessage(result.message || t.errors.transferFailed);
|
|
19141
|
-
transitionTo("error");
|
|
19142
|
-
onTransferError?.({
|
|
19143
|
-
message: result.message || t.errors.transferFailed,
|
|
19144
|
-
code: result.status
|
|
19145
|
-
});
|
|
19146
|
-
}
|
|
19259
|
+
applyConfirmResult(result);
|
|
19147
19260
|
} catch (err) {
|
|
19148
19261
|
const message = err instanceof Error ? err.message : t.errors.transferFailed;
|
|
19149
19262
|
setErrorMessage(message);
|
|
@@ -19300,6 +19413,9 @@ function CoinbaseConnect({
|
|
|
19300
19413
|
setShowTransferDetails(false);
|
|
19301
19414
|
transitionTo("enter_amount");
|
|
19302
19415
|
break;
|
|
19416
|
+
case "mfa_enrollment":
|
|
19417
|
+
transitionTo("transfer_confirm");
|
|
19418
|
+
break;
|
|
19303
19419
|
case "mfa":
|
|
19304
19420
|
transitionTo("transfer_confirm");
|
|
19305
19421
|
break;
|
|
@@ -20856,6 +20972,55 @@ function CoinbaseConnect({
|
|
|
20856
20972
|
] })
|
|
20857
20973
|
] });
|
|
20858
20974
|
}
|
|
20975
|
+
if (view === "mfa_enrollment") {
|
|
20976
|
+
return /* @__PURE__ */ jsxs46(Fragment9, { children: [
|
|
20977
|
+
/* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
|
|
20978
|
+
/* @__PURE__ */ jsxs46(
|
|
20979
|
+
"div",
|
|
20980
|
+
{
|
|
20981
|
+
className: "uf-flex uf-flex-col uf-items-center uf-px-4 uf-pb-4",
|
|
20982
|
+
style: viewTransitionStyle,
|
|
20983
|
+
children: [
|
|
20984
|
+
/* @__PURE__ */ jsx51(
|
|
20985
|
+
DepositErrorState,
|
|
20986
|
+
{
|
|
20987
|
+
title: t.transfer.mfaEnrollmentTitle,
|
|
20988
|
+
message: t.transfer.mfaEnrollmentMessage
|
|
20989
|
+
}
|
|
20990
|
+
),
|
|
20991
|
+
/* @__PURE__ */ jsxs46(
|
|
20992
|
+
"a",
|
|
20993
|
+
{
|
|
20994
|
+
href: "https://www.coinbase.com/settings/security",
|
|
20995
|
+
target: "_blank",
|
|
20996
|
+
rel: "noopener noreferrer",
|
|
20997
|
+
className: "uf-text-sm uf-underline uf-mb-8 uf-inline-flex uf-items-center uf-gap-1",
|
|
20998
|
+
style: { color: colors2.primary, fontFamily: fonts.medium },
|
|
20999
|
+
children: [
|
|
21000
|
+
t.transfer.mfaEnrollmentSettingsLink,
|
|
21001
|
+
/* @__PURE__ */ jsx51(ExternalLink4, { className: "uf-w-3.5 uf-h-3.5" })
|
|
21002
|
+
]
|
|
21003
|
+
}
|
|
21004
|
+
),
|
|
21005
|
+
/* @__PURE__ */ jsx51(
|
|
21006
|
+
"button",
|
|
21007
|
+
{
|
|
21008
|
+
onClick: handleConfirmTransfer,
|
|
21009
|
+
disabled: isLoading,
|
|
21010
|
+
className: "uf-w-full uf-rounded-xl uf-py-3.5 uf-text-sm uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-50 uf-flex uf-items-center uf-justify-center uf-gap-2",
|
|
21011
|
+
style: {
|
|
21012
|
+
backgroundColor: colors2.primary,
|
|
21013
|
+
color: "#fff",
|
|
21014
|
+
fontFamily: fonts.medium
|
|
21015
|
+
},
|
|
21016
|
+
children: isLoading ? /* @__PURE__ */ jsx51(Loader27, { className: "uf-w-4 uf-h-4 uf-animate-spin" }) : t.continue
|
|
21017
|
+
}
|
|
21018
|
+
)
|
|
21019
|
+
]
|
|
21020
|
+
}
|
|
21021
|
+
)
|
|
21022
|
+
] });
|
|
21023
|
+
}
|
|
20859
21024
|
if (view === "mfa") {
|
|
20860
21025
|
return /* @__PURE__ */ jsxs46(Fragment9, { children: [
|
|
20861
21026
|
/* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
|
|
@@ -27015,7 +27180,11 @@ function WalletConnect({
|
|
|
27015
27180
|
chain: String(token.chain_id),
|
|
27016
27181
|
network: token.network,
|
|
27017
27182
|
token: token.symbol ?? token.token_address,
|
|
27018
|
-
currency: token.currency
|
|
27183
|
+
currency: token.currency,
|
|
27184
|
+
// No execution exists yet — it's created when this send lands on the
|
|
27185
|
+
// wallet. The wallet id is what that execution will carry, so it's
|
|
27186
|
+
// how a send that never completes is matched to what followed.
|
|
27187
|
+
deposit_wallet_id: activeDepositWallet?.id
|
|
27019
27188
|
});
|
|
27020
27189
|
setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
|
|
27021
27190
|
setHasSignedTransaction(true);
|
|
@@ -27605,7 +27774,7 @@ function DepositModal({
|
|
|
27605
27774
|
const applePaySubTitle = applePaySubTitleProp ?? t.applePayMenu.subtitle;
|
|
27606
27775
|
const googlePayTitle = googlePayTitleProp ?? t.googlePayMenu.title;
|
|
27607
27776
|
const googlePaySubTitle = googlePaySubTitleProp ?? t.googlePayMenu.subtitle;
|
|
27608
|
-
const { track, startSession, endSession, getSessionId, subscribe } = useAnalytics();
|
|
27777
|
+
const { track, startSession, endSession, getSessionId, setUserId, subscribe } = useAnalytics();
|
|
27609
27778
|
const normalizedPrefilledAmountUsd = useMemo17(
|
|
27610
27779
|
() => normalizePrefilledUsdAmount(prefilledAmountUsd),
|
|
27611
27780
|
[prefilledAmountUsd]
|
|
@@ -27613,6 +27782,7 @@ function DepositModal({
|
|
|
27613
27782
|
const analyticsMethod = (method) => method === "transfer" ? "transfer_crypto" : method;
|
|
27614
27783
|
const journeyActiveRef = useRef16(false);
|
|
27615
27784
|
const journeySessionIdRef = useRef16(void 0);
|
|
27785
|
+
const journeyExternalUserIdRef = useRef16(void 0);
|
|
27616
27786
|
const externalUserId = userId || void 0;
|
|
27617
27787
|
const emitEvent = useCallback14(
|
|
27618
27788
|
(event) => onEvent?.({ ...event, externalUserId }),
|
|
@@ -27640,6 +27810,9 @@ function DepositModal({
|
|
|
27640
27810
|
method: analyticsMethod(method),
|
|
27641
27811
|
flow_type: "deposit",
|
|
27642
27812
|
amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
|
|
27813
|
+
// The one high-cardinality field we do send: the join key from a
|
|
27814
|
+
// funnel session back to the execution row it produced.
|
|
27815
|
+
execution_id: data.executionId ?? execution?.id,
|
|
27643
27816
|
// Flat, low-cardinality execution dimensions for PostHog breakdowns
|
|
27644
27817
|
// (precise/opaque fields like base units, addresses, tx hashes live in
|
|
27645
27818
|
// the onEvent DirectExecution instead).
|
|
@@ -27667,6 +27840,7 @@ function DepositModal({
|
|
|
27667
27840
|
method: analyticsMethod(method),
|
|
27668
27841
|
flow_type: "deposit",
|
|
27669
27842
|
error_code: error.code,
|
|
27843
|
+
execution_id: execution?.id,
|
|
27670
27844
|
failure_reason: execution?.failureReason ?? void 0,
|
|
27671
27845
|
status: execution?.status,
|
|
27672
27846
|
source_chain_type: execution?.sourceChainType,
|
|
@@ -28095,8 +28269,10 @@ function DepositModal({
|
|
|
28095
28269
|
const beginJourney = useCallback14(() => {
|
|
28096
28270
|
journeySessionIdRef.current = startSession();
|
|
28097
28271
|
journeyActiveRef.current = true;
|
|
28272
|
+
journeyExternalUserIdRef.current = userId;
|
|
28273
|
+
setUserId(null);
|
|
28098
28274
|
track("widget_opened", { flow_type: "deposit" });
|
|
28099
|
-
}, [startSession, track]);
|
|
28275
|
+
}, [startSession, track, setUserId, userId]);
|
|
28100
28276
|
const handleClose = () => {
|
|
28101
28277
|
finalizeJourney();
|
|
28102
28278
|
onOpenChange(false);
|
|
@@ -28121,6 +28297,11 @@ function DepositModal({
|
|
|
28121
28297
|
}
|
|
28122
28298
|
beginJourney();
|
|
28123
28299
|
}, [open]);
|
|
28300
|
+
useLayoutEffect2(() => {
|
|
28301
|
+
if (!open || journeyExternalUserIdRef.current === userId) return;
|
|
28302
|
+
journeyExternalUserIdRef.current = userId;
|
|
28303
|
+
setUserId(null);
|
|
28304
|
+
}, [open, userId, setUserId]);
|
|
28124
28305
|
useLayoutEffect2(() => {
|
|
28125
28306
|
if (!open) return;
|
|
28126
28307
|
if (resetViewTimeoutRef.current) {
|
|
@@ -29032,6 +29213,7 @@ function DepositModal({
|
|
|
29032
29213
|
destinationChainType,
|
|
29033
29214
|
destinationChainId,
|
|
29034
29215
|
destinationTokenAddress,
|
|
29216
|
+
contractCalls,
|
|
29035
29217
|
cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
|
|
29036
29218
|
view: cashAppView,
|
|
29037
29219
|
onViewChange: setCashAppView,
|
|
@@ -29395,6 +29577,9 @@ function CheckoutModal({
|
|
|
29395
29577
|
flowCompletedRef.current = true;
|
|
29396
29578
|
track("flow_completed", {
|
|
29397
29579
|
flow_type: "checkout",
|
|
29580
|
+
// Checkout has no direct execution; the intent is what a funnel
|
|
29581
|
+
// session joins back to.
|
|
29582
|
+
payment_intent_id: data.paymentIntentId,
|
|
29398
29583
|
...method ? { method: method === "transfer" ? "transfer_crypto" : method } : {}
|
|
29399
29584
|
});
|
|
29400
29585
|
}
|
|
@@ -29615,7 +29800,7 @@ function CheckoutModal({
|
|
|
29615
29800
|
journeySessionIdRef.current = startSession();
|
|
29616
29801
|
journeyActiveRef.current = true;
|
|
29617
29802
|
flowCompletedRef.current = false;
|
|
29618
|
-
setUserId(null);
|
|
29803
|
+
setUserId(paymentIntentUserId ?? null);
|
|
29619
29804
|
track("widget_opened", { flow_type: "checkout" });
|
|
29620
29805
|
if (resetViewTimeoutRef.current) {
|
|
29621
29806
|
clearTimeout(resetViewTimeoutRef.current);
|
|
@@ -30056,7 +30241,7 @@ function CheckoutModal({
|
|
|
30056
30241
|
}
|
|
30057
30242
|
|
|
30058
30243
|
// src/components/withdrawals/WithdrawModal.tsx
|
|
30059
|
-
import { useState as useState49, useEffect as
|
|
30244
|
+
import { useState as useState49, useEffect as useEffect47, useLayoutEffect as useLayoutEffect4, useCallback as useCallback17, useMemo as useMemo21, useRef as useRef20 } from "react";
|
|
30060
30245
|
import { AlertTriangle as AlertTriangle8, ChevronRight as ChevronRight22, Clock as Clock6 } from "lucide-react";
|
|
30061
30246
|
|
|
30062
30247
|
// src/hooks/use-supported-destination-tokens.ts
|
|
@@ -30224,7 +30409,7 @@ import { useQuery as useQuery24 } from "@tanstack/react-query";
|
|
|
30224
30409
|
import { queryExecutions as queryExecutions4, ActionType as ActionType4 } from "@unifold/core";
|
|
30225
30410
|
function useExecutions(userId, publishableKey, options) {
|
|
30226
30411
|
const actionType = options?.actionType ?? ActionType4.Deposit;
|
|
30227
|
-
|
|
30412
|
+
const query = useQuery24({
|
|
30228
30413
|
queryKey: ["unifold", "executions", actionType, userId, publishableKey],
|
|
30229
30414
|
queryFn: () => queryExecutions4(userId, publishableKey, actionType),
|
|
30230
30415
|
enabled: (options?.enabled ?? true) && !!userId,
|
|
@@ -30233,6 +30418,8 @@ function useExecutions(userId, publishableKey, options) {
|
|
|
30233
30418
|
gcTime: 1e3 * 60 * 5,
|
|
30234
30419
|
refetchOnWindowFocus: false
|
|
30235
30420
|
});
|
|
30421
|
+
useStampInternalUserId({ internalUserId: query.data?.data[0]?.user_id });
|
|
30422
|
+
return query;
|
|
30236
30423
|
}
|
|
30237
30424
|
|
|
30238
30425
|
// src/hooks/use-withdraw-polling.ts
|
|
@@ -30574,7 +30761,7 @@ function WithdrawDoubleInput({
|
|
|
30574
30761
|
}
|
|
30575
30762
|
|
|
30576
30763
|
// src/components/withdrawals/WithdrawForm.tsx
|
|
30577
|
-
import { useState as useState47, useCallback as useCallback16, useMemo as useMemo20, useEffect as
|
|
30764
|
+
import { useState as useState47, useCallback as useCallback16, useMemo as useMemo20, useEffect as useEffect45 } from "react";
|
|
30578
30765
|
import {
|
|
30579
30766
|
AlertTriangle as AlertTriangle7,
|
|
30580
30767
|
ArrowUpDown,
|
|
@@ -30857,7 +31044,6 @@ import { useMemo as useMemo19 } from "react";
|
|
|
30857
31044
|
import { ActionType as ActionType6 } from "@unifold/core";
|
|
30858
31045
|
|
|
30859
31046
|
// src/hooks/use-get-deposit-address.ts
|
|
30860
|
-
import { useEffect as useEffect45 } from "react";
|
|
30861
31047
|
import { useQuery as useQuery26 } from "@tanstack/react-query";
|
|
30862
31048
|
import { getDepositAddress } from "@unifold/core";
|
|
30863
31049
|
function useGetDepositAddress(params) {
|
|
@@ -30871,7 +31057,6 @@ function useGetDepositAddress(params) {
|
|
|
30871
31057
|
actionType,
|
|
30872
31058
|
enabled = true
|
|
30873
31059
|
} = params;
|
|
30874
|
-
const { setUserId } = useAnalytics();
|
|
30875
31060
|
const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
|
|
30876
31061
|
const query = useQuery26({
|
|
30877
31062
|
queryKey: [
|
|
@@ -30903,11 +31088,7 @@ function useGetDepositAddress(params) {
|
|
|
30903
31088
|
refetchOnWindowFocus: false,
|
|
30904
31089
|
retry: 1
|
|
30905
31090
|
});
|
|
30906
|
-
|
|
30907
|
-
if (query.data?.user_id) {
|
|
30908
|
-
setUserId(query.data.user_id);
|
|
30909
|
-
}
|
|
30910
|
-
}, [query.data?.user_id, setUserId]);
|
|
31091
|
+
useStampInternalUserId({ internalUserId: query.data?.user_id });
|
|
30911
31092
|
return query;
|
|
30912
31093
|
}
|
|
30913
31094
|
|
|
@@ -31047,14 +31228,14 @@ function WithdrawForm({
|
|
|
31047
31228
|
const [detailsExpanded, setDetailsExpanded] = useState47(false);
|
|
31048
31229
|
const [glossaryOpen, setGlossaryOpen] = useState47(false);
|
|
31049
31230
|
const [isMaxed, setIsMaxed] = useState47(false);
|
|
31050
|
-
|
|
31231
|
+
useEffect45(() => {
|
|
31051
31232
|
setRecipientAddress(recipientAddressProp || "");
|
|
31052
31233
|
setAmount("");
|
|
31053
31234
|
setInputUnit("fiat");
|
|
31054
31235
|
setSubmitError(null);
|
|
31055
31236
|
setIsMaxed(false);
|
|
31056
31237
|
}, [recipientAddressProp]);
|
|
31057
|
-
|
|
31238
|
+
useEffect45(() => {
|
|
31058
31239
|
setIsMaxed(false);
|
|
31059
31240
|
}, [balanceData?.balanceBaseUnit]);
|
|
31060
31241
|
const trimmedAddress = recipientAddress.trim();
|
|
@@ -31855,7 +32036,7 @@ function WithdrawExecutionItem({ execution, onClick }) {
|
|
|
31855
32036
|
}
|
|
31856
32037
|
|
|
31857
32038
|
// src/components/withdrawals/WithdrawConfirmingView.tsx
|
|
31858
|
-
import { useState as useState48, useEffect as
|
|
32039
|
+
import { useState as useState48, useEffect as useEffect46 } from "react";
|
|
31859
32040
|
import { Fragment as Fragment19, jsx as jsx76, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
31860
32041
|
function truncateAddress4(addr) {
|
|
31861
32042
|
if (addr.length <= 12) return addr;
|
|
@@ -31873,7 +32054,7 @@ function WithdrawConfirmingView({
|
|
|
31873
32054
|
const t = strings.withdrawModal.details;
|
|
31874
32055
|
const [showButton, setShowButton] = useState48(false);
|
|
31875
32056
|
const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
|
|
31876
|
-
|
|
32057
|
+
useEffect46(() => {
|
|
31877
32058
|
if (latestExecution) return;
|
|
31878
32059
|
const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
|
|
31879
32060
|
return () => clearTimeout(timer);
|
|
@@ -32035,7 +32216,7 @@ function WithdrawModal({
|
|
|
32035
32216
|
);
|
|
32036
32217
|
const onEventRef = useRef20(emitEvent);
|
|
32037
32218
|
onEventRef.current = emitEvent;
|
|
32038
|
-
|
|
32219
|
+
useEffect47(
|
|
32039
32220
|
() => subscribe((event) => {
|
|
32040
32221
|
if (event.properties?.flow_type !== "withdraw") return;
|
|
32041
32222
|
const selection = selectionPayload(event);
|
|
@@ -32052,12 +32233,16 @@ function WithdrawModal({
|
|
|
32052
32233
|
);
|
|
32053
32234
|
const journeyActiveRef = useRef20(false);
|
|
32054
32235
|
const journeySessionIdRef = useRef20(void 0);
|
|
32236
|
+
const journeyExternalUserIdRef = useRef20(void 0);
|
|
32055
32237
|
const onWithdrawSuccessFor = useCallback17(
|
|
32056
32238
|
(data) => {
|
|
32057
32239
|
const execution = data.execution?.data.object;
|
|
32058
32240
|
track("flow_completed", {
|
|
32059
32241
|
flow_type: "withdraw",
|
|
32060
32242
|
amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
|
|
32243
|
+
// The one high-cardinality field we do send: the join key from a
|
|
32244
|
+
// funnel session back to the execution row it produced.
|
|
32245
|
+
execution_id: data.executionId ?? execution?.id,
|
|
32061
32246
|
// Flat, low-cardinality execution dimensions for PostHog breakdowns.
|
|
32062
32247
|
status: execution?.status,
|
|
32063
32248
|
source_chain_type: execution?.sourceChainType,
|
|
@@ -32078,6 +32263,7 @@ function WithdrawModal({
|
|
|
32078
32263
|
track("flow_failed", {
|
|
32079
32264
|
flow_type: "withdraw",
|
|
32080
32265
|
error_code: error.code,
|
|
32266
|
+
execution_id: execution?.id,
|
|
32081
32267
|
failure_reason: execution?.failureReason ?? void 0,
|
|
32082
32268
|
status: execution?.status,
|
|
32083
32269
|
source_chain_type: execution?.sourceChainType,
|
|
@@ -32099,7 +32285,7 @@ function WithdrawModal({
|
|
|
32099
32285
|
const [resolvedTheme, setResolvedTheme] = useState49(
|
|
32100
32286
|
theme === "auto" ? "dark" : theme
|
|
32101
32287
|
);
|
|
32102
|
-
|
|
32288
|
+
useEffect47(() => {
|
|
32103
32289
|
if (theme === "auto") {
|
|
32104
32290
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
32105
32291
|
setResolvedTheme(mq.matches ? "dark" : "light");
|
|
@@ -32151,6 +32337,7 @@ function WithdrawModal({
|
|
|
32151
32337
|
) ?? null : null;
|
|
32152
32338
|
const [view, setView] = useState49("form");
|
|
32153
32339
|
const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState49();
|
|
32340
|
+
const withdrawDepositWalletIdRef = useRef20(void 0);
|
|
32154
32341
|
const [selectedExecution, setSelectedExecution] = useState49(null);
|
|
32155
32342
|
const [submittedTxInfo, setSubmittedTxInfo] = useState49(null);
|
|
32156
32343
|
const { executions: realtimeExecutions } = useWithdrawPolling({
|
|
@@ -32188,6 +32375,7 @@ function WithdrawModal({
|
|
|
32188
32375
|
if (!depositWallet) {
|
|
32189
32376
|
throw new Error(`No deposit wallet available for ${sourceChainType}`);
|
|
32190
32377
|
}
|
|
32378
|
+
withdrawDepositWalletIdRef.current = depositWallet.id;
|
|
32191
32379
|
setWithdrawDepositWalletId(depositWallet.id);
|
|
32192
32380
|
return depositWallet;
|
|
32193
32381
|
},
|
|
@@ -32207,7 +32395,12 @@ function WithdrawModal({
|
|
|
32207
32395
|
currency: tokenData?.currency,
|
|
32208
32396
|
amount: txInfo.amount,
|
|
32209
32397
|
amount_base_unit: txInfo.amountBaseUnit,
|
|
32210
|
-
...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {}
|
|
32398
|
+
...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {},
|
|
32399
|
+
// The execution doesn't exist yet — it's created when the user's send
|
|
32400
|
+
// lands on the withdraw deposit wallet, and carries this id. So a
|
|
32401
|
+
// withdrawal confirmed but never completed still joins to whatever
|
|
32402
|
+
// did (or didn't) follow on that wallet.
|
|
32403
|
+
deposit_wallet_id: withdrawDepositWalletIdRef.current
|
|
32211
32404
|
});
|
|
32212
32405
|
emitEvent({
|
|
32213
32406
|
id: generatePrefixedKSUID12("sevt"),
|
|
@@ -32241,8 +32434,10 @@ function WithdrawModal({
|
|
|
32241
32434
|
const beginJourney = useCallback17(() => {
|
|
32242
32435
|
journeySessionIdRef.current = startSession();
|
|
32243
32436
|
journeyActiveRef.current = true;
|
|
32437
|
+
journeyExternalUserIdRef.current = externalUserId;
|
|
32438
|
+
setUserId(null);
|
|
32244
32439
|
track("widget_opened", { flow_type: "withdraw" });
|
|
32245
|
-
}, [startSession, track]);
|
|
32440
|
+
}, [startSession, track, setUserId, externalUserId]);
|
|
32246
32441
|
const handleClose = useCallback17(() => {
|
|
32247
32442
|
finalizeJourney();
|
|
32248
32443
|
onOpenChange(false);
|
|
@@ -32251,6 +32446,7 @@ function WithdrawModal({
|
|
|
32251
32446
|
setView("form");
|
|
32252
32447
|
setSelectedExecution(null);
|
|
32253
32448
|
setSubmittedTxInfo(null);
|
|
32449
|
+
withdrawDepositWalletIdRef.current = void 0;
|
|
32254
32450
|
setWithdrawDepositWalletId(void 0);
|
|
32255
32451
|
resetViewTimeoutRef.current = null;
|
|
32256
32452
|
}, 200);
|
|
@@ -32268,9 +32464,15 @@ function WithdrawModal({
|
|
|
32268
32464
|
setView("form");
|
|
32269
32465
|
setSelectedExecution(null);
|
|
32270
32466
|
setSubmittedTxInfo(null);
|
|
32467
|
+
withdrawDepositWalletIdRef.current = void 0;
|
|
32271
32468
|
setWithdrawDepositWalletId(void 0);
|
|
32272
32469
|
}, [open]);
|
|
32273
|
-
|
|
32470
|
+
useLayoutEffect4(() => {
|
|
32471
|
+
if (!open || journeyExternalUserIdRef.current === externalUserId) return;
|
|
32472
|
+
journeyExternalUserIdRef.current = externalUserId;
|
|
32473
|
+
setUserId(null);
|
|
32474
|
+
}, [open, externalUserId, setUserId]);
|
|
32475
|
+
useEffect47(
|
|
32274
32476
|
() => () => {
|
|
32275
32477
|
if (journeyActiveRef.current) {
|
|
32276
32478
|
journeyActiveRef.current = false;
|
|
@@ -32279,12 +32481,12 @@ function WithdrawModal({
|
|
|
32279
32481
|
},
|
|
32280
32482
|
[endSession, getSessionId]
|
|
32281
32483
|
);
|
|
32282
|
-
|
|
32484
|
+
useEffect47(() => {
|
|
32283
32485
|
if (!open) return;
|
|
32284
32486
|
const screen = view === "detail" ? "tracker_detail" : view;
|
|
32285
32487
|
track("screen_viewed", { flow_type: "withdraw", screen });
|
|
32286
32488
|
}, [open, view, track]);
|
|
32287
|
-
|
|
32489
|
+
useEffect47(
|
|
32288
32490
|
() => () => {
|
|
32289
32491
|
if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
|
|
32290
32492
|
},
|