@unifold/ui-react 0.1.76 → 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 +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +345 -139
- package/dist/index.mjs +292 -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
|
|
|
@@ -5454,6 +5484,10 @@ function BuyWithCard({
|
|
|
5454
5484
|
wallet_address: wallet.address,
|
|
5455
5485
|
subdivision_code: userIpInfo?.subdivisionCode || void 0,
|
|
5456
5486
|
external_id: externalId,
|
|
5487
|
+
// The rail this quote was priced for, so the provider opens on it. Most
|
|
5488
|
+
// are `card`, which is also the server default, but a local rail (e.g.
|
|
5489
|
+
// `upi` in India) is the whole reason its provider was quoted.
|
|
5490
|
+
payment_method_type: selectedProvider.payment_method_type,
|
|
5457
5491
|
// Exactly one of source_amount / destination_amount (mutually exclusive):
|
|
5458
5492
|
// destination mode starts the session by the fixed crypto amount (fees on
|
|
5459
5493
|
// top); otherwise by the entered fiat amount.
|
|
@@ -5471,7 +5505,11 @@ function BuyWithCard({
|
|
|
5471
5505
|
method: "card",
|
|
5472
5506
|
flow_type: "deposit",
|
|
5473
5507
|
provider: selectedProvider.service_provider,
|
|
5474
|
-
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
|
|
5475
5513
|
});
|
|
5476
5514
|
onEvent?.({
|
|
5477
5515
|
id: generatePrefixedKSUID2("sevt"),
|
|
@@ -6983,6 +7021,8 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
6983
7021
|
const [limitUpgradeError, setLimitUpgradeError] = useState15(null);
|
|
6984
7022
|
const [upgradeSubmitting, setUpgradeSubmitting] = useState15(false);
|
|
6985
7023
|
const upgradeFlowAbortRef = useRef6(null);
|
|
7024
|
+
const applyLimitRoutingRef = useRef6(() => {
|
|
7025
|
+
});
|
|
6986
7026
|
const [amount, setAmount] = useState15(amountUsd ?? "");
|
|
6987
7027
|
const [preparedOrder, setPreparedOrder] = useState15(null);
|
|
6988
7028
|
const sessionAbortRef = useRef6(null);
|
|
@@ -7117,6 +7157,14 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7117
7157
|
},
|
|
7118
7158
|
[email, normalizedPhone, userId]
|
|
7119
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
|
+
});
|
|
7120
7168
|
const createSessionAndSendOtp = useCallback4(async () => {
|
|
7121
7169
|
setView("submitting_session");
|
|
7122
7170
|
setErrorMessage("");
|
|
@@ -7126,7 +7174,12 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7126
7174
|
email,
|
|
7127
7175
|
phone: normalizedPhone,
|
|
7128
7176
|
terms_accepted: true,
|
|
7129
|
-
|
|
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.
|
|
7130
7183
|
},
|
|
7131
7184
|
publishableKey
|
|
7132
7185
|
);
|
|
@@ -7136,6 +7189,34 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7136
7189
|
}
|
|
7137
7190
|
setClientSecret(session.client_secret);
|
|
7138
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
|
+
}
|
|
7139
7220
|
await sendOnrampVerificationOtp(session.id, "phone", session.client_secret, publishableKey);
|
|
7140
7221
|
setResendCooldown(30);
|
|
7141
7222
|
setView("phone_otp");
|
|
@@ -7144,19 +7225,19 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7144
7225
|
setErrorMessage(prettifyVerificationError(raw));
|
|
7145
7226
|
setView("phone_input");
|
|
7146
7227
|
}
|
|
7147
|
-
}, [
|
|
7228
|
+
}, [
|
|
7229
|
+
email,
|
|
7230
|
+
normalizedPhone,
|
|
7231
|
+
publishableKey,
|
|
7232
|
+
storeWalletPaySession,
|
|
7233
|
+
userId,
|
|
7234
|
+
amountUsd,
|
|
7235
|
+
refetchWalletPayLimits
|
|
7236
|
+
]);
|
|
7148
7237
|
const clearUpgradeFields = useCallback4(() => {
|
|
7149
7238
|
setSsnLast4("");
|
|
7150
7239
|
setDobInput("");
|
|
7151
7240
|
}, []);
|
|
7152
|
-
const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
|
|
7153
|
-
userId,
|
|
7154
|
-
publishableKey,
|
|
7155
|
-
normalizedPhone,
|
|
7156
|
-
userEmail,
|
|
7157
|
-
sessionPhoneVerified: verificationSession?.phone?.status === "verified",
|
|
7158
|
-
isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
|
|
7159
|
-
});
|
|
7160
7241
|
const pollLimitUpgradeStatus = useCallback4(
|
|
7161
7242
|
async (signal) => {
|
|
7162
7243
|
const POLL_INTERVAL_MS5 = 1500;
|
|
@@ -7267,6 +7348,7 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7267
7348
|
},
|
|
7268
7349
|
[startUpgradePolling]
|
|
7269
7350
|
);
|
|
7351
|
+
applyLimitRoutingRef.current = applyLimitRouting;
|
|
7270
7352
|
const hasInitializedRef = useRef6(false);
|
|
7271
7353
|
useEffect12(() => {
|
|
7272
7354
|
if (hasInitializedRef.current) return;
|
|
@@ -7496,7 +7578,10 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7496
7578
|
track("flow_started", {
|
|
7497
7579
|
method,
|
|
7498
7580
|
flow_type: "deposit",
|
|
7499
|
-
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
|
|
7500
7585
|
});
|
|
7501
7586
|
onEvent?.({
|
|
7502
7587
|
id: generatePrefixedKSUID3("sevt"),
|
|
@@ -7546,6 +7631,7 @@ var BuyWithWalletPay = React8.forwardRef(
|
|
|
7546
7631
|
defaultTokenLoading,
|
|
7547
7632
|
defaultTokenError,
|
|
7548
7633
|
depositWallet?.address,
|
|
7634
|
+
depositWalletId,
|
|
7549
7635
|
userEmail,
|
|
7550
7636
|
publishableKey,
|
|
7551
7637
|
onEvent,
|
|
@@ -8520,7 +8606,7 @@ var FALLBACK_AGREEMENTS = [
|
|
|
8520
8606
|
{
|
|
8521
8607
|
key: "guest_checkout_terms",
|
|
8522
8608
|
name: "Guest Checkout Terms of Service",
|
|
8523
|
-
url: "https://www.coinbase.com/legal/
|
|
8609
|
+
url: "https://www.coinbase.com/legal/guest-checkout/us"
|
|
8524
8610
|
},
|
|
8525
8611
|
{
|
|
8526
8612
|
key: "user_agreement",
|
|
@@ -8540,22 +8626,24 @@ function LegalDisclaimer({ legalAgreements, loading }) {
|
|
|
8540
8626
|
return /* @__PURE__ */ jsxs14(
|
|
8541
8627
|
"div",
|
|
8542
8628
|
{
|
|
8543
|
-
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",
|
|
8544
8630
|
"aria-hidden": true,
|
|
8545
8631
|
"aria-busy": "true",
|
|
8546
8632
|
children: [
|
|
8547
|
-
/* @__PURE__ */ jsx18("div", { className: "uf-h-2
|
|
8548
|
-
/* @__PURE__ */ jsx18("div", { className: "uf-h-2
|
|
8549
|
-
/* @__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 } })
|
|
8550
8636
|
]
|
|
8551
8637
|
}
|
|
8552
8638
|
);
|
|
8553
8639
|
}
|
|
8554
8640
|
const agreements = legalAgreements?.agreements ?? FALLBACK_AGREEMENTS;
|
|
8641
|
+
const shortLabels = t.agreements;
|
|
8642
|
+
const lastSeparator = t.lastSeparator.replace(/\s+$/, "\xA0");
|
|
8555
8643
|
return /* @__PURE__ */ jsxs14(
|
|
8556
8644
|
"p",
|
|
8557
8645
|
{
|
|
8558
|
-
className: "uf-text-[
|
|
8646
|
+
className: "uf-text-[10px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-opacity-60 uf-text-center",
|
|
8559
8647
|
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
8560
8648
|
children: [
|
|
8561
8649
|
t.prefix,
|
|
@@ -8566,12 +8654,12 @@ function LegalDisclaimer({ legalAgreements, loading }) {
|
|
|
8566
8654
|
href: a.url,
|
|
8567
8655
|
target: "_blank",
|
|
8568
8656
|
rel: "noopener noreferrer",
|
|
8569
|
-
className: "uf-underline",
|
|
8570
|
-
style: { color:
|
|
8571
|
-
children: a.name
|
|
8657
|
+
className: "uf-no-underline",
|
|
8658
|
+
style: { color: "inherit", textDecoration: "none", whiteSpace: "nowrap" },
|
|
8659
|
+
children: shortLabels[a.key] ?? a.name
|
|
8572
8660
|
}
|
|
8573
8661
|
),
|
|
8574
|
-
idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ?
|
|
8662
|
+
idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? lastSeparator : ""
|
|
8575
8663
|
] }, a.key)),
|
|
8576
8664
|
t.suffix
|
|
8577
8665
|
]
|
|
@@ -9255,6 +9343,7 @@ function PayWithCashApp({
|
|
|
9255
9343
|
destinationChainType,
|
|
9256
9344
|
destinationChainId,
|
|
9257
9345
|
destinationTokenAddress,
|
|
9346
|
+
contractCalls,
|
|
9258
9347
|
cashAppIconUrl,
|
|
9259
9348
|
view: controlledView,
|
|
9260
9349
|
onViewChange,
|
|
@@ -9347,7 +9436,8 @@ function PayWithCashApp({
|
|
|
9347
9436
|
destination_token_address: destinationTokenAddress,
|
|
9348
9437
|
recipient_address: recipientAddress,
|
|
9349
9438
|
source_amount: amount,
|
|
9350
|
-
external_id: externalId
|
|
9439
|
+
external_id: externalId,
|
|
9440
|
+
...contractCalls?.length ? { contract_calls: contractCalls } : {}
|
|
9351
9441
|
},
|
|
9352
9442
|
publishableKey
|
|
9353
9443
|
);
|
|
@@ -9360,7 +9450,10 @@ function PayWithCashApp({
|
|
|
9360
9450
|
track("flow_started", {
|
|
9361
9451
|
method: "cashapp",
|
|
9362
9452
|
flow_type: "deposit",
|
|
9363
|
-
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
|
|
9364
9457
|
});
|
|
9365
9458
|
onEvent?.({
|
|
9366
9459
|
id: generatePrefixedKSUID5("sevt"),
|
|
@@ -9385,6 +9478,8 @@ function PayWithCashApp({
|
|
|
9385
9478
|
destinationChainType,
|
|
9386
9479
|
destinationChainId,
|
|
9387
9480
|
destinationTokenAddress,
|
|
9481
|
+
contractCalls,
|
|
9482
|
+
depositWalletId,
|
|
9388
9483
|
onEvent,
|
|
9389
9484
|
onDepositError,
|
|
9390
9485
|
track,
|
|
@@ -10005,7 +10100,10 @@ function BankTransfer({
|
|
|
10005
10100
|
method: "bank_transfer",
|
|
10006
10101
|
flow_type: "deposit",
|
|
10007
10102
|
provider: request.service_provider,
|
|
10008
|
-
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
|
|
10009
10107
|
});
|
|
10010
10108
|
onEvent?.({
|
|
10011
10109
|
id: generatePrefixedKSUID6("sevt"),
|
|
@@ -16270,7 +16368,11 @@ function PayWithStripeLink({
|
|
|
16270
16368
|
if (checkoutResult.successful) {
|
|
16271
16369
|
handledTerminalSessionRef.current = null;
|
|
16272
16370
|
executionReconciledSessionRef.current = null;
|
|
16273
|
-
track("flow_started", {
|
|
16371
|
+
track("flow_started", {
|
|
16372
|
+
method: "stripe_link",
|
|
16373
|
+
flow_type: "deposit",
|
|
16374
|
+
deposit_wallet_id: depositWalletId
|
|
16375
|
+
});
|
|
16274
16376
|
setConfirmedSessionId(activeSessionId);
|
|
16275
16377
|
setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
|
|
16276
16378
|
if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
|
|
@@ -17767,7 +17869,14 @@ function PayWithStripeLink({
|
|
|
17767
17869
|
]
|
|
17768
17870
|
}
|
|
17769
17871
|
),
|
|
17770
|
-
/* @__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
|
+
)
|
|
17771
17880
|
]
|
|
17772
17881
|
}
|
|
17773
17882
|
);
|
|
@@ -19075,6 +19184,9 @@ function CoinbaseConnect({
|
|
|
19075
19184
|
flow_type: "deposit",
|
|
19076
19185
|
method: "exchange_connect",
|
|
19077
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,
|
|
19078
19190
|
amount_usd: sendAmount || void 0,
|
|
19079
19191
|
currency: selectedAsset?.currency.toLowerCase().replace(/[^a-z0-9]+/g, "_"),
|
|
19080
19192
|
chain: sourceChain?.chain_id,
|
|
@@ -19082,6 +19194,34 @@ function CoinbaseConnect({
|
|
|
19082
19194
|
network: sourceChain?.network
|
|
19083
19195
|
});
|
|
19084
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
|
+
};
|
|
19085
19225
|
const handleConfirmTransfer = async () => {
|
|
19086
19226
|
if (!transferIntent || !accessToken) return;
|
|
19087
19227
|
setIsLoading(true);
|
|
@@ -19116,30 +19256,7 @@ function CoinbaseConnect({
|
|
|
19116
19256
|
});
|
|
19117
19257
|
throw err;
|
|
19118
19258
|
});
|
|
19119
|
-
|
|
19120
|
-
track("verification_started", {
|
|
19121
|
-
flow_type: "deposit",
|
|
19122
|
-
method: "exchange_connect",
|
|
19123
|
-
provider: IntegrationProvider.COINBASE,
|
|
19124
|
-
verification_type: "mfa",
|
|
19125
|
-
verification_status: result.status
|
|
19126
|
-
});
|
|
19127
|
-
transitionTo("mfa");
|
|
19128
|
-
setMfaCode("");
|
|
19129
|
-
setMfaError(false);
|
|
19130
|
-
} else if (result.status === "completed") {
|
|
19131
|
-
trackTransferStarted();
|
|
19132
|
-
setConfirmResult(result);
|
|
19133
|
-
transitionTo("success");
|
|
19134
|
-
onTransferSuccess?.(result);
|
|
19135
|
-
} else {
|
|
19136
|
-
setErrorMessage(result.message || t.errors.transferFailed);
|
|
19137
|
-
transitionTo("error");
|
|
19138
|
-
onTransferError?.({
|
|
19139
|
-
message: result.message || t.errors.transferFailed,
|
|
19140
|
-
code: result.status
|
|
19141
|
-
});
|
|
19142
|
-
}
|
|
19259
|
+
applyConfirmResult(result);
|
|
19143
19260
|
} catch (err) {
|
|
19144
19261
|
const message = err instanceof Error ? err.message : t.errors.transferFailed;
|
|
19145
19262
|
setErrorMessage(message);
|
|
@@ -19296,6 +19413,9 @@ function CoinbaseConnect({
|
|
|
19296
19413
|
setShowTransferDetails(false);
|
|
19297
19414
|
transitionTo("enter_amount");
|
|
19298
19415
|
break;
|
|
19416
|
+
case "mfa_enrollment":
|
|
19417
|
+
transitionTo("transfer_confirm");
|
|
19418
|
+
break;
|
|
19299
19419
|
case "mfa":
|
|
19300
19420
|
transitionTo("transfer_confirm");
|
|
19301
19421
|
break;
|
|
@@ -20852,6 +20972,55 @@ function CoinbaseConnect({
|
|
|
20852
20972
|
] })
|
|
20853
20973
|
] });
|
|
20854
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
|
+
}
|
|
20855
21024
|
if (view === "mfa") {
|
|
20856
21025
|
return /* @__PURE__ */ jsxs46(Fragment9, { children: [
|
|
20857
21026
|
/* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
|
|
@@ -27011,7 +27180,11 @@ function WalletConnect({
|
|
|
27011
27180
|
chain: String(token.chain_id),
|
|
27012
27181
|
network: token.network,
|
|
27013
27182
|
token: token.symbol ?? token.token_address,
|
|
27014
|
-
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
|
|
27015
27188
|
});
|
|
27016
27189
|
setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
|
|
27017
27190
|
setHasSignedTransaction(true);
|
|
@@ -27601,7 +27774,7 @@ function DepositModal({
|
|
|
27601
27774
|
const applePaySubTitle = applePaySubTitleProp ?? t.applePayMenu.subtitle;
|
|
27602
27775
|
const googlePayTitle = googlePayTitleProp ?? t.googlePayMenu.title;
|
|
27603
27776
|
const googlePaySubTitle = googlePaySubTitleProp ?? t.googlePayMenu.subtitle;
|
|
27604
|
-
const { track, startSession, endSession, getSessionId, subscribe } = useAnalytics();
|
|
27777
|
+
const { track, startSession, endSession, getSessionId, setUserId, subscribe } = useAnalytics();
|
|
27605
27778
|
const normalizedPrefilledAmountUsd = useMemo17(
|
|
27606
27779
|
() => normalizePrefilledUsdAmount(prefilledAmountUsd),
|
|
27607
27780
|
[prefilledAmountUsd]
|
|
@@ -27609,6 +27782,7 @@ function DepositModal({
|
|
|
27609
27782
|
const analyticsMethod = (method) => method === "transfer" ? "transfer_crypto" : method;
|
|
27610
27783
|
const journeyActiveRef = useRef16(false);
|
|
27611
27784
|
const journeySessionIdRef = useRef16(void 0);
|
|
27785
|
+
const journeyExternalUserIdRef = useRef16(void 0);
|
|
27612
27786
|
const externalUserId = userId || void 0;
|
|
27613
27787
|
const emitEvent = useCallback14(
|
|
27614
27788
|
(event) => onEvent?.({ ...event, externalUserId }),
|
|
@@ -27636,6 +27810,9 @@ function DepositModal({
|
|
|
27636
27810
|
method: analyticsMethod(method),
|
|
27637
27811
|
flow_type: "deposit",
|
|
27638
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,
|
|
27639
27816
|
// Flat, low-cardinality execution dimensions for PostHog breakdowns
|
|
27640
27817
|
// (precise/opaque fields like base units, addresses, tx hashes live in
|
|
27641
27818
|
// the onEvent DirectExecution instead).
|
|
@@ -27663,6 +27840,7 @@ function DepositModal({
|
|
|
27663
27840
|
method: analyticsMethod(method),
|
|
27664
27841
|
flow_type: "deposit",
|
|
27665
27842
|
error_code: error.code,
|
|
27843
|
+
execution_id: execution?.id,
|
|
27666
27844
|
failure_reason: execution?.failureReason ?? void 0,
|
|
27667
27845
|
status: execution?.status,
|
|
27668
27846
|
source_chain_type: execution?.sourceChainType,
|
|
@@ -28091,8 +28269,10 @@ function DepositModal({
|
|
|
28091
28269
|
const beginJourney = useCallback14(() => {
|
|
28092
28270
|
journeySessionIdRef.current = startSession();
|
|
28093
28271
|
journeyActiveRef.current = true;
|
|
28272
|
+
journeyExternalUserIdRef.current = userId;
|
|
28273
|
+
setUserId(null);
|
|
28094
28274
|
track("widget_opened", { flow_type: "deposit" });
|
|
28095
|
-
}, [startSession, track]);
|
|
28275
|
+
}, [startSession, track, setUserId, userId]);
|
|
28096
28276
|
const handleClose = () => {
|
|
28097
28277
|
finalizeJourney();
|
|
28098
28278
|
onOpenChange(false);
|
|
@@ -28117,6 +28297,11 @@ function DepositModal({
|
|
|
28117
28297
|
}
|
|
28118
28298
|
beginJourney();
|
|
28119
28299
|
}, [open]);
|
|
28300
|
+
useLayoutEffect2(() => {
|
|
28301
|
+
if (!open || journeyExternalUserIdRef.current === userId) return;
|
|
28302
|
+
journeyExternalUserIdRef.current = userId;
|
|
28303
|
+
setUserId(null);
|
|
28304
|
+
}, [open, userId, setUserId]);
|
|
28120
28305
|
useLayoutEffect2(() => {
|
|
28121
28306
|
if (!open) return;
|
|
28122
28307
|
if (resetViewTimeoutRef.current) {
|
|
@@ -29028,6 +29213,7 @@ function DepositModal({
|
|
|
29028
29213
|
destinationChainType,
|
|
29029
29214
|
destinationChainId,
|
|
29030
29215
|
destinationTokenAddress,
|
|
29216
|
+
contractCalls,
|
|
29031
29217
|
cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
|
|
29032
29218
|
view: cashAppView,
|
|
29033
29219
|
onViewChange: setCashAppView,
|
|
@@ -29391,6 +29577,9 @@ function CheckoutModal({
|
|
|
29391
29577
|
flowCompletedRef.current = true;
|
|
29392
29578
|
track("flow_completed", {
|
|
29393
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,
|
|
29394
29583
|
...method ? { method: method === "transfer" ? "transfer_crypto" : method } : {}
|
|
29395
29584
|
});
|
|
29396
29585
|
}
|
|
@@ -29611,7 +29800,7 @@ function CheckoutModal({
|
|
|
29611
29800
|
journeySessionIdRef.current = startSession();
|
|
29612
29801
|
journeyActiveRef.current = true;
|
|
29613
29802
|
flowCompletedRef.current = false;
|
|
29614
|
-
setUserId(null);
|
|
29803
|
+
setUserId(paymentIntentUserId ?? null);
|
|
29615
29804
|
track("widget_opened", { flow_type: "checkout" });
|
|
29616
29805
|
if (resetViewTimeoutRef.current) {
|
|
29617
29806
|
clearTimeout(resetViewTimeoutRef.current);
|
|
@@ -30052,7 +30241,7 @@ function CheckoutModal({
|
|
|
30052
30241
|
}
|
|
30053
30242
|
|
|
30054
30243
|
// src/components/withdrawals/WithdrawModal.tsx
|
|
30055
|
-
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";
|
|
30056
30245
|
import { AlertTriangle as AlertTriangle8, ChevronRight as ChevronRight22, Clock as Clock6 } from "lucide-react";
|
|
30057
30246
|
|
|
30058
30247
|
// src/hooks/use-supported-destination-tokens.ts
|
|
@@ -30220,7 +30409,7 @@ import { useQuery as useQuery24 } from "@tanstack/react-query";
|
|
|
30220
30409
|
import { queryExecutions as queryExecutions4, ActionType as ActionType4 } from "@unifold/core";
|
|
30221
30410
|
function useExecutions(userId, publishableKey, options) {
|
|
30222
30411
|
const actionType = options?.actionType ?? ActionType4.Deposit;
|
|
30223
|
-
|
|
30412
|
+
const query = useQuery24({
|
|
30224
30413
|
queryKey: ["unifold", "executions", actionType, userId, publishableKey],
|
|
30225
30414
|
queryFn: () => queryExecutions4(userId, publishableKey, actionType),
|
|
30226
30415
|
enabled: (options?.enabled ?? true) && !!userId,
|
|
@@ -30229,6 +30418,8 @@ function useExecutions(userId, publishableKey, options) {
|
|
|
30229
30418
|
gcTime: 1e3 * 60 * 5,
|
|
30230
30419
|
refetchOnWindowFocus: false
|
|
30231
30420
|
});
|
|
30421
|
+
useStampInternalUserId({ internalUserId: query.data?.data[0]?.user_id });
|
|
30422
|
+
return query;
|
|
30232
30423
|
}
|
|
30233
30424
|
|
|
30234
30425
|
// src/hooks/use-withdraw-polling.ts
|
|
@@ -30570,7 +30761,7 @@ function WithdrawDoubleInput({
|
|
|
30570
30761
|
}
|
|
30571
30762
|
|
|
30572
30763
|
// src/components/withdrawals/WithdrawForm.tsx
|
|
30573
|
-
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";
|
|
30574
30765
|
import {
|
|
30575
30766
|
AlertTriangle as AlertTriangle7,
|
|
30576
30767
|
ArrowUpDown,
|
|
@@ -30853,7 +31044,6 @@ import { useMemo as useMemo19 } from "react";
|
|
|
30853
31044
|
import { ActionType as ActionType6 } from "@unifold/core";
|
|
30854
31045
|
|
|
30855
31046
|
// src/hooks/use-get-deposit-address.ts
|
|
30856
|
-
import { useEffect as useEffect45 } from "react";
|
|
30857
31047
|
import { useQuery as useQuery26 } from "@tanstack/react-query";
|
|
30858
31048
|
import { getDepositAddress } from "@unifold/core";
|
|
30859
31049
|
function useGetDepositAddress(params) {
|
|
@@ -30867,7 +31057,6 @@ function useGetDepositAddress(params) {
|
|
|
30867
31057
|
actionType,
|
|
30868
31058
|
enabled = true
|
|
30869
31059
|
} = params;
|
|
30870
|
-
const { setUserId } = useAnalytics();
|
|
30871
31060
|
const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
|
|
30872
31061
|
const query = useQuery26({
|
|
30873
31062
|
queryKey: [
|
|
@@ -30899,11 +31088,7 @@ function useGetDepositAddress(params) {
|
|
|
30899
31088
|
refetchOnWindowFocus: false,
|
|
30900
31089
|
retry: 1
|
|
30901
31090
|
});
|
|
30902
|
-
|
|
30903
|
-
if (query.data?.user_id) {
|
|
30904
|
-
setUserId(query.data.user_id);
|
|
30905
|
-
}
|
|
30906
|
-
}, [query.data?.user_id, setUserId]);
|
|
31091
|
+
useStampInternalUserId({ internalUserId: query.data?.user_id });
|
|
30907
31092
|
return query;
|
|
30908
31093
|
}
|
|
30909
31094
|
|
|
@@ -31043,14 +31228,14 @@ function WithdrawForm({
|
|
|
31043
31228
|
const [detailsExpanded, setDetailsExpanded] = useState47(false);
|
|
31044
31229
|
const [glossaryOpen, setGlossaryOpen] = useState47(false);
|
|
31045
31230
|
const [isMaxed, setIsMaxed] = useState47(false);
|
|
31046
|
-
|
|
31231
|
+
useEffect45(() => {
|
|
31047
31232
|
setRecipientAddress(recipientAddressProp || "");
|
|
31048
31233
|
setAmount("");
|
|
31049
31234
|
setInputUnit("fiat");
|
|
31050
31235
|
setSubmitError(null);
|
|
31051
31236
|
setIsMaxed(false);
|
|
31052
31237
|
}, [recipientAddressProp]);
|
|
31053
|
-
|
|
31238
|
+
useEffect45(() => {
|
|
31054
31239
|
setIsMaxed(false);
|
|
31055
31240
|
}, [balanceData?.balanceBaseUnit]);
|
|
31056
31241
|
const trimmedAddress = recipientAddress.trim();
|
|
@@ -31851,7 +32036,7 @@ function WithdrawExecutionItem({ execution, onClick }) {
|
|
|
31851
32036
|
}
|
|
31852
32037
|
|
|
31853
32038
|
// src/components/withdrawals/WithdrawConfirmingView.tsx
|
|
31854
|
-
import { useState as useState48, useEffect as
|
|
32039
|
+
import { useState as useState48, useEffect as useEffect46 } from "react";
|
|
31855
32040
|
import { Fragment as Fragment19, jsx as jsx76, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
31856
32041
|
function truncateAddress4(addr) {
|
|
31857
32042
|
if (addr.length <= 12) return addr;
|
|
@@ -31869,7 +32054,7 @@ function WithdrawConfirmingView({
|
|
|
31869
32054
|
const t = strings.withdrawModal.details;
|
|
31870
32055
|
const [showButton, setShowButton] = useState48(false);
|
|
31871
32056
|
const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
|
|
31872
|
-
|
|
32057
|
+
useEffect46(() => {
|
|
31873
32058
|
if (latestExecution) return;
|
|
31874
32059
|
const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
|
|
31875
32060
|
return () => clearTimeout(timer);
|
|
@@ -32031,7 +32216,7 @@ function WithdrawModal({
|
|
|
32031
32216
|
);
|
|
32032
32217
|
const onEventRef = useRef20(emitEvent);
|
|
32033
32218
|
onEventRef.current = emitEvent;
|
|
32034
|
-
|
|
32219
|
+
useEffect47(
|
|
32035
32220
|
() => subscribe((event) => {
|
|
32036
32221
|
if (event.properties?.flow_type !== "withdraw") return;
|
|
32037
32222
|
const selection = selectionPayload(event);
|
|
@@ -32048,12 +32233,16 @@ function WithdrawModal({
|
|
|
32048
32233
|
);
|
|
32049
32234
|
const journeyActiveRef = useRef20(false);
|
|
32050
32235
|
const journeySessionIdRef = useRef20(void 0);
|
|
32236
|
+
const journeyExternalUserIdRef = useRef20(void 0);
|
|
32051
32237
|
const onWithdrawSuccessFor = useCallback17(
|
|
32052
32238
|
(data) => {
|
|
32053
32239
|
const execution = data.execution?.data.object;
|
|
32054
32240
|
track("flow_completed", {
|
|
32055
32241
|
flow_type: "withdraw",
|
|
32056
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,
|
|
32057
32246
|
// Flat, low-cardinality execution dimensions for PostHog breakdowns.
|
|
32058
32247
|
status: execution?.status,
|
|
32059
32248
|
source_chain_type: execution?.sourceChainType,
|
|
@@ -32074,6 +32263,7 @@ function WithdrawModal({
|
|
|
32074
32263
|
track("flow_failed", {
|
|
32075
32264
|
flow_type: "withdraw",
|
|
32076
32265
|
error_code: error.code,
|
|
32266
|
+
execution_id: execution?.id,
|
|
32077
32267
|
failure_reason: execution?.failureReason ?? void 0,
|
|
32078
32268
|
status: execution?.status,
|
|
32079
32269
|
source_chain_type: execution?.sourceChainType,
|
|
@@ -32095,7 +32285,7 @@ function WithdrawModal({
|
|
|
32095
32285
|
const [resolvedTheme, setResolvedTheme] = useState49(
|
|
32096
32286
|
theme === "auto" ? "dark" : theme
|
|
32097
32287
|
);
|
|
32098
|
-
|
|
32288
|
+
useEffect47(() => {
|
|
32099
32289
|
if (theme === "auto") {
|
|
32100
32290
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
32101
32291
|
setResolvedTheme(mq.matches ? "dark" : "light");
|
|
@@ -32147,6 +32337,7 @@ function WithdrawModal({
|
|
|
32147
32337
|
) ?? null : null;
|
|
32148
32338
|
const [view, setView] = useState49("form");
|
|
32149
32339
|
const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState49();
|
|
32340
|
+
const withdrawDepositWalletIdRef = useRef20(void 0);
|
|
32150
32341
|
const [selectedExecution, setSelectedExecution] = useState49(null);
|
|
32151
32342
|
const [submittedTxInfo, setSubmittedTxInfo] = useState49(null);
|
|
32152
32343
|
const { executions: realtimeExecutions } = useWithdrawPolling({
|
|
@@ -32184,6 +32375,7 @@ function WithdrawModal({
|
|
|
32184
32375
|
if (!depositWallet) {
|
|
32185
32376
|
throw new Error(`No deposit wallet available for ${sourceChainType}`);
|
|
32186
32377
|
}
|
|
32378
|
+
withdrawDepositWalletIdRef.current = depositWallet.id;
|
|
32187
32379
|
setWithdrawDepositWalletId(depositWallet.id);
|
|
32188
32380
|
return depositWallet;
|
|
32189
32381
|
},
|
|
@@ -32203,7 +32395,12 @@ function WithdrawModal({
|
|
|
32203
32395
|
currency: tokenData?.currency,
|
|
32204
32396
|
amount: txInfo.amount,
|
|
32205
32397
|
amount_base_unit: txInfo.amountBaseUnit,
|
|
32206
|
-
...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
|
|
32207
32404
|
});
|
|
32208
32405
|
emitEvent({
|
|
32209
32406
|
id: generatePrefixedKSUID12("sevt"),
|
|
@@ -32237,8 +32434,10 @@ function WithdrawModal({
|
|
|
32237
32434
|
const beginJourney = useCallback17(() => {
|
|
32238
32435
|
journeySessionIdRef.current = startSession();
|
|
32239
32436
|
journeyActiveRef.current = true;
|
|
32437
|
+
journeyExternalUserIdRef.current = externalUserId;
|
|
32438
|
+
setUserId(null);
|
|
32240
32439
|
track("widget_opened", { flow_type: "withdraw" });
|
|
32241
|
-
}, [startSession, track]);
|
|
32440
|
+
}, [startSession, track, setUserId, externalUserId]);
|
|
32242
32441
|
const handleClose = useCallback17(() => {
|
|
32243
32442
|
finalizeJourney();
|
|
32244
32443
|
onOpenChange(false);
|
|
@@ -32247,6 +32446,7 @@ function WithdrawModal({
|
|
|
32247
32446
|
setView("form");
|
|
32248
32447
|
setSelectedExecution(null);
|
|
32249
32448
|
setSubmittedTxInfo(null);
|
|
32449
|
+
withdrawDepositWalletIdRef.current = void 0;
|
|
32250
32450
|
setWithdrawDepositWalletId(void 0);
|
|
32251
32451
|
resetViewTimeoutRef.current = null;
|
|
32252
32452
|
}, 200);
|
|
@@ -32264,9 +32464,15 @@ function WithdrawModal({
|
|
|
32264
32464
|
setView("form");
|
|
32265
32465
|
setSelectedExecution(null);
|
|
32266
32466
|
setSubmittedTxInfo(null);
|
|
32467
|
+
withdrawDepositWalletIdRef.current = void 0;
|
|
32267
32468
|
setWithdrawDepositWalletId(void 0);
|
|
32268
32469
|
}, [open]);
|
|
32269
|
-
|
|
32470
|
+
useLayoutEffect4(() => {
|
|
32471
|
+
if (!open || journeyExternalUserIdRef.current === externalUserId) return;
|
|
32472
|
+
journeyExternalUserIdRef.current = externalUserId;
|
|
32473
|
+
setUserId(null);
|
|
32474
|
+
}, [open, externalUserId, setUserId]);
|
|
32475
|
+
useEffect47(
|
|
32270
32476
|
() => () => {
|
|
32271
32477
|
if (journeyActiveRef.current) {
|
|
32272
32478
|
journeyActiveRef.current = false;
|
|
@@ -32275,12 +32481,12 @@ function WithdrawModal({
|
|
|
32275
32481
|
},
|
|
32276
32482
|
[endSession, getSessionId]
|
|
32277
32483
|
);
|
|
32278
|
-
|
|
32484
|
+
useEffect47(() => {
|
|
32279
32485
|
if (!open) return;
|
|
32280
32486
|
const screen = view === "detail" ? "tracker_detail" : view;
|
|
32281
32487
|
track("screen_viewed", { flow_type: "withdraw", screen });
|
|
32282
32488
|
}, [open, view, track]);
|
|
32283
|
-
|
|
32489
|
+
useEffect47(
|
|
32284
32490
|
() => () => {
|
|
32285
32491
|
if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
|
|
32286
32492
|
},
|