@unifold/ui-react 0.1.77 → 0.1.79

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.js CHANGED
@@ -564,6 +564,9 @@ var en_default = {
564
564
  transactionBreakdown: "Transaction breakdown",
565
565
  networkFee: "Network fee",
566
566
  confirmOrder: "Confirm Order",
567
+ mfaEnrollmentTitle: "Enable SMS or Authy 2FA",
568
+ mfaEnrollmentMessage: "Please make sure you enable SMS or Authy 2FA in your Coinbase account. Press Continue after you enable it.",
569
+ mfaEnrollmentSettingsLink: "Open Coinbase security settings",
567
570
  termsNoticePrefix: "By clicking on Confirm Order, you agree to our ",
568
571
  termsNoticeLink: "terms",
569
572
  termsNoticeSuffix: "."
@@ -694,7 +697,12 @@ var en_default = {
694
697
  prefix: "By continuing, you agree to Coinbase's ",
695
698
  separator: ", ",
696
699
  lastSeparator: ", and ",
697
- suffix: ". Coinbase is the regulated provider of this fiat-to-crypto onramp."
700
+ suffix: ".",
701
+ agreements: {
702
+ guest_checkout_terms: "Terms of Service",
703
+ user_agreement: "User Agreement",
704
+ privacy_policy: "Privacy Policy"
705
+ }
698
706
  },
699
707
  errors: {
700
708
  rateLimited: "Too many attempts. Please wait a few minutes and try again.",
@@ -1355,6 +1363,9 @@ var zh_default = {
1355
1363
  transactionBreakdown: "\u4EA4\u6613\u660E\u7EC6",
1356
1364
  networkFee: "\u7F51\u7EDC\u624B\u7EED\u8D39",
1357
1365
  confirmOrder: "\u786E\u8BA4\u8BA2\u5355",
1366
+ mfaEnrollmentTitle: "\u8BF7\u542F\u7528\u77ED\u4FE1\u6216 Authy \u53CC\u91CD\u9A8C\u8BC1",
1367
+ 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",
1368
+ mfaEnrollmentSettingsLink: "\u6253\u5F00 Coinbase \u5B89\u5168\u8BBE\u7F6E",
1358
1369
  termsNoticePrefix: "\u70B9\u51FB\u201C\u786E\u8BA4\u8BA2\u5355\u201D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u4EEC\u7684",
1359
1370
  termsNoticeLink: "\u6761\u6B3E",
1360
1371
  termsNoticeSuffix: "\u3002"
@@ -1485,7 +1496,12 @@ var zh_default = {
1485
1496
  prefix: "\u7EE7\u7EED\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
1486
1497
  separator: "\u3001",
1487
1498
  lastSeparator: "\u548C",
1488
- suffix: "\u3002Coinbase \u662F\u672C\u6CD5\u5E01\u5151\u52A0\u5BC6\u8D27\u5E01\u5145\u503C\u670D\u52A1\u7684\u53D7\u76D1\u7BA1\u63D0\u4F9B\u65B9\u3002"
1499
+ suffix: "\u3002",
1500
+ agreements: {
1501
+ guest_checkout_terms: "\u670D\u52A1\u6761\u6B3E",
1502
+ user_agreement: "\u7528\u6237\u534F\u8BAE",
1503
+ privacy_policy: "\u9690\u79C1\u653F\u7B56"
1504
+ }
1489
1505
  },
1490
1506
  errors: {
1491
1507
  rateLimited: "\u5C1D\u8BD5\u6B21\u6570\u8FC7\u591A\u3002\u8BF7\u7A0D\u7B49\u51E0\u5206\u949F\u540E\u91CD\u8BD5\u3002",
@@ -2146,6 +2162,9 @@ var zh_TW_default = {
2146
2162
  transactionBreakdown: "\u4EA4\u6613\u660E\u7D30",
2147
2163
  networkFee: "\u7DB2\u8DEF\u624B\u7E8C\u8CBB",
2148
2164
  confirmOrder: "\u78BA\u8A8D\u8A02\u55AE",
2165
+ mfaEnrollmentTitle: "\u8ACB\u555F\u7528\u7C21\u8A0A\u6216 Authy \u96D9\u91CD\u9A57\u8B49",
2166
+ 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",
2167
+ mfaEnrollmentSettingsLink: "\u958B\u555F Coinbase \u5B89\u5168\u8A2D\u5B9A",
2149
2168
  termsNoticePrefix: "\u9EDE\u64CA\u300C\u78BA\u8A8D\u8A02\u55AE\u300D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u5011\u7684",
2150
2169
  termsNoticeLink: "\u689D\u6B3E",
2151
2170
  termsNoticeSuffix: "\u3002"
@@ -2276,7 +2295,12 @@ var zh_TW_default = {
2276
2295
  prefix: "\u7E7C\u7E8C\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
2277
2296
  separator: "\u3001",
2278
2297
  lastSeparator: "\u548C",
2279
- suffix: "\u3002Coinbase \u662F\u672C\u6CD5\u5E63\u514C\u52A0\u5BC6\u8CA8\u5E63\u5132\u503C\u670D\u52D9\u7684\u53D7\u76E3\u7BA1\u63D0\u4F9B\u65B9\u3002"
2298
+ suffix: "\u3002",
2299
+ agreements: {
2300
+ guest_checkout_terms: "\u670D\u52D9\u689D\u6B3E",
2301
+ user_agreement: "\u4F7F\u7528\u8005\u5354\u8B70",
2302
+ privacy_policy: "\u96B1\u79C1\u6B0A\u653F\u7B56"
2303
+ }
2280
2304
  },
2281
2305
  errors: {
2282
2306
  rateLimited: "\u5617\u8A66\u6B21\u6578\u904E\u591A\u3002\u8ACB\u7A0D\u7B49\u5E7E\u5206\u9418\u5F8C\u91CD\u8A66\u3002",
@@ -3203,10 +3227,12 @@ var import_lucide_react9 = require("lucide-react");
3203
3227
  var import_core9 = require("@unifold/core");
3204
3228
 
3205
3229
  // src/hooks/use-deposit-address.ts
3206
- var import_react = require("react");
3207
3230
  var import_react_query = require("@tanstack/react-query");
3208
3231
  var import_core = require("@unifold/core");
3209
3232
 
3233
+ // src/hooks/use-internal-user-id.ts
3234
+ var import_react = require("react");
3235
+
3210
3236
  // src/context/AnalyticsContext.tsx
3211
3237
  var React5 = __toESM(require("react"));
3212
3238
  var import_jsx_runtime5 = require("react/jsx-runtime");
@@ -3238,6 +3264,15 @@ function useAnalytics() {
3238
3264
  return { track, startSession, endSession, getSessionId, setUserId, subscribe };
3239
3265
  }
3240
3266
 
3267
+ // src/hooks/use-internal-user-id.ts
3268
+ function useStampInternalUserId({ internalUserId }) {
3269
+ const { setUserId } = useAnalytics();
3270
+ (0, import_react.useEffect)(() => {
3271
+ if (!internalUserId) return;
3272
+ setUserId(internalUserId);
3273
+ }, [internalUserId, setUserId]);
3274
+ }
3275
+
3241
3276
  // src/hooks/use-deposit-address.ts
3242
3277
  function useDepositAddress(params) {
3243
3278
  const {
@@ -3251,7 +3286,6 @@ function useDepositAddress(params) {
3251
3286
  contractCalls,
3252
3287
  enabled = true
3253
3288
  } = params;
3254
- const { setUserId } = useAnalytics();
3255
3289
  const query = (0, import_react_query.useQuery)({
3256
3290
  queryKey: [
3257
3291
  "unifold",
@@ -3294,11 +3328,7 @@ function useDepositAddress(params) {
3294
3328
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
3295
3329
  // 1s, 2s, 4s (max 10s)
3296
3330
  });
3297
- (0, import_react.useEffect)(() => {
3298
- if (query.data?.user_id) {
3299
- setUserId(query.data.user_id);
3300
- }
3301
- }, [query.data?.user_id, setUserId]);
3331
+ useStampInternalUserId({ internalUserId: query.data?.user_id });
3302
3332
  return query;
3303
3333
  }
3304
3334
 
@@ -5589,7 +5619,11 @@ function BuyWithCard({
5589
5619
  method: "card",
5590
5620
  flow_type: "deposit",
5591
5621
  provider: selectedProvider.service_provider,
5592
- amount_usd: amount
5622
+ amount_usd: amount,
5623
+ // The execution only exists once the provider's payout lands on this
5624
+ // wallet, and it carries this id — so it's the join key for a purchase
5625
+ // that starts here and never reaches flow_completed.
5626
+ deposit_wallet_id: depositWalletId
5593
5627
  });
5594
5628
  onEvent?.({
5595
5629
  id: (0, import_core9.generatePrefixedKSUID)("sevt"),
@@ -7090,6 +7124,8 @@ var BuyWithWalletPay = React8.forwardRef(
7090
7124
  const [limitUpgradeError, setLimitUpgradeError] = (0, import_react15.useState)(null);
7091
7125
  const [upgradeSubmitting, setUpgradeSubmitting] = (0, import_react15.useState)(false);
7092
7126
  const upgradeFlowAbortRef = (0, import_react15.useRef)(null);
7127
+ const applyLimitRoutingRef = (0, import_react15.useRef)(() => {
7128
+ });
7093
7129
  const [amount, setAmount] = (0, import_react15.useState)(amountUsd ?? "");
7094
7130
  const [preparedOrder, setPreparedOrder] = (0, import_react15.useState)(null);
7095
7131
  const sessionAbortRef = (0, import_react15.useRef)(null);
@@ -7224,6 +7260,14 @@ var BuyWithWalletPay = React8.forwardRef(
7224
7260
  },
7225
7261
  [email, normalizedPhone, userId]
7226
7262
  );
7263
+ const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
7264
+ userId,
7265
+ publishableKey,
7266
+ normalizedPhone,
7267
+ userEmail,
7268
+ sessionPhoneVerified: verificationSession?.phone?.status === "verified",
7269
+ isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
7270
+ });
7227
7271
  const createSessionAndSendOtp = (0, import_react15.useCallback)(async () => {
7228
7272
  setView("submitting_session");
7229
7273
  setErrorMessage("");
@@ -7233,7 +7277,12 @@ var BuyWithWalletPay = React8.forwardRef(
7233
7277
  email,
7234
7278
  phone: normalizedPhone,
7235
7279
  terms_accepted: true,
7236
- email_already_verified: true
7280
+ // TODO: when the API honors `false`, this will trigger email OTP.
7281
+ // Today `false` still skips email (we don't verify it) and JWT ev
7282
+ // is null. Don't send `true` — that was a fake attest.
7283
+ email_already_verified: false
7284
+ // Coinbase stays Redis-only + JWT until bank-transfer identity
7285
+ // is live. Do not persist from this path yet.
7237
7286
  },
7238
7287
  publishableKey
7239
7288
  );
@@ -7243,6 +7292,34 @@ var BuyWithWalletPay = React8.forwardRef(
7243
7292
  }
7244
7293
  setClientSecret(session.client_secret);
7245
7294
  storeWalletPaySession();
7295
+ if (session.status === "verified") {
7296
+ const tokenRes = await (0, import_core15.exchangeOnrampVerificationToken)(
7297
+ session.id,
7298
+ session.client_secret,
7299
+ publishableKey
7300
+ );
7301
+ setOnrampToken(tokenRes);
7302
+ storeWalletPaySession({
7303
+ emailVerifiedAt: session.email.verified_at,
7304
+ phoneVerifiedAt: session.phone.verified_at,
7305
+ onrampToken: tokenRes.token,
7306
+ onrampTokenExpiresAtMs: Date.now() + tokenRes.expires_in * 1e3
7307
+ });
7308
+ if (amountUsd) setAmount(amountUsd);
7309
+ try {
7310
+ const result = await refetchWalletPayLimits();
7311
+ if (result.data) {
7312
+ const nextView = getViewForLimitStatus(result.data);
7313
+ if (nextView) {
7314
+ applyLimitRoutingRef.current(nextView, result.data.upgrade_status);
7315
+ return;
7316
+ }
7317
+ }
7318
+ } catch {
7319
+ }
7320
+ setView("amount");
7321
+ return;
7322
+ }
7246
7323
  await (0, import_core15.sendOnrampVerificationOtp)(session.id, "phone", session.client_secret, publishableKey);
7247
7324
  setResendCooldown(30);
7248
7325
  setView("phone_otp");
@@ -7251,19 +7328,19 @@ var BuyWithWalletPay = React8.forwardRef(
7251
7328
  setErrorMessage(prettifyVerificationError(raw));
7252
7329
  setView("phone_input");
7253
7330
  }
7254
- }, [email, normalizedPhone, publishableKey, storeWalletPaySession]);
7331
+ }, [
7332
+ email,
7333
+ normalizedPhone,
7334
+ publishableKey,
7335
+ storeWalletPaySession,
7336
+ userId,
7337
+ amountUsd,
7338
+ refetchWalletPayLimits
7339
+ ]);
7255
7340
  const clearUpgradeFields = (0, import_react15.useCallback)(() => {
7256
7341
  setSsnLast4("");
7257
7342
  setDobInput("");
7258
7343
  }, []);
7259
- const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
7260
- userId,
7261
- publishableKey,
7262
- normalizedPhone,
7263
- userEmail,
7264
- sessionPhoneVerified: verificationSession?.phone?.status === "verified",
7265
- isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
7266
- });
7267
7344
  const pollLimitUpgradeStatus = (0, import_react15.useCallback)(
7268
7345
  async (signal) => {
7269
7346
  const POLL_INTERVAL_MS5 = 1500;
@@ -7374,6 +7451,7 @@ var BuyWithWalletPay = React8.forwardRef(
7374
7451
  },
7375
7452
  [startUpgradePolling]
7376
7453
  );
7454
+ applyLimitRoutingRef.current = applyLimitRouting;
7377
7455
  const hasInitializedRef = (0, import_react15.useRef)(false);
7378
7456
  (0, import_react15.useEffect)(() => {
7379
7457
  if (hasInitializedRef.current) return;
@@ -7603,7 +7681,10 @@ var BuyWithWalletPay = React8.forwardRef(
7603
7681
  track("flow_started", {
7604
7682
  method,
7605
7683
  flow_type: "deposit",
7606
- amount_usd: walletPayAmountUsd
7684
+ amount_usd: walletPayAmountUsd,
7685
+ // No execution yet — one appears when the payout lands on this
7686
+ // wallet, carrying the same id.
7687
+ deposit_wallet_id: depositWalletId
7607
7688
  });
7608
7689
  onEvent?.({
7609
7690
  id: (0, import_core15.generatePrefixedKSUID)("sevt"),
@@ -7653,6 +7734,7 @@ var BuyWithWalletPay = React8.forwardRef(
7653
7734
  defaultTokenLoading,
7654
7735
  defaultTokenError,
7655
7736
  depositWallet?.address,
7737
+ depositWalletId,
7656
7738
  userEmail,
7657
7739
  publishableKey,
7658
7740
  onEvent,
@@ -8627,7 +8709,7 @@ var FALLBACK_AGREEMENTS = [
8627
8709
  {
8628
8710
  key: "guest_checkout_terms",
8629
8711
  name: "Guest Checkout Terms of Service",
8630
- url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
8712
+ url: "https://www.coinbase.com/legal/guest-checkout/us"
8631
8713
  },
8632
8714
  {
8633
8715
  key: "user_agreement",
@@ -8647,22 +8729,24 @@ function LegalDisclaimer({ legalAgreements, loading }) {
8647
8729
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
8648
8730
  "div",
8649
8731
  {
8650
- className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse",
8732
+ className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse uf-opacity-50",
8651
8733
  "aria-hidden": true,
8652
8734
  "aria-busy": "true",
8653
8735
  children: [
8654
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "uf-h-2.5 uf-rounded uf-w-full", style: { backgroundColor: colors2.card } }),
8655
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "uf-h-2.5 uf-rounded uf-w-11/12", style: { backgroundColor: colors2.card } }),
8656
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "uf-h-2.5 uf-rounded uf-w-3/4", style: { backgroundColor: colors2.card } })
8736
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "uf-h-2 uf-rounded uf-w-full", style: { backgroundColor: colors2.card } }),
8737
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "uf-h-2 uf-rounded uf-w-11/12", style: { backgroundColor: colors2.card } }),
8738
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "uf-h-2 uf-rounded uf-w-3/4", style: { backgroundColor: colors2.card } })
8657
8739
  ]
8658
8740
  }
8659
8741
  );
8660
8742
  }
8661
8743
  const agreements = legalAgreements?.agreements ?? FALLBACK_AGREEMENTS;
8744
+ const shortLabels = t.agreements;
8745
+ const lastSeparator = t.lastSeparator.replace(/\s+$/, "\xA0");
8662
8746
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
8663
8747
  "p",
8664
8748
  {
8665
- className: "uf-text-[11px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-px-1",
8749
+ className: "uf-text-[10px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-opacity-60 uf-text-center",
8666
8750
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
8667
8751
  children: [
8668
8752
  t.prefix,
@@ -8673,12 +8757,12 @@ function LegalDisclaimer({ legalAgreements, loading }) {
8673
8757
  href: a.url,
8674
8758
  target: "_blank",
8675
8759
  rel: "noopener noreferrer",
8676
- className: "uf-underline",
8677
- style: { color: colors2.foreground },
8678
- children: a.name
8760
+ className: "uf-no-underline",
8761
+ style: { color: "inherit", textDecoration: "none", whiteSpace: "nowrap" },
8762
+ children: shortLabels[a.key] ?? a.name
8679
8763
  }
8680
8764
  ),
8681
- idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? t.lastSeparator : ""
8765
+ idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? lastSeparator : ""
8682
8766
  ] }, a.key)),
8683
8767
  t.suffix
8684
8768
  ]
@@ -9321,23 +9405,7 @@ function PayWithExchange({
9321
9405
  // src/components/deposits/PayWithCashApp.tsx
9322
9406
  var import_react18 = require("react");
9323
9407
  var import_lucide_react13 = require("lucide-react");
9324
- var import_core19 = require("@unifold/core");
9325
-
9326
- // src/hooks/use-cashapp-limits.ts
9327
- var import_react_query9 = require("@tanstack/react-query");
9328
9408
  var import_core18 = require("@unifold/core");
9329
- function useCashAppLimits({ publishableKey, currency = "usd" }) {
9330
- return (0, import_react_query9.useQuery)({
9331
- queryKey: ["unifold", "cashAppLimits", currency, publishableKey],
9332
- queryFn: () => (0, import_core18.getCashAppLimits)(currency, publishableKey),
9333
- enabled: !!publishableKey,
9334
- staleTime: 2 * 60 * 6e4,
9335
- gcTime: 4 * 60 * 6e4,
9336
- retry: 2
9337
- });
9338
- }
9339
-
9340
- // src/components/deposits/PayWithCashApp.tsx
9341
9409
  var import_jsx_runtime20 = require("react/jsx-runtime");
9342
9410
  var POLL_INTERVAL_MS3 = 5e3;
9343
9411
  var FALLBACK_MIN_USD = 5;
@@ -9350,6 +9418,7 @@ function PayWithCashApp({
9350
9418
  destinationChainType,
9351
9419
  destinationChainId,
9352
9420
  destinationTokenAddress,
9421
+ contractCalls,
9353
9422
  cashAppIconUrl,
9354
9423
  view: controlledView,
9355
9424
  onViewChange,
@@ -9373,9 +9442,11 @@ function PayWithCashApp({
9373
9442
  const b = parseInt(bg.slice(4, 6), 16);
9374
9443
  return (r * 299 + g * 587 + b * 114) / 1e3 < 128;
9375
9444
  })();
9376
- const { data: limits, isLoading: limitsLoading } = useCashAppLimits({ publishableKey });
9377
- const minUsd = limits?.minimum_amount ?? FALLBACK_MIN_USD;
9378
- const maxUsd = limits?.maximum_amount ?? null;
9445
+ const { data: fiatCurrencies, isLoading: limitsLoading } = useFiatCurrencies({
9446
+ publishableKey
9447
+ });
9448
+ const minUsd = fiatCurrencies?.data.find((entry) => entry.currency_code.toLowerCase() === "usd")?.minimum_amount ?? FALLBACK_MIN_USD;
9449
+ const quickAmounts = SUGGESTED_AMOUNTS.filter((value) => value >= minUsd);
9379
9450
  const [amount, setAmount] = (0, import_react18.useState)(() => sanitizePrefilledUsd(prefilledAmountUsd));
9380
9451
  const [loading, setLoading] = (0, import_react18.useState)(false);
9381
9452
  const [session, setSession] = (0, import_react18.useState)(null);
@@ -9430,11 +9501,13 @@ function PayWithCashApp({
9430
9501
  setError(strings.depositModal.cashAppErrors.missingFields);
9431
9502
  return;
9432
9503
  }
9504
+ const amountNum2 = parseFloat(amount);
9505
+ if (isNaN(amountNum2) || amountNum2 < minUsd) return;
9433
9506
  setLoading(true);
9434
9507
  setError(null);
9435
9508
  try {
9436
- const externalId = (0, import_core19.generatePrefixedKSUID)("ca");
9437
- const result = await (0, import_core19.createCashAppSession)(
9509
+ const externalId = (0, import_core18.generatePrefixedKSUID)("ca");
9510
+ const result = await (0, import_core18.createCashAppSession)(
9438
9511
  {
9439
9512
  external_user_id: userId,
9440
9513
  destination_chain_type: destinationChainType,
@@ -9442,7 +9515,8 @@ function PayWithCashApp({
9442
9515
  destination_token_address: destinationTokenAddress,
9443
9516
  recipient_address: recipientAddress,
9444
9517
  source_amount: amount,
9445
- external_id: externalId
9518
+ external_id: externalId,
9519
+ ...contractCalls?.length ? { contract_calls: contractCalls } : {}
9446
9520
  },
9447
9521
  publishableKey
9448
9522
  );
@@ -9455,11 +9529,14 @@ function PayWithCashApp({
9455
9529
  track("flow_started", {
9456
9530
  method: "cashapp",
9457
9531
  flow_type: "deposit",
9458
- amount_usd: amount
9532
+ amount_usd: amount,
9533
+ // No execution yet — one appears when the payout lands on this
9534
+ // wallet, carrying the same id.
9535
+ deposit_wallet_id: depositWalletId
9459
9536
  });
9460
9537
  onEvent?.({
9461
- id: (0, import_core19.generatePrefixedKSUID)("sevt"),
9462
- type: import_core19.DepositEventType.ONRAMP_SESSION_CREATED,
9538
+ id: (0, import_core18.generatePrefixedKSUID)("sevt"),
9539
+ type: import_core18.DepositEventType.ONRAMP_SESSION_CREATED,
9463
9540
  created: Math.floor(Date.now() / 1e3),
9464
9541
  sessionId: getSessionId() ?? "",
9465
9542
  method: "cashapp",
@@ -9474,12 +9551,15 @@ function PayWithCashApp({
9474
9551
  }
9475
9552
  }, [
9476
9553
  amount,
9554
+ minUsd,
9477
9555
  userId,
9478
9556
  publishableKey,
9479
9557
  recipientAddress,
9480
9558
  destinationChainType,
9481
9559
  destinationChainId,
9482
9560
  destinationTokenAddress,
9561
+ contractCalls,
9562
+ depositWalletId,
9483
9563
  onEvent,
9484
9564
  onDepositError,
9485
9565
  track,
@@ -9490,7 +9570,7 @@ function PayWithCashApp({
9490
9570
  if (status === "completed" || status === "failed") return;
9491
9571
  const poll = async () => {
9492
9572
  try {
9493
- const result = await (0, import_core19.getCashAppSessionStatus)(session.external_id, publishableKey);
9573
+ const result = await (0, import_core18.getCashAppSessionStatus)(session.external_id, publishableKey);
9494
9574
  setStatus(result.status);
9495
9575
  if (result.status === "failed") {
9496
9576
  setError(strings.depositModal.cashAppErrors.paymentFailed);
@@ -9575,8 +9655,7 @@ function PayWithCashApp({
9575
9655
  const amountNum = parseFloat(amount);
9576
9656
  const hasInput = !isNaN(amountNum) && amountNum > 0;
9577
9657
  const belowMin = hasInput && amountNum < minUsd;
9578
- const aboveMax = hasInput && maxUsd !== null && amountNum > maxUsd;
9579
- const isValidAmount = hasInput && !belowMin && !aboveMax;
9658
+ const isValidAmount = hasInput && !belowMin;
9580
9659
  if (view === "amount") {
9581
9660
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
9582
9661
  "div",
@@ -9605,7 +9684,7 @@ function PayWithCashApp({
9605
9684
  }
9606
9685
  }
9607
9686
  ) }) }),
9608
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "uf-flex uf-gap-3 uf-justify-center", children: SUGGESTED_AMOUNTS.map((quickAmount) => {
9687
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "uf-flex uf-gap-3 uf-justify-center", children: quickAmounts.map((quickAmount) => {
9609
9688
  const isSelected = parseFloat(amount) === quickAmount;
9610
9689
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
9611
9690
  "button",
@@ -9631,23 +9710,17 @@ function PayWithCashApp({
9631
9710
  quickAmount
9632
9711
  );
9633
9712
  }) }),
9634
- amount && amountNum < minUsd && !error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9713
+ !limitsLoading && minUsd > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9635
9714
  "div",
9636
9715
  {
9637
- className: "uf-text-sm uf-text-center uf-mt-3 uf-px-2",
9638
- style: { color: colors2.error, fontFamily: fonts.regular },
9639
- children: interpolate(strings.common.minimumAmount, { amount: `$${minUsd}` })
9640
- }
9641
- ) : amount && maxUsd !== null && amountNum > maxUsd && !error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9642
- "div",
9643
- {
9644
- className: "uf-text-sm uf-text-center uf-mt-3 uf-px-2",
9645
- style: { color: colors2.error, fontFamily: fonts.regular },
9646
- children: interpolate(strings.common.maximumAmount, {
9647
- amount: `$${maxUsd.toLocaleString()}`
9716
+ className: "uf-text-center uf-text-xs uf-mt-4",
9717
+ style: { color: colors2.warning, fontFamily: fonts.regular },
9718
+ children: interpolate(strings.common.minimumDeposit, {
9719
+ amount: `$${minUsd.toFixed(2)}`
9648
9720
  })
9649
9721
  }
9650
- ) : error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9722
+ ),
9723
+ error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9651
9724
  "div",
9652
9725
  {
9653
9726
  className: "uf-text-sm uf-text-center uf-mt-3 uf-px-2",
@@ -9656,7 +9729,7 @@ function PayWithCashApp({
9656
9729
  }
9657
9730
  ) : null
9658
9731
  ] }),
9659
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "uf-px-1", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9732
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "uf-px-1 uf-mt-5", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9660
9733
  "button",
9661
9734
  {
9662
9735
  onClick: handleCreateSession,
@@ -9875,20 +9948,20 @@ function PayWithCashApp({
9875
9948
  // src/components/deposits/BankTransfer.tsx
9876
9949
  var import_react19 = require("react");
9877
9950
  var import_lucide_react14 = require("lucide-react");
9878
- var import_core21 = require("@unifold/core");
9951
+ var import_core20 = require("@unifold/core");
9879
9952
 
9880
9953
  // src/hooks/use-bank-transfer-providers.ts
9881
- var import_react_query10 = require("@tanstack/react-query");
9882
- var import_core20 = require("@unifold/core");
9954
+ var import_react_query9 = require("@tanstack/react-query");
9955
+ var import_core19 = require("@unifold/core");
9883
9956
  function useBankTransferProviders({
9884
9957
  publishableKey,
9885
9958
  enabled = true,
9886
9959
  countryCode
9887
9960
  }) {
9888
9961
  const normalizedCountry = countryCode?.toUpperCase();
9889
- const { data: providers, isLoading } = (0, import_react_query10.useQuery)({
9962
+ const { data: providers, isLoading } = (0, import_react_query9.useQuery)({
9890
9963
  queryKey: ["unifold", "bankTransferProviders", publishableKey, normalizedCountry ?? null],
9891
- queryFn: () => (0, import_core20.getBankTransferProviders)(publishableKey, { countryCode: normalizedCountry }),
9964
+ queryFn: () => (0, import_core19.getBankTransferProviders)(publishableKey, { countryCode: normalizedCountry }),
9892
9965
  enabled,
9893
9966
  staleTime: 1e3 * 60 * 30,
9894
9967
  refetchOnMount: true,
@@ -9971,7 +10044,7 @@ function BankTransfer({
9971
10044
  const providers = providersResponse?.data ?? [];
9972
10045
  const pollingWalletId = (0, import_react19.useMemo)(() => {
9973
10046
  if (!defaultToken) return void 0;
9974
- return (0, import_core21.getWalletByChainType)(
10047
+ return (0, import_core20.getWalletByChainType)(
9975
10048
  wallets,
9976
10049
  defaultToken.destination_token_metadata.chain_type
9977
10050
  )?.id;
@@ -10004,7 +10077,7 @@ function BankTransfer({
10004
10077
  let rate = sourceCurrency2 === "usd" ? 1 : fiatExchangeRates[sourceCurrency2];
10005
10078
  if ((!rate || rate <= 0) && sourceCurrency2 !== "usd") {
10006
10079
  try {
10007
- const response = await (0, import_core21.getFiatExchangeRates)({}, publishableKey);
10080
+ const response = await (0, import_core20.getFiatExchangeRates)({}, publishableKey);
10008
10081
  if (response?.rates) {
10009
10082
  setFiatExchangeRates((prev) => ({
10010
10083
  ...prev,
@@ -10037,7 +10110,7 @@ function BankTransfer({
10037
10110
  setSessionError(strings.buyWithCard.errors.destinationTokenUnresolved);
10038
10111
  return;
10039
10112
  }
10040
- const wallet = (0, import_core21.getWalletByChainType)(
10113
+ const wallet = (0, import_core20.getWalletByChainType)(
10041
10114
  wallets,
10042
10115
  defaultToken.destination_token_metadata.chain_type
10043
10116
  );
@@ -10086,18 +10159,21 @@ function BankTransfer({
10086
10159
  setView("pending");
10087
10160
  };
10088
10161
  const openSession = (request) => {
10089
- const externalId = (0, import_core21.generatePrefixedKSUID)("orsext");
10162
+ const externalId = (0, import_core20.generatePrefixedKSUID)("orsext");
10090
10163
  const requestWithId = { ...request, external_id: externalId };
10091
- const sessionStartUrl = (0, import_core21.getOnrampSessionStartUrl)(requestWithId, publishableKey);
10164
+ const sessionStartUrl = (0, import_core20.getOnrampSessionStartUrl)(requestWithId, publishableKey);
10092
10165
  track("flow_started", {
10093
10166
  method: "bank_transfer",
10094
10167
  flow_type: "deposit",
10095
10168
  provider: request.service_provider,
10096
- amount_usd: request.source_amount
10169
+ amount_usd: request.source_amount,
10170
+ // No execution yet — one appears when the provider's payout lands on
10171
+ // this wallet, carrying the same id.
10172
+ deposit_wallet_id: pollingWalletId
10097
10173
  });
10098
10174
  onEvent?.({
10099
- id: (0, import_core21.generatePrefixedKSUID)("sevt"),
10100
- type: import_core21.DepositEventType.ONRAMP_SESSION_CREATED,
10175
+ id: (0, import_core20.generatePrefixedKSUID)("sevt"),
10176
+ type: import_core20.DepositEventType.ONRAMP_SESSION_CREATED,
10101
10177
  created: Math.floor(Date.now() / 1e3),
10102
10178
  sessionId: getSessionId() ?? "",
10103
10179
  method: "bank_transfer",
@@ -10111,7 +10187,7 @@ function BankTransfer({
10111
10187
  };
10112
10188
  const offerable = providers.filter((provider) => provider.enabled);
10113
10189
  const noEnabledProviders = providers.length > 0 && offerable.length === 0;
10114
- const sourceCurrencyIcon = assetCdnUrl ? (0, import_core21.getIconUrlWithCdn)(`/icons/currencies/png/${sourceCurrency}.png`, assetCdnUrl) : void 0;
10190
+ const sourceCurrencyIcon = assetCdnUrl ? (0, import_core20.getIconUrlWithCdn)(`/icons/currencies/png/${sourceCurrency}.png`, assetCdnUrl) : void 0;
10115
10191
  const onrampTokenIcon = defaultToken?.destination_token_metadata?.icon_url;
10116
10192
  const onrampChainIcon = defaultToken?.destination_token_metadata?.chain?.icon_url;
10117
10193
  const onrampTokenSymbol = defaultToken?.destination_token_metadata?.symbol?.toUpperCase() ?? "USDC";
@@ -10572,12 +10648,12 @@ function BankTransfer({
10572
10648
 
10573
10649
  // src/components/deposits/DepositExecutionItem.tsx
10574
10650
  var import_lucide_react15 = require("lucide-react");
10575
- var import_core22 = require("@unifold/core");
10651
+ var import_core21 = require("@unifold/core");
10576
10652
  var import_jsx_runtime22 = require("react/jsx-runtime");
10577
10653
  function DepositExecutionItem({ execution, onClick }) {
10578
10654
  const { colors: colors2, fonts, components } = useTheme();
10579
10655
  const { t: strings, locale } = useI18n();
10580
- const isPending = execution.status === import_core22.ExecutionStatus.PENDING || execution.status === import_core22.ExecutionStatus.WAITING || execution.status === import_core22.ExecutionStatus.DELAYED;
10656
+ const isPending = execution.status === import_core21.ExecutionStatus.PENDING || execution.status === import_core21.ExecutionStatus.WAITING || execution.status === import_core21.ExecutionStatus.DELAYED;
10581
10657
  const formatDateTime = (timestamp) => {
10582
10658
  try {
10583
10659
  const date = new Date(timestamp);
@@ -10624,7 +10700,7 @@ function DepositExecutionItem({ execution, onClick }) {
10624
10700
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
10625
10701
  "img",
10626
10702
  {
10627
- src: execution.destination_token_metadata?.icon_url || (0, import_core22.getIconUrl)("/icons/tokens/svg/usdc.svg"),
10703
+ src: execution.destination_token_metadata?.icon_url || (0, import_core21.getIconUrl)("/icons/tokens/svg/usdc.svg"),
10628
10704
  alt: "Token",
10629
10705
  width: 36,
10630
10706
  height: 36,
@@ -11637,7 +11713,7 @@ function BankTransferButton({
11637
11713
  // src/components/deposits/buttons/BrowserWalletButton.tsx
11638
11714
  var React33 = __toESM(require("react"));
11639
11715
  var import_lucide_react25 = require("lucide-react");
11640
- var import_core23 = require("@unifold/core");
11716
+ var import_core22 = require("@unifold/core");
11641
11717
 
11642
11718
  // src/lib/eip6963-store.ts
11643
11719
  var import_mipd = require("mipd");
@@ -14127,7 +14203,7 @@ function BrowserWalletButton({
14127
14203
  let cancelled = false;
14128
14204
  const walletChainType = wallet.type === "phantom-solana" || wallet.type === "solflare" || wallet.type === "backpack" || wallet.type === "glow" ? "solana" : "ethereum";
14129
14205
  setIsLoadingBalance(true);
14130
- (0, import_core23.getAddressBalances)(wallet.address, walletChainType, publishableKey).then((response) => {
14206
+ (0, import_core22.getAddressBalances)(wallet.address, walletChainType, publishableKey).then((response) => {
14131
14207
  if (cancelled) return;
14132
14208
  if (response.balances && response.balances.length > 0) {
14133
14209
  const totalUsd = response.balances.reduce((sum, balance) => {
@@ -14693,7 +14769,7 @@ function capitalize(s) {
14693
14769
  }
14694
14770
 
14695
14771
  // src/components/deposits/stripe-link/PayWithStripeLink.tsx
14696
- var import_core24 = require("@unifold/core");
14772
+ var import_core23 = require("@unifold/core");
14697
14773
 
14698
14774
  // src/components/deposits/stripe-link/use-stripe-onramp.ts
14699
14775
  var import_react20 = require("react");
@@ -14851,7 +14927,7 @@ var STRIPE_SESSION_STATUS = {
14851
14927
  var STRIPE_SESSION_POLL_INTERVAL_MS = 3e3;
14852
14928
  var STRIPE_CONSUMED_PAYMENT_METHOD_CODE = "payment_method_unexpected_state";
14853
14929
  function isConsumedPaymentMethodError(err) {
14854
- return err instanceof import_core24.StripeApiResponseError && (err.errorType === "stripe_onramp_payment_method_consumed" || err.stripeCode === STRIPE_CONSUMED_PAYMENT_METHOD_CODE);
14930
+ return err instanceof import_core23.StripeApiResponseError && (err.errorType === "stripe_onramp_payment_method_consumed" || err.stripeCode === STRIPE_CONSUMED_PAYMENT_METHOD_CODE);
14855
14931
  }
14856
14932
  function describeStripePaymentFailure(reason) {
14857
14933
  if (!reason) return null;
@@ -15009,7 +15085,7 @@ function PayWithStripeLink({
15009
15085
  let active = true;
15010
15086
  const fetchConfig = async () => {
15011
15087
  try {
15012
- const cfg = await (0, import_core24.stripeGetConfig)(publishableKey);
15088
+ const cfg = await (0, import_core23.stripeGetConfig)(publishableKey);
15013
15089
  if (active && cfg.publishable_key) setResolvedStripeKey(cfg.publishable_key);
15014
15090
  else if (active) {
15015
15091
  console.error("[PayWithStripeLink] Config response missing publishable_key");
@@ -15031,7 +15107,7 @@ function PayWithStripeLink({
15031
15107
  let active = true;
15032
15108
  const retryConfig = async () => {
15033
15109
  try {
15034
- const cfg = await (0, import_core24.stripeGetConfig)(publishableKey);
15110
+ const cfg = await (0, import_core23.stripeGetConfig)(publishableKey);
15035
15111
  if (active && cfg.publishable_key) setResolvedStripeKey(cfg.publishable_key);
15036
15112
  } catch (err) {
15037
15113
  const msg = err instanceof Error ? err.message : t.formErrors.configLoadFailed;
@@ -15097,7 +15173,7 @@ function PayWithStripeLink({
15097
15173
  if (!rt) return null;
15098
15174
  const doRefresh = async () => {
15099
15175
  try {
15100
- const res = await (0, import_core24.stripeRefreshToken)(rt, publishableKey);
15176
+ const res = await (0, import_core23.stripeRefreshToken)(rt, publishableKey);
15101
15177
  const newToken = res.access_token;
15102
15178
  const newRefresh = extractRefreshToken(res) || rt;
15103
15179
  setOauthToken(newToken);
@@ -15131,7 +15207,7 @@ function PayWithStripeLink({
15131
15207
  try {
15132
15208
  return await fn(token);
15133
15209
  } catch (err) {
15134
- const is403 = err instanceof import_core24.StripeApiResponseError && err.statusCode === 403 || err instanceof Error && (err.message.includes("403") || err.message.toLowerCase().includes("forbidden"));
15210
+ const is403 = err instanceof import_core23.StripeApiResponseError && err.statusCode === 403 || err instanceof Error && (err.message.includes("403") || err.message.toLowerCase().includes("forbidden"));
15135
15211
  if (is403) {
15136
15212
  if (!refreshTokenRef.current) {
15137
15213
  setStep("email");
@@ -15166,7 +15242,7 @@ function PayWithStripeLink({
15166
15242
  return;
15167
15243
  }
15168
15244
  try {
15169
- const res = await (0, import_core24.stripeRefreshToken)(stored.refreshToken, publishableKey);
15245
+ const res = await (0, import_core23.stripeRefreshToken)(stored.refreshToken, publishableKey);
15170
15246
  if (cancelled) return;
15171
15247
  token = res.access_token;
15172
15248
  refresh = extractRefreshToken(res) || stored.refreshToken;
@@ -15189,7 +15265,7 @@ function PayWithStripeLink({
15189
15265
  refreshTokenRef.current = refresh;
15190
15266
  if (stored.email) setEmail(stored.email);
15191
15267
  try {
15192
- const cust = await (0, import_core24.stripeGetCustomer)(stored.customerId, token, publishableKey);
15268
+ const cust = await (0, import_core23.stripeGetCustomer)(stored.customerId, token, publishableKey);
15193
15269
  if (cancelled) return;
15194
15270
  setCustomer(cust);
15195
15271
  const tiers = cust.kyc_tiers ?? [];
@@ -15198,7 +15274,7 @@ function PayWithStripeLink({
15198
15274
  const hasPending = ["l0", "l1", "l2"].some((t2) => getTierStatus(t2) === "pending");
15199
15275
  if (l1Status === "verified" && !hasPending) {
15200
15276
  try {
15201
- const pmResult = await (0, import_core24.stripeListPaymentTokens)(
15277
+ const pmResult = await (0, import_core23.stripeListPaymentTokens)(
15202
15278
  stored.customerId,
15203
15279
  token,
15204
15280
  publishableKey
@@ -15358,7 +15434,7 @@ function PayWithStripeLink({
15358
15434
  (0, import_react21.useEffect)(() => {
15359
15435
  if (!destinationTokenAddress || !destinationChainId || !destinationChainType) return;
15360
15436
  let cancelled = false;
15361
- (0, import_core24.stripeGetDefaultToken)(
15437
+ (0, import_core23.stripeGetDefaultToken)(
15362
15438
  {
15363
15439
  tokenAddress: destinationTokenAddress,
15364
15440
  chainId: destinationChainId,
@@ -15428,7 +15504,7 @@ function PayWithStripeLink({
15428
15504
  enabled: !externalWallets?.length
15429
15505
  });
15430
15506
  const depositWallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
15431
- const onrampWalletAddress = (0, import_core24.getWalletByChainType)(depositWallets, stripeDestChainType)?.address;
15507
+ const onrampWalletAddress = (0, import_core23.getWalletByChainType)(depositWallets, stripeDestChainType)?.address;
15432
15508
  const [registeredWalletKey, setRegisteredWalletKey] = (0, import_react21.useState)(null);
15433
15509
  const walletKeyFor = (address) => `${stripeDestNetwork}:${stripeDestChainType === "ethereum" ? address.toLowerCase() : address}`;
15434
15510
  const isOnrampWalletRegistered = !!onrampWalletAddress && registeredWalletKey === walletKeyFor(onrampWalletAddress);
@@ -15441,7 +15517,7 @@ function PayWithStripeLink({
15441
15517
  );
15442
15518
  }
15443
15519
  }, [depositWallets, onrampWalletAddress, stripeDestChainType]);
15444
- const depositWalletId = (0, import_core24.getWalletByChainType)(depositWallets, stripeDestChainType)?.id;
15520
+ const depositWalletId = (0, import_core23.getWalletByChainType)(depositWallets, stripeDestChainType)?.id;
15445
15521
  const depositPollingActive = step === "checkout" || step === "success";
15446
15522
  const { executions } = useDepositPolling({
15447
15523
  userId,
@@ -15468,7 +15544,7 @@ function PayWithStripeLink({
15468
15544
  executionReconciledSessionRef.current = confirmedSessionId;
15469
15545
  handledTerminalSessionRef.current = confirmedSessionId;
15470
15546
  let cancelled = false;
15471
- void withTokenRefresh((tok) => (0, import_core24.stripeGetSession)(confirmedSessionId, tok, publishableKey)).then((session) => {
15547
+ void withTokenRefresh((tok) => (0, import_core23.stripeGetSession)(confirmedSessionId, tok, publishableKey)).then((session) => {
15472
15548
  if (cancelled) return;
15473
15549
  setSessionStatus(
15474
15550
  session.status === STRIPE_SESSION_STATUS.REJECTED || session.status === STRIPE_SESSION_STATUS.EXPIRED ? session.status : STRIPE_SESSION_STATUS.FULFILLMENT_COMPLETE
@@ -15494,7 +15570,7 @@ function PayWithStripeLink({
15494
15570
  const poll = async () => {
15495
15571
  try {
15496
15572
  const session = await withTokenRefresh(
15497
- (tok) => (0, import_core24.stripeGetSession)(confirmedSessionId, tok, publishableKey)
15573
+ (tok) => (0, import_core23.stripeGetSession)(confirmedSessionId, tok, publishableKey)
15498
15574
  );
15499
15575
  if (cancelled) return;
15500
15576
  setSessionStatus(session.status);
@@ -15533,7 +15609,7 @@ function PayWithStripeLink({
15533
15609
  setLoading(true);
15534
15610
  setError(null);
15535
15611
  try {
15536
- const result = await (0, import_core24.stripeCreateAuthIntent)(emailToUse.trim(), publishableKey);
15612
+ const result = await (0, import_core23.stripeCreateAuthIntent)(emailToUse.trim(), publishableKey);
15537
15613
  setAuthIntentId(result.auth_intent_id);
15538
15614
  setStep("auth");
15539
15615
  } catch (err) {
@@ -15567,7 +15643,7 @@ function PayWithStripeLink({
15567
15643
  }
15568
15644
  const formattedPhone = `+1${digits}`;
15569
15645
  await sdk.registerLinkUser(email.trim(), formattedPhone, "US");
15570
- const result = await (0, import_core24.stripeCreateAuthIntent)(email.trim(), publishableKey);
15646
+ const result = await (0, import_core23.stripeCreateAuthIntent)(email.trim(), publishableKey);
15571
15647
  setAuthIntentId(result.auth_intent_id);
15572
15648
  setStep("auth");
15573
15649
  } catch (err) {
@@ -15610,7 +15686,7 @@ function PayWithStripeLink({
15610
15686
  return;
15611
15687
  }
15612
15688
  try {
15613
- const authResult = await (0, import_core24.stripeCreateAuthIntent)(knownEmail, publishableKey);
15689
+ const authResult = await (0, import_core23.stripeCreateAuthIntent)(knownEmail, publishableKey);
15614
15690
  setAuthIntentId(authResult.auth_intent_id);
15615
15691
  setStep("auth");
15616
15692
  } catch (err) {
@@ -15637,7 +15713,7 @@ function PayWithStripeLink({
15637
15713
  setCustomerId(result.crypto_customer_id);
15638
15714
  sdkAuthenticatedRef.current = true;
15639
15715
  everAuthenticatedRef.current = true;
15640
- const tokens = await (0, import_core24.stripeExchangeTokens)(
15716
+ const tokens = await (0, import_core23.stripeExchangeTokens)(
15641
15717
  authIntentId,
15642
15718
  publishableKey,
15643
15719
  result.crypto_customer_id
@@ -15715,7 +15791,7 @@ function PayWithStripeLink({
15715
15791
  }
15716
15792
  try {
15717
15793
  const cust = await withTokenRefresh(
15718
- (tok) => (0, import_core24.stripeGetCustomer)(customerId, tok, publishableKey)
15794
+ (tok) => (0, import_core23.stripeGetCustomer)(customerId, tok, publishableKey)
15719
15795
  );
15720
15796
  if (!mounted) return;
15721
15797
  setCustomer(cust);
@@ -15914,7 +15990,7 @@ function PayWithStripeLink({
15914
15990
  try {
15915
15991
  if (!onrampWalletAddress) return;
15916
15992
  const existingWallets = await withTokenRefresh(
15917
- (tok) => (0, import_core24.stripeListWallets)(customerId, tok, publishableKey)
15993
+ (tok) => (0, import_core23.stripeListWallets)(customerId, tok, publishableKey)
15918
15994
  );
15919
15995
  if (!mounted) return;
15920
15996
  setWallets(existingWallets.data);
@@ -15974,7 +16050,7 @@ function PayWithStripeLink({
15974
16050
  return isEvm ? a.toLowerCase() === b.toLowerCase() : a === b;
15975
16051
  };
15976
16052
  const list = await withTokenRefresh(
15977
- (tok) => (0, import_core24.stripeListWallets)(customerId, tok, publishableKey)
16053
+ (tok) => (0, import_core23.stripeListWallets)(customerId, tok, publishableKey)
15978
16054
  );
15979
16055
  if (cancelled) return;
15980
16056
  setWallets(list.data);
@@ -16024,7 +16100,7 @@ function PayWithStripeLink({
16024
16100
  setLoading(true);
16025
16101
  try {
16026
16102
  const existing = await withTokenRefresh(
16027
- (tok) => (0, import_core24.stripeListPaymentTokens)(customerId, tok, publishableKey)
16103
+ (tok) => (0, import_core23.stripeListPaymentTokens)(customerId, tok, publishableKey)
16028
16104
  );
16029
16105
  if (!mounted) return;
16030
16106
  setPaymentTokens(existing.data);
@@ -16044,7 +16120,7 @@ function PayWithStripeLink({
16044
16120
  try {
16045
16121
  const sdk = await initialize();
16046
16122
  if (!sdk) throw new Error("SDK failed to load");
16047
- const authResult = await (0, import_core24.stripeCreateAuthIntent)(email, publishableKey);
16123
+ const authResult = await (0, import_core23.stripeCreateAuthIntent)(email, publishableKey);
16048
16124
  if (!mounted) return;
16049
16125
  setAuthIntentId(authResult.auth_intent_id);
16050
16126
  setStep("auth");
@@ -16095,7 +16171,7 @@ function PayWithStripeLink({
16095
16171
  if (!sdkAuthenticatedRef.current) {
16096
16172
  if (email) {
16097
16173
  pendingAddPaymentRef.current = true;
16098
- const authResult = await (0, import_core24.stripeCreateAuthIntent)(email, publishableKey);
16174
+ const authResult = await (0, import_core23.stripeCreateAuthIntent)(email, publishableKey);
16099
16175
  if (!mounted) return;
16100
16176
  setAuthIntentId(authResult.auth_intent_id);
16101
16177
  setStep("auth");
@@ -16130,7 +16206,7 @@ function PayWithStripeLink({
16130
16206
  if (display) {
16131
16207
  applyAndAdvance();
16132
16208
  if (customerId && accessTokenRef.current) {
16133
- (0, import_core24.stripeListPaymentTokens)(customerId, accessTokenRef.current, publishableKey).then((tokens) => {
16209
+ (0, import_core23.stripeListPaymentTokens)(customerId, accessTokenRef.current, publishableKey).then((tokens) => {
16134
16210
  if (mounted) setPaymentTokens(tokens.data);
16135
16211
  }).catch(() => {
16136
16212
  });
@@ -16139,7 +16215,7 @@ function PayWithStripeLink({
16139
16215
  }
16140
16216
  try {
16141
16217
  if (customerId && accessTokenRef.current) {
16142
- const tokens = await (0, import_core24.stripeListPaymentTokens)(
16218
+ const tokens = await (0, import_core23.stripeListPaymentTokens)(
16143
16219
  customerId,
16144
16220
  accessTokenRef.current,
16145
16221
  publishableKey
@@ -16200,10 +16276,10 @@ function PayWithStripeLink({
16200
16276
  setRequiredStepUp(tier ?? null);
16201
16277
  setStep("amount");
16202
16278
  if (customerId && onrampWalletAddress) {
16203
- void withTokenRefresh((tok) => (0, import_core24.stripeGetCustomer)(customerId, tok, publishableKey)).then((cust) => setCustomer(cust)).catch(() => {
16279
+ void withTokenRefresh((tok) => (0, import_core23.stripeGetCustomer)(customerId, tok, publishableKey)).then((cust) => setCustomer(cust)).catch(() => {
16204
16280
  });
16205
16281
  void withTokenRefresh(
16206
- (tok) => (0, import_core24.stripeGetTransactionLimits)(
16282
+ (tok) => (0, import_core23.stripeGetTransactionLimits)(
16207
16283
  {
16208
16284
  cryptoCustomerId: customerId,
16209
16285
  destinationNetwork: getStripeNetwork(),
@@ -16264,13 +16340,13 @@ function PayWithStripeLink({
16264
16340
  return coordinator.performCheckout(sid, async (onrampSessionId) => {
16265
16341
  try {
16266
16342
  await withTokenRefresh(
16267
- (tok) => (0, import_core24.stripeRefreshQuote)(onrampSessionId, tok, publishableKey)
16343
+ (tok) => (0, import_core23.stripeRefreshQuote)(onrampSessionId, tok, publishableKey)
16268
16344
  );
16269
16345
  } catch {
16270
16346
  }
16271
16347
  try {
16272
16348
  const confirmResponse = await withTokenRefresh(
16273
- (tok) => (0, import_core24.stripeConfirmSession)(onrampSessionId, tok, {}, publishableKey)
16349
+ (tok) => (0, import_core23.stripeConfirmSession)(onrampSessionId, tok, {}, publishableKey)
16274
16350
  );
16275
16351
  lastConfirmError = null;
16276
16352
  return confirmResponse.client_secret ?? "";
@@ -16282,13 +16358,13 @@ function PayWithStripeLink({
16282
16358
  };
16283
16359
  const lastErrorFor = async (sid) => {
16284
16360
  const sessionState = await withTokenRefresh(
16285
- (tok) => (0, import_core24.stripeGetSession)(sid, tok, publishableKey)
16361
+ (tok) => (0, import_core23.stripeGetSession)(sid, tok, publishableKey)
16286
16362
  );
16287
16363
  return sessionState.transaction_details?.last_error ?? null;
16288
16364
  };
16289
16365
  const createFreshSession = async () => {
16290
16366
  const fresh = await withTokenRefresh(
16291
- (tok) => (0, import_core24.stripeCreateSession)(
16367
+ (tok) => (0, import_core23.stripeCreateSession)(
16292
16368
  {
16293
16369
  cryptoCustomerId: customerId,
16294
16370
  paymentToken: selectedPaymentToken,
@@ -16333,7 +16409,11 @@ function PayWithStripeLink({
16333
16409
  if (checkoutResult.successful) {
16334
16410
  handledTerminalSessionRef.current = null;
16335
16411
  executionReconciledSessionRef.current = null;
16336
- track("flow_started", { method: "stripe_link", flow_type: "deposit" });
16412
+ track("flow_started", {
16413
+ method: "stripe_link",
16414
+ flow_type: "deposit",
16415
+ deposit_wallet_id: depositWalletId
16416
+ });
16337
16417
  setConfirmedSessionId(activeSessionId);
16338
16418
  setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
16339
16419
  if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
@@ -16356,7 +16436,7 @@ function PayWithStripeLink({
16356
16436
  } else if (isConsumedPaymentMethodError(lastConfirmError)) {
16357
16437
  dropConsumedToken(CONSUMED_TOKEN_MESSAGE, lastConfirmError);
16358
16438
  } else {
16359
- const confirmErr = lastConfirmError instanceof import_core24.StripeApiResponseError ? lastConfirmError : void 0;
16439
+ const confirmErr = lastConfirmError instanceof import_core23.StripeApiResponseError ? lastConfirmError : void 0;
16360
16440
  const reason = describeStripePaymentFailure(lastError) ?? describeStripePaymentFailure(confirmErr?.stripeCode) ?? unmappedPaymentFailureMessage(confirmErr?.stripeMessage);
16361
16441
  if (!isRetriablePaymentToken(selectedPaymentToken)) {
16362
16442
  dropConsumedToken(reason, lastConfirmError ?? void 0);
@@ -16374,7 +16454,7 @@ function PayWithStripeLink({
16374
16454
  }
16375
16455
  } catch (err) {
16376
16456
  if (isStale()) return;
16377
- const stripeErr = lastConfirmError instanceof import_core24.StripeApiResponseError ? lastConfirmError : err instanceof import_core24.StripeApiResponseError ? err : void 0;
16457
+ const stripeErr = lastConfirmError instanceof import_core23.StripeApiResponseError ? lastConfirmError : err instanceof import_core23.StripeApiResponseError ? err : void 0;
16378
16458
  const effectiveError = stripeErr ?? err;
16379
16459
  const msg = stripeErr?.message ?? (err instanceof Error ? err.message : t.formErrors.checkoutFailed);
16380
16460
  const errorType = stripeErr?.errorType;
@@ -16422,7 +16502,7 @@ function PayWithStripeLink({
16422
16502
  if (!customerId) return;
16423
16503
  try {
16424
16504
  const existing = await withTokenRefresh(
16425
- (tok) => (0, import_core24.stripeListPaymentTokens)(customerId, tok, publishableKey)
16505
+ (tok) => (0, import_core23.stripeListPaymentTokens)(customerId, tok, publishableKey)
16426
16506
  );
16427
16507
  setPaymentTokens(existing.data);
16428
16508
  const stored = getStoredSelectedToken(customerId);
@@ -16459,7 +16539,7 @@ function PayWithStripeLink({
16459
16539
  const fetchLimits = async () => {
16460
16540
  try {
16461
16541
  const result = await withTokenRefresh(
16462
- (tok) => (0, import_core24.stripeGetTransactionLimits)(
16542
+ (tok) => (0, import_core23.stripeGetTransactionLimits)(
16463
16543
  {
16464
16544
  cryptoCustomerId: customerId,
16465
16545
  destinationNetwork: getStripeNetwork(),
@@ -16535,8 +16615,8 @@ function PayWithStripeLink({
16535
16615
  const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken && // Never refresh (and thereby reuse) a session already checked out —
16536
16616
  // its PaymentIntent is spent. Build a fresh one instead.
16537
16617
  !spentSessionIdsRef.current.has(existing.id);
16538
- const session = canRefreshExisting ? await withTokenRefresh((tok) => (0, import_core24.stripeRefreshQuote)(existing.id, tok, publishableKey)) : await withTokenRefresh(
16539
- (tok) => (0, import_core24.stripeCreateSession)(
16618
+ const session = canRefreshExisting ? await withTokenRefresh((tok) => (0, import_core23.stripeRefreshQuote)(existing.id, tok, publishableKey)) : await withTokenRefresh(
16619
+ (tok) => (0, import_core23.stripeCreateSession)(
16540
16620
  {
16541
16621
  cryptoCustomerId: customerId,
16542
16622
  paymentToken: selectedPaymentToken,
@@ -16578,7 +16658,7 @@ function PayWithStripeLink({
16578
16658
  }
16579
16659
  } else {
16580
16660
  setSessionForCheckout(null);
16581
- const result = await (0, import_core24.stripeGetQuotes)(
16661
+ const result = await (0, import_core23.stripeGetQuotes)(
16582
16662
  {
16583
16663
  sourceAmount: amount,
16584
16664
  sourceCurrency: "usd",
@@ -16606,7 +16686,7 @@ function PayWithStripeLink({
16606
16686
  if (!active) return;
16607
16687
  setQuote(null);
16608
16688
  setSessionForCheckout(null);
16609
- const qErrorType = err instanceof import_core24.StripeApiResponseError ? err.errorType : void 0;
16689
+ const qErrorType = err instanceof import_core23.StripeApiResponseError ? err.errorType : void 0;
16610
16690
  if (qErrorType === "stripe_onramp_missing_document_verification") {
16611
16691
  setLimitReachedAmount(num);
16612
16692
  setRequiredStepUp("l2");
@@ -17830,7 +17910,14 @@ function PayWithStripeLink({
17830
17910
  ]
17831
17911
  }
17832
17912
  ),
17833
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref: authMountRef, className: "uf-w-full uf-min-h-[200px]" })
17913
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
17914
+ "div",
17915
+ {
17916
+ ref: authMountRef,
17917
+ className: "uf-w-full uf-min-h-[200px]",
17918
+ style: { colorScheme: "only light" }
17919
+ }
17920
+ )
17834
17921
  ]
17835
17922
  }
17836
17923
  );
@@ -18382,11 +18469,11 @@ function PayWithStripeLink({
18382
18469
  // src/components/deposits/CoinbaseConnect.tsx
18383
18470
  var import_react22 = require("react");
18384
18471
  var import_lucide_react29 = require("lucide-react");
18385
- var import_core27 = require("@unifold/core");
18472
+ var import_core26 = require("@unifold/core");
18386
18473
 
18387
18474
  // src/hooks/use-project-config.ts
18388
- var import_react_query11 = require("@tanstack/react-query");
18389
- var import_core25 = require("@unifold/core");
18475
+ var import_react_query10 = require("@tanstack/react-query");
18476
+ var import_core24 = require("@unifold/core");
18390
18477
  function useProjectConfig({
18391
18478
  publishableKey,
18392
18479
  enabled = true,
@@ -18397,17 +18484,17 @@ function useProjectConfig({
18397
18484
  data: projectConfig,
18398
18485
  isLoading,
18399
18486
  error
18400
- } = (0, import_react_query11.useQuery)({
18487
+ } = (0, import_react_query10.useQuery)({
18401
18488
  // Country is part of the key so a region change refetches the region-aware
18402
18489
  // config. Omitted when undefined so callers that don't pass a country keep
18403
18490
  // sharing the base cache entry.
18404
18491
  queryKey: countryCode ? ["unifold", "projectConfig", publishableKey, countryCode, subdivisionCode ?? null] : ["unifold", "projectConfig", publishableKey],
18405
- queryFn: () => (0, import_core25.getProjectConfig)(publishableKey, countryCode ? { countryCode, subdivisionCode } : void 0),
18492
+ queryFn: () => (0, import_core24.getProjectConfig)(publishableKey, countryCode ? { countryCode, subdivisionCode } : void 0),
18406
18493
  enabled,
18407
18494
  // Keep the previous (e.g. no-country) config visible while the region-aware
18408
18495
  // config refetches after the country resolves, so unrelated config-driven
18409
18496
  // UI doesn't flash back to defaults.
18410
- placeholderData: import_react_query11.keepPreviousData,
18497
+ placeholderData: import_react_query10.keepPreviousData,
18411
18498
  staleTime: 1e3 * 60 * 30,
18412
18499
  refetchOnMount: true,
18413
18500
  refetchOnWindowFocus: true
@@ -18416,14 +18503,14 @@ function useProjectConfig({
18416
18503
  }
18417
18504
 
18418
18505
  // src/hooks/use-integration-transfer-default-token.ts
18419
- var import_react_query12 = require("@tanstack/react-query");
18420
- var import_core26 = require("@unifold/core");
18506
+ var import_react_query11 = require("@tanstack/react-query");
18507
+ var import_core25 = require("@unifold/core");
18421
18508
  function useIntegrationTransferDefaultToken({
18422
18509
  params,
18423
18510
  publishableKey,
18424
18511
  enabled = true
18425
18512
  }) {
18426
- return (0, import_react_query12.useQuery)({
18513
+ return (0, import_react_query11.useQuery)({
18427
18514
  queryKey: [
18428
18515
  "unifold",
18429
18516
  "integrationTransferDefaultToken",
@@ -18436,7 +18523,7 @@ function useIntegrationTransferDefaultToken({
18436
18523
  params?.country_code ?? null,
18437
18524
  params?.subdivision_code ?? null
18438
18525
  ],
18439
- queryFn: () => (0, import_core26.getIntegrationTransferDefaultToken)(params, publishableKey),
18526
+ queryFn: () => (0, import_core25.getIntegrationTransferDefaultToken)(params, publishableKey),
18440
18527
  enabled: enabled && !!params,
18441
18528
  staleTime: 1e3 * 60 * 5,
18442
18529
  gcTime: 1e3 * 60 * 30,
@@ -18540,7 +18627,7 @@ function CoinbaseConnect({
18540
18627
  const appName = projectConfig?.project_name ?? "Unifold";
18541
18628
  const { t: strings } = useI18n();
18542
18629
  const t = strings.connectExchange;
18543
- const initialView = skipToHoldings && getStoredIntegrationToken(import_core27.IntegrationProvider.COINBASE) ? "holdings" : "select_exchange";
18630
+ const initialView = skipToHoldings && getStoredIntegrationToken(import_core26.IntegrationProvider.COINBASE) ? "holdings" : "select_exchange";
18544
18631
  const [view, setView] = (0, import_react22.useState)(initialView);
18545
18632
  const [prevView, setPrevView] = (0, import_react22.useState)(initialView);
18546
18633
  const [isTransitioning, setIsTransitioning] = (0, import_react22.useState)(false);
@@ -18576,7 +18663,7 @@ function CoinbaseConnect({
18576
18663
  }, [selectedExchange]);
18577
18664
  const defaultTokenParams = (0, import_react22.useMemo)(
18578
18665
  () => selectedAsset ? {
18579
- integration_provider: import_core27.IntegrationProvider.COINBASE,
18666
+ integration_provider: import_core26.IntegrationProvider.COINBASE,
18580
18667
  source_currency: selectedAsset.currency.toLowerCase(),
18581
18668
  destination_token_address: destinationTokenAddress,
18582
18669
  destination_chain_id: destinationChainId,
@@ -18697,16 +18784,16 @@ function CoinbaseConnect({
18697
18784
  const tryRefreshToken = (0, import_react22.useCallback)(
18698
18785
  async (currentToken) => {
18699
18786
  try {
18700
- const result = await (0, import_core27.refreshIntegrationToken)(currentToken, publishableKey);
18787
+ const result = await (0, import_core26.refreshIntegrationToken)(currentToken, publishableKey);
18701
18788
  setStoredIntegrationToken({
18702
- integration_provider: import_core27.IntegrationProvider.COINBASE,
18789
+ integration_provider: import_core26.IntegrationProvider.COINBASE,
18703
18790
  access_token: result.access_token,
18704
18791
  expires_at: result.expires_at
18705
18792
  });
18706
18793
  setAccessToken(result.access_token);
18707
18794
  return result.access_token;
18708
18795
  } catch {
18709
- clearStoredIntegrationToken(import_core27.IntegrationProvider.COINBASE);
18796
+ clearStoredIntegrationToken(import_core26.IntegrationProvider.COINBASE);
18710
18797
  setAccessToken(null);
18711
18798
  return null;
18712
18799
  }
@@ -18714,7 +18801,7 @@ function CoinbaseConnect({
18714
18801
  [publishableKey]
18715
18802
  );
18716
18803
  (0, import_react22.useEffect)(() => {
18717
- const stored = getStoredIntegrationToken(import_core27.IntegrationProvider.COINBASE);
18804
+ const stored = getStoredIntegrationToken(import_core26.IntegrationProvider.COINBASE);
18718
18805
  if (stored) {
18719
18806
  setAccessToken(stored.access_token);
18720
18807
  if (skipToHoldings) {
@@ -18726,7 +18813,7 @@ function CoinbaseConnect({
18726
18813
  const userSubdivisionCode = userIpInfo?.subdivisionCode ?? void 0;
18727
18814
  (0, import_react22.useEffect)(() => {
18728
18815
  let cancelled = false;
18729
- (0, import_core27.getIntegrationExchanges)(
18816
+ (0, import_core26.getIntegrationExchanges)(
18730
18817
  publishableKey,
18731
18818
  userCountryCode ? {
18732
18819
  country_code: userCountryCode,
@@ -18739,7 +18826,7 @@ function CoinbaseConnect({
18739
18826
  if (prev) {
18740
18827
  return res.data.find((e) => e.service_provider === prev.service_provider) ?? prev;
18741
18828
  }
18742
- return res.data.find((e) => e.service_provider === import_core27.IntegrationProvider.COINBASE) ?? null;
18829
+ return res.data.find((e) => e.service_provider === import_core26.IntegrationProvider.COINBASE) ?? null;
18743
18830
  });
18744
18831
  }).catch(() => {
18745
18832
  }).finally(() => {
@@ -18753,8 +18840,8 @@ function CoinbaseConnect({
18753
18840
  async (token) => {
18754
18841
  setIsLoading(true);
18755
18842
  try {
18756
- const result = await (0, import_core27.getIntegrationHoldings)(
18757
- import_core27.IntegrationProvider.COINBASE,
18843
+ const result = await (0, import_core26.getIntegrationHoldings)(
18844
+ import_core26.IntegrationProvider.COINBASE,
18758
18845
  token,
18759
18846
  publishableKey
18760
18847
  );
@@ -18771,8 +18858,8 @@ function CoinbaseConnect({
18771
18858
  const refreshed = await tryRefreshToken(token);
18772
18859
  if (refreshed) {
18773
18860
  try {
18774
- const retryResult = await (0, import_core27.getIntegrationHoldings)(
18775
- import_core27.IntegrationProvider.COINBASE,
18861
+ const retryResult = await (0, import_core26.getIntegrationHoldings)(
18862
+ import_core26.IntegrationProvider.COINBASE,
18776
18863
  refreshed,
18777
18864
  publishableKey
18778
18865
  );
@@ -18789,12 +18876,12 @@ function CoinbaseConnect({
18789
18876
  retryFailed = true;
18790
18877
  }
18791
18878
  }
18792
- clearStoredIntegrationToken(import_core27.IntegrationProvider.COINBASE);
18879
+ clearStoredIntegrationToken(import_core26.IntegrationProvider.COINBASE);
18793
18880
  setAccessToken(null);
18794
18881
  track("account_connection_failed", {
18795
18882
  flow_type: "deposit",
18796
18883
  method: "exchange_connect",
18797
- provider: import_core27.IntegrationProvider.COINBASE,
18884
+ provider: import_core26.IntegrationProvider.COINBASE,
18798
18885
  failure_reason: retryFailed ? "holdings_unavailable" : "token_refresh_failed"
18799
18886
  });
18800
18887
  transitionTo("select_exchange");
@@ -18870,7 +18957,7 @@ function CoinbaseConnect({
18870
18957
  ...userIpInfo?.subdivisionCode ? { subdivision_code: userIpInfo.subdivisionCode } : {}
18871
18958
  };
18872
18959
  setRedirectSession({ exchange, requestParams });
18873
- window.open((0, import_core27.getIntegrationExchangeSessionStartUrl)(requestParams, publishableKey), "_blank");
18960
+ window.open((0, import_core26.getIntegrationExchangeSessionStartUrl)(requestParams, publishableKey), "_blank");
18874
18961
  transitionTo("redirect_pending");
18875
18962
  };
18876
18963
  const handleCreateRedirectTransferSession = async () => {
@@ -18881,7 +18968,7 @@ function CoinbaseConnect({
18881
18968
  if (redirectMinDepositUsd > 0 && amountNum < redirectMinDepositUsd) return;
18882
18969
  setIsLoading(true);
18883
18970
  try {
18884
- const result = await (0, import_core27.createIntegrationExchangeSession)(
18971
+ const result = await (0, import_core26.createIntegrationExchangeSession)(
18885
18972
  {
18886
18973
  service_provider: exchange.service_provider,
18887
18974
  wallet_addresses: [{ address: wallet.address, chain_type: wallet.chain_type }],
@@ -18915,7 +19002,7 @@ function CoinbaseConnect({
18915
19002
  const handleReopenRedirectExchange = () => {
18916
19003
  if (!redirectSession?.requestParams) return;
18917
19004
  window.open(
18918
- (0, import_core27.getIntegrationExchangeSessionStartUrl)(redirectSession.requestParams, publishableKey),
19005
+ (0, import_core26.getIntegrationExchangeSessionStartUrl)(redirectSession.requestParams, publishableKey),
18919
19006
  "_blank"
18920
19007
  );
18921
19008
  };
@@ -18932,7 +19019,7 @@ function CoinbaseConnect({
18932
19019
  const externalId = redirectSession.externalId;
18933
19020
  const poll = async () => {
18934
19021
  try {
18935
- const result = await (0, import_core27.getOnrampSessionStatus)(externalId, publishableKey);
19022
+ const result = await (0, import_core26.getOnrampSessionStatus)(externalId, publishableKey);
18936
19023
  setRedirectStatus(result.status);
18937
19024
  if (result.status === "failed") {
18938
19025
  setErrorMessage("Payment failed");
@@ -18962,8 +19049,8 @@ function CoinbaseConnect({
18962
19049
  handleOpenRedirectExchange(exchange);
18963
19050
  return;
18964
19051
  }
18965
- if (exchange.service_provider === import_core27.IntegrationProvider.COINBASE) {
18966
- const stored = getStoredIntegrationToken(import_core27.IntegrationProvider.COINBASE);
19052
+ if (exchange.service_provider === import_core26.IntegrationProvider.COINBASE) {
19053
+ const stored = getStoredIntegrationToken(import_core26.IntegrationProvider.COINBASE);
18967
19054
  if (stored) {
18968
19055
  setAccessToken(stored.access_token);
18969
19056
  connectingReasonRef.current = "holdings";
@@ -18981,20 +19068,20 @@ function CoinbaseConnect({
18981
19068
  track("account_connection_started", {
18982
19069
  flow_type: "deposit",
18983
19070
  method: "exchange_connect",
18984
- provider: import_core27.IntegrationProvider.COINBASE
19071
+ provider: import_core26.IntegrationProvider.COINBASE
18985
19072
  });
18986
19073
  try {
18987
- const { redirect_url, state } = await (0, import_core27.startIntegrationOAuth)(publishableKey);
19074
+ const { redirect_url, state } = await (0, import_core26.startIntegrationOAuth)(publishableKey);
18988
19075
  popupRef.current = window.open(redirect_url, "_blank", "width=500,height=700");
18989
19076
  pollRef.current = setInterval(async () => {
18990
19077
  try {
18991
- const result = await (0, import_core27.authenticateIntegrationOAuth)({ state }, publishableKey);
19078
+ const result = await (0, import_core26.authenticateIntegrationOAuth)({ state }, publishableKey);
18992
19079
  if (result.status === "completed") {
18993
19080
  if (pollRef.current) clearInterval(pollRef.current);
18994
19081
  pollRef.current = null;
18995
19082
  if (oauthAbandonedRef.current || viewRef.current !== "connecting") return;
18996
19083
  setStoredIntegrationToken({
18997
- integration_provider: import_core27.IntegrationProvider.COINBASE,
19084
+ integration_provider: import_core26.IntegrationProvider.COINBASE,
18998
19085
  access_token: result.access_token,
18999
19086
  expires_at: result.expires_at
19000
19087
  });
@@ -19002,7 +19089,7 @@ function CoinbaseConnect({
19002
19089
  track("account_connected", {
19003
19090
  flow_type: "deposit",
19004
19091
  method: "exchange_connect",
19005
- provider: import_core27.IntegrationProvider.COINBASE
19092
+ provider: import_core26.IntegrationProvider.COINBASE
19006
19093
  });
19007
19094
  transitionTo("connected");
19008
19095
  }
@@ -19014,7 +19101,7 @@ function CoinbaseConnect({
19014
19101
  track("account_connection_failed", {
19015
19102
  flow_type: "deposit",
19016
19103
  method: "exchange_connect",
19017
- provider: import_core27.IntegrationProvider.COINBASE,
19104
+ provider: import_core26.IntegrationProvider.COINBASE,
19018
19105
  failure_reason: "oauth_start_failed",
19019
19106
  error_code: message
19020
19107
  });
@@ -19060,9 +19147,9 @@ function CoinbaseConnect({
19060
19147
  if (matchingWallet?.id) {
19061
19148
  setTransferDepositWalletId(matchingWallet.id);
19062
19149
  }
19063
- const createTransfer = async (token) => (0, import_core27.createIntegrationTransfer)(
19150
+ const createTransfer = async (token) => (0, import_core26.createIntegrationTransfer)(
19064
19151
  {
19065
- integration_provider: import_core27.IntegrationProvider.COINBASE,
19152
+ integration_provider: import_core26.IntegrationProvider.COINBASE,
19066
19153
  access_token: token,
19067
19154
  currency: selectedAsset.currency.toLowerCase(),
19068
19155
  amount: cryptoAmount,
@@ -19087,7 +19174,7 @@ function CoinbaseConnect({
19087
19174
  track("account_connection_failed", {
19088
19175
  flow_type: "deposit",
19089
19176
  method: "exchange_connect",
19090
- provider: import_core27.IntegrationProvider.COINBASE,
19177
+ provider: import_core26.IntegrationProvider.COINBASE,
19091
19178
  failure_reason: "token_refresh_failed"
19092
19179
  });
19093
19180
  throw new Error("Session expired. Please reconnect your exchange.");
@@ -19105,12 +19192,15 @@ function CoinbaseConnect({
19105
19192
  setIsLoading(false);
19106
19193
  }
19107
19194
  };
19108
- const transferErrorType = (err) => err instanceof import_core27.IntegrationTransferError ? err.errorType : void 0;
19195
+ const transferErrorType = (err) => err instanceof import_core26.IntegrationTransferError ? err.errorType : void 0;
19109
19196
  const trackTransferStarted = () => {
19110
19197
  track("flow_started", {
19111
19198
  flow_type: "deposit",
19112
19199
  method: "exchange_connect",
19113
- provider: import_core27.IntegrationProvider.COINBASE,
19200
+ provider: import_core26.IntegrationProvider.COINBASE,
19201
+ // No execution yet — one appears when the exchange's transfer lands on
19202
+ // this wallet, carrying the same id.
19203
+ deposit_wallet_id: transferDepositWalletId,
19114
19204
  amount_usd: sendAmount || void 0,
19115
19205
  currency: selectedAsset?.currency.toLowerCase().replace(/[^a-z0-9]+/g, "_"),
19116
19206
  chain: sourceChain?.chain_id,
@@ -19118,13 +19208,41 @@ function CoinbaseConnect({
19118
19208
  network: sourceChain?.network
19119
19209
  });
19120
19210
  };
19211
+ const applyConfirmResult = (result) => {
19212
+ if (result.status === "mfa_required") {
19213
+ track("verification_started", {
19214
+ flow_type: "deposit",
19215
+ method: "exchange_connect",
19216
+ provider: import_core26.IntegrationProvider.COINBASE,
19217
+ verification_type: "mfa",
19218
+ verification_status: result.status
19219
+ });
19220
+ transitionTo("mfa");
19221
+ setMfaCode("");
19222
+ setMfaError(false);
19223
+ } else if (result.status === "mfa_enrollment_required") {
19224
+ transitionTo("mfa_enrollment");
19225
+ } else if (result.status === "completed") {
19226
+ trackTransferStarted();
19227
+ setConfirmResult(result);
19228
+ transitionTo("success");
19229
+ onTransferSuccess?.(result);
19230
+ } else {
19231
+ setErrorMessage(result.message || t.errors.transferFailed);
19232
+ transitionTo("error");
19233
+ onTransferError?.({
19234
+ message: result.message || t.errors.transferFailed,
19235
+ code: result.status
19236
+ });
19237
+ }
19238
+ };
19121
19239
  const handleConfirmTransfer = async () => {
19122
19240
  if (!transferIntent || !accessToken) return;
19123
19241
  setIsLoading(true);
19124
19242
  let sessionExpired = false;
19125
19243
  try {
19126
19244
  let token = accessToken;
19127
- const result = await (0, import_core27.confirmIntegrationTransfer)(
19245
+ const result = await (0, import_core26.confirmIntegrationTransfer)(
19128
19246
  transferIntent.id,
19129
19247
  token,
19130
19248
  void 0,
@@ -19136,7 +19254,7 @@ function CoinbaseConnect({
19136
19254
  const refreshed = await tryRefreshToken(token);
19137
19255
  if (refreshed) {
19138
19256
  token = refreshed;
19139
- return (0, import_core27.confirmIntegrationTransfer)(
19257
+ return (0, import_core26.confirmIntegrationTransfer)(
19140
19258
  transferIntent.id,
19141
19259
  refreshed,
19142
19260
  void 0,
@@ -19147,35 +19265,12 @@ function CoinbaseConnect({
19147
19265
  track("account_connection_failed", {
19148
19266
  flow_type: "deposit",
19149
19267
  method: "exchange_connect",
19150
- provider: import_core27.IntegrationProvider.COINBASE,
19268
+ provider: import_core26.IntegrationProvider.COINBASE,
19151
19269
  failure_reason: "token_refresh_failed"
19152
19270
  });
19153
19271
  throw err;
19154
19272
  });
19155
- if (result.status === "mfa_required") {
19156
- track("verification_started", {
19157
- flow_type: "deposit",
19158
- method: "exchange_connect",
19159
- provider: import_core27.IntegrationProvider.COINBASE,
19160
- verification_type: "mfa",
19161
- verification_status: result.status
19162
- });
19163
- transitionTo("mfa");
19164
- setMfaCode("");
19165
- setMfaError(false);
19166
- } else if (result.status === "completed") {
19167
- trackTransferStarted();
19168
- setConfirmResult(result);
19169
- transitionTo("success");
19170
- onTransferSuccess?.(result);
19171
- } else {
19172
- setErrorMessage(result.message || t.errors.transferFailed);
19173
- transitionTo("error");
19174
- onTransferError?.({
19175
- message: result.message || t.errors.transferFailed,
19176
- code: result.status
19177
- });
19178
- }
19273
+ applyConfirmResult(result);
19179
19274
  } catch (err) {
19180
19275
  const message = err instanceof Error ? err.message : t.errors.transferFailed;
19181
19276
  setErrorMessage(message);
@@ -19195,11 +19290,11 @@ function CoinbaseConnect({
19195
19290
  track("verification_submitted", {
19196
19291
  flow_type: "deposit",
19197
19292
  method: "exchange_connect",
19198
- provider: import_core27.IntegrationProvider.COINBASE,
19293
+ provider: import_core26.IntegrationProvider.COINBASE,
19199
19294
  verification_type: "mfa"
19200
19295
  });
19201
19296
  try {
19202
- const result = await (0, import_core27.confirmIntegrationTransfer)(
19297
+ const result = await (0, import_core26.confirmIntegrationTransfer)(
19203
19298
  transferIntent.id,
19204
19299
  accessToken,
19205
19300
  mfaCode,
@@ -19209,7 +19304,7 @@ function CoinbaseConnect({
19209
19304
  track("verification_failed", {
19210
19305
  flow_type: "deposit",
19211
19306
  method: "exchange_connect",
19212
- provider: import_core27.IntegrationProvider.COINBASE,
19307
+ provider: import_core26.IntegrationProvider.COINBASE,
19213
19308
  verification_type: "mfa",
19214
19309
  verification_status: result.status,
19215
19310
  failure_reason: "invalid_code"
@@ -19220,7 +19315,7 @@ function CoinbaseConnect({
19220
19315
  track("verification_completed", {
19221
19316
  flow_type: "deposit",
19222
19317
  method: "exchange_connect",
19223
- provider: import_core27.IntegrationProvider.COINBASE,
19318
+ provider: import_core26.IntegrationProvider.COINBASE,
19224
19319
  verification_type: "mfa",
19225
19320
  verification_status: result.status
19226
19321
  });
@@ -19232,7 +19327,7 @@ function CoinbaseConnect({
19232
19327
  track("verification_failed", {
19233
19328
  flow_type: "deposit",
19234
19329
  method: "exchange_connect",
19235
- provider: import_core27.IntegrationProvider.COINBASE,
19330
+ provider: import_core26.IntegrationProvider.COINBASE,
19236
19331
  verification_type: "mfa",
19237
19332
  verification_status: result.status,
19238
19333
  failure_reason: result.message || "transfer_failed"
@@ -19249,7 +19344,7 @@ function CoinbaseConnect({
19249
19344
  track("verification_failed", {
19250
19345
  flow_type: "deposit",
19251
19346
  method: "exchange_connect",
19252
- provider: import_core27.IntegrationProvider.COINBASE,
19347
+ provider: import_core26.IntegrationProvider.COINBASE,
19253
19348
  verification_type: "mfa",
19254
19349
  failure_reason: errorType || (err instanceof Error ? err.message : "mfa_request_failed")
19255
19350
  });
@@ -19282,14 +19377,14 @@ function CoinbaseConnect({
19282
19377
  track("account_connection_failed", {
19283
19378
  flow_type: "deposit",
19284
19379
  method: "exchange_connect",
19285
- provider: import_core27.IntegrationProvider.COINBASE,
19380
+ provider: import_core26.IntegrationProvider.COINBASE,
19286
19381
  failure_reason: "abandoned"
19287
19382
  });
19288
19383
  } else if (view === "mfa") {
19289
19384
  track("verification_failed", {
19290
19385
  flow_type: "deposit",
19291
19386
  method: "exchange_connect",
19292
- provider: import_core27.IntegrationProvider.COINBASE,
19387
+ provider: import_core26.IntegrationProvider.COINBASE,
19293
19388
  verification_type: "mfa",
19294
19389
  failure_reason: "abandoned"
19295
19390
  });
@@ -19332,6 +19427,9 @@ function CoinbaseConnect({
19332
19427
  setShowTransferDetails(false);
19333
19428
  transitionTo("enter_amount");
19334
19429
  break;
19430
+ case "mfa_enrollment":
19431
+ transitionTo("transfer_confirm");
19432
+ break;
19335
19433
  case "mfa":
19336
19434
  transitionTo("transfer_confirm");
19337
19435
  break;
@@ -19447,7 +19545,7 @@ function CoinbaseConnect({
19447
19545
  },
19448
19546
  children: t.comingSoon
19449
19547
  }
19450
- ) : accessToken && exchange.service_provider === import_core27.IntegrationProvider.COINBASE ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
19548
+ ) : accessToken && exchange.service_provider === import_core26.IntegrationProvider.COINBASE ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
19451
19549
  "span",
19452
19550
  {
19453
19551
  className: "uf-text-xs uf-px-2.5 uf-py-1 uf-rounded-full",
@@ -20888,6 +20986,55 @@ function CoinbaseConnect({
20888
20986
  ] })
20889
20987
  ] });
20890
20988
  }
20989
+ if (view === "mfa_enrollment") {
20990
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
20991
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
20992
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
20993
+ "div",
20994
+ {
20995
+ className: "uf-flex uf-flex-col uf-items-center uf-px-4 uf-pb-4",
20996
+ style: viewTransitionStyle,
20997
+ children: [
20998
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
20999
+ DepositErrorState,
21000
+ {
21001
+ title: t.transfer.mfaEnrollmentTitle,
21002
+ message: t.transfer.mfaEnrollmentMessage
21003
+ }
21004
+ ),
21005
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
21006
+ "a",
21007
+ {
21008
+ href: "https://www.coinbase.com/settings/security",
21009
+ target: "_blank",
21010
+ rel: "noopener noreferrer",
21011
+ className: "uf-text-sm uf-underline uf-mb-8 uf-inline-flex uf-items-center uf-gap-1",
21012
+ style: { color: colors2.primary, fontFamily: fonts.medium },
21013
+ children: [
21014
+ t.transfer.mfaEnrollmentSettingsLink,
21015
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react29.ExternalLink, { className: "uf-w-3.5 uf-h-3.5" })
21016
+ ]
21017
+ }
21018
+ ),
21019
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
21020
+ "button",
21021
+ {
21022
+ onClick: handleConfirmTransfer,
21023
+ disabled: isLoading,
21024
+ 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",
21025
+ style: {
21026
+ backgroundColor: colors2.primary,
21027
+ color: "#fff",
21028
+ fontFamily: fonts.medium
21029
+ },
21030
+ children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react29.Loader2, { className: "uf-w-4 uf-h-4 uf-animate-spin" }) : t.continue
21031
+ }
21032
+ )
21033
+ ]
21034
+ }
21035
+ )
21036
+ ] });
21037
+ }
20891
21038
  if (view === "mfa") {
20892
21039
  return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
20893
21040
  /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
@@ -21173,15 +21320,15 @@ function resolveDepositMenuLayout(layout, displayMode) {
21173
21320
  }
21174
21321
 
21175
21322
  // src/hooks/use-exchanges.ts
21176
- var import_react_query13 = require("@tanstack/react-query");
21177
- var import_core28 = require("@unifold/core");
21323
+ var import_react_query12 = require("@tanstack/react-query");
21324
+ var import_core27 = require("@unifold/core");
21178
21325
  function useExchanges({
21179
21326
  publishableKey,
21180
21327
  enabled = true
21181
21328
  }) {
21182
- const { data: exchanges = [], isLoading } = (0, import_react_query13.useQuery)({
21329
+ const { data: exchanges = [], isLoading } = (0, import_react_query12.useQuery)({
21183
21330
  queryKey: ["unifold", "exchanges", publishableKey],
21184
- queryFn: () => (0, import_core28.getExchanges)(void 0, publishableKey).then((res) => res.data),
21331
+ queryFn: () => (0, import_core27.getExchanges)(void 0, publishableKey).then((res) => res.data),
21185
21332
  enabled,
21186
21333
  staleTime: 1e3 * 60 * 30,
21187
21334
  refetchOnMount: false,
@@ -21191,8 +21338,8 @@ function useExchanges({
21191
21338
  }
21192
21339
 
21193
21340
  // src/hooks/use-public-incident.ts
21194
- var import_react_query14 = require("@tanstack/react-query");
21195
- var import_core29 = require("@unifold/core");
21341
+ var import_react_query13 = require("@tanstack/react-query");
21342
+ var import_core28 = require("@unifold/core");
21196
21343
  function usePublicIncident({
21197
21344
  publishableKey,
21198
21345
  enabled = true
@@ -21201,9 +21348,9 @@ function usePublicIncident({
21201
21348
  data: incident,
21202
21349
  isLoading,
21203
21350
  error
21204
- } = (0, import_react_query14.useQuery)({
21351
+ } = (0, import_react_query13.useQuery)({
21205
21352
  queryKey: ["unifold", "publicIncident", publishableKey],
21206
- queryFn: () => (0, import_core29.getPublicIncident)(publishableKey),
21353
+ queryFn: () => (0, import_core28.getPublicIncident)(publishableKey),
21207
21354
  enabled,
21208
21355
  staleTime: 1e3 * 30,
21209
21356
  refetchInterval: 1e3 * 30,
@@ -21213,16 +21360,16 @@ function usePublicIncident({
21213
21360
  }
21214
21361
 
21215
21362
  // src/hooks/use-wallet-pay-providers.ts
21216
- var import_react_query15 = require("@tanstack/react-query");
21217
- var import_core30 = require("@unifold/core");
21363
+ var import_react_query14 = require("@tanstack/react-query");
21364
+ var import_core29 = require("@unifold/core");
21218
21365
  function useWalletPayProviders({
21219
21366
  method,
21220
21367
  publishableKey,
21221
21368
  enabled = true
21222
21369
  }) {
21223
- const { data: providers, isLoading } = (0, import_react_query15.useQuery)({
21370
+ const { data: providers, isLoading } = (0, import_react_query14.useQuery)({
21224
21371
  queryKey: ["unifold", "walletPayProviders", method, publishableKey],
21225
- queryFn: () => (0, import_core30.getWalletPayProviders)(method, publishableKey),
21372
+ queryFn: () => (0, import_core29.getWalletPayProviders)(method, publishableKey),
21226
21373
  enabled,
21227
21374
  staleTime: 1e3 * 60 * 30,
21228
21375
  refetchOnMount: true,
@@ -21238,11 +21385,11 @@ function platformSupportsWalletPay(method, platform) {
21238
21385
  }
21239
21386
 
21240
21387
  // src/components/deposits/DepositModal.tsx
21241
- var import_core43 = require("@unifold/core");
21388
+ var import_core42 = require("@unifold/core");
21242
21389
 
21243
21390
  // src/hooks/use-forward-deposit-events.ts
21244
21391
  var import_react23 = require("react");
21245
- var import_core33 = require("@unifold/core");
21392
+ var import_core32 = require("@unifold/core");
21246
21393
  var import_analytics = require("@unifold/analytics");
21247
21394
 
21248
21395
  // src/lib/selection-events.ts
@@ -21315,11 +21462,11 @@ function walletConnectionPayload(event) {
21315
21462
  }
21316
21463
 
21317
21464
  // src/lib/account-connection-events.ts
21318
- var import_core31 = require("@unifold/core");
21465
+ var import_core30 = require("@unifold/core");
21319
21466
  var ACCOUNT_CONNECTION_EVENTS = {
21320
- account_connection_started: import_core31.DepositEventType.ACCOUNT_CONNECTION_STARTED,
21321
- account_connected: import_core31.DepositEventType.ACCOUNT_CONNECTED,
21322
- account_connection_failed: import_core31.DepositEventType.ACCOUNT_CONNECTION_FAILED
21467
+ account_connection_started: import_core30.DepositEventType.ACCOUNT_CONNECTION_STARTED,
21468
+ account_connected: import_core30.DepositEventType.ACCOUNT_CONNECTED,
21469
+ account_connection_failed: import_core30.DepositEventType.ACCOUNT_CONNECTION_FAILED
21323
21470
  };
21324
21471
  var str3 = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
21325
21472
  function accountConnectionPayload(event) {
@@ -21339,11 +21486,11 @@ function accountConnectionPayload(event) {
21339
21486
  }
21340
21487
 
21341
21488
  // src/lib/verification-events.ts
21342
- var import_core32 = require("@unifold/core");
21489
+ var import_core31 = require("@unifold/core");
21343
21490
  var VERIFICATION_EVENTS = {
21344
- verification_started: import_core32.DepositEventType.VERIFICATION_STARTED,
21345
- verification_completed: import_core32.DepositEventType.VERIFICATION_COMPLETED,
21346
- verification_failed: import_core32.DepositEventType.VERIFICATION_FAILED
21491
+ verification_started: import_core31.DepositEventType.VERIFICATION_STARTED,
21492
+ verification_completed: import_core31.DepositEventType.VERIFICATION_COMPLETED,
21493
+ verification_failed: import_core31.DepositEventType.VERIFICATION_FAILED
21347
21494
  };
21348
21495
  function verificationPayload(event) {
21349
21496
  const type = VERIFICATION_EVENTS[event.event];
@@ -21357,9 +21504,9 @@ function verificationPayload(event) {
21357
21504
 
21358
21505
  // src/hooks/use-forward-deposit-events.ts
21359
21506
  var WALLET_CONNECTION_TYPES = {
21360
- started: import_core33.DepositEventType.WALLET_CONNECTION_STARTED,
21361
- connected: import_core33.DepositEventType.WALLET_CONNECTED,
21362
- failed: import_core33.DepositEventType.WALLET_CONNECTION_FAILED
21507
+ started: import_core32.DepositEventType.WALLET_CONNECTION_STARTED,
21508
+ connected: import_core32.DepositEventType.WALLET_CONNECTED,
21509
+ failed: import_core32.DepositEventType.WALLET_CONNECTION_FAILED
21363
21510
  };
21364
21511
  function depositMethodFromAnalytics(method) {
21365
21512
  if (typeof method !== "string") return void 0;
@@ -21383,7 +21530,7 @@ function useForwardDepositEvents(onEvent) {
21383
21530
  if (event.event === "flow_started") {
21384
21531
  onEventRef.current?.({
21385
21532
  ...base,
21386
- type: import_core33.DepositEventType.FLOW_STARTED,
21533
+ type: import_core32.DepositEventType.FLOW_STARTED,
21387
21534
  ...withMethod,
21388
21535
  data: {
21389
21536
  object: {
@@ -21432,7 +21579,7 @@ function useForwardDepositEvents(onEvent) {
21432
21579
  case "token":
21433
21580
  onEventRef.current?.({
21434
21581
  ...base,
21435
- type: import_core33.DepositEventType.TOKEN_SELECTED,
21582
+ type: import_core32.DepositEventType.TOKEN_SELECTED,
21436
21583
  ...withMethod,
21437
21584
  data: { object: selection.data }
21438
21585
  });
@@ -21440,7 +21587,7 @@ function useForwardDepositEvents(onEvent) {
21440
21587
  case "wallet":
21441
21588
  onEventRef.current?.({
21442
21589
  ...base,
21443
- type: import_core33.DepositEventType.WALLET_SELECTED,
21590
+ type: import_core32.DepositEventType.WALLET_SELECTED,
21444
21591
  ...withMethod,
21445
21592
  data: { object: selection.data }
21446
21593
  });
@@ -21448,7 +21595,7 @@ function useForwardDepositEvents(onEvent) {
21448
21595
  case "provider":
21449
21596
  onEventRef.current?.({
21450
21597
  ...base,
21451
- type: import_core33.DepositEventType.PROVIDER_SELECTED,
21598
+ type: import_core32.DepositEventType.PROVIDER_SELECTED,
21452
21599
  ...withMethod,
21453
21600
  data: { object: selection.data }
21454
21601
  });
@@ -21502,8 +21649,8 @@ function useAllowedCountry(publishableKey) {
21502
21649
  }
21503
21650
 
21504
21651
  // src/hooks/use-address-validation.ts
21505
- var import_react_query16 = require("@tanstack/react-query");
21506
- var import_core34 = require("@unifold/core");
21652
+ var import_react_query15 = require("@tanstack/react-query");
21653
+ var import_core33 = require("@unifold/core");
21507
21654
  function useAddressValidation({
21508
21655
  recipientAddress,
21509
21656
  destinationChainType,
@@ -21514,7 +21661,7 @@ function useAddressValidation({
21514
21661
  refetchOnMount = false
21515
21662
  }) {
21516
21663
  const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
21517
- const { data, isLoading, error } = (0, import_react_query16.useQuery)({
21664
+ const { data, isLoading, error } = (0, import_react_query15.useQuery)({
21518
21665
  queryKey: [
21519
21666
  "unifold",
21520
21667
  "addressValidation",
@@ -21523,7 +21670,7 @@ function useAddressValidation({
21523
21670
  destinationChainId,
21524
21671
  destinationTokenAddress
21525
21672
  ],
21526
- queryFn: () => (0, import_core34.verifyRecipientAddress)(
21673
+ queryFn: () => (0, import_core33.verifyRecipientAddress)(
21527
21674
  {
21528
21675
  chain_type: destinationChainType,
21529
21676
  chain_id: destinationChainId,
@@ -21806,7 +21953,7 @@ function PoweredByUnifold({
21806
21953
  }
21807
21954
 
21808
21955
  // src/components/deposits/DepositsModal.tsx
21809
- var import_core35 = require("@unifold/core");
21956
+ var import_core34 = require("@unifold/core");
21810
21957
  var import_jsx_runtime54 = require("react/jsx-runtime");
21811
21958
  function DepositsModal({
21812
21959
  open,
@@ -21825,7 +21972,7 @@ function DepositsModal({
21825
21972
  if (!open || !userId) return;
21826
21973
  const fetchExecutions = async () => {
21827
21974
  try {
21828
- const response = await (0, import_core35.queryExecutions)(userId, publishableKey, import_core35.ActionType.Deposit);
21975
+ const response = await (0, import_core34.queryExecutions)(userId, publishableKey, import_core34.ActionType.Deposit);
21829
21976
  const sorted = [...response.data].sort((a, b) => {
21830
21977
  const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
21831
21978
  const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
@@ -22960,11 +23107,11 @@ var TooltipContent = React37.forwardRef(({ className, sideOffset = 4, ...props }
22960
23107
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
22961
23108
 
22962
23109
  // src/components/deposits/TransferCryptoSingleInput.tsx
22963
- var import_core37 = require("@unifold/core");
23110
+ var import_core36 = require("@unifold/core");
22964
23111
 
22965
23112
  // src/hooks/use-hypercore-activation.ts
22966
- var import_react_query17 = require("@tanstack/react-query");
22967
- var import_core36 = require("@unifold/core");
23113
+ var import_react_query16 = require("@tanstack/react-query");
23114
+ var import_core35 = require("@unifold/core");
22968
23115
 
22969
23116
  // src/lib/constants.ts
22970
23117
  var HYPERCORE_CHAIN_ID = "1337";
@@ -22982,9 +23129,9 @@ function useHypercoreActivation(params) {
22982
23129
  const recipient = recipientAddress?.trim() ?? "";
22983
23130
  const source = sourceAddress?.trim() ?? "";
22984
23131
  const hasAddresses = !!recipient && !!source;
22985
- const { data, isLoading } = (0, import_react_query17.useQuery)({
23132
+ const { data, isLoading } = (0, import_react_query16.useQuery)({
22986
23133
  queryKey: ["unifold", "hypercoreActivation", source, recipient, publishableKey],
22987
- queryFn: () => (0, import_core36.checkHypercoreActivation)(
23134
+ queryFn: () => (0, import_core35.checkHypercoreActivation)(
22988
23135
  {
22989
23136
  source_address: source,
22990
23137
  recipient_address: recipient
@@ -23137,7 +23284,7 @@ function TransferCryptoSingleInput({
23137
23284
  (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
23138
23285
  ) : void 0;
23139
23286
  const currentChainType = currentChainData?.chain_type || "ethereum";
23140
- const currentWallet = (0, import_core37.getWalletByChainType)(wallets, currentChainType);
23287
+ const currentWallet = (0, import_core36.getWalletByChainType)(wallets, currentChainType);
23141
23288
  const depositAddress = currentWallet?.address || "";
23142
23289
  const {
23143
23290
  executions: depositExecutions,
@@ -23379,7 +23526,7 @@ function TransferCryptoSingleInput({
23379
23526
  className: "uf-text-sm uf-font-semibold",
23380
23527
  style: { color: components.card.titleColor, fontFamily: fonts.semibold },
23381
23528
  children: [
23382
- checkoutQuote.isStablecoin ? (0, import_core37.formatStablecoinAmount)(
23529
+ checkoutQuote.isStablecoin ? (0, import_core36.formatStablecoinAmount)(
23383
23530
  checkoutQuote.sourceAmount,
23384
23531
  checkoutQuote.sourceTokenDecimals
23385
23532
  ) : (Number(checkoutQuote.sourceAmount) / 10 ** checkoutQuote.sourceTokenDecimals).toFixed(Math.min(checkoutQuote.sourceTokenDecimals, 6)),
@@ -23879,7 +24026,7 @@ var SelectSeparator = React38.forwardRef(({ className, ...props }, ref) => /* @_
23879
24026
  SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
23880
24027
 
23881
24028
  // src/components/deposits/TransferCryptoDoubleInput.tsx
23882
- var import_core38 = require("@unifold/core");
24029
+ var import_core37 = require("@unifold/core");
23883
24030
  var import_jsx_runtime62 = require("react/jsx-runtime");
23884
24031
  var getChainKey3 = (chainId, chainType) => {
23885
24032
  return `${chainType}:${chainId}`;
@@ -23986,7 +24133,7 @@ function TransferCryptoDoubleInput({
23986
24133
  (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
23987
24134
  ) : void 0;
23988
24135
  const currentChainType = currentChainData?.chain_type || "ethereum";
23989
- const currentWallet = (0, import_core38.getWalletByChainType)(wallets, currentChainType);
24136
+ const currentWallet = (0, import_core37.getWalletByChainType)(wallets, currentChainType);
23990
24137
  const depositAddress = currentWallet?.address || "";
23991
24138
  const {
23992
24139
  executions: depositExecutions,
@@ -24556,7 +24703,7 @@ function TransferCryptoDoubleInput({
24556
24703
  // src/components/deposits/WalletConnect.tsx
24557
24704
  var React39 = __toESM(require("react"));
24558
24705
  var import_lucide_react39 = require("lucide-react");
24559
- var import_core42 = require("@unifold/core");
24706
+ var import_core41 = require("@unifold/core");
24560
24707
 
24561
24708
  // src/lib/wallet-errors.ts
24562
24709
  function messageOf(err) {
@@ -24736,7 +24883,7 @@ function describeWalletError(err, action) {
24736
24883
  }
24737
24884
 
24738
24885
  // src/lib/send-hypercore.ts
24739
- var import_core39 = require("@unifold/core");
24886
+ var import_core38 = require("@unifold/core");
24740
24887
  function isHypercoreChain(chainId) {
24741
24888
  return chainId === HYPERCORE_CHAIN_ID;
24742
24889
  }
@@ -24747,7 +24894,7 @@ async function sendHypercoreEvmTransfer(params) {
24747
24894
  params: []
24748
24895
  });
24749
24896
  const activeChainId = String(parseInt(currentChainHex, 16));
24750
- const buildResult = await (0, import_core39.buildHypercoreTransaction)(
24897
+ const buildResult = await (0, import_core38.buildHypercoreTransaction)(
24751
24898
  {
24752
24899
  signature_chain_id: activeChainId,
24753
24900
  recipient_address: recipientAddress,
@@ -24760,7 +24907,7 @@ async function sendHypercoreEvmTransfer(params) {
24760
24907
  method: "eth_signTypedData_v4",
24761
24908
  params: [fromAddress, JSON.stringify(buildResult.typed_data)]
24762
24909
  });
24763
- await (0, import_core39.sendHypercoreTransaction)(
24910
+ await (0, import_core38.sendHypercoreTransaction)(
24764
24911
  {
24765
24912
  action_payload: buildResult.action_payload,
24766
24913
  signature,
@@ -24772,8 +24919,8 @@ async function sendHypercoreEvmTransfer(params) {
24772
24919
  }
24773
24920
 
24774
24921
  // src/hooks/use-deposit-quote.ts
24775
- var import_react_query18 = require("@tanstack/react-query");
24776
- var import_core40 = require("@unifold/core");
24922
+ var import_react_query17 = require("@tanstack/react-query");
24923
+ var import_core39 = require("@unifold/core");
24777
24924
  function useDepositQuote(params) {
24778
24925
  const {
24779
24926
  publishableKey,
@@ -24799,7 +24946,7 @@ function useDepositQuote(params) {
24799
24946
  ...adjustForSlippage ? { adjust_for_slippage: true } : {},
24800
24947
  ...stablecoinParity ? { stablecoin_parity: true } : {}
24801
24948
  };
24802
- return (0, import_react_query18.useQuery)({
24949
+ return (0, import_react_query17.useQuery)({
24803
24950
  queryKey: [
24804
24951
  "unifold",
24805
24952
  "depositQuote",
@@ -24814,7 +24961,7 @@ function useDepositQuote(params) {
24814
24961
  stablecoinParity,
24815
24962
  publishableKey
24816
24963
  ],
24817
- queryFn: () => (0, import_core40.getDepositQuote)(request, publishableKey),
24964
+ queryFn: () => (0, import_core39.getDepositQuote)(request, publishableKey),
24818
24965
  enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
24819
24966
  staleTime: 3e4,
24820
24967
  gcTime: 5 * 6e4,
@@ -24827,15 +24974,15 @@ function useDepositQuote(params) {
24827
24974
  }
24828
24975
 
24829
24976
  // src/hooks/use-external-wallets.ts
24830
- var import_react_query19 = require("@tanstack/react-query");
24831
- var import_core41 = require("@unifold/core");
24977
+ var import_react_query18 = require("@tanstack/react-query");
24978
+ var import_core40 = require("@unifold/core");
24832
24979
  function useExternalWallets({
24833
24980
  publishableKey,
24834
24981
  enabled = true
24835
24982
  }) {
24836
- const { data: wallets = [], isLoading } = (0, import_react_query19.useQuery)({
24983
+ const { data: wallets = [], isLoading } = (0, import_react_query18.useQuery)({
24837
24984
  queryKey: ["unifold", "external-wallets", publishableKey],
24838
- queryFn: () => (0, import_core41.getExternalWallets)(publishableKey).then((res) => res.data),
24985
+ queryFn: () => (0, import_core40.getExternalWallets)(publishableKey).then((res) => res.data),
24839
24986
  enabled: enabled && !!publishableKey,
24840
24987
  staleTime: 1e3 * 60 * 30,
24841
24988
  refetchOnMount: false,
@@ -26246,7 +26393,7 @@ function WalletConnect({
26246
26393
  try {
26247
26394
  const cleanedAmountUsd = amountUsd?.replace(/[^0-9.]/g, "") ?? "";
26248
26395
  const forwardedAmountUsd = parseFloat(cleanedAmountUsd) > 0 ? cleanedAmountUsd : void 0;
26249
- const res = await (0, import_core42.getWalletMobileDeepLink)(
26396
+ const res = await (0, import_core41.getWalletMobileDeepLink)(
26250
26397
  wallet.id,
26251
26398
  depositAddresses,
26252
26399
  publishableKey,
@@ -26578,7 +26725,7 @@ function WalletConnect({
26578
26725
  destination_chain_type: activeDepositWallet.destination_chain_type,
26579
26726
  ...productType ? { product_type: productType } : {}
26580
26727
  };
26581
- const response = await (0, import_core42.getSupportedDepositTokens)(publishableKey, options);
26728
+ const response = await (0, import_core41.getSupportedDepositTokens)(publishableKey, options);
26582
26729
  if (cancelled) return;
26583
26730
  const supportedToken = response.data.find(
26584
26731
  (t2) => t2.symbol.toLowerCase() === token.symbol.toLowerCase()
@@ -26606,7 +26753,7 @@ function WalletConnect({
26606
26753
  setIsLoading(true);
26607
26754
  setError(null);
26608
26755
  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;
26609
- (0, import_core42.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
26756
+ (0, import_core41.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
26610
26757
  if (cancelled) return;
26611
26758
  const nonZero = response.balances.filter((b) => b.amount !== "0");
26612
26759
  const defaultSource = {
@@ -26899,7 +27046,7 @@ function WalletConnect({
26899
27046
  if (!provider.publicKey) await provider.connect();
26900
27047
  const isNative = token.token_address === "native" || token.token_address === "So11111111111111111111111111111111111111112" || token.token_address === "";
26901
27048
  const smallestUnit = isNative ? decimalToSmallestUnit(amountStr, 9) : decimalToSmallestUnit(amountStr, token.decimals);
26902
- const buildResp = await (0, import_core42.buildSolanaTransaction)(
27049
+ const buildResp = await (0, import_core41.buildSolanaTransaction)(
26903
27050
  {
26904
27051
  chain_id: "mainnet",
26905
27052
  token_address: token.token_address === "" ? "native" : token.token_address,
@@ -26921,7 +27068,7 @@ function WalletConnect({
26921
27068
  const ser = signed.serialize();
26922
27069
  let bs = "";
26923
27070
  for (let i = 0; i < ser.length; i++) bs += String.fromCharCode(ser[i]);
26924
- const resp = await (0, import_core42.sendSolanaTransaction)(
27071
+ const resp = await (0, import_core41.sendSolanaTransaction)(
26925
27072
  { chain_id: "mainnet", signed_transaction: btoa(bs) },
26926
27073
  publishableKey
26927
27074
  );
@@ -26967,7 +27114,7 @@ function WalletConnect({
26967
27114
  } else if (isHypercoreToken) {
26968
27115
  let sendAmount = tokenAmount;
26969
27116
  try {
26970
- const activation = await (0, import_core42.checkHypercoreActivation)(
27117
+ const activation = await (0, import_core41.checkHypercoreActivation)(
26971
27118
  { source_address: walletInfo.address, recipient_address: recipientAddress },
26972
27119
  publishableKey
26973
27120
  );
@@ -26994,7 +27141,11 @@ function WalletConnect({
26994
27141
  chain: String(token.chain_id),
26995
27142
  network: token.network,
26996
27143
  token: token.symbol ?? token.token_address,
26997
- currency: token.currency
27144
+ currency: token.currency,
27145
+ // No execution exists yet — it's created when this send lands on the
27146
+ // wallet. The wallet id is what that execution will carry, so it's
27147
+ // how a send that never completes is matched to what followed.
27148
+ deposit_wallet_id: activeDepositWallet?.id
26998
27149
  });
26999
27150
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
27000
27151
  setHasSignedTransaction(true);
@@ -27324,8 +27475,8 @@ function WalletConnect({
27324
27475
  ] }) });
27325
27476
  }
27326
27477
  if (view === "mobile_deposit_status" && latestDepositExecution) {
27327
- const isComplete = latestDepositExecution.status === import_core42.ExecutionStatus.SUCCEEDED;
27328
- const isFailed = latestDepositExecution.status === import_core42.ExecutionStatus.FAILED;
27478
+ const isComplete = latestDepositExecution.status === import_core41.ExecutionStatus.SUCCEEDED;
27479
+ const isFailed = latestDepositExecution.status === import_core41.ExecutionStatus.FAILED;
27329
27480
  const title = isComplete ? t.paymentComplete : isFailed ? t.paymentFailed : t.paymentProcessing;
27330
27481
  return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(AccentColorOverride, { accentColor: preConnectAccent, accentForeground: preConnectFg, children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { style: viewTransitionStyle, children: [
27331
27482
  /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
@@ -27584,7 +27735,7 @@ function DepositModal({
27584
27735
  const applePaySubTitle = applePaySubTitleProp ?? t.applePayMenu.subtitle;
27585
27736
  const googlePayTitle = googlePayTitleProp ?? t.googlePayMenu.title;
27586
27737
  const googlePaySubTitle = googlePaySubTitleProp ?? t.googlePayMenu.subtitle;
27587
- const { track, startSession, endSession, getSessionId, subscribe } = useAnalytics();
27738
+ const { track, startSession, endSession, getSessionId, setUserId, subscribe } = useAnalytics();
27588
27739
  const normalizedPrefilledAmountUsd = (0, import_react31.useMemo)(
27589
27740
  () => normalizePrefilledUsdAmount(prefilledAmountUsd),
27590
27741
  [prefilledAmountUsd]
@@ -27592,6 +27743,7 @@ function DepositModal({
27592
27743
  const analyticsMethod = (method) => method === "transfer" ? "transfer_crypto" : method;
27593
27744
  const journeyActiveRef = (0, import_react31.useRef)(false);
27594
27745
  const journeySessionIdRef = (0, import_react31.useRef)(void 0);
27746
+ const journeyExternalUserIdRef = (0, import_react31.useRef)(void 0);
27595
27747
  const externalUserId = userId || void 0;
27596
27748
  const emitEvent = (0, import_react31.useCallback)(
27597
27749
  (event) => onEvent?.({ ...event, externalUserId }),
@@ -27602,8 +27754,8 @@ function DepositModal({
27602
27754
  (method) => {
27603
27755
  track("payment_method_selected", { method: analyticsMethod(method), flow_type: "deposit" });
27604
27756
  emitEvent({
27605
- id: (0, import_core43.generatePrefixedKSUID)("sevt"),
27606
- type: import_core43.DepositEventType.METHOD_SELECTED,
27757
+ id: (0, import_core42.generatePrefixedKSUID)("sevt"),
27758
+ type: import_core42.DepositEventType.METHOD_SELECTED,
27607
27759
  created: Math.floor(Date.now() / 1e3),
27608
27760
  sessionId: getSessionId() ?? "",
27609
27761
  method,
@@ -27619,6 +27771,9 @@ function DepositModal({
27619
27771
  method: analyticsMethod(method),
27620
27772
  flow_type: "deposit",
27621
27773
  amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
27774
+ // The one high-cardinality field we do send: the join key from a
27775
+ // funnel session back to the execution row it produced.
27776
+ execution_id: data.executionId ?? execution?.id,
27622
27777
  // Flat, low-cardinality execution dimensions for PostHog breakdowns
27623
27778
  // (precise/opaque fields like base units, addresses, tx hashes live in
27624
27779
  // the onEvent DirectExecution instead).
@@ -27646,6 +27801,7 @@ function DepositModal({
27646
27801
  method: analyticsMethod(method),
27647
27802
  flow_type: "deposit",
27648
27803
  error_code: error.code,
27804
+ execution_id: execution?.id,
27649
27805
  failure_reason: execution?.failureReason ?? void 0,
27650
27806
  status: execution?.status,
27651
27807
  source_chain_type: execution?.sourceChainType,
@@ -27655,8 +27811,8 @@ function DepositModal({
27655
27811
  });
27656
27812
  onDepositError?.({ ...error, method });
27657
27813
  emitEvent({
27658
- id: (0, import_core43.generatePrefixedKSUID)("sevt"),
27659
- type: import_core43.DepositEventType.FLOW_FAILED,
27814
+ id: (0, import_core42.generatePrefixedKSUID)("sevt"),
27815
+ type: import_core42.DepositEventType.FLOW_FAILED,
27660
27816
  created: Math.floor(Date.now() / 1e3),
27661
27817
  sessionId: getSessionId() ?? "",
27662
27818
  method,
@@ -27762,7 +27918,7 @@ function DepositModal({
27762
27918
  const [integrationExchanges, setIntegrationExchanges] = (0, import_react31.useState)([]);
27763
27919
  (0, import_react31.useEffect)(() => {
27764
27920
  if (!showConnectExchange || !open) return;
27765
- (0, import_core43.getIntegrationExchanges)(
27921
+ (0, import_core42.getIntegrationExchanges)(
27766
27922
  publishableKey,
27767
27923
  userIpInfo?.alpha2 ? {
27768
27924
  country_code: userIpInfo.alpha2,
@@ -27773,13 +27929,13 @@ function DepositModal({
27773
27929
  }, [showConnectExchange, open, publishableKey, userIpInfo?.alpha2, userIpInfo?.subdivisionCode]);
27774
27930
  const [connectedExchange, setConnectedExchange] = (0, import_react31.useState)(() => {
27775
27931
  if (!showConnectExchange) return null;
27776
- const stored = getStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE);
27932
+ const stored = getStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE);
27777
27933
  if (!stored) return null;
27778
27934
  return { name: "Coinbase", iconUrl: void 0, balanceUsd: null, isLoading: true };
27779
27935
  });
27780
27936
  (0, import_react31.useEffect)(() => {
27781
27937
  if (!showConnectExchange || !open || view !== "main") return;
27782
- const stored = getStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE);
27938
+ const stored = getStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE);
27783
27939
  if (!stored) {
27784
27940
  setConnectedExchange(null);
27785
27941
  return;
@@ -27799,24 +27955,24 @@ function DepositModal({
27799
27955
  }) : null;
27800
27956
  setConnectedExchange((prev) => prev ? { ...prev, balanceUsd, isLoading: false } : null);
27801
27957
  };
27802
- (0, import_core43.getIntegrationHoldings)(import_core43.IntegrationProvider.COINBASE, stored.access_token, publishableKey).then(processHoldings).catch(async () => {
27958
+ (0, import_core42.getIntegrationHoldings)(import_core42.IntegrationProvider.COINBASE, stored.access_token, publishableKey).then(processHoldings).catch(async () => {
27803
27959
  try {
27804
- const refreshResult = await (0, import_core43.refreshIntegrationToken)(stored.access_token, publishableKey);
27805
- if (!getStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE)) return;
27960
+ const refreshResult = await (0, import_core42.refreshIntegrationToken)(stored.access_token, publishableKey);
27961
+ if (!getStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE)) return;
27806
27962
  setStoredIntegrationToken({
27807
- integration_provider: import_core43.IntegrationProvider.COINBASE,
27963
+ integration_provider: import_core42.IntegrationProvider.COINBASE,
27808
27964
  access_token: refreshResult.access_token,
27809
27965
  expires_at: refreshResult.expires_at
27810
27966
  });
27811
- const retryResult = await (0, import_core43.getIntegrationHoldings)(
27812
- import_core43.IntegrationProvider.COINBASE,
27967
+ const retryResult = await (0, import_core42.getIntegrationHoldings)(
27968
+ import_core42.IntegrationProvider.COINBASE,
27813
27969
  refreshResult.access_token,
27814
27970
  publishableKey
27815
27971
  );
27816
27972
  processHoldings(retryResult);
27817
27973
  } catch {
27818
- if (!getStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE)) return;
27819
- clearStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE);
27974
+ if (!getStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE)) return;
27975
+ clearStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE);
27820
27976
  setConnectedExchange(null);
27821
27977
  }
27822
27978
  });
@@ -27824,7 +27980,7 @@ function DepositModal({
27824
27980
  (0, import_react31.useEffect)(() => {
27825
27981
  if (!connectedExchange || integrationExchanges.length === 0) return;
27826
27982
  const cbExchange = integrationExchanges.find(
27827
- (e) => e.service_provider === import_core43.IntegrationProvider.COINBASE
27983
+ (e) => e.service_provider === import_core42.IntegrationProvider.COINBASE
27828
27984
  );
27829
27985
  const iconUrl = cbExchange?.icon_urls?.find((u) => u.format === "svg")?.url || cbExchange?.icon_urls?.find((u) => u.format === "png")?.url || cbExchange?.icon_url;
27830
27986
  if (iconUrl && iconUrl !== connectedExchange.iconUrl) {
@@ -27943,7 +28099,7 @@ function DepositModal({
27943
28099
  if (view !== "tracker" || !userId) return;
27944
28100
  const fetchExecutions = async () => {
27945
28101
  try {
27946
- const response = await (0, import_core43.queryExecutions)(userId, publishableKey, import_core43.ActionType.Deposit);
28102
+ const response = await (0, import_core42.queryExecutions)(userId, publishableKey, import_core42.ActionType.Deposit);
27947
28103
  const sorted = [...response.data].sort((a, b) => {
27948
28104
  const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
27949
28105
  const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
@@ -27999,7 +28155,7 @@ function DepositModal({
27999
28155
  const template = errors[code] ?? addressValidationMessages.defaultError;
28000
28156
  return interpolate(template, metadata);
28001
28157
  };
28002
- const walletsRecipientError = (0, import_core43.isDepositAddressValidationError)(walletsError) ? walletsError.message : null;
28158
+ const walletsRecipientError = (0, import_core42.isDepositAddressValidationError)(walletsError) ? walletsError.message : null;
28003
28159
  const isRecipientAddressInvalid = isAddressValid === false || walletsRecipientError !== null;
28004
28160
  const recipientInvalidMessage = getAddressValidationErrorMessage(
28005
28161
  addressFailureMessage ?? walletsRecipientError,
@@ -28057,11 +28213,11 @@ function DepositModal({
28057
28213
  if (view === "wallet_connect" && sessionOpenedFromMenu) setView("main");
28058
28214
  };
28059
28215
  const handleExchangeDisconnect = () => {
28060
- const stored = getStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE);
28216
+ const stored = getStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE);
28061
28217
  if (stored) {
28062
- (0, import_core43.revokeIntegrationToken)(stored.access_token, publishableKey);
28218
+ (0, import_core42.revokeIntegrationToken)(stored.access_token, publishableKey);
28063
28219
  }
28064
- clearStoredIntegrationToken(import_core43.IntegrationProvider.COINBASE);
28220
+ clearStoredIntegrationToken(import_core42.IntegrationProvider.COINBASE);
28065
28221
  setConnectedExchange(null);
28066
28222
  if (view === "coinbase_connect" && sessionOpenedFromMenu) setView("main");
28067
28223
  };
@@ -28074,8 +28230,10 @@ function DepositModal({
28074
28230
  const beginJourney = (0, import_react31.useCallback)(() => {
28075
28231
  journeySessionIdRef.current = startSession();
28076
28232
  journeyActiveRef.current = true;
28233
+ journeyExternalUserIdRef.current = userId;
28234
+ setUserId(null);
28077
28235
  track("widget_opened", { flow_type: "deposit" });
28078
- }, [startSession, track]);
28236
+ }, [startSession, track, setUserId, userId]);
28079
28237
  const handleClose = () => {
28080
28238
  finalizeJourney();
28081
28239
  onOpenChange(false);
@@ -28100,6 +28258,11 @@ function DepositModal({
28100
28258
  }
28101
28259
  beginJourney();
28102
28260
  }, [open]);
28261
+ (0, import_react31.useLayoutEffect)(() => {
28262
+ if (!open || journeyExternalUserIdRef.current === userId) return;
28263
+ journeyExternalUserIdRef.current = userId;
28264
+ setUserId(null);
28265
+ }, [open, userId, setUserId]);
28103
28266
  (0, import_react31.useLayoutEffect)(() => {
28104
28267
  if (!open) return;
28105
28268
  if (resetViewTimeoutRef.current) {
@@ -29011,6 +29174,7 @@ function DepositModal({
29011
29174
  destinationChainType,
29012
29175
  destinationChainId,
29013
29176
  destinationTokenAddress,
29177
+ contractCalls,
29014
29178
  cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
29015
29179
  view: cashAppView,
29016
29180
  onViewChange: setCashAppView,
@@ -29112,12 +29276,12 @@ var import_lucide_react41 = require("lucide-react");
29112
29276
 
29113
29277
  // src/hooks/use-forward-checkout-events.ts
29114
29278
  var import_react32 = require("react");
29115
- var import_core44 = require("@unifold/core");
29279
+ var import_core43 = require("@unifold/core");
29116
29280
  var import_analytics2 = require("@unifold/analytics");
29117
29281
  var WALLET_CONNECTION_TYPES2 = {
29118
- started: import_core44.CheckoutEventType.WALLET_CONNECTION_STARTED,
29119
- connected: import_core44.CheckoutEventType.WALLET_CONNECTED,
29120
- failed: import_core44.CheckoutEventType.WALLET_CONNECTION_FAILED
29282
+ started: import_core43.CheckoutEventType.WALLET_CONNECTION_STARTED,
29283
+ connected: import_core43.CheckoutEventType.WALLET_CONNECTED,
29284
+ failed: import_core43.CheckoutEventType.WALLET_CONNECTION_FAILED
29121
29285
  };
29122
29286
  function checkoutMethodFromAnalytics(method) {
29123
29287
  if (method !== "transfer_crypto" && method !== "transfer" && method !== "wallet_connect") {
@@ -29143,7 +29307,7 @@ function useForwardCheckoutEvents(onEvent, journeySessionId) {
29143
29307
  if (event.event === "flow_started") {
29144
29308
  onEventRef.current?.({
29145
29309
  ...base,
29146
- type: import_core44.CheckoutEventType.FLOW_STARTED,
29310
+ type: import_core43.CheckoutEventType.FLOW_STARTED,
29147
29311
  ...withMethod,
29148
29312
  data: {
29149
29313
  object: {
@@ -29171,7 +29335,7 @@ function useForwardCheckoutEvents(onEvent, journeySessionId) {
29171
29335
  case "token":
29172
29336
  onEventRef.current?.({
29173
29337
  ...base,
29174
- type: import_core44.CheckoutEventType.TOKEN_SELECTED,
29338
+ type: import_core43.CheckoutEventType.TOKEN_SELECTED,
29175
29339
  ...withMethod,
29176
29340
  data: { object: selection.data }
29177
29341
  });
@@ -29179,7 +29343,7 @@ function useForwardCheckoutEvents(onEvent, journeySessionId) {
29179
29343
  case "wallet":
29180
29344
  onEventRef.current?.({
29181
29345
  ...base,
29182
- type: import_core44.CheckoutEventType.WALLET_SELECTED,
29346
+ type: import_core43.CheckoutEventType.WALLET_SELECTED,
29183
29347
  ...withMethod,
29184
29348
  data: { object: selection.data }
29185
29349
  });
@@ -29195,14 +29359,14 @@ function useForwardCheckoutEvents(onEvent, journeySessionId) {
29195
29359
  }
29196
29360
 
29197
29361
  // src/hooks/use-payment-intent.ts
29198
- var import_react_query20 = require("@tanstack/react-query");
29199
- var import_core45 = require("@unifold/core");
29362
+ var import_react_query19 = require("@tanstack/react-query");
29363
+ var import_core44 = require("@unifold/core");
29200
29364
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "expired", "refunded", "canceled"]);
29201
29365
  function usePaymentIntent(params) {
29202
29366
  const { clientSecret, publishableKey, enabled = true, pollingInterval = 3e3 } = params;
29203
- return (0, import_react_query20.useQuery)({
29367
+ return (0, import_react_query19.useQuery)({
29204
29368
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
29205
- queryFn: () => (0, import_core45.retrievePaymentIntent)(clientSecret, publishableKey),
29369
+ queryFn: () => (0, import_core44.retrievePaymentIntent)(clientSecret, publishableKey),
29206
29370
  enabled: enabled && !!clientSecret && !!publishableKey,
29207
29371
  staleTime: 0,
29208
29372
  refetchInterval: (query) => {
@@ -29218,7 +29382,7 @@ function usePaymentIntent(params) {
29218
29382
  }
29219
29383
 
29220
29384
  // src/components/checkout/CheckoutModal.tsx
29221
- var import_core46 = require("@unifold/core");
29385
+ var import_core45 = require("@unifold/core");
29222
29386
  var import_jsx_runtime72 = require("react/jsx-runtime");
29223
29387
  function mapToCheckoutPaymentIntent(pi) {
29224
29388
  return {
@@ -29321,8 +29485,8 @@ function CheckoutModal({
29321
29485
  flow_type: "checkout"
29322
29486
  });
29323
29487
  emitEvent({
29324
- id: (0, import_core46.generatePrefixedKSUID)("sevt"),
29325
- type: import_core46.CheckoutEventType.METHOD_SELECTED,
29488
+ id: (0, import_core45.generatePrefixedKSUID)("sevt"),
29489
+ type: import_core45.CheckoutEventType.METHOD_SELECTED,
29326
29490
  created: Math.floor(Date.now() / 1e3),
29327
29491
  sessionId: getSessionId() ?? "",
29328
29492
  method,
@@ -29340,8 +29504,8 @@ function CheckoutModal({
29340
29504
  });
29341
29505
  onCheckoutError?.(error);
29342
29506
  emitEvent({
29343
- id: (0, import_core46.generatePrefixedKSUID)("sevt"),
29344
- type: import_core46.CheckoutEventType.FLOW_FAILED,
29507
+ id: (0, import_core45.generatePrefixedKSUID)("sevt"),
29508
+ type: import_core45.CheckoutEventType.FLOW_FAILED,
29345
29509
  created: Math.floor(Date.now() / 1e3),
29346
29510
  sessionId: journeySessionIdRef.current ?? getSessionId() ?? "",
29347
29511
  method: error.method,
@@ -29371,14 +29535,17 @@ function CheckoutModal({
29371
29535
  flowCompletedRef.current = true;
29372
29536
  track("flow_completed", {
29373
29537
  flow_type: "checkout",
29538
+ // Checkout has no direct execution; the intent is what a funnel
29539
+ // session joins back to.
29540
+ payment_intent_id: data.paymentIntentId,
29374
29541
  ...method ? { method: method === "transfer" ? "transfer_crypto" : method } : {}
29375
29542
  });
29376
29543
  }
29377
29544
  if (isSucceeded && richIntent) {
29378
29545
  const createdSec = data.paymentIntent?.updated_at ? Math.floor(new Date(data.paymentIntent.updated_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3);
29379
29546
  emitEvent({
29380
- id: (0, import_core46.generatePrefixedKSUID)("sevt"),
29381
- type: import_core46.CheckoutEventType.PAYMENT_INTENT_SUCCEEDED,
29547
+ id: (0, import_core45.generatePrefixedKSUID)("sevt"),
29548
+ type: import_core45.CheckoutEventType.PAYMENT_INTENT_SUCCEEDED,
29382
29549
  // A poll can land after the journey ends, when getSessionId() is
29383
29550
  // either empty or already another flow's. The payment belongs to
29384
29551
  // the journey that started it.
@@ -29591,7 +29758,7 @@ function CheckoutModal({
29591
29758
  journeySessionIdRef.current = startSession();
29592
29759
  journeyActiveRef.current = true;
29593
29760
  flowCompletedRef.current = false;
29594
- setUserId(null);
29761
+ setUserId(paymentIntentUserId ?? null);
29595
29762
  track("widget_opened", { flow_type: "checkout" });
29596
29763
  if (resetViewTimeoutRef.current) {
29597
29764
  clearTimeout(resetViewTimeoutRef.current);
@@ -30032,16 +30199,16 @@ function CheckoutModal({
30032
30199
  }
30033
30200
 
30034
30201
  // src/components/withdrawals/WithdrawModal.tsx
30035
- var import_react39 = require("react");
30202
+ var import_react38 = require("react");
30036
30203
  var import_lucide_react44 = require("lucide-react");
30037
30204
 
30038
30205
  // src/hooks/use-supported-destination-tokens.ts
30039
- var import_react_query21 = require("@tanstack/react-query");
30040
- var import_core47 = require("@unifold/core");
30206
+ var import_react_query20 = require("@tanstack/react-query");
30207
+ var import_core46 = require("@unifold/core");
30041
30208
  function useSupportedDestinationTokens(publishableKey, enabled = true) {
30042
- return (0, import_react_query21.useQuery)({
30209
+ return (0, import_react_query20.useQuery)({
30043
30210
  queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
30044
- queryFn: () => (0, import_core47.getSupportedDestinationTokens)(publishableKey),
30211
+ queryFn: () => (0, import_core46.getSupportedDestinationTokens)(publishableKey),
30045
30212
  staleTime: 1e3 * 60 * 5,
30046
30213
  gcTime: 1e3 * 60 * 30,
30047
30214
  refetchOnMount: false,
@@ -30071,8 +30238,8 @@ function useDefaultDestinationToken({
30071
30238
  }
30072
30239
 
30073
30240
  // src/hooks/use-source-token-validation.ts
30074
- var import_react_query22 = require("@tanstack/react-query");
30075
- var import_core48 = require("@unifold/core");
30241
+ var import_react_query21 = require("@tanstack/react-query");
30242
+ var import_core47 = require("@unifold/core");
30076
30243
  function useSourceTokenValidation(params) {
30077
30244
  const {
30078
30245
  sourceChainType,
@@ -30083,7 +30250,7 @@ function useSourceTokenValidation(params) {
30083
30250
  enabled = true
30084
30251
  } = params;
30085
30252
  const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
30086
- return (0, import_react_query22.useQuery)({
30253
+ return (0, import_react_query21.useQuery)({
30087
30254
  queryKey: [
30088
30255
  "unifold",
30089
30256
  "sourceTokenValidation",
@@ -30093,7 +30260,7 @@ function useSourceTokenValidation(params) {
30093
30260
  publishableKey
30094
30261
  ],
30095
30262
  queryFn: async () => {
30096
- const res = await (0, import_core48.getSupportedDepositTokens)(publishableKey);
30263
+ const res = await (0, import_core47.getSupportedDepositTokens)(publishableKey);
30097
30264
  let matchedMinUsd = null;
30098
30265
  let matchedProcessingTime = null;
30099
30266
  let matchedSlippage = null;
@@ -30133,12 +30300,12 @@ function useSourceTokenValidation(params) {
30133
30300
  }
30134
30301
 
30135
30302
  // src/hooks/use-address-balance.ts
30136
- var import_react_query23 = require("@tanstack/react-query");
30137
- var import_core49 = require("@unifold/core");
30303
+ var import_react_query22 = require("@tanstack/react-query");
30304
+ var import_core48 = require("@unifold/core");
30138
30305
  function useAddressBalance(params) {
30139
30306
  const { address, chainType, chainId, tokenAddress, publishableKey, enabled = true } = params;
30140
30307
  const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
30141
- return (0, import_react_query23.useQuery)({
30308
+ return (0, import_react_query22.useQuery)({
30142
30309
  queryKey: [
30143
30310
  "unifold",
30144
30311
  "addressBalance",
@@ -30149,7 +30316,7 @@ function useAddressBalance(params) {
30149
30316
  publishableKey
30150
30317
  ],
30151
30318
  queryFn: async () => {
30152
- const res = await (0, import_core49.getAddressBalance)(
30319
+ const res = await (0, import_core48.getAddressBalance)(
30153
30320
  address,
30154
30321
  chainType,
30155
30322
  chainId,
@@ -30194,24 +30361,26 @@ function useAddressBalance(params) {
30194
30361
  }
30195
30362
 
30196
30363
  // src/hooks/use-executions.ts
30197
- var import_react_query24 = require("@tanstack/react-query");
30198
- var import_core50 = require("@unifold/core");
30364
+ var import_react_query23 = require("@tanstack/react-query");
30365
+ var import_core49 = require("@unifold/core");
30199
30366
  function useExecutions(userId, publishableKey, options) {
30200
- const actionType = options?.actionType ?? import_core50.ActionType.Deposit;
30201
- return (0, import_react_query24.useQuery)({
30367
+ const actionType = options?.actionType ?? import_core49.ActionType.Deposit;
30368
+ const query = (0, import_react_query23.useQuery)({
30202
30369
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
30203
- queryFn: () => (0, import_core50.queryExecutions)(userId, publishableKey, actionType),
30370
+ queryFn: () => (0, import_core49.queryExecutions)(userId, publishableKey, actionType),
30204
30371
  enabled: (options?.enabled ?? true) && !!userId,
30205
30372
  refetchInterval: options?.refetchInterval ?? 3e3,
30206
30373
  staleTime: 0,
30207
30374
  gcTime: 1e3 * 60 * 5,
30208
30375
  refetchOnWindowFocus: false
30209
30376
  });
30377
+ useStampInternalUserId({ internalUserId: query.data?.data[0]?.user_id });
30378
+ return query;
30210
30379
  }
30211
30380
 
30212
30381
  // src/hooks/use-withdraw-polling.ts
30213
30382
  var import_react34 = require("react");
30214
- var import_core51 = require("@unifold/core");
30383
+ var import_core50 = require("@unifold/core");
30215
30384
  var POLL_INTERVAL_MS4 = 2500;
30216
30385
  var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
30217
30386
  var CUTOFF_BUFFER_MS2 = 6e4;
@@ -30234,15 +30403,15 @@ function useWithdrawPolling({
30234
30403
  const journeySessionId = () => sessionIdRef.current || (getSessionId() ?? "");
30235
30404
  const executionCreatedSec = (execution) => 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);
30236
30405
  const createExecutionSuccessEvent = (execution) => ({
30237
- id: (0, import_core51.generatePrefixedKSUID)("sevt"),
30238
- type: import_core51.WithdrawEventType.DIRECT_EXECUTION_SUCCEEDED,
30406
+ id: (0, import_core50.generatePrefixedKSUID)("sevt"),
30407
+ type: import_core50.WithdrawEventType.DIRECT_EXECUTION_SUCCEEDED,
30239
30408
  created: executionCreatedSec(execution),
30240
30409
  sessionId: journeySessionId(),
30241
30410
  data: { object: mapToDirectExecution(execution) }
30242
30411
  });
30243
30412
  const createExecutionFailedEvent = (execution) => ({
30244
- id: (0, import_core51.generatePrefixedKSUID)("sevt"),
30245
- type: import_core51.WithdrawEventType.DIRECT_EXECUTION_FAILED,
30413
+ id: (0, import_core50.generatePrefixedKSUID)("sevt"),
30414
+ type: import_core50.WithdrawEventType.DIRECT_EXECUTION_FAILED,
30246
30415
  created: executionCreatedSec(execution),
30247
30416
  sessionId: journeySessionId(),
30248
30417
  data: { object: mapToDirectExecution(execution) }
@@ -30294,7 +30463,7 @@ function useWithdrawPolling({
30294
30463
  const enabledAt = enabledAtRef.current;
30295
30464
  const poll = async () => {
30296
30465
  try {
30297
- const response = await (0, import_core51.queryExecutions)(userId, publishableKey, import_core51.ActionType.Withdraw);
30466
+ const response = await (0, import_core50.queryExecutions)(userId, publishableKey, import_core50.ActionType.Withdraw);
30298
30467
  const cutoff = new Date(enabledAt.getTime() - CUTOFF_BUFFER_MS2);
30299
30468
  const sorted = [...response.data].sort((a, b) => {
30300
30469
  const tA = a.created_at ? new Date(a.created_at).getTime() : 0;
@@ -30302,11 +30471,11 @@ function useWithdrawPolling({
30302
30471
  return tB - tA;
30303
30472
  });
30304
30473
  const inProgress = [
30305
- import_core51.ExecutionStatus.PENDING,
30306
- import_core51.ExecutionStatus.WAITING,
30307
- import_core51.ExecutionStatus.DELAYED
30474
+ import_core50.ExecutionStatus.PENDING,
30475
+ import_core50.ExecutionStatus.WAITING,
30476
+ import_core50.ExecutionStatus.DELAYED
30308
30477
  ];
30309
- const terminal = [import_core51.ExecutionStatus.SUCCEEDED, import_core51.ExecutionStatus.FAILED];
30478
+ const terminal = [import_core50.ExecutionStatus.SUCCEEDED, import_core50.ExecutionStatus.FAILED];
30310
30479
  let target = null;
30311
30480
  for (const ex of sorted) {
30312
30481
  const t = ex.created_at ? new Date(ex.created_at) : null;
@@ -30336,7 +30505,7 @@ function useWithdrawPolling({
30336
30505
  }
30337
30506
  return [...list, ex];
30338
30507
  });
30339
- if (ex.status === import_core51.ExecutionStatus.SUCCEEDED && (!prev || inProgress.includes(prev))) {
30508
+ if (ex.status === import_core50.ExecutionStatus.SUCCEEDED && (!prev || inProgress.includes(prev))) {
30340
30509
  onSuccessRef.current?.({
30341
30510
  message: "Withdrawal completed successfully",
30342
30511
  executionId: ex.id,
@@ -30344,7 +30513,7 @@ function useWithdrawPolling({
30344
30513
  transaction: ex,
30345
30514
  execution: createExecutionSuccessEvent(ex)
30346
30515
  });
30347
- } else if (ex.status === import_core51.ExecutionStatus.FAILED && prev !== import_core51.ExecutionStatus.FAILED) {
30516
+ } else if (ex.status === import_core50.ExecutionStatus.FAILED && prev !== import_core50.ExecutionStatus.FAILED) {
30348
30517
  onErrorRef.current?.({
30349
30518
  message: "Withdrawal failed",
30350
30519
  code: "WITHDRAW_FAILED",
@@ -30374,7 +30543,7 @@ function useWithdrawPolling({
30374
30543
  if (!enabled || !depositWalletId) return;
30375
30544
  const trigger = async () => {
30376
30545
  try {
30377
- await (0, import_core51.pollDirectExecutions)({ deposit_wallet_id: depositWalletId }, publishableKey);
30546
+ await (0, import_core50.pollDirectExecutions)({ deposit_wallet_id: depositWalletId }, publishableKey);
30378
30547
  } catch {
30379
30548
  }
30380
30549
  };
@@ -30541,13 +30710,13 @@ function WithdrawDoubleInput({
30541
30710
  }
30542
30711
 
30543
30712
  // src/components/withdrawals/WithdrawForm.tsx
30544
- var import_react37 = require("react");
30713
+ var import_react36 = require("react");
30545
30714
  var import_lucide_react42 = require("lucide-react");
30546
- var import_core56 = require("@unifold/core");
30715
+ var import_core55 = require("@unifold/core");
30547
30716
 
30548
30717
  // src/hooks/use-verify-recipient-address.ts
30549
- var import_react_query25 = require("@tanstack/react-query");
30550
- var import_core52 = require("@unifold/core");
30718
+ var import_react_query24 = require("@tanstack/react-query");
30719
+ var import_core51 = require("@unifold/core");
30551
30720
  function useVerifyRecipientAddress(params) {
30552
30721
  const {
30553
30722
  chainType,
@@ -30559,7 +30728,7 @@ function useVerifyRecipientAddress(params) {
30559
30728
  } = params;
30560
30729
  const trimmedAddress = recipientAddress?.trim() || "";
30561
30730
  const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
30562
- return (0, import_react_query25.useQuery)({
30731
+ return (0, import_react_query24.useQuery)({
30563
30732
  queryKey: [
30564
30733
  "unifold",
30565
30734
  "verifyRecipientAddress",
@@ -30569,7 +30738,7 @@ function useVerifyRecipientAddress(params) {
30569
30738
  trimmedAddress,
30570
30739
  publishableKey
30571
30740
  ],
30572
- queryFn: () => (0, import_core52.verifyRecipientAddress)(
30741
+ queryFn: () => (0, import_core51.verifyRecipientAddress)(
30573
30742
  {
30574
30743
  chain_type: chainType,
30575
30744
  chain_id: chainId,
@@ -30588,7 +30757,7 @@ function useVerifyRecipientAddress(params) {
30588
30757
  }
30589
30758
 
30590
30759
  // src/components/withdrawals/send-withdraw.ts
30591
- var import_core53 = require("@unifold/core");
30760
+ var import_core52 = require("@unifold/core");
30592
30761
  async function sendEvmWithdraw(params) {
30593
30762
  const {
30594
30763
  provider,
@@ -30677,7 +30846,7 @@ async function sendSolanaWithdraw(params) {
30677
30846
  if (!provider.publicKey) {
30678
30847
  await provider.connect();
30679
30848
  }
30680
- const buildResponse = await (0, import_core53.buildSolanaTransaction)(
30849
+ const buildResponse = await (0, import_core52.buildSolanaTransaction)(
30681
30850
  {
30682
30851
  chain_id: "mainnet",
30683
30852
  token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
@@ -30703,7 +30872,7 @@ async function sendSolanaWithdraw(params) {
30703
30872
  for (let i = 0; i < serialized.length; i++) {
30704
30873
  binaryStr += String.fromCharCode(serialized[i]);
30705
30874
  }
30706
- const sendResponse = await (0, import_core53.sendSolanaTransaction)(
30875
+ const sendResponse = await (0, import_core52.sendSolanaTransaction)(
30707
30876
  { chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
30708
30877
  publishableKey
30709
30878
  );
@@ -30804,13 +30973,12 @@ async function detectBrowserWallet(chainType, senderAddress) {
30804
30973
  }
30805
30974
 
30806
30975
  // src/hooks/use-hypercore-withdraw-activation.ts
30807
- var import_react36 = require("react");
30808
- var import_core55 = require("@unifold/core");
30809
-
30810
- // src/hooks/use-get-deposit-address.ts
30811
30976
  var import_react35 = require("react");
30812
- var import_react_query26 = require("@tanstack/react-query");
30813
30977
  var import_core54 = require("@unifold/core");
30978
+
30979
+ // src/hooks/use-get-deposit-address.ts
30980
+ var import_react_query25 = require("@tanstack/react-query");
30981
+ var import_core53 = require("@unifold/core");
30814
30982
  function useGetDepositAddress(params) {
30815
30983
  const {
30816
30984
  userId,
@@ -30822,9 +30990,8 @@ function useGetDepositAddress(params) {
30822
30990
  actionType,
30823
30991
  enabled = true
30824
30992
  } = params;
30825
- const { setUserId } = useAnalytics();
30826
30993
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
30827
- const query = (0, import_react_query26.useQuery)({
30994
+ const query = (0, import_react_query25.useQuery)({
30828
30995
  queryKey: [
30829
30996
  "unifold",
30830
30997
  "getDepositAddress",
@@ -30836,7 +31003,7 @@ function useGetDepositAddress(params) {
30836
31003
  actionType ?? null,
30837
31004
  publishableKey
30838
31005
  ],
30839
- queryFn: () => (0, import_core54.getDepositAddress)(
31006
+ queryFn: () => (0, import_core53.getDepositAddress)(
30840
31007
  {
30841
31008
  external_user_id: userId,
30842
31009
  recipient_address: recipientAddress,
@@ -30854,11 +31021,7 @@ function useGetDepositAddress(params) {
30854
31021
  refetchOnWindowFocus: false,
30855
31022
  retry: 1
30856
31023
  });
30857
- (0, import_react35.useEffect)(() => {
30858
- if (query.data?.user_id) {
30859
- setUserId(query.data.user_id);
30860
- }
30861
- }, [query.data?.user_id, setUserId]);
31024
+ useStampInternalUserId({ internalUserId: query.data?.user_id });
30862
31025
  return query;
30863
31026
  }
30864
31027
 
@@ -30896,10 +31059,10 @@ function useHypercoreWithdrawActivation(params) {
30896
31059
  destinationChainType,
30897
31060
  destinationChainId,
30898
31061
  destinationTokenAddress,
30899
- actionType: import_core55.ActionType.Withdraw,
31062
+ actionType: import_core54.ActionType.Withdraw,
30900
31063
  enabled: enabled && isHypercore(sourceChainId)
30901
31064
  });
30902
- const depositWalletAddress = (0, import_react36.useMemo)(() => {
31065
+ const depositWalletAddress = (0, import_react35.useMemo)(() => {
30903
31066
  const wallets = depositWalletLookup.data?.data ?? [];
30904
31067
  return wallets.find((w) => w.chain_type === sourceChainType)?.address;
30905
31068
  }, [depositWalletLookup.data, sourceChainType]);
@@ -30990,22 +31153,22 @@ function WithdrawForm({
30990
31153
  const strings = useI18n().t;
30991
31154
  const t = strings.withdrawModal;
30992
31155
  const tCrypto = strings.transferCrypto;
30993
- const [recipientAddress, setRecipientAddress] = (0, import_react37.useState)(recipientAddressProp || "");
30994
- const [amount, setAmount] = (0, import_react37.useState)("");
30995
- const [inputUnit, setInputUnit] = (0, import_react37.useState)("fiat");
30996
- const [isSubmitting, setIsSubmitting] = (0, import_react37.useState)(false);
30997
- const [submitError, setSubmitError] = (0, import_react37.useState)(null);
30998
- const [detailsExpanded, setDetailsExpanded] = (0, import_react37.useState)(false);
30999
- const [glossaryOpen, setGlossaryOpen] = (0, import_react37.useState)(false);
31000
- const [isMaxed, setIsMaxed] = (0, import_react37.useState)(false);
31001
- (0, import_react37.useEffect)(() => {
31156
+ const [recipientAddress, setRecipientAddress] = (0, import_react36.useState)(recipientAddressProp || "");
31157
+ const [amount, setAmount] = (0, import_react36.useState)("");
31158
+ const [inputUnit, setInputUnit] = (0, import_react36.useState)("fiat");
31159
+ const [isSubmitting, setIsSubmitting] = (0, import_react36.useState)(false);
31160
+ const [submitError, setSubmitError] = (0, import_react36.useState)(null);
31161
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react36.useState)(false);
31162
+ const [glossaryOpen, setGlossaryOpen] = (0, import_react36.useState)(false);
31163
+ const [isMaxed, setIsMaxed] = (0, import_react36.useState)(false);
31164
+ (0, import_react36.useEffect)(() => {
31002
31165
  setRecipientAddress(recipientAddressProp || "");
31003
31166
  setAmount("");
31004
31167
  setInputUnit("fiat");
31005
31168
  setSubmitError(null);
31006
31169
  setIsMaxed(false);
31007
31170
  }, [recipientAddressProp]);
31008
- (0, import_react37.useEffect)(() => {
31171
+ (0, import_react36.useEffect)(() => {
31009
31172
  setIsMaxed(false);
31010
31173
  }, [balanceData?.balanceBaseUnit]);
31011
31174
  const trimmedAddress = recipientAddress.trim();
@@ -31023,7 +31186,7 @@ function WithdrawForm({
31023
31186
  enabled: debouncedAddress.length > 5 && !!selectedChain
31024
31187
  });
31025
31188
  const isDebouncing = trimmedAddress !== debouncedAddress;
31026
- const addressError = (0, import_react37.useMemo)(() => {
31189
+ const addressError = (0, import_react36.useMemo)(() => {
31027
31190
  if (!trimmedAddress || trimmedAddress.length <= 5) return null;
31028
31191
  if (isDebouncing || isVerifyingAddress) return null;
31029
31192
  if (verifyError) return t.invalidAddress;
@@ -31067,33 +31230,33 @@ function WithdrawForm({
31067
31230
  destinationTokenAddress: selectedChain?.token_address,
31068
31231
  enabled: isAddressValid
31069
31232
  });
31070
- const exchangeRate = (0, import_react37.useMemo)(() => {
31233
+ const exchangeRate = (0, import_react36.useMemo)(() => {
31071
31234
  if (!balanceData?.exchangeRate) return 0;
31072
31235
  return parseFloat(balanceData.exchangeRate);
31073
31236
  }, [balanceData]);
31074
- const balanceCrypto = (0, import_react37.useMemo)(() => {
31237
+ const balanceCrypto = (0, import_react36.useMemo)(() => {
31075
31238
  if (!balanceData?.balanceHuman) return 0;
31076
31239
  return parseFloat(balanceData.balanceHuman);
31077
31240
  }, [balanceData]);
31078
- const balanceUsdNum = (0, import_react37.useMemo)(() => {
31241
+ const balanceUsdNum = (0, import_react36.useMemo)(() => {
31079
31242
  if (!balanceData?.balanceUsd) return 0;
31080
31243
  return parseFloat(balanceData.balanceUsd);
31081
31244
  }, [balanceData]);
31082
31245
  const tokenSymbol = sourceTokenSymbol || balanceData?.symbol || "TOKEN";
31083
31246
  const sourceDecimals = balanceData?.decimals ?? 6;
31084
- const cryptoAmountFromInput = (0, import_react37.useMemo)(() => {
31247
+ const cryptoAmountFromInput = (0, import_react36.useMemo)(() => {
31085
31248
  const val = parseFloat(amount);
31086
31249
  if (!val || val <= 0) return 0;
31087
31250
  if (inputUnit === "crypto") return val;
31088
31251
  return exchangeRate > 0 ? val / exchangeRate : 0;
31089
31252
  }, [amount, inputUnit, exchangeRate]);
31090
- const fiatAmountFromInput = (0, import_react37.useMemo)(() => {
31253
+ const fiatAmountFromInput = (0, import_react36.useMemo)(() => {
31091
31254
  const val = parseFloat(amount);
31092
31255
  if (!val || val <= 0) return 0;
31093
31256
  if (inputUnit === "fiat") return val;
31094
31257
  return val * exchangeRate;
31095
31258
  }, [amount, inputUnit, exchangeRate]);
31096
- const convertedDisplay = (0, import_react37.useMemo)(() => {
31259
+ const convertedDisplay = (0, import_react36.useMemo)(() => {
31097
31260
  if (!amount || parseFloat(amount) <= 0) return null;
31098
31261
  if (inputUnit === "crypto") {
31099
31262
  return `$${fiatAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
@@ -31112,7 +31275,7 @@ function WithdrawForm({
31112
31275
  isMaxed,
31113
31276
  isStablecoin
31114
31277
  ]);
31115
- const balanceDisplay = (0, import_react37.useMemo)(() => {
31278
+ const balanceDisplay = (0, import_react36.useMemo)(() => {
31116
31279
  if (isLoadingBalance || !balanceData) return null;
31117
31280
  if (inputUnit === "crypto") {
31118
31281
  const displayDecimals = isStablecoin ? 2 : 6;
@@ -31135,7 +31298,7 @@ function WithdrawForm({
31135
31298
  tokenSymbol,
31136
31299
  isStablecoin
31137
31300
  ]);
31138
- const handleSwitchUnit = (0, import_react37.useCallback)(() => {
31301
+ const handleSwitchUnit = (0, import_react36.useCallback)(() => {
31139
31302
  if (isMaxed && balanceData) {
31140
31303
  if (inputUnit === "crypto") {
31141
31304
  setAmount((Math.round(balanceUsdNum * 100) / 100).toFixed(2));
@@ -31162,7 +31325,7 @@ function WithdrawForm({
31162
31325
  setInputUnit("crypto");
31163
31326
  }
31164
31327
  }, [amount, inputUnit, exchangeRate, sourceDecimals, isMaxed, balanceData, balanceUsdNum]);
31165
- const handleMaxClick = (0, import_react37.useCallback)(() => {
31328
+ const handleMaxClick = (0, import_react36.useCallback)(() => {
31166
31329
  if (inputUnit === "crypto") {
31167
31330
  if (balanceCrypto <= 0) return;
31168
31331
  setAmount(balanceData?.balanceHuman ?? "0");
@@ -31176,7 +31339,7 @@ function WithdrawForm({
31176
31339
  const isBelowMinimum = minimumWithdrawAmountUsd !== null && fiatAmountFromInput > 0 && Math.round(fiatAmountFromInput * 100) / 100 < minimumWithdrawAmountUsd;
31177
31340
  const isOverBalance = inputUnit === "crypto" ? cryptoAmountFromInput > 0 && balanceCrypto > 0 && cryptoAmountFromInput > balanceCrypto : fiatAmountFromInput > 0 && balanceUsdNum > 0 && Math.round(fiatAmountFromInput * 100) / 100 > Math.round(balanceUsdNum * 100) / 100;
31178
31341
  const isFormValid = trimmedAddress.length > 0 && amount.trim().length > 0 && cryptoAmountFromInput > 0 && isAddressValid && !isBelowMinimum && !isOverBalance && !isBalanceBelowMinimum && !!balanceData;
31179
- const handleWithdraw = (0, import_react37.useCallback)(async () => {
31342
+ const handleWithdraw = (0, import_react36.useCallback)(async () => {
31180
31343
  if (!selectedToken || !selectedChain) return;
31181
31344
  if (!isFormValid) return;
31182
31345
  setIsSubmitting(true);
@@ -31199,7 +31362,7 @@ function WithdrawForm({
31199
31362
  let humanAmount = isMaxed ? balanceData.balanceHuman : toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
31200
31363
  if (isHypercoreChain(sourceChainId)) {
31201
31364
  try {
31202
- const check = await (0, import_core56.checkHypercoreActivation)(
31365
+ const check = await (0, import_core55.checkHypercoreActivation)(
31203
31366
  {
31204
31367
  source_address: senderAddress,
31205
31368
  recipient_address: depositWallet.address
@@ -31655,12 +31818,12 @@ function WithdrawForm({
31655
31818
 
31656
31819
  // src/components/withdrawals/WithdrawExecutionItem.tsx
31657
31820
  var import_lucide_react43 = require("lucide-react");
31658
- var import_core57 = require("@unifold/core");
31821
+ var import_core56 = require("@unifold/core");
31659
31822
  var import_jsx_runtime75 = require("react/jsx-runtime");
31660
31823
  function WithdrawExecutionItem({ execution, onClick }) {
31661
31824
  const { colors: colors2, fonts, components } = useTheme();
31662
31825
  const { t: strings, locale } = useI18n();
31663
- const isPending = execution.status === import_core57.ExecutionStatus.PENDING || execution.status === import_core57.ExecutionStatus.WAITING || execution.status === import_core57.ExecutionStatus.DELAYED;
31826
+ const isPending = execution.status === import_core56.ExecutionStatus.PENDING || execution.status === import_core56.ExecutionStatus.WAITING || execution.status === import_core56.ExecutionStatus.DELAYED;
31664
31827
  const formatDateTime = (timestamp) => {
31665
31828
  try {
31666
31829
  const date = new Date(timestamp);
@@ -31707,7 +31870,7 @@ function WithdrawExecutionItem({ execution, onClick }) {
31707
31870
  /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
31708
31871
  "img",
31709
31872
  {
31710
- src: execution.destination_token_metadata?.icon_url || (0, import_core57.getIconUrl)("/icons/tokens/svg/usdc.svg"),
31873
+ src: execution.destination_token_metadata?.icon_url || (0, import_core56.getIconUrl)("/icons/tokens/svg/usdc.svg"),
31711
31874
  alt: "Token",
31712
31875
  width: 36,
31713
31876
  height: 36,
@@ -31806,7 +31969,7 @@ function WithdrawExecutionItem({ execution, onClick }) {
31806
31969
  }
31807
31970
 
31808
31971
  // src/components/withdrawals/WithdrawConfirmingView.tsx
31809
- var import_react38 = require("react");
31972
+ var import_react37 = require("react");
31810
31973
  var import_jsx_runtime76 = require("react/jsx-runtime");
31811
31974
  function truncateAddress4(addr) {
31812
31975
  if (addr.length <= 12) return addr;
@@ -31822,9 +31985,9 @@ function WithdrawConfirmingView({
31822
31985
  const { colors: colors2, fonts, components } = useTheme();
31823
31986
  const { t: strings } = useI18n();
31824
31987
  const t = strings.withdrawModal.details;
31825
- const [showButton, setShowButton] = (0, import_react38.useState)(false);
31988
+ const [showButton, setShowButton] = (0, import_react37.useState)(false);
31826
31989
  const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
31827
- (0, import_react38.useEffect)(() => {
31990
+ (0, import_react37.useEffect)(() => {
31828
31991
  if (latestExecution) return;
31829
31992
  const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
31830
31993
  return () => clearTimeout(timer);
@@ -31945,7 +32108,7 @@ function WithdrawConfirmingView({
31945
32108
  }
31946
32109
 
31947
32110
  // src/components/withdrawals/WithdrawModal.tsx
31948
- var import_core58 = require("@unifold/core");
32111
+ var import_core57 = require("@unifold/core");
31949
32112
  var import_jsx_runtime77 = require("react/jsx-runtime");
31950
32113
  var getChainKey5 = (chainId, chainType) => `${chainType}:${chainId}`;
31951
32114
  function WithdrawModal({
@@ -31974,35 +32137,39 @@ function WithdrawModal({
31974
32137
  const { colors: colors2, fonts, components } = useTheme();
31975
32138
  const t = useI18n().t.withdrawModal;
31976
32139
  const { track, startSession, endSession, getSessionId, setUserId, subscribe } = useAnalytics();
31977
- const emitEvent = (0, import_react39.useCallback)(
32140
+ const emitEvent = (0, import_react38.useCallback)(
31978
32141
  (event) => onEvent?.({ ...event, externalUserId }),
31979
32142
  [onEvent, externalUserId]
31980
32143
  );
31981
- const onEventRef = (0, import_react39.useRef)(emitEvent);
32144
+ const onEventRef = (0, import_react38.useRef)(emitEvent);
31982
32145
  onEventRef.current = emitEvent;
31983
- (0, import_react39.useEffect)(
32146
+ (0, import_react38.useEffect)(
31984
32147
  () => subscribe((event) => {
31985
32148
  if (event.properties?.flow_type !== "withdraw") return;
31986
32149
  const selection = selectionPayload(event);
31987
32150
  if (selection?.kind !== "token") return;
31988
32151
  onEventRef.current?.({
31989
- id: (0, import_core58.generatePrefixedKSUID)("sevt"),
32152
+ id: (0, import_core57.generatePrefixedKSUID)("sevt"),
31990
32153
  created: Math.floor(Date.now() / 1e3),
31991
32154
  sessionId: getSessionId() ?? "",
31992
- type: import_core58.WithdrawEventType.TOKEN_SELECTED,
32155
+ type: import_core57.WithdrawEventType.TOKEN_SELECTED,
31993
32156
  data: { object: selection.data }
31994
32157
  });
31995
32158
  }),
31996
32159
  [subscribe, getSessionId]
31997
32160
  );
31998
- const journeyActiveRef = (0, import_react39.useRef)(false);
31999
- const journeySessionIdRef = (0, import_react39.useRef)(void 0);
32000
- const onWithdrawSuccessFor = (0, import_react39.useCallback)(
32161
+ const journeyActiveRef = (0, import_react38.useRef)(false);
32162
+ const journeySessionIdRef = (0, import_react38.useRef)(void 0);
32163
+ const journeyExternalUserIdRef = (0, import_react38.useRef)(void 0);
32164
+ const onWithdrawSuccessFor = (0, import_react38.useCallback)(
32001
32165
  (data) => {
32002
32166
  const execution = data.execution?.data.object;
32003
32167
  track("flow_completed", {
32004
32168
  flow_type: "withdraw",
32005
32169
  amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
32170
+ // The one high-cardinality field we do send: the join key from a
32171
+ // funnel session back to the execution row it produced.
32172
+ execution_id: data.executionId ?? execution?.id,
32006
32173
  // Flat, low-cardinality execution dimensions for PostHog breakdowns.
32007
32174
  status: execution?.status,
32008
32175
  source_chain_type: execution?.sourceChainType,
@@ -32017,12 +32184,13 @@ function WithdrawModal({
32017
32184
  },
32018
32185
  [onWithdrawSuccess, emitEvent, track]
32019
32186
  );
32020
- const onWithdrawErrorFor = (0, import_react39.useCallback)(
32187
+ const onWithdrawErrorFor = (0, import_react38.useCallback)(
32021
32188
  (error) => {
32022
32189
  const execution = error.execution?.data.object;
32023
32190
  track("flow_failed", {
32024
32191
  flow_type: "withdraw",
32025
32192
  error_code: error.code,
32193
+ execution_id: execution?.id,
32026
32194
  failure_reason: execution?.failureReason ?? void 0,
32027
32195
  status: execution?.status,
32028
32196
  source_chain_type: execution?.sourceChainType,
@@ -32037,14 +32205,14 @@ function WithdrawModal({
32037
32205
  },
32038
32206
  [onWithdrawError, emitEvent, track]
32039
32207
  );
32040
- const [containerEl, setContainerEl] = (0, import_react39.useState)(null);
32041
- const containerCallbackRef = (0, import_react39.useCallback)((el) => {
32208
+ const [containerEl, setContainerEl] = (0, import_react38.useState)(null);
32209
+ const containerCallbackRef = (0, import_react38.useCallback)((el) => {
32042
32210
  setContainerEl(el);
32043
32211
  }, []);
32044
- const [resolvedTheme, setResolvedTheme] = (0, import_react39.useState)(
32212
+ const [resolvedTheme, setResolvedTheme] = (0, import_react38.useState)(
32045
32213
  theme === "auto" ? "dark" : theme
32046
32214
  );
32047
- (0, import_react39.useEffect)(() => {
32215
+ (0, import_react38.useEffect)(() => {
32048
32216
  if (theme === "auto") {
32049
32217
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
32050
32218
  setResolvedTheme(mq.matches ? "dark" : "light");
@@ -32059,7 +32227,7 @@ function WithdrawModal({
32059
32227
  publishableKey,
32060
32228
  open
32061
32229
  );
32062
- const destinationTokens = (0, import_react39.useMemo)(() => tokensResponse?.data ?? [], [tokensResponse]);
32230
+ const destinationTokens = (0, import_react38.useMemo)(() => tokensResponse?.data ?? [], [tokensResponse]);
32063
32231
  const { data: sourceValidation, isLoading: isCheckingSourceToken } = useSourceTokenValidation({
32064
32232
  sourceChainType,
32065
32233
  sourceChainId,
@@ -32094,10 +32262,11 @@ function WithdrawModal({
32094
32262
  const selectedChain = selectedToken && selectedChainKey ? selectedToken.chains.find(
32095
32263
  (c) => getChainKey5(c.chain_id, c.chain_type) === selectedChainKey
32096
32264
  ) ?? null : null;
32097
- const [view, setView] = (0, import_react39.useState)("form");
32098
- const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react39.useState)();
32099
- const [selectedExecution, setSelectedExecution] = (0, import_react39.useState)(null);
32100
- const [submittedTxInfo, setSubmittedTxInfo] = (0, import_react39.useState)(null);
32265
+ const [view, setView] = (0, import_react38.useState)("form");
32266
+ const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react38.useState)();
32267
+ const withdrawDepositWalletIdRef = (0, import_react38.useRef)(void 0);
32268
+ const [selectedExecution, setSelectedExecution] = (0, import_react38.useState)(null);
32269
+ const [submittedTxInfo, setSubmittedTxInfo] = (0, import_react38.useState)(null);
32101
32270
  const { executions: realtimeExecutions } = useWithdrawPolling({
32102
32271
  userId: externalUserId,
32103
32272
  publishableKey,
@@ -32107,21 +32276,21 @@ function WithdrawModal({
32107
32276
  onWithdrawError: onWithdrawErrorFor
32108
32277
  });
32109
32278
  const { data: allWithdrawalsData } = useExecutions(externalUserId, publishableKey, {
32110
- actionType: import_core58.ActionType.Withdraw,
32279
+ actionType: import_core57.ActionType.Withdraw,
32111
32280
  enabled: open,
32112
32281
  refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
32113
32282
  });
32114
32283
  const allWithdrawals = allWithdrawalsData?.data ?? [];
32115
- const handleDepositWalletCreation = (0, import_react39.useCallback)(
32284
+ const handleDepositWalletCreation = (0, import_react38.useCallback)(
32116
32285
  async (params) => {
32117
- const response = await (0, import_core58.createDepositAddress)(
32286
+ const response = await (0, import_core57.createDepositAddress)(
32118
32287
  {
32119
32288
  external_user_id: externalUserId,
32120
32289
  destination_chain_type: params.destinationChainType,
32121
32290
  destination_chain_id: params.destinationChainId,
32122
32291
  destination_token_address: params.destinationTokenAddress,
32123
32292
  recipient_address: params.recipientAddress,
32124
- action_type: import_core58.ActionType.Withdraw,
32293
+ action_type: import_core57.ActionType.Withdraw,
32125
32294
  source_chain_type: sourceChainType
32126
32295
  },
32127
32296
  publishableKey
@@ -32129,16 +32298,17 @@ function WithdrawModal({
32129
32298
  if (response.user_id) {
32130
32299
  setUserId(response.user_id);
32131
32300
  }
32132
- const depositWallet = (0, import_core58.getWalletByChainType)(response.data, sourceChainType);
32301
+ const depositWallet = (0, import_core57.getWalletByChainType)(response.data, sourceChainType);
32133
32302
  if (!depositWallet) {
32134
32303
  throw new Error(`No deposit wallet available for ${sourceChainType}`);
32135
32304
  }
32305
+ withdrawDepositWalletIdRef.current = depositWallet.id;
32136
32306
  setWithdrawDepositWalletId(depositWallet.id);
32137
32307
  return depositWallet;
32138
32308
  },
32139
32309
  [externalUserId, publishableKey, sourceChainType, setUserId]
32140
32310
  );
32141
- const handleWithdrawStarted = (0, import_react39.useCallback)(
32311
+ const handleWithdrawStarted = (0, import_react38.useCallback)(
32142
32312
  (txInfo) => {
32143
32313
  const tokenData = destinationTokens.find((t2) => t2.symbol === txInfo.destinationTokenSymbol);
32144
32314
  const chainData = tokenData?.chains.find(
@@ -32152,11 +32322,16 @@ function WithdrawModal({
32152
32322
  currency: tokenData?.currency,
32153
32323
  amount: txInfo.amount,
32154
32324
  amount_base_unit: txInfo.amountBaseUnit,
32155
- ...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {}
32325
+ ...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {},
32326
+ // The execution doesn't exist yet — it's created when the user's send
32327
+ // lands on the withdraw deposit wallet, and carries this id. So a
32328
+ // withdrawal confirmed but never completed still joins to whatever
32329
+ // did (or didn't) follow on that wallet.
32330
+ deposit_wallet_id: withdrawDepositWalletIdRef.current
32156
32331
  });
32157
32332
  emitEvent({
32158
- id: (0, import_core58.generatePrefixedKSUID)("sevt"),
32159
- type: import_core58.WithdrawEventType.FLOW_STARTED,
32333
+ id: (0, import_core57.generatePrefixedKSUID)("sevt"),
32334
+ type: import_core57.WithdrawEventType.FLOW_STARTED,
32160
32335
  created: Math.floor(Date.now() / 1e3),
32161
32336
  sessionId: getSessionId() ?? "",
32162
32337
  data: {
@@ -32172,23 +32347,25 @@ function WithdrawModal({
32172
32347
  },
32173
32348
  [track, emitEvent, getSessionId, destinationTokens]
32174
32349
  );
32175
- const handleWithdrawSubmitted = (0, import_react39.useCallback)((txInfo) => {
32350
+ const handleWithdrawSubmitted = (0, import_react38.useCallback)((txInfo) => {
32176
32351
  setSubmittedTxInfo(txInfo);
32177
32352
  setView("confirming");
32178
32353
  }, []);
32179
- const resetViewTimeoutRef = (0, import_react39.useRef)(null);
32180
- const finalizeJourney = (0, import_react39.useCallback)(() => {
32354
+ const resetViewTimeoutRef = (0, import_react38.useRef)(null);
32355
+ const finalizeJourney = (0, import_react38.useCallback)(() => {
32181
32356
  if (!journeyActiveRef.current) return;
32182
32357
  journeyActiveRef.current = false;
32183
32358
  track("widget_closed", { flow_type: "withdraw" });
32184
32359
  if (getSessionId() === journeySessionIdRef.current) endSession();
32185
32360
  }, [track, getSessionId, endSession]);
32186
- const beginJourney = (0, import_react39.useCallback)(() => {
32361
+ const beginJourney = (0, import_react38.useCallback)(() => {
32187
32362
  journeySessionIdRef.current = startSession();
32188
32363
  journeyActiveRef.current = true;
32364
+ journeyExternalUserIdRef.current = externalUserId;
32365
+ setUserId(null);
32189
32366
  track("widget_opened", { flow_type: "withdraw" });
32190
- }, [startSession, track]);
32191
- const handleClose = (0, import_react39.useCallback)(() => {
32367
+ }, [startSession, track, setUserId, externalUserId]);
32368
+ const handleClose = (0, import_react38.useCallback)(() => {
32192
32369
  finalizeJourney();
32193
32370
  onOpenChange(false);
32194
32371
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
@@ -32196,11 +32373,12 @@ function WithdrawModal({
32196
32373
  setView("form");
32197
32374
  setSelectedExecution(null);
32198
32375
  setSubmittedTxInfo(null);
32376
+ withdrawDepositWalletIdRef.current = void 0;
32199
32377
  setWithdrawDepositWalletId(void 0);
32200
32378
  resetViewTimeoutRef.current = null;
32201
32379
  }, 200);
32202
32380
  }, [onOpenChange, finalizeJourney]);
32203
- (0, import_react39.useLayoutEffect)(() => {
32381
+ (0, import_react38.useLayoutEffect)(() => {
32204
32382
  if (!open) {
32205
32383
  finalizeJourney();
32206
32384
  return;
@@ -32213,9 +32391,15 @@ function WithdrawModal({
32213
32391
  setView("form");
32214
32392
  setSelectedExecution(null);
32215
32393
  setSubmittedTxInfo(null);
32394
+ withdrawDepositWalletIdRef.current = void 0;
32216
32395
  setWithdrawDepositWalletId(void 0);
32217
32396
  }, [open]);
32218
- (0, import_react39.useEffect)(
32397
+ (0, import_react38.useLayoutEffect)(() => {
32398
+ if (!open || journeyExternalUserIdRef.current === externalUserId) return;
32399
+ journeyExternalUserIdRef.current = externalUserId;
32400
+ setUserId(null);
32401
+ }, [open, externalUserId, setUserId]);
32402
+ (0, import_react38.useEffect)(
32219
32403
  () => () => {
32220
32404
  if (journeyActiveRef.current) {
32221
32405
  journeyActiveRef.current = false;
@@ -32224,18 +32408,18 @@ function WithdrawModal({
32224
32408
  },
32225
32409
  [endSession, getSessionId]
32226
32410
  );
32227
- (0, import_react39.useEffect)(() => {
32411
+ (0, import_react38.useEffect)(() => {
32228
32412
  if (!open) return;
32229
32413
  const screen = view === "detail" ? "tracker_detail" : view;
32230
32414
  track("screen_viewed", { flow_type: "withdraw", screen });
32231
32415
  }, [open, view, track]);
32232
- (0, import_react39.useEffect)(
32416
+ (0, import_react38.useEffect)(
32233
32417
  () => () => {
32234
32418
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
32235
32419
  },
32236
32420
  []
32237
32421
  );
32238
- const trackAssetSelected = (0, import_react39.useCallback)(
32422
+ const trackAssetSelected = (0, import_react38.useCallback)(
32239
32423
  (symbol, chainKey) => {
32240
32424
  const [chainType, chainId] = (chainKey ?? "").split(":");
32241
32425
  const tokenData = destinationTokens.find((t2) => t2.symbol === symbol);
@@ -32253,14 +32437,14 @@ function WithdrawModal({
32253
32437
  },
32254
32438
  [destinationTokens, track]
32255
32439
  );
32256
- const handleTokenSymbolChange = (0, import_react39.useCallback)(
32440
+ const handleTokenSymbolChange = (0, import_react38.useCallback)(
32257
32441
  (symbol) => {
32258
32442
  trackAssetSelected(symbol, selectedChainKey);
32259
32443
  setSelectedTokenSymbol(symbol);
32260
32444
  },
32261
32445
  [setSelectedTokenSymbol, selectedChainKey, trackAssetSelected]
32262
32446
  );
32263
- const handleChainKeyChange = (0, import_react39.useCallback)(
32447
+ const handleChainKeyChange = (0, import_react38.useCallback)(
32264
32448
  (chainKey) => {
32265
32449
  trackAssetSelected(selectedTokenSymbol, chainKey);
32266
32450
  setSelectedChainKey(chainKey);
@@ -32449,16 +32633,16 @@ function WithdrawModal({
32449
32633
  }
32450
32634
 
32451
32635
  // src/components/withdrawals/WithdrawTokenSelector.tsx
32452
- var import_react40 = require("react");
32636
+ var import_react39 = require("react");
32453
32637
  var import_lucide_react45 = require("lucide-react");
32454
32638
  var import_fuse2 = __toESM(require("fuse.js"));
32455
32639
  var import_jsx_runtime78 = require("react/jsx-runtime");
32456
32640
  function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
32457
32641
  const { themeClass, colors: colors2, fonts, components } = useTheme();
32458
32642
  const t = useI18n().t.withdrawModal;
32459
- const [searchQuery, setSearchQuery] = (0, import_react40.useState)("");
32460
- const [hoveredKey, setHoveredKey] = (0, import_react40.useState)(null);
32461
- const allOptions = (0, import_react40.useMemo)(() => {
32643
+ const [searchQuery, setSearchQuery] = (0, import_react39.useState)("");
32644
+ const [hoveredKey, setHoveredKey] = (0, import_react39.useState)(null);
32645
+ const allOptions = (0, import_react39.useMemo)(() => {
32462
32646
  const options = [];
32463
32647
  tokens.forEach((token) => {
32464
32648
  token.chains.forEach((chain) => {
@@ -32467,7 +32651,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
32467
32651
  });
32468
32652
  return options;
32469
32653
  }, [tokens]);
32470
- const fuse = (0, import_react40.useMemo)(
32654
+ const fuse = (0, import_react39.useMemo)(
32471
32655
  () => new import_fuse2.default(allOptions, {
32472
32656
  keys: [
32473
32657
  { name: "token.symbol", weight: 2 },
@@ -32480,7 +32664,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
32480
32664
  }),
32481
32665
  [allOptions]
32482
32666
  );
32483
- const filteredOptions = (0, import_react40.useMemo)(() => {
32667
+ const filteredOptions = (0, import_react39.useMemo)(() => {
32484
32668
  if (!searchQuery.trim()) return allOptions;
32485
32669
  const query = searchQuery.trim();
32486
32670
  const results = fuse.search(query);