@unifold/connect-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.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";
@@ -6194,8 +6194,6 @@ import {
6194
6194
  generatePrefixedKSUID as generatePrefixedKSUID5,
6195
6195
  DepositEventType as DepositEventType4
6196
6196
  } from "@unifold/core";
6197
- import { useQuery as useQuery9 } from "@tanstack/react-query";
6198
- import { getCashAppLimits } from "@unifold/core";
6199
6197
  import { Fragment as Fragment62, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
6200
6198
  import { useCallback as useCallback62, useEffect as useEffect162, useMemo as useMemo92, useRef as useRef72, useState as useState19 } from "react";
6201
6199
  import {
@@ -6206,7 +6204,7 @@ import {
6206
6204
  getWalletByChainType as getWalletByChainType3,
6207
6205
  generatePrefixedKSUID as generatePrefixedKSUID6
6208
6206
  } from "@unifold/core";
6209
- import { useQuery as useQuery10 } from "@tanstack/react-query";
6207
+ import { useQuery as useQuery9 } from "@tanstack/react-query";
6210
6208
  import { getBankTransferProviders } from "@unifold/core";
6211
6209
  import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
6212
6210
  import { ExecutionStatus as ExecutionStatus4, getIconUrl as getIconUrl4 } from "@unifold/core";
@@ -6502,18 +6500,18 @@ import {
6502
6500
  IntegrationTransferError,
6503
6501
  IntegrationProvider
6504
6502
  } from "@unifold/core";
6505
- import { useQuery as useQuery11, keepPreviousData } from "@tanstack/react-query";
6503
+ import { useQuery as useQuery10, keepPreviousData } from "@tanstack/react-query";
6506
6504
  import { getProjectConfig } from "@unifold/core";
6507
- import { useQuery as useQuery12 } from "@tanstack/react-query";
6505
+ import { useQuery as useQuery11 } from "@tanstack/react-query";
6508
6506
  import {
6509
6507
  getIntegrationTransferDefaultToken
6510
6508
  } from "@unifold/core";
6511
6509
  import { Fragment as Fragment92, jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
6512
- import { useQuery as useQuery13 } from "@tanstack/react-query";
6510
+ import { useQuery as useQuery12 } from "@tanstack/react-query";
6513
6511
  import { getExchanges } from "@unifold/core";
6514
- import { useQuery as useQuery14 } from "@tanstack/react-query";
6512
+ import { useQuery as useQuery13 } from "@tanstack/react-query";
6515
6513
  import { getPublicIncident } from "@unifold/core";
6516
- import { useQuery as useQuery15 } from "@tanstack/react-query";
6514
+ import { useQuery as useQuery14 } from "@tanstack/react-query";
6517
6515
  import {
6518
6516
  getWalletPayProviders
6519
6517
  } from "@unifold/core";
@@ -6625,7 +6623,7 @@ function generateKSUID() {
6625
6623
  function generatePrefixedKSUID(prefix) {
6626
6624
  return `${prefix}_${generateKSUID()}`;
6627
6625
  }
6628
- var PACKAGE_VERSION = "0.1.77";
6626
+ var PACKAGE_VERSION = "0.1.79";
6629
6627
  var LIBRARY_NAME = "@unifold/analytics";
6630
6628
  var DEFAULT_DEDUP_MS = 500;
6631
6629
  var SESSION_PREFIX = "asess";
@@ -6715,8 +6713,12 @@ var EventTracker = class {
6715
6713
  }
6716
6714
  /**
6717
6715
  * 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.
6716
+ * (`user_<ksuid>`). Pass `null` to clear.
6717
+ *
6718
+ * The tracker is shared across flows and outlives any one journey, so a
6719
+ * journey stamps its own user at the start — with the id if it already
6720
+ * knows one, `null` if it doesn't — rather than inheriting whatever the
6721
+ * previous journey left here.
6720
6722
  */
6721
6723
  setUserId(userId) {
6722
6724
  this.userId = userId || void 0;
@@ -6727,8 +6729,8 @@ var EventTracker = class {
6727
6729
  * {@link EventTracker.endSession} carries it.
6728
6730
  *
6729
6731
  * 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.
6732
+ * via {@link EventTracker.setUserId}, and persists until the host replaces
6733
+ * it which the SDK's modals do on every journey start.
6732
6734
  */
6733
6735
  startSession() {
6734
6736
  this.sessionId = generatePrefixedKSUID(SESSION_PREFIX);
@@ -6775,7 +6777,7 @@ function createEventTracker(config) {
6775
6777
  // ../ui-react/dist/index.mjs
6776
6778
  import { DepositEventType as DepositEventType6 } from "@unifold/core";
6777
6779
  import { DepositEventType as DepositEventType7 } from "@unifold/core";
6778
- import { useQuery as useQuery16 } from "@tanstack/react-query";
6780
+ import { useQuery as useQuery15 } from "@tanstack/react-query";
6779
6781
  import {
6780
6782
  verifyRecipientAddress
6781
6783
  } from "@unifold/core";
@@ -11534,7 +11536,7 @@ import {
11534
11536
  getWalletByChainType as getWalletByChainType5,
11535
11537
  formatStablecoinAmount
11536
11538
  } from "@unifold/core";
11537
- import { useQuery as useQuery17 } from "@tanstack/react-query";
11539
+ import { useQuery as useQuery16 } from "@tanstack/react-query";
11538
11540
  import { checkHypercoreActivation } from "@unifold/core";
11539
11541
  import { jsx as jsx59, jsxs as jsxs52 } from "react/jsx-runtime";
11540
11542
  import { Fragment as Fragment12, jsx as jsx60, jsxs as jsxs53 } from "react/jsx-runtime";
@@ -12793,9 +12795,9 @@ import {
12793
12795
  buildHypercoreTransaction as buildHypercoreTransactionFromBackend,
12794
12796
  sendHypercoreTransaction as sendHypercoreTransactionToBackend
12795
12797
  } from "@unifold/core";
12796
- import { useQuery as useQuery18 } from "@tanstack/react-query";
12798
+ import { useQuery as useQuery17 } from "@tanstack/react-query";
12797
12799
  import { getDepositQuote } from "@unifold/core";
12798
- import { useQuery as useQuery19 } from "@tanstack/react-query";
12800
+ import { useQuery as useQuery18 } from "@tanstack/react-query";
12799
12801
  import { getExternalWallets } from "@unifold/core";
12800
12802
  import { jsx as jsx63 } from "react/jsx-runtime";
12801
12803
  import { jsx as jsx64, jsxs as jsxs56 } from "react/jsx-runtime";
@@ -12812,23 +12814,23 @@ import { jsx as jsx71 } from "react/jsx-runtime";
12812
12814
  import { useState as useState45, useEffect as useEffect43, useLayoutEffect as useLayoutEffect32, useCallback as useCallback15, useRef as useRef182, useMemo as useMemo18 } from "react";
12813
12815
  import { useEffect as useEffect422, useRef as useRef172 } from "react";
12814
12816
  import { CheckoutEventType } from "@unifold/core";
12815
- import { useQuery as useQuery20 } from "@tanstack/react-query";
12817
+ import { useQuery as useQuery19 } from "@tanstack/react-query";
12816
12818
  import { retrievePaymentIntent } from "@unifold/core";
12817
12819
  import {
12818
12820
  CheckoutEventType as CheckoutEventType2,
12819
12821
  generatePrefixedKSUID as generatePrefixedKSUID10
12820
12822
  } from "@unifold/core";
12821
12823
  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";
12823
- import { useQuery as useQuery21 } from "@tanstack/react-query";
12824
+ import { useState as useState49, useEffect as useEffect47, useLayoutEffect as useLayoutEffect42, useCallback as useCallback17, useMemo as useMemo21, useRef as useRef20 } from "react";
12825
+ import { useQuery as useQuery20 } from "@tanstack/react-query";
12824
12826
  import {
12825
12827
  getSupportedDestinationTokens
12826
12828
  } from "@unifold/core";
12827
- import { useQuery as useQuery22 } from "@tanstack/react-query";
12829
+ import { useQuery as useQuery21 } from "@tanstack/react-query";
12828
12830
  import { getSupportedDepositTokens as getSupportedDepositTokens3 } from "@unifold/core";
12829
- import { useQuery as useQuery23 } from "@tanstack/react-query";
12831
+ import { useQuery as useQuery22 } from "@tanstack/react-query";
12830
12832
  import { getAddressBalance as getAddressBalance2 } from "@unifold/core";
12831
- import { useQuery as useQuery24 } from "@tanstack/react-query";
12833
+ import { useQuery as useQuery23 } from "@tanstack/react-query";
12832
12834
  import { queryExecutions as queryExecutions4, ActionType as ActionType4 } from "@unifold/core";
12833
12835
  import { useState as useState46, useEffect as useEffect44, useRef as useRef192 } from "react";
12834
12836
  import {
@@ -12840,11 +12842,11 @@ import {
12840
12842
  ActionType as ActionType5
12841
12843
  } from "@unifold/core";
12842
12844
  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";
12845
+ import { useState as useState47, useCallback as useCallback16, useMemo as useMemo20, useEffect as useEffect45 } from "react";
12844
12846
  import {
12845
12847
  checkHypercoreActivation as checkHypercoreActivation3
12846
12848
  } from "@unifold/core";
12847
- import { useQuery as useQuery25 } from "@tanstack/react-query";
12849
+ import { useQuery as useQuery24 } from "@tanstack/react-query";
12848
12850
  import { verifyRecipientAddress as verifyRecipientAddress2 } from "@unifold/core";
12849
12851
  import {
12850
12852
  buildSolanaTransaction as buildSolanaTransaction2,
@@ -12852,13 +12854,12 @@ import {
12852
12854
  } from "@unifold/core";
12853
12855
  import { useMemo as useMemo19 } from "react";
12854
12856
  import { ActionType as ActionType6 } from "@unifold/core";
12855
- import { useEffect as useEffect45 } from "react";
12856
- import { useQuery as useQuery26 } from "@tanstack/react-query";
12857
+ import { useQuery as useQuery25 } from "@tanstack/react-query";
12857
12858
  import { getDepositAddress } from "@unifold/core";
12858
12859
  import { Fragment as Fragment18, jsx as jsx74, jsxs as jsxs64 } from "react/jsx-runtime";
12859
12860
  import { ExecutionStatus as ExecutionStatus7, getIconUrl as getIconUrl5 } from "@unifold/core";
12860
12861
  import { jsx as jsx75, jsxs as jsxs65 } from "react/jsx-runtime";
12861
- import { useState as useState48, useEffect as useEffect47 } from "react";
12862
+ import { useState as useState48, useEffect as useEffect46 } from "react";
12862
12863
  import { Fragment as Fragment19, jsx as jsx76, jsxs as jsxs66 } from "react/jsx-runtime";
12863
12864
  import {
12864
12865
  createDepositAddress as createDepositAddress2,
@@ -13268,6 +13269,9 @@ var en_default = {
13268
13269
  transactionBreakdown: "Transaction breakdown",
13269
13270
  networkFee: "Network fee",
13270
13271
  confirmOrder: "Confirm Order",
13272
+ mfaEnrollmentTitle: "Enable SMS or Authy 2FA",
13273
+ mfaEnrollmentMessage: "Please make sure you enable SMS or Authy 2FA in your Coinbase account. Press Continue after you enable it.",
13274
+ mfaEnrollmentSettingsLink: "Open Coinbase security settings",
13271
13275
  termsNoticePrefix: "By clicking on Confirm Order, you agree to our ",
13272
13276
  termsNoticeLink: "terms",
13273
13277
  termsNoticeSuffix: "."
@@ -13398,7 +13402,12 @@ var en_default = {
13398
13402
  prefix: "By continuing, you agree to Coinbase's ",
13399
13403
  separator: ", ",
13400
13404
  lastSeparator: ", and ",
13401
- suffix: ". Coinbase is the regulated provider of this fiat-to-crypto onramp."
13405
+ suffix: ".",
13406
+ agreements: {
13407
+ guest_checkout_terms: "Terms of Service",
13408
+ user_agreement: "User Agreement",
13409
+ privacy_policy: "Privacy Policy"
13410
+ }
13402
13411
  },
13403
13412
  errors: {
13404
13413
  rateLimited: "Too many attempts. Please wait a few minutes and try again.",
@@ -14057,6 +14066,9 @@ var zh_default = {
14057
14066
  transactionBreakdown: "\u4EA4\u6613\u660E\u7EC6",
14058
14067
  networkFee: "\u7F51\u7EDC\u624B\u7EED\u8D39",
14059
14068
  confirmOrder: "\u786E\u8BA4\u8BA2\u5355",
14069
+ mfaEnrollmentTitle: "\u8BF7\u542F\u7528\u77ED\u4FE1\u6216 Authy \u53CC\u91CD\u9A8C\u8BC1",
14070
+ 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",
14071
+ mfaEnrollmentSettingsLink: "\u6253\u5F00 Coinbase \u5B89\u5168\u8BBE\u7F6E",
14060
14072
  termsNoticePrefix: "\u70B9\u51FB\u201C\u786E\u8BA4\u8BA2\u5355\u201D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u4EEC\u7684",
14061
14073
  termsNoticeLink: "\u6761\u6B3E",
14062
14074
  termsNoticeSuffix: "\u3002"
@@ -14187,7 +14199,12 @@ var zh_default = {
14187
14199
  prefix: "\u7EE7\u7EED\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
14188
14200
  separator: "\u3001",
14189
14201
  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"
14202
+ suffix: "\u3002",
14203
+ agreements: {
14204
+ guest_checkout_terms: "\u670D\u52A1\u6761\u6B3E",
14205
+ user_agreement: "\u7528\u6237\u534F\u8BAE",
14206
+ privacy_policy: "\u9690\u79C1\u653F\u7B56"
14207
+ }
14191
14208
  },
14192
14209
  errors: {
14193
14210
  rateLimited: "\u5C1D\u8BD5\u6B21\u6570\u8FC7\u591A\u3002\u8BF7\u7A0D\u7B49\u51E0\u5206\u949F\u540E\u91CD\u8BD5\u3002",
@@ -14846,6 +14863,9 @@ var zh_TW_default = {
14846
14863
  transactionBreakdown: "\u4EA4\u6613\u660E\u7D30",
14847
14864
  networkFee: "\u7DB2\u8DEF\u624B\u7E8C\u8CBB",
14848
14865
  confirmOrder: "\u78BA\u8A8D\u8A02\u55AE",
14866
+ mfaEnrollmentTitle: "\u8ACB\u555F\u7528\u7C21\u8A0A\u6216 Authy \u96D9\u91CD\u9A57\u8B49",
14867
+ 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",
14868
+ mfaEnrollmentSettingsLink: "\u958B\u555F Coinbase \u5B89\u5168\u8A2D\u5B9A",
14849
14869
  termsNoticePrefix: "\u9EDE\u64CA\u300C\u78BA\u8A8D\u8A02\u55AE\u300D\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u5011\u7684",
14850
14870
  termsNoticeLink: "\u689D\u6B3E",
14851
14871
  termsNoticeSuffix: "\u3002"
@@ -14976,7 +14996,12 @@ var zh_TW_default = {
14976
14996
  prefix: "\u7E7C\u7E8C\u5373\u8868\u793A\u60A8\u540C\u610F Coinbase \u7684",
14977
14997
  separator: "\u3001",
14978
14998
  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"
14999
+ suffix: "\u3002",
15000
+ agreements: {
15001
+ guest_checkout_terms: "\u670D\u52D9\u689D\u6B3E",
15002
+ user_agreement: "\u4F7F\u7528\u8005\u5354\u8B70",
15003
+ privacy_policy: "\u96B1\u79C1\u6B0A\u653F\u7B56"
15004
+ }
14980
15005
  },
14981
15006
  errors: {
14982
15007
  rateLimited: "\u5617\u8A66\u6B21\u6578\u904E\u591A\u3002\u8ACB\u7A0D\u7B49\u5E7E\u5206\u9418\u5F8C\u91CD\u8A66\u3002",
@@ -15892,6 +15917,13 @@ function useAnalytics() {
15892
15917
  );
15893
15918
  return { track, startSession, endSession, getSessionId, setUserId, subscribe };
15894
15919
  }
15920
+ function useStampInternalUserId({ internalUserId }) {
15921
+ const { setUserId } = useAnalytics();
15922
+ useEffect32(() => {
15923
+ if (!internalUserId) return;
15924
+ setUserId(internalUserId);
15925
+ }, [internalUserId, setUserId]);
15926
+ }
15895
15927
  function useDepositAddress(params) {
15896
15928
  const {
15897
15929
  userId,
@@ -15904,7 +15936,6 @@ function useDepositAddress(params) {
15904
15936
  contractCalls,
15905
15937
  enabled = true
15906
15938
  } = params;
15907
- const { setUserId } = useAnalytics();
15908
15939
  const query = useQuery({
15909
15940
  queryKey: [
15910
15941
  "unifold",
@@ -15947,11 +15978,7 @@ function useDepositAddress(params) {
15947
15978
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
15948
15979
  // 1s, 2s, 4s (max 10s)
15949
15980
  });
15950
- useEffect32(() => {
15951
- if (query.data?.user_id) {
15952
- setUserId(query.data.user_id);
15953
- }
15954
- }, [query.data?.user_id, setUserId]);
15981
+ useStampInternalUserId({ internalUserId: query.data?.user_id });
15955
15982
  return query;
15956
15983
  }
15957
15984
  function useDebounce(value, delay) {
@@ -18174,7 +18201,11 @@ function BuyWithCard({
18174
18201
  method: "card",
18175
18202
  flow_type: "deposit",
18176
18203
  provider: selectedProvider.service_provider,
18177
- amount_usd: amount
18204
+ amount_usd: amount,
18205
+ // The execution only exists once the provider's payout lands on this
18206
+ // wallet, and it carries this id — so it's the join key for a purchase
18207
+ // that starts here and never reaches flow_completed.
18208
+ deposit_wallet_id: depositWalletId
18178
18209
  });
18179
18210
  onEvent?.({
18180
18211
  id: generatePrefixedKSUID2("sevt"),
@@ -19611,6 +19642,8 @@ var BuyWithWalletPay = React82.forwardRef(
19611
19642
  const [limitUpgradeError, setLimitUpgradeError] = useState152(null);
19612
19643
  const [upgradeSubmitting, setUpgradeSubmitting] = useState152(false);
19613
19644
  const upgradeFlowAbortRef = useRef62(null);
19645
+ const applyLimitRoutingRef = useRef62(() => {
19646
+ });
19614
19647
  const [amount, setAmount] = useState152(amountUsd ?? "");
19615
19648
  const [preparedOrder, setPreparedOrder] = useState152(null);
19616
19649
  const sessionAbortRef = useRef62(null);
@@ -19745,6 +19778,14 @@ var BuyWithWalletPay = React82.forwardRef(
19745
19778
  },
19746
19779
  [email, normalizedPhone, userId]
19747
19780
  );
19781
+ const { action: initialAction, refetchWalletPayLimits } = useWalletPayInitialScreen({
19782
+ userId,
19783
+ publishableKey,
19784
+ normalizedPhone,
19785
+ userEmail,
19786
+ sessionPhoneVerified: verificationSession?.phone?.status === "verified",
19787
+ isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
19788
+ });
19748
19789
  const createSessionAndSendOtp = useCallback42(async () => {
19749
19790
  setView("submitting_session");
19750
19791
  setErrorMessage("");
@@ -19754,7 +19795,12 @@ var BuyWithWalletPay = React82.forwardRef(
19754
19795
  email,
19755
19796
  phone: normalizedPhone,
19756
19797
  terms_accepted: true,
19757
- email_already_verified: true
19798
+ // TODO: when the API honors `false`, this will trigger email OTP.
19799
+ // Today `false` still skips email (we don't verify it) and JWT ev
19800
+ // is null. Don't send `true` — that was a fake attest.
19801
+ email_already_verified: false
19802
+ // Coinbase stays Redis-only + JWT until bank-transfer identity
19803
+ // is live. Do not persist from this path yet.
19758
19804
  },
19759
19805
  publishableKey
19760
19806
  );
@@ -19764,6 +19810,34 @@ var BuyWithWalletPay = React82.forwardRef(
19764
19810
  }
19765
19811
  setClientSecret(session.client_secret);
19766
19812
  storeWalletPaySession();
19813
+ if (session.status === "verified") {
19814
+ const tokenRes = await exchangeOnrampVerificationToken(
19815
+ session.id,
19816
+ session.client_secret,
19817
+ publishableKey
19818
+ );
19819
+ setOnrampToken(tokenRes);
19820
+ storeWalletPaySession({
19821
+ emailVerifiedAt: session.email.verified_at,
19822
+ phoneVerifiedAt: session.phone.verified_at,
19823
+ onrampToken: tokenRes.token,
19824
+ onrampTokenExpiresAtMs: Date.now() + tokenRes.expires_in * 1e3
19825
+ });
19826
+ if (amountUsd) setAmount(amountUsd);
19827
+ try {
19828
+ const result = await refetchWalletPayLimits();
19829
+ if (result.data) {
19830
+ const nextView = getViewForLimitStatus(result.data);
19831
+ if (nextView) {
19832
+ applyLimitRoutingRef.current(nextView, result.data.upgrade_status);
19833
+ return;
19834
+ }
19835
+ }
19836
+ } catch {
19837
+ }
19838
+ setView("amount");
19839
+ return;
19840
+ }
19767
19841
  await sendOnrampVerificationOtp(session.id, "phone", session.client_secret, publishableKey);
19768
19842
  setResendCooldown(30);
19769
19843
  setView("phone_otp");
@@ -19772,19 +19846,19 @@ var BuyWithWalletPay = React82.forwardRef(
19772
19846
  setErrorMessage(prettifyVerificationError(raw));
19773
19847
  setView("phone_input");
19774
19848
  }
19775
- }, [email, normalizedPhone, publishableKey, storeWalletPaySession]);
19849
+ }, [
19850
+ email,
19851
+ normalizedPhone,
19852
+ publishableKey,
19853
+ storeWalletPaySession,
19854
+ userId,
19855
+ amountUsd,
19856
+ refetchWalletPayLimits
19857
+ ]);
19776
19858
  const clearUpgradeFields = useCallback42(() => {
19777
19859
  setSsnLast4("");
19778
19860
  setDobInput("");
19779
19861
  }, []);
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
19862
  const pollLimitUpgradeStatus = useCallback42(
19789
19863
  async (signal) => {
19790
19864
  const POLL_INTERVAL_MS5 = 1500;
@@ -19895,6 +19969,7 @@ var BuyWithWalletPay = React82.forwardRef(
19895
19969
  },
19896
19970
  [startUpgradePolling]
19897
19971
  );
19972
+ applyLimitRoutingRef.current = applyLimitRouting;
19898
19973
  const hasInitializedRef = useRef62(false);
19899
19974
  useEffect122(() => {
19900
19975
  if (hasInitializedRef.current) return;
@@ -20124,7 +20199,10 @@ var BuyWithWalletPay = React82.forwardRef(
20124
20199
  track("flow_started", {
20125
20200
  method,
20126
20201
  flow_type: "deposit",
20127
- amount_usd: walletPayAmountUsd
20202
+ amount_usd: walletPayAmountUsd,
20203
+ // No execution yet — one appears when the payout lands on this
20204
+ // wallet, carrying the same id.
20205
+ deposit_wallet_id: depositWalletId
20128
20206
  });
20129
20207
  onEvent?.({
20130
20208
  id: generatePrefixedKSUID32("sevt"),
@@ -20174,6 +20252,7 @@ var BuyWithWalletPay = React82.forwardRef(
20174
20252
  defaultTokenLoading,
20175
20253
  defaultTokenError,
20176
20254
  depositWallet?.address,
20255
+ depositWalletId,
20177
20256
  userEmail,
20178
20257
  publishableKey,
20179
20258
  onEvent,
@@ -21148,7 +21227,7 @@ var FALLBACK_AGREEMENTS = [
21148
21227
  {
21149
21228
  key: "guest_checkout_terms",
21150
21229
  name: "Guest Checkout Terms of Service",
21151
- url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
21230
+ url: "https://www.coinbase.com/legal/guest-checkout/us"
21152
21231
  },
21153
21232
  {
21154
21233
  key: "user_agreement",
@@ -21168,22 +21247,24 @@ function LegalDisclaimer({ legalAgreements, loading }) {
21168
21247
  return /* @__PURE__ */ jsxs14(
21169
21248
  "div",
21170
21249
  {
21171
- className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse",
21250
+ className: "uf-mt-3 uf-mb-3 uf-px-1 uf-space-y-1.5 uf-animate-pulse uf-opacity-50",
21172
21251
  "aria-hidden": true,
21173
21252
  "aria-busy": "true",
21174
21253
  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 } })
21254
+ /* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-full", style: { backgroundColor: colors2.card } }),
21255
+ /* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-11/12", style: { backgroundColor: colors2.card } }),
21256
+ /* @__PURE__ */ jsx18("div", { className: "uf-h-2 uf-rounded uf-w-3/4", style: { backgroundColor: colors2.card } })
21178
21257
  ]
21179
21258
  }
21180
21259
  );
21181
21260
  }
21182
21261
  const agreements = legalAgreements?.agreements ?? FALLBACK_AGREEMENTS;
21262
+ const shortLabels = t.agreements;
21263
+ const lastSeparator = t.lastSeparator.replace(/\s+$/, "\xA0");
21183
21264
  return /* @__PURE__ */ jsxs14(
21184
21265
  "p",
21185
21266
  {
21186
- className: "uf-text-[11px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-px-1",
21267
+ className: "uf-text-[10px] uf-leading-relaxed uf-mt-3 uf-mb-3 uf-opacity-60 uf-text-center",
21187
21268
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
21188
21269
  children: [
21189
21270
  t.prefix,
@@ -21194,12 +21275,12 @@ function LegalDisclaimer({ legalAgreements, loading }) {
21194
21275
  href: a.url,
21195
21276
  target: "_blank",
21196
21277
  rel: "noopener noreferrer",
21197
- className: "uf-underline",
21198
- style: { color: colors2.foreground },
21199
- children: a.name
21278
+ className: "uf-no-underline",
21279
+ style: { color: "inherit", textDecoration: "none", whiteSpace: "nowrap" },
21280
+ children: shortLabels[a.key] ?? a.name
21200
21281
  }
21201
21282
  ),
21202
- idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? t.lastSeparator : ""
21283
+ idx < arr.length - 2 ? t.separator : idx === arr.length - 2 ? lastSeparator : ""
21203
21284
  ] }, a.key)),
21204
21285
  t.suffix
21205
21286
  ]
@@ -21821,16 +21902,6 @@ function PayWithExchange({
21821
21902
  }
21822
21903
  );
21823
21904
  }
21824
- function useCashAppLimits({ publishableKey, currency = "usd" }) {
21825
- return useQuery9({
21826
- queryKey: ["unifold", "cashAppLimits", currency, publishableKey],
21827
- queryFn: () => getCashAppLimits(currency, publishableKey),
21828
- enabled: !!publishableKey,
21829
- staleTime: 2 * 60 * 6e4,
21830
- gcTime: 4 * 60 * 6e4,
21831
- retry: 2
21832
- });
21833
- }
21834
21905
  var POLL_INTERVAL_MS3 = 5e3;
21835
21906
  var FALLBACK_MIN_USD = 5;
21836
21907
  var SUGGESTED_AMOUNTS = [25, 50, 100];
@@ -21842,6 +21913,7 @@ function PayWithCashApp({
21842
21913
  destinationChainType,
21843
21914
  destinationChainId,
21844
21915
  destinationTokenAddress,
21916
+ contractCalls,
21845
21917
  cashAppIconUrl,
21846
21918
  view: controlledView,
21847
21919
  onViewChange,
@@ -21865,9 +21937,11 @@ function PayWithCashApp({
21865
21937
  const b = parseInt(bg.slice(4, 6), 16);
21866
21938
  return (r2 * 299 + g * 587 + b * 114) / 1e3 < 128;
21867
21939
  })();
21868
- const { data: limits, isLoading: limitsLoading } = useCashAppLimits({ publishableKey });
21869
- const minUsd = limits?.minimum_amount ?? FALLBACK_MIN_USD;
21870
- const maxUsd = limits?.maximum_amount ?? null;
21940
+ const { data: fiatCurrencies, isLoading: limitsLoading } = useFiatCurrencies({
21941
+ publishableKey
21942
+ });
21943
+ const minUsd = fiatCurrencies?.data.find((entry) => entry.currency_code.toLowerCase() === "usd")?.minimum_amount ?? FALLBACK_MIN_USD;
21944
+ const quickAmounts = SUGGESTED_AMOUNTS.filter((value) => value >= minUsd);
21871
21945
  const [amount, setAmount] = useState18(() => sanitizePrefilledUsd(prefilledAmountUsd));
21872
21946
  const [loading, setLoading] = useState18(false);
21873
21947
  const [session, setSession] = useState18(null);
@@ -21922,6 +21996,8 @@ function PayWithCashApp({
21922
21996
  setError(strings.depositModal.cashAppErrors.missingFields);
21923
21997
  return;
21924
21998
  }
21999
+ const amountNum2 = parseFloat(amount);
22000
+ if (isNaN(amountNum2) || amountNum2 < minUsd) return;
21925
22001
  setLoading(true);
21926
22002
  setError(null);
21927
22003
  try {
@@ -21934,7 +22010,8 @@ function PayWithCashApp({
21934
22010
  destination_token_address: destinationTokenAddress,
21935
22011
  recipient_address: recipientAddress,
21936
22012
  source_amount: amount,
21937
- external_id: externalId
22013
+ external_id: externalId,
22014
+ ...contractCalls?.length ? { contract_calls: contractCalls } : {}
21938
22015
  },
21939
22016
  publishableKey
21940
22017
  );
@@ -21947,7 +22024,10 @@ function PayWithCashApp({
21947
22024
  track("flow_started", {
21948
22025
  method: "cashapp",
21949
22026
  flow_type: "deposit",
21950
- amount_usd: amount
22027
+ amount_usd: amount,
22028
+ // No execution yet — one appears when the payout lands on this
22029
+ // wallet, carrying the same id.
22030
+ deposit_wallet_id: depositWalletId
21951
22031
  });
21952
22032
  onEvent?.({
21953
22033
  id: generatePrefixedKSUID5("sevt"),
@@ -21966,12 +22046,15 @@ function PayWithCashApp({
21966
22046
  }
21967
22047
  }, [
21968
22048
  amount,
22049
+ minUsd,
21969
22050
  userId,
21970
22051
  publishableKey,
21971
22052
  recipientAddress,
21972
22053
  destinationChainType,
21973
22054
  destinationChainId,
21974
22055
  destinationTokenAddress,
22056
+ contractCalls,
22057
+ depositWalletId,
21975
22058
  onEvent,
21976
22059
  onDepositError,
21977
22060
  track,
@@ -22067,8 +22150,7 @@ function PayWithCashApp({
22067
22150
  const amountNum = parseFloat(amount);
22068
22151
  const hasInput = !isNaN(amountNum) && amountNum > 0;
22069
22152
  const belowMin = hasInput && amountNum < minUsd;
22070
- const aboveMax = hasInput && maxUsd !== null && amountNum > maxUsd;
22071
- const isValidAmount = hasInput && !belowMin && !aboveMax;
22153
+ const isValidAmount = hasInput && !belowMin;
22072
22154
  if (view === "amount") {
22073
22155
  return /* @__PURE__ */ jsxs16(
22074
22156
  "div",
@@ -22097,7 +22179,7 @@ function PayWithCashApp({
22097
22179
  }
22098
22180
  }
22099
22181
  ) }) }),
22100
- /* @__PURE__ */ jsx20("div", { className: "uf-flex uf-gap-3 uf-justify-center", children: SUGGESTED_AMOUNTS.map((quickAmount) => {
22182
+ /* @__PURE__ */ jsx20("div", { className: "uf-flex uf-gap-3 uf-justify-center", children: quickAmounts.map((quickAmount) => {
22101
22183
  const isSelected = parseFloat(amount) === quickAmount;
22102
22184
  return /* @__PURE__ */ jsxs16(
22103
22185
  "button",
@@ -22123,23 +22205,17 @@ function PayWithCashApp({
22123
22205
  quickAmount
22124
22206
  );
22125
22207
  }) }),
22126
- amount && amountNum < minUsd && !error ? /* @__PURE__ */ jsx20(
22208
+ !limitsLoading && minUsd > 0 && /* @__PURE__ */ jsx20(
22127
22209
  "div",
22128
22210
  {
22129
- className: "uf-text-sm uf-text-center uf-mt-3 uf-px-2",
22130
- style: { color: colors2.error, fontFamily: fonts.regular },
22131
- children: interpolate(strings.common.minimumAmount, { amount: `$${minUsd}` })
22132
- }
22133
- ) : amount && maxUsd !== null && amountNum > maxUsd && !error ? /* @__PURE__ */ jsx20(
22134
- "div",
22135
- {
22136
- className: "uf-text-sm uf-text-center uf-mt-3 uf-px-2",
22137
- style: { color: colors2.error, fontFamily: fonts.regular },
22138
- children: interpolate(strings.common.maximumAmount, {
22139
- amount: `$${maxUsd.toLocaleString()}`
22211
+ className: "uf-text-center uf-text-xs uf-mt-4",
22212
+ style: { color: colors2.warning, fontFamily: fonts.regular },
22213
+ children: interpolate(strings.common.minimumDeposit, {
22214
+ amount: `$${minUsd.toFixed(2)}`
22140
22215
  })
22141
22216
  }
22142
- ) : error ? /* @__PURE__ */ jsx20(
22217
+ ),
22218
+ error ? /* @__PURE__ */ jsx20(
22143
22219
  "div",
22144
22220
  {
22145
22221
  className: "uf-text-sm uf-text-center uf-mt-3 uf-px-2",
@@ -22148,7 +22224,7 @@ function PayWithCashApp({
22148
22224
  }
22149
22225
  ) : null
22150
22226
  ] }),
22151
- /* @__PURE__ */ jsx20("div", { className: "uf-px-1", children: /* @__PURE__ */ jsx20(
22227
+ /* @__PURE__ */ jsx20("div", { className: "uf-px-1 uf-mt-5", children: /* @__PURE__ */ jsx20(
22152
22228
  "button",
22153
22229
  {
22154
22230
  onClick: handleCreateSession,
@@ -22369,7 +22445,7 @@ function useBankTransferProviders({
22369
22445
  countryCode
22370
22446
  }) {
22371
22447
  const normalizedCountry = countryCode?.toUpperCase();
22372
- const { data: providers, isLoading } = useQuery10({
22448
+ const { data: providers, isLoading } = useQuery9({
22373
22449
  queryKey: ["unifold", "bankTransferProviders", publishableKey, normalizedCountry ?? null],
22374
22450
  queryFn: () => getBankTransferProviders(publishableKey, { countryCode: normalizedCountry }),
22375
22451
  enabled,
@@ -22573,7 +22649,10 @@ function BankTransfer({
22573
22649
  method: "bank_transfer",
22574
22650
  flow_type: "deposit",
22575
22651
  provider: request.service_provider,
22576
- amount_usd: request.source_amount
22652
+ amount_usd: request.source_amount,
22653
+ // No execution yet — one appears when the provider's payout lands on
22654
+ // this wallet, carrying the same id.
22655
+ deposit_wallet_id: pollingWalletId
22577
22656
  });
22578
22657
  onEvent?.({
22579
22658
  id: generatePrefixedKSUID6("sevt"),
@@ -28654,7 +28733,11 @@ function PayWithStripeLink({
28654
28733
  if (checkoutResult.successful) {
28655
28734
  handledTerminalSessionRef.current = null;
28656
28735
  executionReconciledSessionRef.current = null;
28657
- track("flow_started", { method: "stripe_link", flow_type: "deposit" });
28736
+ track("flow_started", {
28737
+ method: "stripe_link",
28738
+ flow_type: "deposit",
28739
+ deposit_wallet_id: depositWalletId
28740
+ });
28658
28741
  setConfirmedSessionId(activeSessionId);
28659
28742
  setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
28660
28743
  if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
@@ -30151,7 +30234,14 @@ function PayWithStripeLink({
30151
30234
  ]
30152
30235
  }
30153
30236
  ),
30154
- /* @__PURE__ */ jsx50("div", { ref: authMountRef, className: "uf-w-full uf-min-h-[200px]" })
30237
+ /* @__PURE__ */ jsx50(
30238
+ "div",
30239
+ {
30240
+ ref: authMountRef,
30241
+ className: "uf-w-full uf-min-h-[200px]",
30242
+ style: { colorScheme: "only light" }
30243
+ }
30244
+ )
30155
30245
  ]
30156
30246
  }
30157
30247
  );
@@ -30709,7 +30799,7 @@ function useProjectConfig({
30709
30799
  data: projectConfig,
30710
30800
  isLoading,
30711
30801
  error
30712
- } = useQuery11({
30802
+ } = useQuery10({
30713
30803
  // Country is part of the key so a region change refetches the region-aware
30714
30804
  // config. Omitted when undefined so callers that don't pass a country keep
30715
30805
  // sharing the base cache entry.
@@ -30731,7 +30821,7 @@ function useIntegrationTransferDefaultToken({
30731
30821
  publishableKey,
30732
30822
  enabled = true
30733
30823
  }) {
30734
- return useQuery12({
30824
+ return useQuery11({
30735
30825
  queryKey: [
30736
30826
  "unifold",
30737
30827
  "integrationTransferDefaultToken",
@@ -31414,6 +31504,9 @@ function CoinbaseConnect({
31414
31504
  flow_type: "deposit",
31415
31505
  method: "exchange_connect",
31416
31506
  provider: IntegrationProvider.COINBASE,
31507
+ // No execution yet — one appears when the exchange's transfer lands on
31508
+ // this wallet, carrying the same id.
31509
+ deposit_wallet_id: transferDepositWalletId,
31417
31510
  amount_usd: sendAmount || void 0,
31418
31511
  currency: selectedAsset?.currency.toLowerCase().replace(/[^a-z0-9]+/g, "_"),
31419
31512
  chain: sourceChain?.chain_id,
@@ -31421,6 +31514,34 @@ function CoinbaseConnect({
31421
31514
  network: sourceChain?.network
31422
31515
  });
31423
31516
  };
31517
+ const applyConfirmResult = (result) => {
31518
+ if (result.status === "mfa_required") {
31519
+ track("verification_started", {
31520
+ flow_type: "deposit",
31521
+ method: "exchange_connect",
31522
+ provider: IntegrationProvider.COINBASE,
31523
+ verification_type: "mfa",
31524
+ verification_status: result.status
31525
+ });
31526
+ transitionTo("mfa");
31527
+ setMfaCode("");
31528
+ setMfaError(false);
31529
+ } else if (result.status === "mfa_enrollment_required") {
31530
+ transitionTo("mfa_enrollment");
31531
+ } else if (result.status === "completed") {
31532
+ trackTransferStarted();
31533
+ setConfirmResult(result);
31534
+ transitionTo("success");
31535
+ onTransferSuccess?.(result);
31536
+ } else {
31537
+ setErrorMessage(result.message || t.errors.transferFailed);
31538
+ transitionTo("error");
31539
+ onTransferError?.({
31540
+ message: result.message || t.errors.transferFailed,
31541
+ code: result.status
31542
+ });
31543
+ }
31544
+ };
31424
31545
  const handleConfirmTransfer = async () => {
31425
31546
  if (!transferIntent || !accessToken) return;
31426
31547
  setIsLoading(true);
@@ -31455,30 +31576,7 @@ function CoinbaseConnect({
31455
31576
  });
31456
31577
  throw err;
31457
31578
  });
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
- }
31579
+ applyConfirmResult(result);
31482
31580
  } catch (err) {
31483
31581
  const message = err instanceof Error ? err.message : t.errors.transferFailed;
31484
31582
  setErrorMessage(message);
@@ -31635,6 +31733,9 @@ function CoinbaseConnect({
31635
31733
  setShowTransferDetails(false);
31636
31734
  transitionTo("enter_amount");
31637
31735
  break;
31736
+ case "mfa_enrollment":
31737
+ transitionTo("transfer_confirm");
31738
+ break;
31638
31739
  case "mfa":
31639
31740
  transitionTo("transfer_confirm");
31640
31741
  break;
@@ -33191,6 +33292,55 @@ function CoinbaseConnect({
33191
33292
  ] })
33192
33293
  ] });
33193
33294
  }
33295
+ if (view === "mfa_enrollment") {
33296
+ return /* @__PURE__ */ jsxs46(Fragment92, { children: [
33297
+ /* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
33298
+ /* @__PURE__ */ jsxs46(
33299
+ "div",
33300
+ {
33301
+ className: "uf-flex uf-flex-col uf-items-center uf-px-4 uf-pb-4",
33302
+ style: viewTransitionStyle,
33303
+ children: [
33304
+ /* @__PURE__ */ jsx51(
33305
+ DepositErrorState,
33306
+ {
33307
+ title: t.transfer.mfaEnrollmentTitle,
33308
+ message: t.transfer.mfaEnrollmentMessage
33309
+ }
33310
+ ),
33311
+ /* @__PURE__ */ jsxs46(
33312
+ "a",
33313
+ {
33314
+ href: "https://www.coinbase.com/settings/security",
33315
+ target: "_blank",
33316
+ rel: "noopener noreferrer",
33317
+ className: "uf-text-sm uf-underline uf-mb-8 uf-inline-flex uf-items-center uf-gap-1",
33318
+ style: { color: colors2.primary, fontFamily: fonts.medium },
33319
+ children: [
33320
+ t.transfer.mfaEnrollmentSettingsLink,
33321
+ /* @__PURE__ */ jsx51(ExternalLink, { className: "uf-w-3.5 uf-h-3.5" })
33322
+ ]
33323
+ }
33324
+ ),
33325
+ /* @__PURE__ */ jsx51(
33326
+ "button",
33327
+ {
33328
+ onClick: handleConfirmTransfer,
33329
+ disabled: isLoading,
33330
+ 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",
33331
+ style: {
33332
+ backgroundColor: colors2.primary,
33333
+ color: "#fff",
33334
+ fontFamily: fonts.medium
33335
+ },
33336
+ children: isLoading ? /* @__PURE__ */ jsx51(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin" }) : t.continue
33337
+ }
33338
+ )
33339
+ ]
33340
+ }
33341
+ )
33342
+ ] });
33343
+ }
33194
33344
  if (view === "mfa") {
33195
33345
  return /* @__PURE__ */ jsxs46(Fragment92, { children: [
33196
33346
  /* @__PURE__ */ jsx51(DepositHeader, { title: t.title, showBack: true, onBack: handleBack, onClose }),
@@ -33474,7 +33624,7 @@ function useExchanges({
33474
33624
  publishableKey,
33475
33625
  enabled = true
33476
33626
  }) {
33477
- const { data: exchanges = [], isLoading } = useQuery13({
33627
+ const { data: exchanges = [], isLoading } = useQuery12({
33478
33628
  queryKey: ["unifold", "exchanges", publishableKey],
33479
33629
  queryFn: () => getExchanges(void 0, publishableKey).then((res) => res.data),
33480
33630
  enabled,
@@ -33492,7 +33642,7 @@ function usePublicIncident({
33492
33642
  data: incident,
33493
33643
  isLoading,
33494
33644
  error
33495
- } = useQuery14({
33645
+ } = useQuery13({
33496
33646
  queryKey: ["unifold", "publicIncident", publishableKey],
33497
33647
  queryFn: () => getPublicIncident(publishableKey),
33498
33648
  enabled,
@@ -33507,7 +33657,7 @@ function useWalletPayProviders({
33507
33657
  publishableKey,
33508
33658
  enabled = true
33509
33659
  }) {
33510
- const { data: providers, isLoading } = useQuery15({
33660
+ const { data: providers, isLoading } = useQuery14({
33511
33661
  queryKey: ["unifold", "walletPayProviders", method, publishableKey],
33512
33662
  queryFn: () => getWalletPayProviders(method, publishableKey),
33513
33663
  enabled,
@@ -33773,7 +33923,7 @@ function useAddressValidation({
33773
33923
  refetchOnMount = false
33774
33924
  }) {
33775
33925
  const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
33776
- const { data, isLoading, error } = useQuery16({
33926
+ const { data, isLoading, error } = useQuery15({
33777
33927
  queryKey: [
33778
33928
  "unifold",
33779
33929
  "addressValidation",
@@ -35176,7 +35326,7 @@ function useHypercoreActivation(params) {
35176
35326
  const recipient = recipientAddress?.trim() ?? "";
35177
35327
  const source = sourceAddress?.trim() ?? "";
35178
35328
  const hasAddresses = !!recipient && !!source;
35179
- const { data, isLoading } = useQuery17({
35329
+ const { data, isLoading } = useQuery16({
35180
35330
  queryKey: ["unifold", "hypercoreActivation", source, recipient, publishableKey],
35181
35331
  queryFn: () => checkHypercoreActivation(
35182
35332
  {
@@ -36955,7 +37105,7 @@ function useDepositQuote(params) {
36955
37105
  ...adjustForSlippage ? { adjust_for_slippage: true } : {},
36956
37106
  ...stablecoinParity ? { stablecoin_parity: true } : {}
36957
37107
  };
36958
- return useQuery18({
37108
+ return useQuery17({
36959
37109
  queryKey: [
36960
37110
  "unifold",
36961
37111
  "depositQuote",
@@ -36985,7 +37135,7 @@ function useExternalWallets({
36985
37135
  publishableKey,
36986
37136
  enabled = true
36987
37137
  }) {
36988
- const { data: wallets = [], isLoading } = useQuery19({
37138
+ const { data: wallets = [], isLoading } = useQuery18({
36989
37139
  queryKey: ["unifold", "external-wallets", publishableKey],
36990
37140
  queryFn: () => getExternalWallets(publishableKey).then((res) => res.data),
36991
37141
  enabled: enabled && !!publishableKey,
@@ -39118,7 +39268,11 @@ function WalletConnect({
39118
39268
  chain: String(token.chain_id),
39119
39269
  network: token.network,
39120
39270
  token: token.symbol ?? token.token_address,
39121
- currency: token.currency
39271
+ currency: token.currency,
39272
+ // No execution exists yet — it's created when this send lands on the
39273
+ // wallet. The wallet id is what that execution will carry, so it's
39274
+ // how a send that never completes is matched to what followed.
39275
+ deposit_wallet_id: activeDepositWallet?.id
39122
39276
  });
39123
39277
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
39124
39278
  setHasSignedTransaction(true);
@@ -39705,7 +39859,7 @@ function DepositModal({
39705
39859
  const applePaySubTitle = applePaySubTitleProp ?? t.applePayMenu.subtitle;
39706
39860
  const googlePayTitle = googlePayTitleProp ?? t.googlePayMenu.title;
39707
39861
  const googlePaySubTitle = googlePaySubTitleProp ?? t.googlePayMenu.subtitle;
39708
- const { track, startSession, endSession, getSessionId, subscribe } = useAnalytics();
39862
+ const { track, startSession, endSession, getSessionId, setUserId, subscribe } = useAnalytics();
39709
39863
  const normalizedPrefilledAmountUsd = useMemo17(
39710
39864
  () => normalizePrefilledUsdAmount(prefilledAmountUsd),
39711
39865
  [prefilledAmountUsd]
@@ -39713,6 +39867,7 @@ function DepositModal({
39713
39867
  const analyticsMethod = (method) => method === "transfer" ? "transfer_crypto" : method;
39714
39868
  const journeyActiveRef = useRef16(false);
39715
39869
  const journeySessionIdRef = useRef16(void 0);
39870
+ const journeyExternalUserIdRef = useRef16(void 0);
39716
39871
  const externalUserId = userId || void 0;
39717
39872
  const emitEvent = useCallback14(
39718
39873
  (event) => onEvent?.({ ...event, externalUserId }),
@@ -39740,6 +39895,9 @@ function DepositModal({
39740
39895
  method: analyticsMethod(method),
39741
39896
  flow_type: "deposit",
39742
39897
  amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
39898
+ // The one high-cardinality field we do send: the join key from a
39899
+ // funnel session back to the execution row it produced.
39900
+ execution_id: data.executionId ?? execution?.id,
39743
39901
  // Flat, low-cardinality execution dimensions for PostHog breakdowns
39744
39902
  // (precise/opaque fields like base units, addresses, tx hashes live in
39745
39903
  // the onEvent DirectExecution instead).
@@ -39767,6 +39925,7 @@ function DepositModal({
39767
39925
  method: analyticsMethod(method),
39768
39926
  flow_type: "deposit",
39769
39927
  error_code: error.code,
39928
+ execution_id: execution?.id,
39770
39929
  failure_reason: execution?.failureReason ?? void 0,
39771
39930
  status: execution?.status,
39772
39931
  source_chain_type: execution?.sourceChainType,
@@ -40195,8 +40354,10 @@ function DepositModal({
40195
40354
  const beginJourney = useCallback14(() => {
40196
40355
  journeySessionIdRef.current = startSession();
40197
40356
  journeyActiveRef.current = true;
40357
+ journeyExternalUserIdRef.current = userId;
40358
+ setUserId(null);
40198
40359
  track("widget_opened", { flow_type: "deposit" });
40199
- }, [startSession, track]);
40360
+ }, [startSession, track, setUserId, userId]);
40200
40361
  const handleClose = () => {
40201
40362
  finalizeJourney();
40202
40363
  onOpenChange(false);
@@ -40221,6 +40382,11 @@ function DepositModal({
40221
40382
  }
40222
40383
  beginJourney();
40223
40384
  }, [open]);
40385
+ useLayoutEffect22(() => {
40386
+ if (!open || journeyExternalUserIdRef.current === userId) return;
40387
+ journeyExternalUserIdRef.current = userId;
40388
+ setUserId(null);
40389
+ }, [open, userId, setUserId]);
40224
40390
  useLayoutEffect22(() => {
40225
40391
  if (!open) return;
40226
40392
  if (resetViewTimeoutRef.current) {
@@ -41132,6 +41298,7 @@ function DepositModal({
41132
41298
  destinationChainType,
41133
41299
  destinationChainId,
41134
41300
  destinationTokenAddress,
41301
+ contractCalls,
41135
41302
  cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
41136
41303
  view: cashAppView,
41137
41304
  onViewChange: setCashAppView,
@@ -41300,7 +41467,7 @@ function useForwardCheckoutEvents(onEvent, journeySessionId) {
41300
41467
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "expired", "refunded", "canceled"]);
41301
41468
  function usePaymentIntent(params) {
41302
41469
  const { clientSecret, publishableKey, enabled = true, pollingInterval = 3e3 } = params;
41303
- return useQuery20({
41470
+ return useQuery19({
41304
41471
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
41305
41472
  queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
41306
41473
  enabled: enabled && !!clientSecret && !!publishableKey,
@@ -41467,6 +41634,9 @@ function CheckoutModal({
41467
41634
  flowCompletedRef.current = true;
41468
41635
  track("flow_completed", {
41469
41636
  flow_type: "checkout",
41637
+ // Checkout has no direct execution; the intent is what a funnel
41638
+ // session joins back to.
41639
+ payment_intent_id: data.paymentIntentId,
41470
41640
  ...method ? { method: method === "transfer" ? "transfer_crypto" : method } : {}
41471
41641
  });
41472
41642
  }
@@ -41687,7 +41857,7 @@ function CheckoutModal({
41687
41857
  journeySessionIdRef.current = startSession();
41688
41858
  journeyActiveRef.current = true;
41689
41859
  flowCompletedRef.current = false;
41690
- setUserId(null);
41860
+ setUserId(paymentIntentUserId ?? null);
41691
41861
  track("widget_opened", { flow_type: "checkout" });
41692
41862
  if (resetViewTimeoutRef.current) {
41693
41863
  clearTimeout(resetViewTimeoutRef.current);
@@ -42127,7 +42297,7 @@ function CheckoutModal({
42127
42297
  ) }) });
42128
42298
  }
42129
42299
  function useSupportedDestinationTokens(publishableKey, enabled = true) {
42130
- return useQuery21({
42300
+ return useQuery20({
42131
42301
  queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
42132
42302
  queryFn: () => getSupportedDestinationTokens(publishableKey),
42133
42303
  staleTime: 1e3 * 60 * 5,
@@ -42165,7 +42335,7 @@ function useSourceTokenValidation(params) {
42165
42335
  enabled = true
42166
42336
  } = params;
42167
42337
  const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
42168
- return useQuery22({
42338
+ return useQuery21({
42169
42339
  queryKey: [
42170
42340
  "unifold",
42171
42341
  "sourceTokenValidation",
@@ -42216,7 +42386,7 @@ function useSourceTokenValidation(params) {
42216
42386
  function useAddressBalance(params) {
42217
42387
  const { address, chainType, chainId, tokenAddress, publishableKey, enabled = true } = params;
42218
42388
  const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
42219
- return useQuery23({
42389
+ return useQuery22({
42220
42390
  queryKey: [
42221
42391
  "unifold",
42222
42392
  "addressBalance",
@@ -42272,7 +42442,7 @@ function useAddressBalance(params) {
42272
42442
  }
42273
42443
  function useExecutions(userId, publishableKey, options) {
42274
42444
  const actionType = options?.actionType ?? ActionType4.Deposit;
42275
- return useQuery24({
42445
+ const query = useQuery23({
42276
42446
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
42277
42447
  queryFn: () => queryExecutions4(userId, publishableKey, actionType),
42278
42448
  enabled: (options?.enabled ?? true) && !!userId,
@@ -42281,6 +42451,8 @@ function useExecutions(userId, publishableKey, options) {
42281
42451
  gcTime: 1e3 * 60 * 5,
42282
42452
  refetchOnWindowFocus: false
42283
42453
  });
42454
+ useStampInternalUserId({ internalUserId: query.data?.data[0]?.user_id });
42455
+ return query;
42284
42456
  }
42285
42457
  var POLL_INTERVAL_MS4 = 2500;
42286
42458
  var POLL_ENDPOINT_INTERVAL_MS2 = 5e3;
@@ -42617,7 +42789,7 @@ function useVerifyRecipientAddress(params) {
42617
42789
  } = params;
42618
42790
  const trimmedAddress = recipientAddress?.trim() || "";
42619
42791
  const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
42620
- return useQuery25({
42792
+ return useQuery24({
42621
42793
  queryKey: [
42622
42794
  "unifold",
42623
42795
  "verifyRecipientAddress",
@@ -42655,9 +42827,8 @@ function useGetDepositAddress(params) {
42655
42827
  actionType,
42656
42828
  enabled = true
42657
42829
  } = params;
42658
- const { setUserId } = useAnalytics();
42659
42830
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
42660
- const query = useQuery26({
42831
+ const query = useQuery25({
42661
42832
  queryKey: [
42662
42833
  "unifold",
42663
42834
  "getDepositAddress",
@@ -42687,11 +42858,7 @@ function useGetDepositAddress(params) {
42687
42858
  refetchOnWindowFocus: false,
42688
42859
  retry: 1
42689
42860
  });
42690
- useEffect45(() => {
42691
- if (query.data?.user_id) {
42692
- setUserId(query.data.user_id);
42693
- }
42694
- }, [query.data?.user_id, setUserId]);
42861
+ useStampInternalUserId({ internalUserId: query.data?.user_id });
42695
42862
  return query;
42696
42863
  }
42697
42864
  var isHypercore = (chainId) => chainId === HYPERCORE_CHAIN_ID;
@@ -42826,14 +42993,14 @@ function WithdrawForm({
42826
42993
  const [detailsExpanded, setDetailsExpanded] = useState47(false);
42827
42994
  const [glossaryOpen, setGlossaryOpen] = useState47(false);
42828
42995
  const [isMaxed, setIsMaxed] = useState47(false);
42829
- useEffect46(() => {
42996
+ useEffect45(() => {
42830
42997
  setRecipientAddress(recipientAddressProp || "");
42831
42998
  setAmount("");
42832
42999
  setInputUnit("fiat");
42833
43000
  setSubmitError(null);
42834
43001
  setIsMaxed(false);
42835
43002
  }, [recipientAddressProp]);
42836
- useEffect46(() => {
43003
+ useEffect45(() => {
42837
43004
  setIsMaxed(false);
42838
43005
  }, [balanceData?.balanceBaseUnit]);
42839
43006
  const trimmedAddress = recipientAddress.trim();
@@ -43643,7 +43810,7 @@ function WithdrawConfirmingView({
43643
43810
  const t = strings.withdrawModal.details;
43644
43811
  const [showButton, setShowButton] = useState48(false);
43645
43812
  const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
43646
- useEffect47(() => {
43813
+ useEffect46(() => {
43647
43814
  if (latestExecution) return;
43648
43815
  const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
43649
43816
  return () => clearTimeout(timer);
@@ -43795,7 +43962,7 @@ function WithdrawModal({
43795
43962
  );
43796
43963
  const onEventRef = useRef20(emitEvent);
43797
43964
  onEventRef.current = emitEvent;
43798
- useEffect48(
43965
+ useEffect47(
43799
43966
  () => subscribe((event) => {
43800
43967
  if (event.properties?.flow_type !== "withdraw") return;
43801
43968
  const selection = selectionPayload(event);
@@ -43812,12 +43979,16 @@ function WithdrawModal({
43812
43979
  );
43813
43980
  const journeyActiveRef = useRef20(false);
43814
43981
  const journeySessionIdRef = useRef20(void 0);
43982
+ const journeyExternalUserIdRef = useRef20(void 0);
43815
43983
  const onWithdrawSuccessFor = useCallback17(
43816
43984
  (data) => {
43817
43985
  const execution = data.execution?.data.object;
43818
43986
  track("flow_completed", {
43819
43987
  flow_type: "withdraw",
43820
43988
  amount_usd: execution?.destinationAmountUsd ?? execution?.sourceAmountUsd,
43989
+ // The one high-cardinality field we do send: the join key from a
43990
+ // funnel session back to the execution row it produced.
43991
+ execution_id: data.executionId ?? execution?.id,
43821
43992
  // Flat, low-cardinality execution dimensions for PostHog breakdowns.
43822
43993
  status: execution?.status,
43823
43994
  source_chain_type: execution?.sourceChainType,
@@ -43838,6 +44009,7 @@ function WithdrawModal({
43838
44009
  track("flow_failed", {
43839
44010
  flow_type: "withdraw",
43840
44011
  error_code: error.code,
44012
+ execution_id: execution?.id,
43841
44013
  failure_reason: execution?.failureReason ?? void 0,
43842
44014
  status: execution?.status,
43843
44015
  source_chain_type: execution?.sourceChainType,
@@ -43859,7 +44031,7 @@ function WithdrawModal({
43859
44031
  const [resolvedTheme, setResolvedTheme] = useState49(
43860
44032
  theme === "auto" ? "dark" : theme
43861
44033
  );
43862
- useEffect48(() => {
44034
+ useEffect47(() => {
43863
44035
  if (theme === "auto") {
43864
44036
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
43865
44037
  setResolvedTheme(mq.matches ? "dark" : "light");
@@ -43911,6 +44083,7 @@ function WithdrawModal({
43911
44083
  ) ?? null : null;
43912
44084
  const [view, setView] = useState49("form");
43913
44085
  const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState49();
44086
+ const withdrawDepositWalletIdRef = useRef20(void 0);
43914
44087
  const [selectedExecution, setSelectedExecution] = useState49(null);
43915
44088
  const [submittedTxInfo, setSubmittedTxInfo] = useState49(null);
43916
44089
  const { executions: realtimeExecutions } = useWithdrawPolling({
@@ -43948,6 +44121,7 @@ function WithdrawModal({
43948
44121
  if (!depositWallet) {
43949
44122
  throw new Error(`No deposit wallet available for ${sourceChainType}`);
43950
44123
  }
44124
+ withdrawDepositWalletIdRef.current = depositWallet.id;
43951
44125
  setWithdrawDepositWalletId(depositWallet.id);
43952
44126
  return depositWallet;
43953
44127
  },
@@ -43967,7 +44141,12 @@ function WithdrawModal({
43967
44141
  currency: tokenData?.currency,
43968
44142
  amount: txInfo.amount,
43969
44143
  amount_base_unit: txInfo.amountBaseUnit,
43970
- ...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {}
44144
+ ...txInfo.amountUsd ? { amount_usd: txInfo.amountUsd } : {},
44145
+ // The execution doesn't exist yet — it's created when the user's send
44146
+ // lands on the withdraw deposit wallet, and carries this id. So a
44147
+ // withdrawal confirmed but never completed still joins to whatever
44148
+ // did (or didn't) follow on that wallet.
44149
+ deposit_wallet_id: withdrawDepositWalletIdRef.current
43971
44150
  });
43972
44151
  emitEvent({
43973
44152
  id: generatePrefixedKSUID12("sevt"),
@@ -44001,8 +44180,10 @@ function WithdrawModal({
44001
44180
  const beginJourney = useCallback17(() => {
44002
44181
  journeySessionIdRef.current = startSession();
44003
44182
  journeyActiveRef.current = true;
44183
+ journeyExternalUserIdRef.current = externalUserId;
44184
+ setUserId(null);
44004
44185
  track("widget_opened", { flow_type: "withdraw" });
44005
- }, [startSession, track]);
44186
+ }, [startSession, track, setUserId, externalUserId]);
44006
44187
  const handleClose = useCallback17(() => {
44007
44188
  finalizeJourney();
44008
44189
  onOpenChange(false);
@@ -44011,6 +44192,7 @@ function WithdrawModal({
44011
44192
  setView("form");
44012
44193
  setSelectedExecution(null);
44013
44194
  setSubmittedTxInfo(null);
44195
+ withdrawDepositWalletIdRef.current = void 0;
44014
44196
  setWithdrawDepositWalletId(void 0);
44015
44197
  resetViewTimeoutRef.current = null;
44016
44198
  }, 200);
@@ -44028,9 +44210,15 @@ function WithdrawModal({
44028
44210
  setView("form");
44029
44211
  setSelectedExecution(null);
44030
44212
  setSubmittedTxInfo(null);
44213
+ withdrawDepositWalletIdRef.current = void 0;
44031
44214
  setWithdrawDepositWalletId(void 0);
44032
44215
  }, [open]);
44033
- useEffect48(
44216
+ useLayoutEffect42(() => {
44217
+ if (!open || journeyExternalUserIdRef.current === externalUserId) return;
44218
+ journeyExternalUserIdRef.current = externalUserId;
44219
+ setUserId(null);
44220
+ }, [open, externalUserId, setUserId]);
44221
+ useEffect47(
44034
44222
  () => () => {
44035
44223
  if (journeyActiveRef.current) {
44036
44224
  journeyActiveRef.current = false;
@@ -44039,12 +44227,12 @@ function WithdrawModal({
44039
44227
  },
44040
44228
  [endSession, getSessionId]
44041
44229
  );
44042
- useEffect48(() => {
44230
+ useEffect47(() => {
44043
44231
  if (!open) return;
44044
44232
  const screen = view === "detail" ? "tracker_detail" : view;
44045
44233
  track("screen_viewed", { flow_type: "withdraw", screen });
44046
44234
  }, [open, view, track]);
44047
- useEffect48(
44235
+ useEffect47(
44048
44236
  () => () => {
44049
44237
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
44050
44238
  },