@unifold/connect-react 0.1.77 → 0.1.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -6093,12 +6093,12 @@ import {
6093
6093
  generatePrefixedKSUID as generatePrefixedKSUID2,
6094
6094
  DepositEventType as DepositEventType2
6095
6095
  } from "@unifold/core";
6096
- import { useEffect as useEffect32 } from "react";
6097
6096
  import { useQuery } from "@tanstack/react-query";
6098
6097
  import {
6099
6098
  createDepositAddress,
6100
6099
  isDepositAddressValidationError
6101
6100
  } from "@unifold/core";
6101
+ import { useEffect as useEffect32 } from "react";
6102
6102
  import * as React52 from "react";
6103
6103
  import { jsx as jsx52 } from "react/jsx-runtime";
6104
6104
  import { useEffect as useEffect42, useState as useState32 } from "react";
@@ -6625,7 +6625,7 @@ function generateKSUID() {
6625
6625
  function generatePrefixedKSUID(prefix) {
6626
6626
  return `${prefix}_${generateKSUID()}`;
6627
6627
  }
6628
- var PACKAGE_VERSION = "0.1.77";
6628
+ var PACKAGE_VERSION = "0.1.78";
6629
6629
  var LIBRARY_NAME = "@unifold/analytics";
6630
6630
  var DEFAULT_DEDUP_MS = 500;
6631
6631
  var SESSION_PREFIX = "asess";
@@ -6715,8 +6715,12 @@ var EventTracker = class {
6715
6715
  }
6716
6716
  /**
6717
6717
  * Associate subsequent events with an internal Unifold user.id
6718
- * (`user_<ksuid>`). Pass `null` to clear. Usually called once the
6719
- * deposit-addresses response returns the id.
6718
+ * (`user_<ksuid>`). Pass `null` to clear.
6719
+ *
6720
+ * The tracker is shared across flows and outlives any one journey, so a
6721
+ * journey stamps its own user at the start — with the id if it already
6722
+ * knows one, `null` if it doesn't — rather than inheriting whatever the
6723
+ * previous journey left here.
6720
6724
  */
6721
6725
  setUserId(userId) {
6722
6726
  this.userId = userId || void 0;
@@ -6727,8 +6731,8 @@ var EventTracker = class {
6727
6731
  * {@link EventTracker.endSession} carries it.
6728
6732
  *
6729
6733
  * Does not touch `userId`: the internal `user_<ksuid>` is attached separately
6730
- * via {@link EventTracker.setUserId} once the deposit-addresses response
6731
- * returns, and persists until the host replaces it.
6734
+ * via {@link EventTracker.setUserId}, and persists until the host replaces
6735
+ * it which the SDK's modals do on every journey start.
6732
6736
  */
6733
6737
  startSession() {
6734
6738
  this.sessionId = generatePrefixedKSUID(SESSION_PREFIX);
@@ -12819,7 +12823,7 @@ import {
12819
12823
  generatePrefixedKSUID as generatePrefixedKSUID10
12820
12824
  } from "@unifold/core";
12821
12825
  import { Fragment as Fragment17, jsx as jsx722, jsxs as jsxs62 } from "react/jsx-runtime";
12822
- import { useState as useState49, useEffect as useEffect48, useLayoutEffect as useLayoutEffect42, useCallback as useCallback17, useMemo as useMemo21, useRef as useRef20 } from "react";
12826
+ import { useState as useState49, useEffect as useEffect47, useLayoutEffect as useLayoutEffect42, useCallback as useCallback17, useMemo as useMemo21, useRef as useRef20 } from "react";
12823
12827
  import { useQuery as useQuery21 } from "@tanstack/react-query";
12824
12828
  import {
12825
12829
  getSupportedDestinationTokens
@@ -12840,7 +12844,7 @@ import {
12840
12844
  ActionType as ActionType5
12841
12845
  } from "@unifold/core";
12842
12846
  import { jsx as jsx73, jsxs as jsxs63 } from "react/jsx-runtime";
12843
- import { useState as useState47, useCallback as useCallback16, useMemo as useMemo20, useEffect as useEffect46 } from "react";
12847
+ import { useState as useState47, useCallback as useCallback16, useMemo as useMemo20, useEffect as useEffect45 } from "react";
12844
12848
  import {
12845
12849
  checkHypercoreActivation as checkHypercoreActivation3
12846
12850
  } from "@unifold/core";
@@ -12852,13 +12856,12 @@ import {
12852
12856
  } from "@unifold/core";
12853
12857
  import { useMemo as useMemo19 } from "react";
12854
12858
  import { ActionType as ActionType6 } from "@unifold/core";
12855
- import { useEffect as useEffect45 } from "react";
12856
12859
  import { useQuery as useQuery26 } from "@tanstack/react-query";
12857
12860
  import { getDepositAddress } from "@unifold/core";
12858
12861
  import { Fragment as Fragment18, jsx as jsx74, jsxs as jsxs64 } from "react/jsx-runtime";
12859
12862
  import { ExecutionStatus as ExecutionStatus7, getIconUrl as getIconUrl5 } from "@unifold/core";
12860
12863
  import { jsx as jsx75, jsxs as jsxs65 } from "react/jsx-runtime";
12861
- import { useState as useState48, useEffect as useEffect47 } from "react";
12864
+ import { useState as useState48, useEffect as useEffect46 } from "react";
12862
12865
  import { Fragment as Fragment19, jsx as jsx76, jsxs as jsxs66 } from "react/jsx-runtime";
12863
12866
  import {
12864
12867
  createDepositAddress as createDepositAddress2,
@@ -13268,6 +13271,9 @@ var en_default = {
13268
13271
  transactionBreakdown: "Transaction breakdown",
13269
13272
  networkFee: "Network fee",
13270
13273
  confirmOrder: "Confirm Order",
13274
+ mfaEnrollmentTitle: "Enable SMS or Authy 2FA",
13275
+ mfaEnrollmentMessage: "Please make sure you enable SMS or Authy 2FA in your Coinbase account. Press Continue after you enable it.",
13276
+ mfaEnrollmentSettingsLink: "Open Coinbase security settings",
13271
13277
  termsNoticePrefix: "By clicking on Confirm Order, you agree to our ",
13272
13278
  termsNoticeLink: "terms",
13273
13279
  termsNoticeSuffix: "."
@@ -13398,7 +13404,12 @@ var en_default = {
13398
13404
  prefix: "By continuing, you agree to Coinbase's ",
13399
13405
  separator: ", ",
13400
13406
  lastSeparator: ", and ",
13401
- suffix: ". Coinbase is the regulated provider of this fiat-to-crypto onramp."
13407
+ suffix: ".",
13408
+ agreements: {
13409
+ guest_checkout_terms: "Terms of Service",
13410
+ user_agreement: "User Agreement",
13411
+ privacy_policy: "Privacy Policy"
13412
+ }
13402
13413
  },
13403
13414
  errors: {
13404
13415
  rateLimited: "Too many attempts. Please wait a few minutes and try again.",
@@ -14057,6 +14068,9 @@ var zh_default = {
14057
14068
  transactionBreakdown: "\u4EA4\u6613\u660E\u7EC6",
14058
14069
  networkFee: "\u7F51\u7EDC\u624B\u7EED\u8D39",
14059
14070
  confirmOrder: "\u786E\u8BA4\u8BA2\u5355",
14071
+ mfaEnrollmentTitle: "\u8BF7\u542F\u7528\u77ED\u4FE1\u6216 Authy \u53CC\u91CD\u9A8C\u8BC1",
14072
+ 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",
14073
+ mfaEnrollmentSettingsLink: "\u6253\u5F00 Coinbase \u5B89\u5168\u8BBE\u7F6E",
14060
14074
  termsNoticePrefix: "\u70B9\u51FB\u201C\u786E\u8BA4\u8BA2\u5355\u201D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u4EEC\u7684",
14061
14075
  termsNoticeLink: "\u6761\u6B3E",
14062
14076
  termsNoticeSuffix: "\u3002"
@@ -14187,7 +14201,12 @@ var zh_default = {
14187
14201
  prefix: "\u7EE7\u7EED\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
14188
14202
  separator: "\u3001",
14189
14203
  lastSeparator: "\u548C",
14190
- suffix: "\u3002Coinbase \u662F\u672C\u6CD5\u5E01\u5151\u52A0\u5BC6\u8D27\u5E01\u5145\u503C\u670D\u52A1\u7684\u53D7\u76D1\u7BA1\u63D0\u4F9B\u65B9\u3002"
14204
+ suffix: "\u3002",
14205
+ agreements: {
14206
+ guest_checkout_terms: "\u670D\u52A1\u6761\u6B3E",
14207
+ user_agreement: "\u7528\u6237\u534F\u8BAE",
14208
+ privacy_policy: "\u9690\u79C1\u653F\u7B56"
14209
+ }
14191
14210
  },
14192
14211
  errors: {
14193
14212
  rateLimited: "\u5C1D\u8BD5\u6B21\u6570\u8FC7\u591A\u3002\u8BF7\u7A0D\u7B49\u51E0\u5206\u949F\u540E\u91CD\u8BD5\u3002",
@@ -14846,6 +14865,9 @@ var zh_TW_default = {
14846
14865
  transactionBreakdown: "\u4EA4\u6613\u660E\u7D30",
14847
14866
  networkFee: "\u7DB2\u8DEF\u624B\u7E8C\u8CBB",
14848
14867
  confirmOrder: "\u78BA\u8A8D\u8A02\u55AE",
14868
+ mfaEnrollmentTitle: "\u8ACB\u555F\u7528\u7C21\u8A0A\u6216 Authy \u96D9\u91CD\u9A57\u8B49",
14869
+ 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",
14870
+ mfaEnrollmentSettingsLink: "\u958B\u555F Coinbase \u5B89\u5168\u8A2D\u5B9A",
14849
14871
  termsNoticePrefix: "\u9EDE\u64CA\u300C\u78BA\u8A8D\u8A02\u55AE\u300D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u5011\u7684",
14850
14872
  termsNoticeLink: "\u689D\u6B3E",
14851
14873
  termsNoticeSuffix: "\u3002"
@@ -14976,7 +14998,12 @@ var zh_TW_default = {
14976
14998
  prefix: "\u7E7C\u7E8C\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
14977
14999
  separator: "\u3001",
14978
15000
  lastSeparator: "\u548C",
14979
- suffix: "\u3002Coinbase \u662F\u672C\u6CD5\u5E63\u514C\u52A0\u5BC6\u8CA8\u5E63\u5132\u503C\u670D\u52D9\u7684\u53D7\u76E3\u7BA1\u63D0\u4F9B\u65B9\u3002"
15001
+ suffix: "\u3002",
15002
+ agreements: {
15003
+ guest_checkout_terms: "\u670D\u52D9\u689D\u6B3E",
15004
+ user_agreement: "\u4F7F\u7528\u8005\u5354\u8B70",
15005
+ privacy_policy: "\u96B1\u79C1\u6B0A\u653F\u7B56"
15006
+ }
14980
15007
  },
14981
15008
  errors: {
14982
15009
  rateLimited: "\u5617\u8A66\u6B21\u6578\u904E\u591A\u3002\u8ACB\u7A0D\u7B49\u5E7E\u5206\u9418\u5F8C\u91CD\u8A66\u3002",
@@ -15892,6 +15919,13 @@ function useAnalytics() {
15892
15919
  );
15893
15920
  return { track, startSession, endSession, getSessionId, setUserId, subscribe };
15894
15921
  }
15922
+ function useStampInternalUserId({ internalUserId }) {
15923
+ const { setUserId } = useAnalytics();
15924
+ useEffect32(() => {
15925
+ if (!internalUserId) return;
15926
+ setUserId(internalUserId);
15927
+ }, [internalUserId, setUserId]);
15928
+ }
15895
15929
  function useDepositAddress(params) {
15896
15930
  const {
15897
15931
  userId,
@@ -15904,7 +15938,6 @@ function useDepositAddress(params) {
15904
15938
  contractCalls,
15905
15939
  enabled = true
15906
15940
  } = params;
15907
- const { setUserId } = useAnalytics();
15908
15941
  const query = useQuery({
15909
15942
  queryKey: [
15910
15943
  "unifold",
@@ -15947,11 +15980,7 @@ function useDepositAddress(params) {
15947
15980
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
15948
15981
  // 1s, 2s, 4s (max 10s)
15949
15982
  });
15950
- useEffect32(() => {
15951
- if (query.data?.user_id) {
15952
- setUserId(query.data.user_id);
15953
- }
15954
- }, [query.data?.user_id, setUserId]);
15983
+ useStampInternalUserId({ internalUserId: query.data?.user_id });
15955
15984
  return query;
15956
15985
  }
15957
15986
  function useDebounce(value, delay) {
@@ -18174,7 +18203,11 @@ function BuyWithCard({
18174
18203
  method: "card",
18175
18204
  flow_type: "deposit",
18176
18205
  provider: selectedProvider.service_provider,
18177
- amount_usd: amount
18206
+ amount_usd: amount,
18207
+ // The execution only exists once the provider's payout lands on this
18208
+ // wallet, and it carries this id — so it's the join key for a purchase
18209
+ // that starts here and never reaches flow_completed.
18210
+ deposit_wallet_id: depositWalletId
18178
18211
  });
18179
18212
  onEvent?.({
18180
18213
  id: generatePrefixedKSUID2("sevt"),
@@ -19611,6 +19644,8 @@ var BuyWithWalletPay = React82.forwardRef(
19611
19644
  const [limitUpgradeError, setLimitUpgradeError] = useState152(null);
19612
19645
  const [upgradeSubmitting, setUpgradeSubmitting] = useState152(false);
19613
19646
  const upgradeFlowAbortRef = useRef62(null);
19647
+ const applyLimitRoutingRef = useRef62(() => {
19648
+ });
19614
19649
  const [amount, setAmount] = useState152(amountUsd ?? "");
19615
19650
  const [preparedOrder, setPreparedOrder] = useState152(null);
19616
19651
  const sessionAbortRef = useRef62(null);
@@ -19745,6 +19780,14 @@ var BuyWithWalletPay = React82.forwardRef(
19745
19780
  },
19746
19781
  [email, normalizedPhone, userId]
19747
19782
  );
19783
+ const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
19784
+ userId,
19785
+ publishableKey,
19786
+ normalizedPhone,
19787
+ userEmail,
19788
+ sessionPhoneVerified: verificationSession?.phone?.status === "verified",
19789
+ isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
19790
+ });
19748
19791
  const createSessionAndSendOtp = useCallback42(async () => {
19749
19792
  setView("submitting_session");
19750
19793
  setErrorMessage("");
@@ -19754,7 +19797,12 @@ var BuyWithWalletPay = React82.forwardRef(
19754
19797
  email,
19755
19798
  phone: normalizedPhone,
19756
19799
  terms_accepted: true,
19757
- email_already_verified: true
19800
+ // TODO: when the API honors `false`, this will trigger email OTP.
19801
+ // Today `false` still skips email (we don't verify it) and JWT ev
19802
+ // is null. Don't send `true` — that was a fake attest.
19803
+ email_already_verified: false
19804
+ // Coinbase stays Redis-only + JWT until bank-transfer identity
19805
+ // is live. Do not persist from this path yet.
19758
19806
  },
19759
19807
  publishableKey
19760
19808
  );
@@ -19764,6 +19812,34 @@ var BuyWithWalletPay = React82.forwardRef(
19764
19812
  }
19765
19813
  setClientSecret(session.client_secret);
19766
19814
  storeWalletPaySession();
19815
+ if (session.status === "verified") {
19816
+ const tokenRes = await exchangeOnrampVerificationToken(
19817
+ session.id,
19818
+ session.client_secret,
19819
+ publishableKey
19820
+ );
19821
+ setOnrampToken(tokenRes);
19822
+ storeWalletPaySession({
19823
+ emailVerifiedAt: session.email.verified_at,
19824
+ phoneVerifiedAt: session.phone.verified_at,
19825
+ onrampToken: tokenRes.token,
19826
+ onrampTokenExpiresAtMs: Date.now() + tokenRes.expires_in * 1e3
19827
+ });
19828
+ if (amountUsd) setAmount(amountUsd);
19829
+ try {
19830
+ const result = await refetchWalletPayLimits();
19831
+ if (result.data) {
19832
+ const nextView = getViewForLimitStatus(result.data);
19833
+ if (nextView) {
19834
+ applyLimitRoutingRef.current(nextView, result.data.upgrade_status);
19835
+ return;
19836
+ }
19837
+ }
19838
+ } catch {
19839
+ }
19840
+ setView("amount");
19841
+ return;
19842
+ }
19767
19843
  await sendOnrampVerificationOtp(session.id, "phone", session.client_secret, publishableKey);
19768
19844
  setResendCooldown(30);
19769
19845
  setView("phone_otp");
@@ -19772,19 +19848,19 @@ var BuyWithWalletPay = React82.forwardRef(
19772
19848
  setErrorMessage(prettifyVerificationError(raw));
19773
19849
  setView("phone_input");
19774
19850
  }
19775
- }, [email, normalizedPhone, publishableKey, storeWalletPaySession]);
19851
+ }, [
19852
+ email,
19853
+ normalizedPhone,
19854
+ publishableKey,
19855
+ storeWalletPaySession,
19856
+ userId,
19857
+ amountUsd,
19858
+ refetchWalletPayLimits
19859
+ ]);
19776
19860
  const clearUpgradeFields = useCallback42(() => {
19777
19861
  setSsnLast4("");
19778
19862
  setDobInput("");
19779
19863
  }, []);
19780
- const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
19781
- userId,
19782
- publishableKey,
19783
- normalizedPhone,
19784
- userEmail,
19785
- sessionPhoneVerified: verificationSession?.phone?.status === "verified",
19786
- isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
19787
- });
19788
19864
  const pollLimitUpgradeStatus = useCallback42(
19789
19865
  async (signal) => {
19790
19866
  const POLL_INTERVAL_MS5 = 1500;
@@ -19895,6 +19971,7 @@ var BuyWithWalletPay = React82.forwardRef(
19895
19971
  },
19896
19972
  [startUpgradePolling]
19897
19973
  );
19974
+ applyLimitRoutingRef.current = applyLimitRouting;
19898
19975
  const hasInitializedRef = useRef62(false);
19899
19976
  useEffect122(() => {
19900
19977
  if (hasInitializedRef.current) return;
@@ -20124,7 +20201,10 @@ var BuyWithWalletPay = React82.forwardRef(
20124
20201
  track("flow_started", {
20125
20202
  method,
20126
20203
  flow_type: "deposit",
20127
- amount_usd: walletPayAmountUsd
20204
+ amount_usd: walletPayAmountUsd,
20205
+ // No execution yet — one appears when the payout lands on this
20206
+ // wallet, carrying the same id.
20207
+ deposit_wallet_id: depositWalletId
20128
20208
  });
20129
20209
  onEvent?.({
20130
20210
  id: generatePrefixedKSUID32("sevt"),
@@ -20174,6 +20254,7 @@ var BuyWithWalletPay = React82.forwardRef(
20174
20254
  defaultTokenLoading,
20175
20255
  defaultTokenError,
20176
20256
  depositWallet?.address,
20257
+ depositWalletId,
20177
20258
  userEmail,
20178
20259
  publishableKey,
20179
20260
  onEvent,
@@ -21148,7 +21229,7 @@ var FALLBACK_AGREEMENTS = [
21148
21229
  {
21149
21230
  key: "guest_checkout_terms",
21150
21231
  name: "Guest Checkout Terms of Service",
21151
- url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
21232
+ url: "https://www.coinbase.com/legal/guest-checkout/us"
21152
21233
  },
21153
21234
  {
21154
21235
  key: "user_agreement",
@@ -21168,22 +21249,24 @@ function LegalDisclaimer({ legalAgreements, loading }) {
21168
21249
  return /* @__PURE__ */ jsxs14(
21169
21250
  "div",
21170
21251
  {
21171
- className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse",
21252
+ className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse uf-opacity-50",
21172
21253
  "aria-hidden": true,
21173
21254
  "aria-busy": "true",
21174
21255
  children: [
21175
- /* @__PURE__ */ jsx18("div", { className: "uf-h-2.5 uf-rounded uf-w-full", style: { backgroundColor: colors2.card } }),
21176
- /* @__PURE__ */ jsx18("div", { className: "uf-h-2.5 uf-rounded uf-w-11/12", style: { backgroundColor: colors2.card } }),
21177
- /* @__PURE__ */ jsx18("div", { className: "uf-h-2.5 uf-rounded uf-w-3/4", style: { backgroundColor: colors2.card } })
21256
+ /* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-full", style: { backgroundColor: colors2.card } }),
21257
+ /* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-11/12", style: { backgroundColor: colors2.card } }),
21258
+ /* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-3/4", style: { backgroundColor: colors2.card } })
21178
21259
  ]
21179
21260
  }
21180
21261
  );
21181
21262
  }
21182
21263
  const agreements = legalAgreements?.agreements ?? FALLBACK_AGREEMENTS;
21264
+ const shortLabels = t.agreements;
21265
+ const lastSeparator = t.lastSeparator.replace(/\s+$/, "\xA0");
21183
21266
  return /* @__PURE__ */ jsxs14(
21184
21267
  "p",
21185
21268
  {
21186
- className: "uf-text-[11px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-px-1",
21269
+ className: "uf-text-[10px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-opacity-60 uf-text-center",
21187
21270
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
21188
21271
  children: [
21189
21272
  t.prefix,
@@ -21194,12 +21277,12 @@ function LegalDisclaimer({ legalAgreements, loading }) {
21194
21277
  href: a.url,
21195
21278
  target: "_blank",
21196
21279
  rel: "noopener noreferrer",
21197
- className: "uf-underline",
21198
- style: { color: colors2.foreground },
21199
- children: a.name
21280
+ className: "uf-no-underline",
21281
+ style: { color: "inherit", textDecoration: "none", whiteSpace: "nowrap" },
21282
+ children: shortLabels[a.key] ?? a.name
21200
21283
  }
21201
21284
  ),
21202
- idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? t.lastSeparator : ""
21285
+ idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? lastSeparator : ""
21203
21286
  ] }, a.key)),
21204
21287
  t.suffix
21205
21288
  ]
@@ -21842,6 +21925,7 @@ function PayWithCashApp({
21842
21925
  destinationChainType,
21843
21926
  destinationChainId,
21844
21927
  destinationTokenAddress,
21928
+ contractCalls,
21845
21929
  cashAppIconUrl,
21846
21930
  view: controlledView,
21847
21931
  onViewChange,
@@ -21934,7 +22018,8 @@ function PayWithCashApp({
21934
22018
  destination_token_address: destinationTokenAddress,
21935
22019
  recipient_address: recipientAddress,
21936
22020
  source_amount: amount,
21937
- external_id: externalId
22021
+ external_id: externalId,
22022
+ ...contractCalls?.length ? { contract_calls: contractCalls } : {}
21938
22023
  },
21939
22024
  publishableKey
21940
22025
  );
@@ -21947,7 +22032,10 @@ function PayWithCashApp({
21947
22032
  track("flow_started", {
21948
22033
  method: "cashapp",
21949
22034
  flow_type: "deposit",
21950
- amount_usd: amount
22035
+ amount_usd: amount,
22036
+ // No execution yet — one appears when the payout lands on this
22037
+ // wallet, carrying the same id.
22038
+ deposit_wallet_id: depositWalletId
21951
22039
  });
21952
22040
  onEvent?.({
21953
22041
  id: generatePrefixedKSUID5("sevt"),
@@ -21972,6 +22060,8 @@ function PayWithCashApp({
21972
22060
  destinationChainType,
21973
22061
  destinationChainId,
21974
22062
  destinationTokenAddress,
22063
+ contractCalls,
22064
+ depositWalletId,
21975
22065
  onEvent,
21976
22066
  onDepositError,
21977
22067
  track,
@@ -22573,7 +22663,10 @@ function BankTransfer({
22573
22663
  method: "bank_transfer",
22574
22664
  flow_type: "deposit",
22575
22665
  provider: request.service_provider,
22576
- amount_usd: request.source_amount
22666
+ amount_usd: request.source_amount,
22667
+ // No execution yet — one appears when the provider's payout lands on
22668
+ // this wallet, carrying the same id.
22669
+ deposit_wallet_id: pollingWalletId
22577
22670
  });
22578
22671
  onEvent?.({
22579
22672
  id: generatePrefixedKSUID6("sevt"),
@@ -28654,7 +28747,11 @@ function PayWithStripeLink({
28654
28747
  if (checkoutResult.successful) {
28655
28748
  handledTerminalSessionRef.current = null;
28656
28749
  executionReconciledSessionRef.current = null;
28657
- track("flow_started", { method: "stripe_link", flow_type: "deposit" });
28750
+ track("flow_started", {
28751
+ method: "stripe_link",
28752
+ flow_type: "deposit",
28753
+ deposit_wallet_id: depositWalletId
28754
+ });
28658
28755
  setConfirmedSessionId(activeSessionId);
28659
28756
  setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
28660
28757
  if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
@@ -30151,7 +30248,14 @@ function PayWithStripeLink({
30151
30248
  ]
30152
30249
  }
30153
30250
  ),
30154
- /* @__PURE__ */ jsx50("div", { ref: authMountRef, className: "uf-w-full uf-min-h-[200px]" })
30251
+ /* @__PURE__ */ jsx50(
30252
+ "div",
30253
+ {
30254
+ ref: authMountRef,
30255
+ className: "uf-w-full uf-min-h-[200px]",
30256
+ style: { colorScheme: "only light" }
30257
+ }
30258
+ )
30155
30259
  ]
30156
30260
  }
30157
30261
  );
@@ -31414,6 +31518,9 @@ function CoinbaseConnect({
31414
31518
  flow_type: "deposit",
31415
31519
  method: "exchange_connect",
31416
31520
  provider: IntegrationProvider.COINBASE,
31521
+ // No execution yet — one appears when the exchange's transfer lands on
31522
+ // this wallet, carrying the same id.
31523
+ deposit_wallet_id: transferDepositWalletId,
31417
31524
  amount_usd: sendAmount || void 0,
31418
31525
  currency: selectedAsset?.currency.toLowerCase().replace(/[^a-z0-9]+/g, "_"),
31419
31526
  chain: sourceChain?.chain_id,
@@ -31421,6 +31528,34 @@ function CoinbaseConnect({
31421
31528
  network: sourceChain?.network
31422
31529
  });
31423
31530
  };
31531
+ const applyConfirmResult = (result) => {
31532
+ if (result.status === "mfa_required") {
31533
+ track("verification_started", {
31534
+ flow_type: "deposit",
31535
+ method: "exchange_connect",
31536
+ provider: IntegrationProvider.COINBASE,
31537
+ verification_type: "mfa",
31538
+ verification_status: result.status
31539
+ });
31540
+ transitionTo("mfa");
31541
+ setMfaCode("");
31542
+ setMfaError(false);
31543
+ } else if (result.status === "mfa_enrollment_required") {
31544
+ transitionTo("mfa_enrollment");
31545
+ } else if (result.status === "completed") {
31546
+ trackTransferStarted();
31547
+ setConfirmResult(result);
31548
+ transitionTo("success");
31549
+ onTransferSuccess?.(result);
31550
+ } else {
31551
+ setErrorMessage(result.message || t.errors.transferFailed);
31552
+ transitionTo("error");
31553
+ onTransferError?.({
31554
+ message: result.message || t.errors.transferFailed,
31555
+ code: result.status
31556
+ });
31557
+ }
31558
+ };
31424
31559
  const handleConfirmTransfer = async () => {
31425
31560
  if (!transferIntent || !accessToken) return;
31426
31561
  setIsLoading(true);
@@ -31455,30 +31590,7 @@ function CoinbaseConnect({
31455
31590
  });
31456
31591
  throw err;
31457
31592
  });
31458
- if (result.status === "mfa_required") {
31459
- track("verification_started", {
31460
- flow_type: "deposit",
31461
- method: "exchange_connect",
31462
- provider: IntegrationProvider.COINBASE,
31463
- verification_type: "mfa",
31464
- verification_status: result.status
31465
- });
31466
- transitionTo("mfa");
31467
- setMfaCode("");
31468
- setMfaError(false);
31469
- } else if (result.status === "completed") {
31470
- trackTransferStarted();
31471
- setConfirmResult(result);
31472
- transitionTo("success");
31473
- onTransferSuccess?.(result);
31474
- } else {
31475
- setErrorMessage(result.message || t.errors.transferFailed);
31476
- transitionTo("error");
31477
- onTransferError?.({
31478
- message: result.message || t.errors.transferFailed,
31479
- code: result.status
31480
- });
31481
- }
31593
+ applyConfirmResult(result);
31482
31594
  } catch (err) {
31483
31595
  const message = err instanceof Error ? err.message : t.errors.transferFailed;
31484
31596
  setErrorMessage(message);
@@ -31635,6 +31747,9 @@ function CoinbaseConnect({
31635
31747
  setShowTransferDetails(false);
31636
31748
  transitionTo("enter_amount");
31637
31749
  break;
31750
+ case "mfa_enrollment":
31751
+ transitionTo("transfer_confirm");
31752
+ break;
31638
31753
  case "mfa":
31639
31754
  transitionTo("transfer_confirm");
31640
31755
  break;
@@ -33191,6 +33306,55 @@ function CoinbaseConnect({
33191
33306
  ] })
33192
33307
  ] });
33193
33308
  }
33309
+ if (view === "mfa_enrollment") {
33310
+ return /* @__PURE__ */ jsxs46(Fragment92, { children: [
33311
+ /* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
33312
+ /* @__PURE__ */ jsxs46(
33313
+ "div",
33314
+ {
33315
+ className: "uf-flex uf-flex-col uf-items-center uf-px-4 uf-pb-4",
33316
+ style: viewTransitionStyle,
33317
+ children: [
33318
+ /* @__PURE__ */ jsx51(
33319
+ DepositErrorState,
33320
+ {
33321
+ title: t.transfer.mfaEnrollmentTitle,
33322
+ message: t.transfer.mfaEnrollmentMessage
33323
+ }
33324
+ ),
33325
+ /* @__PURE__ */ jsxs46(
33326
+ "a",
33327
+ {
33328
+ href: "https://www.coinbase.com/settings/security",
33329
+ target: "_blank",
33330
+ rel: "noopener noreferrer",
33331
+ className: "uf-text-sm uf-underline uf-mb-8 uf-inline-flex uf-items-center uf-gap-1",
33332
+ style: { color: colors2.primary, fontFamily: fonts.medium },
33333
+ children: [
33334
+ t.transfer.mfaEnrollmentSettingsLink,
33335
+ /* @__PURE__ */ jsx51(ExternalLink, { className: "uf-w-3.5 uf-h-3.5" })
33336
+ ]
33337
+ }
33338
+ ),
33339
+ /* @__PURE__ */ jsx51(
33340
+ "button",
33341
+ {
33342
+ onClick: handleConfirmTransfer,
33343
+ disabled: isLoading,
33344
+ 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",
33345
+ style: {
33346
+ backgroundColor: colors2.primary,
33347
+ color: "#fff",
33348
+ fontFamily: fonts.medium
33349
+ },
33350
+ children: isLoading ? /* @__PURE__ */ jsx51(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin" }) : t.continue
33351
+ }
33352
+ )
33353
+ ]
33354
+ }
33355
+ )
33356
+ ] });
33357
+ }
33194
33358
  if (view === "mfa") {
33195
33359
  return /* @__PURE__ */ jsxs46(Fragment92, { children: [
33196
33360
  /* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
@@ -39118,7 +39282,11 @@ function WalletConnect({
39118
39282
  chain: String(token.chain_id),
39119
39283
  network: token.network,
39120
39284
  token: token.symbol ?? token.token_address,
39121
- currency: token.currency
39285
+ currency: token.currency,
39286
+ // No execution exists yet — it's created when this send lands on the
39287
+ // wallet. The wallet id is what that execution will carry, so it's
39288
+ // how a send that never completes is matched to what followed.
39289
+ deposit_wallet_id: activeDepositWallet?.id
39122
39290
  });
39123
39291
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
39124
39292
  setHasSignedTransaction(true);
@@ -39705,7 +39873,7 @@ function DepositModal({
39705
39873
  const applePaySubTitle = applePaySubTitleProp ?? t.applePayMenu.subtitle;
39706
39874
  const googlePayTitle = googlePayTitleProp ?? t.googlePayMenu.title;
39707
39875
  const googlePaySubTitle = googlePaySubTitleProp ?? t.googlePayMenu.subtitle;
39708
- const { track, startSession, endSession, getSessionId, subscribe } = useAnalytics();
39876
+ const { track, startSession, endSession, getSessionId, setUserId, subscribe } = useAnalytics();
39709
39877
  const normalizedPrefilledAmountUsd = useMemo17(
39710
39878
  () => normalizePrefilledUsdAmount(prefilledAmountUsd),
39711
39879
  [prefilledAmountUsd]
@@ -39713,6 +39881,7 @@ function DepositModal({
39713
39881
  const analyticsMethod = (method) => method === "transfer" ? "transfer_crypto" : method;
39714
39882
  const journeyActiveRef = useRef16(false);
39715
39883
  const journeySessionIdRef = useRef16(void 0);
39884
+ const journeyExternalUserIdRef = useRef16(void 0);
39716
39885
  const externalUserId = userId || void 0;
39717
39886
  const emitEvent = useCallback14(
39718
39887
  (event) => onEvent?.({ ...event, externalUserId }),
@@ -39740,6 +39909,9 @@ function DepositModal({
39740
39909
  method: analyticsMethod(method),
39741
39910
  flow_type: "deposit",
39742
39911
  amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
39912
+ // The one high-cardinality field we do send: the join key from a
39913
+ // funnel session back to the execution row it produced.
39914
+ execution_id: data.executionId ?? execution?.id,
39743
39915
  // Flat, low-cardinality execution dimensions for PostHog breakdowns
39744
39916
  // (precise/opaque fields like base units, addresses, tx hashes live in
39745
39917
  // the onEvent DirectExecution instead).
@@ -39767,6 +39939,7 @@ function DepositModal({
39767
39939
  method: analyticsMethod(method),
39768
39940
  flow_type: "deposit",
39769
39941
  error_code: error.code,
39942
+ execution_id: execution?.id,
39770
39943
  failure_reason: execution?.failureReason ?? void 0,
39771
39944
  status: execution?.status,
39772
39945
  source_chain_type: execution?.sourceChainType,
@@ -40195,8 +40368,10 @@ function DepositModal({
40195
40368
  const beginJourney = useCallback14(() => {
40196
40369
  journeySessionIdRef.current = startSession();
40197
40370
  journeyActiveRef.current = true;
40371
+ journeyExternalUserIdRef.current = userId;
40372
+ setUserId(null);
40198
40373
  track("widget_opened", { flow_type: "deposit" });
40199
- }, [startSession, track]);
40374
+ }, [startSession, track, setUserId, userId]);
40200
40375
  const handleClose = () => {
40201
40376
  finalizeJourney();
40202
40377
  onOpenChange(false);
@@ -40221,6 +40396,11 @@ function DepositModal({
40221
40396
  }
40222
40397
  beginJourney();
40223
40398
  }, [open]);
40399
+ useLayoutEffect22(() => {
40400
+ if (!open || journeyExternalUserIdRef.current === userId) return;
40401
+ journeyExternalUserIdRef.current = userId;
40402
+ setUserId(null);
40403
+ }, [open, userId, setUserId]);
40224
40404
  useLayoutEffect22(() => {
40225
40405
  if (!open) return;
40226
40406
  if (resetViewTimeoutRef.current) {
@@ -41132,6 +41312,7 @@ function DepositModal({
41132
41312
  destinationChainType,
41133
41313
  destinationChainId,
41134
41314
  destinationTokenAddress,
41315
+ contractCalls,
41135
41316
  cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
41136
41317
  view: cashAppView,
41137
41318
  onViewChange: setCashAppView,
@@ -41467,6 +41648,9 @@ function CheckoutModal({
41467
41648
  flowCompletedRef.current = true;
41468
41649
  track("flow_completed", {
41469
41650
  flow_type: "checkout",
41651
+ // Checkout has no direct execution; the intent is what a funnel
41652
+ // session joins back to.
41653
+ payment_intent_id: data.paymentIntentId,
41470
41654
  ...method ? { method: method === "transfer" ? "transfer_crypto" : method } : {}
41471
41655
  });
41472
41656
  }
@@ -41687,7 +41871,7 @@ function CheckoutModal({
41687
41871
  journeySessionIdRef.current = startSession();
41688
41872
  journeyActiveRef.current = true;
41689
41873
  flowCompletedRef.current = false;
41690
- setUserId(null);
41874
+ setUserId(paymentIntentUserId ?? null);
41691
41875
  track("widget_opened", { flow_type: "checkout" });
41692
41876
  if (resetViewTimeoutRef.current) {
41693
41877
  clearTimeout(resetViewTimeoutRef.current);
@@ -42272,7 +42456,7 @@ function useAddressBalance(params) {
42272
42456
  }
42273
42457
  function useExecutions(userId, publishableKey, options) {
42274
42458
  const actionType = options?.actionType ?? ActionType4.Deposit;
42275
- return useQuery24({
42459
+ const query = useQuery24({
42276
42460
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
42277
42461
  queryFn: () => queryExecutions4(userId, publishableKey, actionType),
42278
42462
  enabled: (options?.enabled ?? true) && !!userId,
@@ -42281,6 +42465,8 @@ function useExecutions(userId, publishableKey, options) {
42281
42465
  gcTime: 1e3 * 60 * 5,
42282
42466
  refetchOnWindowFocus: false
42283
42467
  });
42468
+ useStampInternalUserId({ internalUserId: query.data?.data[0]?.user_id });
42469
+ return query;
42284
42470
  }
42285
42471
  var POLL_INTERVAL_MS4 = 2500;
42286
42472
  var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
@@ -42655,7 +42841,6 @@ function useGetDepositAddress(params) {
42655
42841
  actionType,
42656
42842
  enabled = true
42657
42843
  } = params;
42658
- const { setUserId } = useAnalytics();
42659
42844
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
42660
42845
  const query = useQuery26({
42661
42846
  queryKey: [
@@ -42687,11 +42872,7 @@ function useGetDepositAddress(params) {
42687
42872
  refetchOnWindowFocus: false,
42688
42873
  retry: 1
42689
42874
  });
42690
- useEffect45(() => {
42691
- if (query.data?.user_id) {
42692
- setUserId(query.data.user_id);
42693
- }
42694
- }, [query.data?.user_id, setUserId]);
42875
+ useStampInternalUserId({ internalUserId: query.data?.user_id });
42695
42876
  return query;
42696
42877
  }
42697
42878
  var isHypercore = (chainId) => chainId === HYPERCORE_CHAIN_ID;
@@ -42826,14 +43007,14 @@ function WithdrawForm({
42826
43007
  const [detailsExpanded, setDetailsExpanded] = useState47(false);
42827
43008
  const [glossaryOpen, setGlossaryOpen] = useState47(false);
42828
43009
  const [isMaxed, setIsMaxed] = useState47(false);
42829
- useEffect46(() => {
43010
+ useEffect45(() => {
42830
43011
  setRecipientAddress(recipientAddressProp || "");
42831
43012
  setAmount("");
42832
43013
  setInputUnit("fiat");
42833
43014
  setSubmitError(null);
42834
43015
  setIsMaxed(false);
42835
43016
  }, [recipientAddressProp]);
42836
- useEffect46(() => {
43017
+ useEffect45(() => {
42837
43018
  setIsMaxed(false);
42838
43019
  }, [balanceData?.balanceBaseUnit]);
42839
43020
  const trimmedAddress = recipientAddress.trim();
@@ -43643,7 +43824,7 @@ function WithdrawConfirmingView({
43643
43824
  const t = strings.withdrawModal.details;
43644
43825
  const [showButton, setShowButton] = useState48(false);
43645
43826
  const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
43646
- useEffect47(() => {
43827
+ useEffect46(() => {
43647
43828
  if (latestExecution) return;
43648
43829
  const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
43649
43830
  return () => clearTimeout(timer);
@@ -43795,7 +43976,7 @@ function WithdrawModal({
43795
43976
  );
43796
43977
  const onEventRef = useRef20(emitEvent);
43797
43978
  onEventRef.current = emitEvent;
43798
- useEffect48(
43979
+ useEffect47(
43799
43980
  () => subscribe((event) => {
43800
43981
  if (event.properties?.flow_type !== "withdraw") return;
43801
43982
  const selection = selectionPayload(event);
@@ -43812,12 +43993,16 @@ function WithdrawModal({
43812
43993
  );
43813
43994
  const journeyActiveRef = useRef20(false);
43814
43995
  const journeySessionIdRef = useRef20(void 0);
43996
+ const journeyExternalUserIdRef = useRef20(void 0);
43815
43997
  const onWithdrawSuccessFor = useCallback17(
43816
43998
  (data) => {
43817
43999
  const execution = data.execution?.data.object;
43818
44000
  track("flow_completed", {
43819
44001
  flow_type: "withdraw",
43820
44002
  amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
44003
+ // The one high-cardinality field we do send: the join key from a
44004
+ // funnel session back to the execution row it produced.
44005
+ execution_id: data.executionId ?? execution?.id,
43821
44006
  // Flat, low-cardinality execution dimensions for PostHog breakdowns.
43822
44007
  status: execution?.status,
43823
44008
  source_chain_type: execution?.sourceChainType,
@@ -43838,6 +44023,7 @@ function WithdrawModal({
43838
44023
  track("flow_failed", {
43839
44024
  flow_type: "withdraw",
43840
44025
  error_code: error.code,
44026
+ execution_id: execution?.id,
43841
44027
  failure_reason: execution?.failureReason ?? void 0,
43842
44028
  status: execution?.status,
43843
44029
  source_chain_type: execution?.sourceChainType,
@@ -43859,7 +44045,7 @@ function WithdrawModal({
43859
44045
  const [resolvedTheme, setResolvedTheme] = useState49(
43860
44046
  theme === "auto" ? "dark" : theme
43861
44047
  );
43862
- useEffect48(() => {
44048
+ useEffect47(() => {
43863
44049
  if (theme === "auto") {
43864
44050
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
43865
44051
  setResolvedTheme(mq.matches ? "dark" : "light");
@@ -43911,6 +44097,7 @@ function WithdrawModal({
43911
44097
  ) ?? null : null;
43912
44098
  const [view, setView] = useState49("form");
43913
44099
  const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState49();
44100
+ const withdrawDepositWalletIdRef = useRef20(void 0);
43914
44101
  const [selectedExecution, setSelectedExecution] = useState49(null);
43915
44102
  const [submittedTxInfo, setSubmittedTxInfo] = useState49(null);
43916
44103
  const { executions: realtimeExecutions } = useWithdrawPolling({
@@ -43948,6 +44135,7 @@ function WithdrawModal({
43948
44135
  if (!depositWallet) {
43949
44136
  throw new Error(`No deposit wallet available for ${sourceChainType}`);
43950
44137
  }
44138
+ withdrawDepositWalletIdRef.current = depositWallet.id;
43951
44139
  setWithdrawDepositWalletId(depositWallet.id);
43952
44140
  return depositWallet;
43953
44141
  },
@@ -43967,7 +44155,12 @@ function WithdrawModal({
43967
44155
  currency: tokenData?.currency,
43968
44156
  amount: txInfo.amount,
43969
44157
  amount_base_unit: txInfo.amountBaseUnit,
43970
- ...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {}
44158
+ ...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {},
44159
+ // The execution doesn't exist yet — it's created when the user's send
44160
+ // lands on the withdraw deposit wallet, and carries this id. So a
44161
+ // withdrawal confirmed but never completed still joins to whatever
44162
+ // did (or didn't) follow on that wallet.
44163
+ deposit_wallet_id: withdrawDepositWalletIdRef.current
43971
44164
  });
43972
44165
  emitEvent({
43973
44166
  id: generatePrefixedKSUID12("sevt"),
@@ -44001,8 +44194,10 @@ function WithdrawModal({
44001
44194
  const beginJourney = useCallback17(() => {
44002
44195
  journeySessionIdRef.current = startSession();
44003
44196
  journeyActiveRef.current = true;
44197
+ journeyExternalUserIdRef.current = externalUserId;
44198
+ setUserId(null);
44004
44199
  track("widget_opened", { flow_type: "withdraw" });
44005
- }, [startSession, track]);
44200
+ }, [startSession, track, setUserId, externalUserId]);
44006
44201
  const handleClose = useCallback17(() => {
44007
44202
  finalizeJourney();
44008
44203
  onOpenChange(false);
@@ -44011,6 +44206,7 @@ function WithdrawModal({
44011
44206
  setView("form");
44012
44207
  setSelectedExecution(null);
44013
44208
  setSubmittedTxInfo(null);
44209
+ withdrawDepositWalletIdRef.current = void 0;
44014
44210
  setWithdrawDepositWalletId(void 0);
44015
44211
  resetViewTimeoutRef.current = null;
44016
44212
  }, 200);
@@ -44028,9 +44224,15 @@ function WithdrawModal({
44028
44224
  setView("form");
44029
44225
  setSelectedExecution(null);
44030
44226
  setSubmittedTxInfo(null);
44227
+ withdrawDepositWalletIdRef.current = void 0;
44031
44228
  setWithdrawDepositWalletId(void 0);
44032
44229
  }, [open]);
44033
- useEffect48(
44230
+ useLayoutEffect42(() => {
44231
+ if (!open || journeyExternalUserIdRef.current === externalUserId) return;
44232
+ journeyExternalUserIdRef.current = externalUserId;
44233
+ setUserId(null);
44234
+ }, [open, externalUserId, setUserId]);
44235
+ useEffect47(
44034
44236
  () => () => {
44035
44237
  if (journeyActiveRef.current) {
44036
44238
  journeyActiveRef.current = false;
@@ -44039,12 +44241,12 @@ function WithdrawModal({
44039
44241
  },
44040
44242
  [endSession, getSessionId]
44041
44243
  );
44042
- useEffect48(() => {
44244
+ useEffect47(() => {
44043
44245
  if (!open) return;
44044
44246
  const screen = view === "detail" ? "tracker_detail" : view;
44045
44247
  track("screen_viewed", { flow_type: "withdraw", screen });
44046
44248
  }, [open, view, track]);
44047
- useEffect48(
44249
+ useEffect47(
44048
44250
  () => () => {
44049
44251
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
44050
44252
  },