@unifold/ui-react 0.1.47 → 0.1.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -528,6 +528,18 @@ interface WithdrawModalProps {
528
528
  sourceTokenSymbol?: string;
529
529
  recipientAddress?: string;
530
530
  senderAddress: string;
531
+ /**
532
+ * Pre-select the destination (receive) token/chain in the withdraw view.
533
+ * All four props are optional. To match a specific token, provide `chainType` + `chainId` + (`symbol` OR `tokenAddress`).
534
+ * If omitted or no match is found in `/supported_destination_tokens`, the first available token and chain are used.
535
+ */
536
+ defaultDestinationChainType?: string;
537
+ /** Destination chain ID (e.g. `"mainnet"`, `"137"`). Must be paired with `defaultDestinationChainType` + symbol or token address. */
538
+ defaultDestinationChainId?: string;
539
+ /** Destination token contract address. Must be paired with `defaultDestinationChainType` + `defaultDestinationChainId`. */
540
+ defaultDestinationTokenAddress?: string;
541
+ /** Destination token symbol (e.g. `"USDC"`). Must be paired with `defaultDestinationChainType` + `defaultDestinationChainId`. */
542
+ defaultDestinationSymbol?: string;
531
543
  onWithdraw: (txInfo: WithdrawTransactionInfo) => void | Promise<void>;
532
544
  onWithdrawSuccess?: (data: {
533
545
  message: string;
@@ -541,7 +553,7 @@ interface WithdrawModalProps {
541
553
  theme?: "light" | "dark" | "auto";
542
554
  hideOverlay?: boolean;
543
555
  }
544
- declare function WithdrawModal({ open, onOpenChange, publishableKey, modalTitle, externalUserId, sourceChainType, sourceChainId, sourceTokenAddress, sourceTokenSymbol, recipientAddress: recipientAddressProp, senderAddress, onWithdraw, onWithdrawSuccess, onWithdrawError, theme, hideOverlay, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
556
+ declare function WithdrawModal({ open, onOpenChange, publishableKey, modalTitle, externalUserId, sourceChainType, sourceChainId, sourceTokenAddress, sourceTokenSymbol, recipientAddress: recipientAddressProp, senderAddress, defaultDestinationChainType, defaultDestinationChainId, defaultDestinationTokenAddress, defaultDestinationSymbol, onWithdraw, onWithdrawSuccess, onWithdrawError, theme, hideOverlay, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
545
557
 
546
558
  interface WithdrawTokenSelectorProps {
547
559
  tokens: DestinationToken[];
package/dist/index.d.ts CHANGED
@@ -528,6 +528,18 @@ interface WithdrawModalProps {
528
528
  sourceTokenSymbol?: string;
529
529
  recipientAddress?: string;
530
530
  senderAddress: string;
531
+ /**
532
+ * Pre-select the destination (receive) token/chain in the withdraw view.
533
+ * All four props are optional. To match a specific token, provide `chainType` + `chainId` + (`symbol` OR `tokenAddress`).
534
+ * If omitted or no match is found in `/supported_destination_tokens`, the first available token and chain are used.
535
+ */
536
+ defaultDestinationChainType?: string;
537
+ /** Destination chain ID (e.g. `"mainnet"`, `"137"`). Must be paired with `defaultDestinationChainType` + symbol or token address. */
538
+ defaultDestinationChainId?: string;
539
+ /** Destination token contract address. Must be paired with `defaultDestinationChainType` + `defaultDestinationChainId`. */
540
+ defaultDestinationTokenAddress?: string;
541
+ /** Destination token symbol (e.g. `"USDC"`). Must be paired with `defaultDestinationChainType` + `defaultDestinationChainId`. */
542
+ defaultDestinationSymbol?: string;
531
543
  onWithdraw: (txInfo: WithdrawTransactionInfo) => void | Promise<void>;
532
544
  onWithdrawSuccess?: (data: {
533
545
  message: string;
@@ -541,7 +553,7 @@ interface WithdrawModalProps {
541
553
  theme?: "light" | "dark" | "auto";
542
554
  hideOverlay?: boolean;
543
555
  }
544
- declare function WithdrawModal({ open, onOpenChange, publishableKey, modalTitle, externalUserId, sourceChainType, sourceChainId, sourceTokenAddress, sourceTokenSymbol, recipientAddress: recipientAddressProp, senderAddress, onWithdraw, onWithdrawSuccess, onWithdrawError, theme, hideOverlay, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
556
+ declare function WithdrawModal({ open, onOpenChange, publishableKey, modalTitle, externalUserId, sourceChainType, sourceChainId, sourceTokenAddress, sourceTokenSymbol, recipientAddress: recipientAddressProp, senderAddress, defaultDestinationChainType, defaultDestinationChainId, defaultDestinationTokenAddress, defaultDestinationSymbol, onWithdraw, onWithdrawSuccess, onWithdrawError, theme, hideOverlay, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
545
557
 
546
558
  interface WithdrawTokenSelectorProps {
547
559
  tokens: DestinationToken[];
package/dist/index.js CHANGED
@@ -2882,16 +2882,6 @@ function BuyWithCard({
2882
2882
  window.open(sessionStartUrl, "_blank");
2883
2883
  handleViewChange("onramp");
2884
2884
  };
2885
- const getProviderBadges = (quote, allQuotes) => {
2886
- const badges = [];
2887
- const maxDestination = Math.max(
2888
- ...allQuotes.map((q) => q.destination_amount)
2889
- );
2890
- if (quote.destination_amount === maxDestination) {
2891
- badges.push("Best price");
2892
- }
2893
- return badges;
2894
- };
2895
2885
  const sortedQuotes = [...quotes].sort(
2896
2886
  (a, b) => b.destination_amount - a.destination_amount
2897
2887
  );
@@ -3096,31 +3086,7 @@ function BuyWithCard({
3096
3086
  children: selectedProvider.service_provider_display_name
3097
3087
  }
3098
3088
  ),
3099
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: [
3100
- isAutoSelected && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3101
- "span",
3102
- {
3103
- className: "uf-text-[10px] uf-font-normal",
3104
- style: {
3105
- color: colors2.success,
3106
- fontFamily: fonts.regular
3107
- },
3108
- children: "Best price"
3109
- }
3110
- ),
3111
- isAutoSelected && selectedProvider.low_kyc === false && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3112
- "span",
3113
- {
3114
- className: "uf-text-[10px]",
3115
- style: {
3116
- color: components.card.labelColor,
3117
- fontFamily: fonts.regular
3118
- },
3119
- children: "\u2022"
3120
- }
3121
- ),
3122
- selectedProvider.low_kyc === false && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" })
3123
- ] })
3089
+ selectedProvider.low_kyc === false && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" }) })
3124
3090
  ] }),
3125
3091
  quotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3126
3092
  import_lucide_react6.ChevronRight,
@@ -3184,7 +3150,6 @@ function BuyWithCard({
3184
3150
  {
3185
3151
  className: `uf-transition-all uf-duration-300 uf-min-h-[420px] uf-flex uf-flex-col ${showQuotesView && !showOnrampView ? "uf-opacity-100" : "uf-opacity-0 uf-pointer-events-none uf-absolute uf-inset-0"}`,
3186
3152
  children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "uf-space-y-2 uf-pt-2 uf-pb-8 uf-overflow-y-auto uf-flex-1 uf-min-h-0", children: sortedQuotes.map((quote, index) => {
3187
- const badges = getProviderBadges(quote, sortedQuotes);
3188
3153
  const displayName = quote.service_provider_display_name;
3189
3154
  const isSelected = selectedProvider?.service_provider === quote.service_provider;
3190
3155
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
@@ -3227,39 +3192,17 @@ function BuyWithCard({
3227
3192
  children: displayName
3228
3193
  }
3229
3194
  ),
3230
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: [
3231
- badges.map((badge, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3232
- "span",
3233
- {
3234
- className: "uf-text-[10px] uf-font-normal",
3235
- style: { color: colors2.success },
3236
- children: [
3237
- badge,
3238
- i < badges.length - 1 && ","
3239
- ]
3195
+ quote.low_kyc === false && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3196
+ "span",
3197
+ {
3198
+ className: "uf-text-[10px] uf-font-normal",
3199
+ style: {
3200
+ color: components.card.subtextRightColor,
3201
+ fontFamily: fonts.regular
3240
3202
  },
3241
- i
3242
- )),
3243
- quote.low_kyc === false && badges.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3244
- "span",
3245
- {
3246
- className: "uf-text-[10px]",
3247
- style: { color: components.card.subtextRightColor },
3248
- children: "\u2022"
3249
- }
3250
- ),
3251
- quote.low_kyc === false && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3252
- "span",
3253
- {
3254
- className: "uf-text-[10px] uf-font-normal",
3255
- style: {
3256
- color: components.card.subtextRightColor,
3257
- fontFamily: fonts.regular
3258
- },
3259
- children: "No document upload"
3260
- }
3261
- )
3262
- ] })
3203
+ children: "No document upload"
3204
+ }
3205
+ ) })
3263
3206
  ] })
3264
3207
  ] }),
3265
3208
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "uf-text-right", children: [
@@ -8032,77 +7975,77 @@ function DepositPollingUi({
8032
7975
  return null;
8033
7976
  }
8034
7977
 
8035
- // src/hooks/use-default-source-token.ts
7978
+ // src/hooks/use-default-token.ts
8036
7979
  var import_react13 = require("react");
8037
7980
  var getChainKey = (chainId, chainType) => {
8038
7981
  return `${chainType}:${chainId}`;
8039
7982
  };
8040
- function resolveSourceToken(supportedTokens, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol) {
8041
- if (!supportedTokens.length) return null;
8042
- let selectedTokenData;
8043
- let selectedChainData;
8044
- const hasChainDefaults = defaultSourceChainType && defaultSourceChainId;
8045
- if (defaultSourceTokenAddress && hasChainDefaults) {
8046
- for (const t11 of supportedTokens) {
7983
+ function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
7984
+ if (!tokens.length) return null;
7985
+ let selectedToken;
7986
+ let selectedChain;
7987
+ const hasChainDefaults = defaultChainType && defaultChainId;
7988
+ if (defaultTokenAddress && hasChainDefaults) {
7989
+ for (const t11 of tokens) {
8047
7990
  const matchingChain = t11.chains.find(
8048
- (c) => c.token_address.toLowerCase() === defaultSourceTokenAddress.toLowerCase() && c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
7991
+ (c) => c.token_address.toLowerCase() === defaultTokenAddress.toLowerCase() && c.chain_type === defaultChainType && c.chain_id === defaultChainId
8049
7992
  );
8050
7993
  if (matchingChain) {
8051
- selectedTokenData = t11;
8052
- selectedChainData = matchingChain;
7994
+ selectedToken = t11;
7995
+ selectedChain = matchingChain;
8053
7996
  break;
8054
7997
  }
8055
7998
  }
8056
7999
  }
8057
- if (!selectedTokenData && defaultSourceSymbol && hasChainDefaults) {
8058
- for (const t11 of supportedTokens) {
8059
- if (t11.symbol !== defaultSourceSymbol) continue;
8000
+ if (!selectedToken && defaultSymbol && hasChainDefaults) {
8001
+ for (const t11 of tokens) {
8002
+ if (t11.symbol !== defaultSymbol) continue;
8060
8003
  const matchedChain = t11.chains.find(
8061
- (c) => c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
8004
+ (c) => c.chain_type === defaultChainType && c.chain_id === defaultChainId
8062
8005
  );
8063
8006
  if (matchedChain) {
8064
- selectedTokenData = t11;
8065
- selectedChainData = matchedChain;
8007
+ selectedToken = t11;
8008
+ selectedChain = matchedChain;
8066
8009
  break;
8067
8010
  }
8068
8011
  }
8069
8012
  }
8070
- if (!selectedTokenData) {
8071
- for (const t11 of supportedTokens) {
8013
+ if (!selectedToken) {
8014
+ for (const t11 of tokens) {
8072
8015
  if (t11.chains.length > 0) {
8073
- selectedTokenData = t11;
8074
- selectedChainData = t11.chains[0];
8016
+ selectedToken = t11;
8017
+ selectedChain = t11.chains[0];
8075
8018
  break;
8076
8019
  }
8077
8020
  }
8078
8021
  }
8079
- if (selectedTokenData && selectedChainData) {
8080
- return { token: selectedTokenData, chain: selectedChainData };
8022
+ if (selectedToken && selectedChain) {
8023
+ return { token: selectedToken, chain: selectedChain };
8081
8024
  }
8082
8025
  return null;
8083
8026
  }
8084
- function useDefaultSourceToken({
8085
- supportedTokens,
8086
- defaultSourceChainType,
8087
- defaultSourceChainId,
8088
- defaultSourceTokenAddress,
8089
- defaultSourceSymbol
8027
+ function useDefaultToken({
8028
+ tokens,
8029
+ defaultChainType,
8030
+ defaultChainId,
8031
+ defaultTokenAddress,
8032
+ defaultSymbol
8090
8033
  }) {
8091
8034
  const [token, setToken] = (0, import_react13.useState)(null);
8092
8035
  const [chain, setChain] = (0, import_react13.useState)(null);
8093
8036
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react13.useState)(false);
8094
8037
  const appliedDefaultsRef = (0, import_react13.useRef)("");
8095
8038
  (0, import_react13.useEffect)(() => {
8096
- if (!supportedTokens.length) return;
8097
- const defaultsKey = `${defaultSourceTokenAddress ?? ""}|${defaultSourceSymbol ?? ""}|${defaultSourceChainType ?? ""}|${defaultSourceChainId ?? ""}`;
8039
+ if (!tokens.length) return;
8040
+ const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
8098
8041
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
8099
8042
  if (initialSelectionDone && !defaultsChanged) return;
8100
- const result = resolveSourceToken(
8101
- supportedTokens,
8102
- defaultSourceChainType,
8103
- defaultSourceChainId,
8104
- defaultSourceTokenAddress,
8105
- defaultSourceSymbol
8043
+ const result = resolveToken(
8044
+ tokens,
8045
+ defaultChainType,
8046
+ defaultChainId,
8047
+ defaultTokenAddress,
8048
+ defaultSymbol
8106
8049
  );
8107
8050
  if (result) {
8108
8051
  setToken(result.token.symbol);
@@ -8111,16 +8054,16 @@ function useDefaultSourceToken({
8111
8054
  setInitialSelectionDone(true);
8112
8055
  }
8113
8056
  }, [
8114
- supportedTokens,
8115
- defaultSourceTokenAddress,
8116
- defaultSourceSymbol,
8117
- defaultSourceChainType,
8118
- defaultSourceChainId,
8057
+ tokens,
8058
+ defaultTokenAddress,
8059
+ defaultSymbol,
8060
+ defaultChainType,
8061
+ defaultChainId,
8119
8062
  initialSelectionDone
8120
8063
  ]);
8121
8064
  (0, import_react13.useEffect)(() => {
8122
- if (!supportedTokens.length || !token) return;
8123
- const currentToken = supportedTokens.find((t11) => t11.symbol === token);
8065
+ if (!tokens.length || !token) return;
8066
+ const currentToken = tokens.find((t11) => t11.symbol === token);
8124
8067
  if (!currentToken || currentToken.chains.length === 0) return;
8125
8068
  const isChainAvailable = chain && currentToken.chains.some((c) => {
8126
8069
  return getChainKey(c.chain_id, c.chain_type) === chain;
@@ -8129,10 +8072,27 @@ function useDefaultSourceToken({
8129
8072
  const firstChain = currentToken.chains[0];
8130
8073
  setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
8131
8074
  }
8132
- }, [token, supportedTokens, chain]);
8075
+ }, [token, tokens, chain]);
8133
8076
  return { token, chain, setToken, setChain, initialSelectionDone };
8134
8077
  }
8135
8078
 
8079
+ // src/hooks/use-default-source-token.ts
8080
+ function useDefaultSourceToken({
8081
+ supportedTokens,
8082
+ defaultSourceChainType,
8083
+ defaultSourceChainId,
8084
+ defaultSourceTokenAddress,
8085
+ defaultSourceSymbol
8086
+ }) {
8087
+ return useDefaultToken({
8088
+ tokens: supportedTokens,
8089
+ defaultChainType: defaultSourceChainType,
8090
+ defaultChainId: defaultSourceChainId,
8091
+ defaultTokenAddress: defaultSourceTokenAddress,
8092
+ defaultSymbol: defaultSourceSymbol
8093
+ });
8094
+ }
8095
+
8136
8096
  // src/components/deposits/shared/DepositFooterLinks.tsx
8137
8097
  var import_jsx_runtime38 = require("react/jsx-runtime");
8138
8098
  function DepositFooterLinks({
@@ -13205,6 +13165,23 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
13205
13165
  });
13206
13166
  }
13207
13167
 
13168
+ // src/hooks/use-default-destination-token.ts
13169
+ function useDefaultDestinationToken({
13170
+ destinationTokens,
13171
+ defaultDestinationChainType,
13172
+ defaultDestinationChainId,
13173
+ defaultDestinationTokenAddress,
13174
+ defaultDestinationSymbol
13175
+ }) {
13176
+ return useDefaultToken({
13177
+ tokens: destinationTokens,
13178
+ defaultChainType: defaultDestinationChainType,
13179
+ defaultChainId: defaultDestinationChainId,
13180
+ defaultTokenAddress: defaultDestinationTokenAddress,
13181
+ defaultSymbol: defaultDestinationSymbol
13182
+ });
13183
+ }
13184
+
13208
13185
  // src/hooks/use-source-token-validation.ts
13209
13186
  var import_react_query12 = require("@tanstack/react-query");
13210
13187
  var import_core27 = require("@unifold/core");
@@ -14736,6 +14713,10 @@ function WithdrawModal({
14736
14713
  sourceTokenSymbol,
14737
14714
  recipientAddress: recipientAddressProp,
14738
14715
  senderAddress,
14716
+ defaultDestinationChainType,
14717
+ defaultDestinationChainId,
14718
+ defaultDestinationTokenAddress,
14719
+ defaultDestinationSymbol,
14739
14720
  onWithdraw,
14740
14721
  onWithdrawSuccess,
14741
14722
  onWithdrawError,
@@ -14779,8 +14760,21 @@ function WithdrawModal({
14779
14760
  publishableKey,
14780
14761
  enabled: open
14781
14762
  });
14782
- const [selectedToken, setSelectedToken] = (0, import_react23.useState)(null);
14783
- const [selectedChain, setSelectedChain] = (0, import_react23.useState)(null);
14763
+ const {
14764
+ token: selectedTokenSymbol,
14765
+ chain: selectedChainKey,
14766
+ setToken: setSelectedTokenSymbol,
14767
+ setChain: setSelectedChainKey,
14768
+ initialSelectionDone
14769
+ } = useDefaultDestinationToken({
14770
+ destinationTokens,
14771
+ defaultDestinationChainType,
14772
+ defaultDestinationChainId,
14773
+ defaultDestinationTokenAddress,
14774
+ defaultDestinationSymbol
14775
+ });
14776
+ const selectedToken = selectedTokenSymbol ? destinationTokens.find((t11) => t11.symbol === selectedTokenSymbol) ?? null : null;
14777
+ const selectedChain = selectedToken && selectedChainKey ? selectedToken.chains.find((c) => getChainKey5(c.chain_id, c.chain_type) === selectedChainKey) ?? null : null;
14784
14778
  const [view, setView] = (0, import_react23.useState)("form");
14785
14779
  const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react23.useState)();
14786
14780
  const [selectedExecution, setSelectedExecution] = (0, import_react23.useState)(null);
@@ -14822,21 +14816,11 @@ function WithdrawModal({
14822
14816
  setSubmittedTxInfo(txInfo);
14823
14817
  setView("confirming");
14824
14818
  }, []);
14825
- (0, import_react23.useEffect)(() => {
14826
- if (!destinationTokens.length || selectedToken) return;
14827
- const first = destinationTokens[0];
14828
- if (first?.chains.length > 0) {
14829
- setSelectedToken(first);
14830
- setSelectedChain(first.chains[0]);
14831
- }
14832
- }, [destinationTokens, selectedToken]);
14833
14819
  const resetViewTimeoutRef = (0, import_react23.useRef)(null);
14834
14820
  const handleClose = (0, import_react23.useCallback)(() => {
14835
14821
  onOpenChange(false);
14836
14822
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
14837
14823
  resetViewTimeoutRef.current = setTimeout(() => {
14838
- setSelectedToken(null);
14839
- setSelectedChain(null);
14840
14824
  setView("form");
14841
14825
  setSelectedExecution(null);
14842
14826
  setSubmittedTxInfo(null);
@@ -14850,8 +14834,6 @@ function WithdrawModal({
14850
14834
  clearTimeout(resetViewTimeoutRef.current);
14851
14835
  resetViewTimeoutRef.current = null;
14852
14836
  }
14853
- setSelectedToken(null);
14854
- setSelectedChain(null);
14855
14837
  setView("form");
14856
14838
  setSelectedExecution(null);
14857
14839
  setSubmittedTxInfo(null);
@@ -14861,19 +14843,13 @@ function WithdrawModal({
14861
14843
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
14862
14844
  }, []);
14863
14845
  const handleTokenSymbolChange = (0, import_react23.useCallback)((symbol) => {
14864
- const tok = destinationTokens.find((t11) => t11.symbol === symbol);
14865
- if (tok) {
14866
- setSelectedToken(tok);
14867
- if (tok.chains.length > 0) setSelectedChain(tok.chains[0]);
14868
- }
14869
- }, [destinationTokens]);
14846
+ setSelectedTokenSymbol(symbol);
14847
+ }, [setSelectedTokenSymbol]);
14870
14848
  const handleChainKeyChange = (0, import_react23.useCallback)((chainKey) => {
14871
- if (!selectedToken) return;
14872
- const chain = selectedToken.chains.find((c) => getChainKey5(c.chain_id, c.chain_type) === chainKey);
14873
- if (chain) setSelectedChain(chain);
14874
- }, [selectedToken]);
14849
+ setSelectedChainKey(chainKey);
14850
+ }, [setSelectedChainKey]);
14875
14851
  const isSourceSupported = sourceValidation?.isSupported ?? null;
14876
- const isAnyLoading = tokensLoading || isCheckingSourceToken;
14852
+ const isAnyLoading = tokensLoading || isCheckingSourceToken || destinationTokens.length > 0 && !initialSelectionDone;
14877
14853
  const withdrawPoweredByFooter = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PoweredByUnifold, { color: colors2.foregroundMuted, className: "uf-flex uf-justify-center uf-shrink-0" }) });
14878
14854
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Dialog, { open: hideOverlay || open, onOpenChange: hideOverlay ? void 0 : handleClose, modal: !hideOverlay, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14879
14855
  DialogContent,
package/dist/index.mjs CHANGED
@@ -2806,16 +2806,6 @@ function BuyWithCard({
2806
2806
  window.open(sessionStartUrl, "_blank");
2807
2807
  handleViewChange("onramp");
2808
2808
  };
2809
- const getProviderBadges = (quote, allQuotes) => {
2810
- const badges = [];
2811
- const maxDestination = Math.max(
2812
- ...allQuotes.map((q) => q.destination_amount)
2813
- );
2814
- if (quote.destination_amount === maxDestination) {
2815
- badges.push("Best price");
2816
- }
2817
- return badges;
2818
- };
2819
2809
  const sortedQuotes = [...quotes].sort(
2820
2810
  (a, b) => b.destination_amount - a.destination_amount
2821
2811
  );
@@ -3020,31 +3010,7 @@ function BuyWithCard({
3020
3010
  children: selectedProvider.service_provider_display_name
3021
3011
  }
3022
3012
  ),
3023
- /* @__PURE__ */ jsxs8("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: [
3024
- isAutoSelected && /* @__PURE__ */ jsx10(
3025
- "span",
3026
- {
3027
- className: "uf-text-[10px] uf-font-normal",
3028
- style: {
3029
- color: colors2.success,
3030
- fontFamily: fonts.regular
3031
- },
3032
- children: "Best price"
3033
- }
3034
- ),
3035
- isAutoSelected && selectedProvider.low_kyc === false && /* @__PURE__ */ jsx10(
3036
- "span",
3037
- {
3038
- className: "uf-text-[10px]",
3039
- style: {
3040
- color: components.card.labelColor,
3041
- fontFamily: fonts.regular
3042
- },
3043
- children: "\u2022"
3044
- }
3045
- ),
3046
- selectedProvider.low_kyc === false && /* @__PURE__ */ jsx10("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" })
3047
- ] })
3013
+ selectedProvider.low_kyc === false && /* @__PURE__ */ jsx10("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: /* @__PURE__ */ jsx10("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" }) })
3048
3014
  ] }),
3049
3015
  quotes.length > 0 && /* @__PURE__ */ jsx10(
3050
3016
  ChevronRight,
@@ -3108,7 +3074,6 @@ function BuyWithCard({
3108
3074
  {
3109
3075
  className: `uf-transition-all uf-duration-300 uf-min-h-[420px] uf-flex uf-flex-col ${showQuotesView && !showOnrampView ? "uf-opacity-100" : "uf-opacity-0 uf-pointer-events-none uf-absolute uf-inset-0"}`,
3110
3076
  children: /* @__PURE__ */ jsx10("div", { className: "uf-space-y-2 uf-pt-2 uf-pb-8 uf-overflow-y-auto uf-flex-1 uf-min-h-0", children: sortedQuotes.map((quote, index) => {
3111
- const badges = getProviderBadges(quote, sortedQuotes);
3112
3077
  const displayName = quote.service_provider_display_name;
3113
3078
  const isSelected = selectedProvider?.service_provider === quote.service_provider;
3114
3079
  return /* @__PURE__ */ jsxs8(
@@ -3151,39 +3116,17 @@ function BuyWithCard({
3151
3116
  children: displayName
3152
3117
  }
3153
3118
  ),
3154
- /* @__PURE__ */ jsxs8("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: [
3155
- badges.map((badge, i) => /* @__PURE__ */ jsxs8(
3156
- "span",
3157
- {
3158
- className: "uf-text-[10px] uf-font-normal",
3159
- style: { color: colors2.success },
3160
- children: [
3161
- badge,
3162
- i < badges.length - 1 && ","
3163
- ]
3119
+ quote.low_kyc === false && /* @__PURE__ */ jsx10("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: /* @__PURE__ */ jsx10(
3120
+ "span",
3121
+ {
3122
+ className: "uf-text-[10px] uf-font-normal",
3123
+ style: {
3124
+ color: components.card.subtextRightColor,
3125
+ fontFamily: fonts.regular
3164
3126
  },
3165
- i
3166
- )),
3167
- quote.low_kyc === false && badges.length > 0 && /* @__PURE__ */ jsx10(
3168
- "span",
3169
- {
3170
- className: "uf-text-[10px]",
3171
- style: { color: components.card.subtextRightColor },
3172
- children: "\u2022"
3173
- }
3174
- ),
3175
- quote.low_kyc === false && /* @__PURE__ */ jsx10(
3176
- "span",
3177
- {
3178
- className: "uf-text-[10px] uf-font-normal",
3179
- style: {
3180
- color: components.card.subtextRightColor,
3181
- fontFamily: fonts.regular
3182
- },
3183
- children: "No document upload"
3184
- }
3185
- )
3186
- ] })
3127
+ children: "No document upload"
3128
+ }
3129
+ ) })
3187
3130
  ] })
3188
3131
  ] }),
3189
3132
  /* @__PURE__ */ jsxs8("div", { className: "uf-text-right", children: [
@@ -7984,77 +7927,77 @@ function DepositPollingUi({
7984
7927
  return null;
7985
7928
  }
7986
7929
 
7987
- // src/hooks/use-default-source-token.ts
7930
+ // src/hooks/use-default-token.ts
7988
7931
  import { useState as useState19, useEffect as useEffect16, useRef as useRef5 } from "react";
7989
7932
  var getChainKey = (chainId, chainType) => {
7990
7933
  return `${chainType}:${chainId}`;
7991
7934
  };
7992
- function resolveSourceToken(supportedTokens, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol) {
7993
- if (!supportedTokens.length) return null;
7994
- let selectedTokenData;
7995
- let selectedChainData;
7996
- const hasChainDefaults = defaultSourceChainType && defaultSourceChainId;
7997
- if (defaultSourceTokenAddress && hasChainDefaults) {
7998
- for (const t11 of supportedTokens) {
7935
+ function resolveToken(tokens, defaultChainType, defaultChainId, defaultTokenAddress, defaultSymbol) {
7936
+ if (!tokens.length) return null;
7937
+ let selectedToken;
7938
+ let selectedChain;
7939
+ const hasChainDefaults = defaultChainType && defaultChainId;
7940
+ if (defaultTokenAddress && hasChainDefaults) {
7941
+ for (const t11 of tokens) {
7999
7942
  const matchingChain = t11.chains.find(
8000
- (c) => c.token_address.toLowerCase() === defaultSourceTokenAddress.toLowerCase() && c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
7943
+ (c) => c.token_address.toLowerCase() === defaultTokenAddress.toLowerCase() && c.chain_type === defaultChainType && c.chain_id === defaultChainId
8001
7944
  );
8002
7945
  if (matchingChain) {
8003
- selectedTokenData = t11;
8004
- selectedChainData = matchingChain;
7946
+ selectedToken = t11;
7947
+ selectedChain = matchingChain;
8005
7948
  break;
8006
7949
  }
8007
7950
  }
8008
7951
  }
8009
- if (!selectedTokenData && defaultSourceSymbol && hasChainDefaults) {
8010
- for (const t11 of supportedTokens) {
8011
- if (t11.symbol !== defaultSourceSymbol) continue;
7952
+ if (!selectedToken && defaultSymbol && hasChainDefaults) {
7953
+ for (const t11 of tokens) {
7954
+ if (t11.symbol !== defaultSymbol) continue;
8012
7955
  const matchedChain = t11.chains.find(
8013
- (c) => c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
7956
+ (c) => c.chain_type === defaultChainType && c.chain_id === defaultChainId
8014
7957
  );
8015
7958
  if (matchedChain) {
8016
- selectedTokenData = t11;
8017
- selectedChainData = matchedChain;
7959
+ selectedToken = t11;
7960
+ selectedChain = matchedChain;
8018
7961
  break;
8019
7962
  }
8020
7963
  }
8021
7964
  }
8022
- if (!selectedTokenData) {
8023
- for (const t11 of supportedTokens) {
7965
+ if (!selectedToken) {
7966
+ for (const t11 of tokens) {
8024
7967
  if (t11.chains.length > 0) {
8025
- selectedTokenData = t11;
8026
- selectedChainData = t11.chains[0];
7968
+ selectedToken = t11;
7969
+ selectedChain = t11.chains[0];
8027
7970
  break;
8028
7971
  }
8029
7972
  }
8030
7973
  }
8031
- if (selectedTokenData && selectedChainData) {
8032
- return { token: selectedTokenData, chain: selectedChainData };
7974
+ if (selectedToken && selectedChain) {
7975
+ return { token: selectedToken, chain: selectedChain };
8033
7976
  }
8034
7977
  return null;
8035
7978
  }
8036
- function useDefaultSourceToken({
8037
- supportedTokens,
8038
- defaultSourceChainType,
8039
- defaultSourceChainId,
8040
- defaultSourceTokenAddress,
8041
- defaultSourceSymbol
7979
+ function useDefaultToken({
7980
+ tokens,
7981
+ defaultChainType,
7982
+ defaultChainId,
7983
+ defaultTokenAddress,
7984
+ defaultSymbol
8042
7985
  }) {
8043
7986
  const [token, setToken] = useState19(null);
8044
7987
  const [chain, setChain] = useState19(null);
8045
7988
  const [initialSelectionDone, setInitialSelectionDone] = useState19(false);
8046
7989
  const appliedDefaultsRef = useRef5("");
8047
7990
  useEffect16(() => {
8048
- if (!supportedTokens.length) return;
8049
- const defaultsKey = `${defaultSourceTokenAddress ?? ""}|${defaultSourceSymbol ?? ""}|${defaultSourceChainType ?? ""}|${defaultSourceChainId ?? ""}`;
7991
+ if (!tokens.length) return;
7992
+ const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
8050
7993
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
8051
7994
  if (initialSelectionDone && !defaultsChanged) return;
8052
- const result = resolveSourceToken(
8053
- supportedTokens,
8054
- defaultSourceChainType,
8055
- defaultSourceChainId,
8056
- defaultSourceTokenAddress,
8057
- defaultSourceSymbol
7995
+ const result = resolveToken(
7996
+ tokens,
7997
+ defaultChainType,
7998
+ defaultChainId,
7999
+ defaultTokenAddress,
8000
+ defaultSymbol
8058
8001
  );
8059
8002
  if (result) {
8060
8003
  setToken(result.token.symbol);
@@ -8063,16 +8006,16 @@ function useDefaultSourceToken({
8063
8006
  setInitialSelectionDone(true);
8064
8007
  }
8065
8008
  }, [
8066
- supportedTokens,
8067
- defaultSourceTokenAddress,
8068
- defaultSourceSymbol,
8069
- defaultSourceChainType,
8070
- defaultSourceChainId,
8009
+ tokens,
8010
+ defaultTokenAddress,
8011
+ defaultSymbol,
8012
+ defaultChainType,
8013
+ defaultChainId,
8071
8014
  initialSelectionDone
8072
8015
  ]);
8073
8016
  useEffect16(() => {
8074
- if (!supportedTokens.length || !token) return;
8075
- const currentToken = supportedTokens.find((t11) => t11.symbol === token);
8017
+ if (!tokens.length || !token) return;
8018
+ const currentToken = tokens.find((t11) => t11.symbol === token);
8076
8019
  if (!currentToken || currentToken.chains.length === 0) return;
8077
8020
  const isChainAvailable = chain && currentToken.chains.some((c) => {
8078
8021
  return getChainKey(c.chain_id, c.chain_type) === chain;
@@ -8081,10 +8024,27 @@ function useDefaultSourceToken({
8081
8024
  const firstChain = currentToken.chains[0];
8082
8025
  setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
8083
8026
  }
8084
- }, [token, supportedTokens, chain]);
8027
+ }, [token, tokens, chain]);
8085
8028
  return { token, chain, setToken, setChain, initialSelectionDone };
8086
8029
  }
8087
8030
 
8031
+ // src/hooks/use-default-source-token.ts
8032
+ function useDefaultSourceToken({
8033
+ supportedTokens,
8034
+ defaultSourceChainType,
8035
+ defaultSourceChainId,
8036
+ defaultSourceTokenAddress,
8037
+ defaultSourceSymbol
8038
+ }) {
8039
+ return useDefaultToken({
8040
+ tokens: supportedTokens,
8041
+ defaultChainType: defaultSourceChainType,
8042
+ defaultChainId: defaultSourceChainId,
8043
+ defaultTokenAddress: defaultSourceTokenAddress,
8044
+ defaultSymbol: defaultSourceSymbol
8045
+ });
8046
+ }
8047
+
8088
8048
  // src/components/deposits/shared/DepositFooterLinks.tsx
8089
8049
  import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
8090
8050
  function DepositFooterLinks({
@@ -13194,6 +13154,23 @@ function useSupportedDestinationTokens(publishableKey, enabled = true) {
13194
13154
  });
13195
13155
  }
13196
13156
 
13157
+ // src/hooks/use-default-destination-token.ts
13158
+ function useDefaultDestinationToken({
13159
+ destinationTokens,
13160
+ defaultDestinationChainType,
13161
+ defaultDestinationChainId,
13162
+ defaultDestinationTokenAddress,
13163
+ defaultDestinationSymbol
13164
+ }) {
13165
+ return useDefaultToken({
13166
+ tokens: destinationTokens,
13167
+ defaultChainType: defaultDestinationChainType,
13168
+ defaultChainId: defaultDestinationChainId,
13169
+ defaultTokenAddress: defaultDestinationTokenAddress,
13170
+ defaultSymbol: defaultDestinationSymbol
13171
+ });
13172
+ }
13173
+
13197
13174
  // src/hooks/use-source-token-validation.ts
13198
13175
  import { useQuery as useQuery12 } from "@tanstack/react-query";
13199
13176
  import { getSupportedDepositTokens as getSupportedDepositTokens3 } from "@unifold/core";
@@ -14755,6 +14732,10 @@ function WithdrawModal({
14755
14732
  sourceTokenSymbol,
14756
14733
  recipientAddress: recipientAddressProp,
14757
14734
  senderAddress,
14735
+ defaultDestinationChainType,
14736
+ defaultDestinationChainId,
14737
+ defaultDestinationTokenAddress,
14738
+ defaultDestinationSymbol,
14758
14739
  onWithdraw,
14759
14740
  onWithdrawSuccess,
14760
14741
  onWithdrawError,
@@ -14798,8 +14779,21 @@ function WithdrawModal({
14798
14779
  publishableKey,
14799
14780
  enabled: open
14800
14781
  });
14801
- const [selectedToken, setSelectedToken] = useState32(null);
14802
- const [selectedChain, setSelectedChain] = useState32(null);
14782
+ const {
14783
+ token: selectedTokenSymbol,
14784
+ chain: selectedChainKey,
14785
+ setToken: setSelectedTokenSymbol,
14786
+ setChain: setSelectedChainKey,
14787
+ initialSelectionDone
14788
+ } = useDefaultDestinationToken({
14789
+ destinationTokens,
14790
+ defaultDestinationChainType,
14791
+ defaultDestinationChainId,
14792
+ defaultDestinationTokenAddress,
14793
+ defaultDestinationSymbol
14794
+ });
14795
+ const selectedToken = selectedTokenSymbol ? destinationTokens.find((t11) => t11.symbol === selectedTokenSymbol) ?? null : null;
14796
+ const selectedChain = selectedToken && selectedChainKey ? selectedToken.chains.find((c) => getChainKey5(c.chain_id, c.chain_type) === selectedChainKey) ?? null : null;
14803
14797
  const [view, setView] = useState32("form");
14804
14798
  const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState32();
14805
14799
  const [selectedExecution, setSelectedExecution] = useState32(null);
@@ -14841,21 +14835,11 @@ function WithdrawModal({
14841
14835
  setSubmittedTxInfo(txInfo);
14842
14836
  setView("confirming");
14843
14837
  }, []);
14844
- useEffect27(() => {
14845
- if (!destinationTokens.length || selectedToken) return;
14846
- const first = destinationTokens[0];
14847
- if (first?.chains.length > 0) {
14848
- setSelectedToken(first);
14849
- setSelectedChain(first.chains[0]);
14850
- }
14851
- }, [destinationTokens, selectedToken]);
14852
14838
  const resetViewTimeoutRef = useRef10(null);
14853
14839
  const handleClose = useCallback7(() => {
14854
14840
  onOpenChange(false);
14855
14841
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
14856
14842
  resetViewTimeoutRef.current = setTimeout(() => {
14857
- setSelectedToken(null);
14858
- setSelectedChain(null);
14859
14843
  setView("form");
14860
14844
  setSelectedExecution(null);
14861
14845
  setSubmittedTxInfo(null);
@@ -14869,8 +14853,6 @@ function WithdrawModal({
14869
14853
  clearTimeout(resetViewTimeoutRef.current);
14870
14854
  resetViewTimeoutRef.current = null;
14871
14855
  }
14872
- setSelectedToken(null);
14873
- setSelectedChain(null);
14874
14856
  setView("form");
14875
14857
  setSelectedExecution(null);
14876
14858
  setSubmittedTxInfo(null);
@@ -14880,19 +14862,13 @@ function WithdrawModal({
14880
14862
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
14881
14863
  }, []);
14882
14864
  const handleTokenSymbolChange = useCallback7((symbol) => {
14883
- const tok = destinationTokens.find((t11) => t11.symbol === symbol);
14884
- if (tok) {
14885
- setSelectedToken(tok);
14886
- if (tok.chains.length > 0) setSelectedChain(tok.chains[0]);
14887
- }
14888
- }, [destinationTokens]);
14865
+ setSelectedTokenSymbol(symbol);
14866
+ }, [setSelectedTokenSymbol]);
14889
14867
  const handleChainKeyChange = useCallback7((chainKey) => {
14890
- if (!selectedToken) return;
14891
- const chain = selectedToken.chains.find((c) => getChainKey5(c.chain_id, c.chain_type) === chainKey);
14892
- if (chain) setSelectedChain(chain);
14893
- }, [selectedToken]);
14868
+ setSelectedChainKey(chainKey);
14869
+ }, [setSelectedChainKey]);
14894
14870
  const isSourceSupported = sourceValidation?.isSupported ?? null;
14895
- const isAnyLoading = tokensLoading || isCheckingSourceToken;
14871
+ const isAnyLoading = tokensLoading || isCheckingSourceToken || destinationTokens.length > 0 && !initialSelectionDone;
14896
14872
  const withdrawPoweredByFooter = /* @__PURE__ */ jsx57("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx57(PoweredByUnifold, { color: colors2.foregroundMuted, className: "uf-flex uf-justify-center uf-shrink-0" }) });
14897
14873
  return /* @__PURE__ */ jsx57(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ jsx57(Dialog, { open: hideOverlay || open, onOpenChange: hideOverlay ? void 0 : handleClose, modal: !hideOverlay, children: /* @__PURE__ */ jsx57(
14898
14874
  DialogContent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifold/ui-react",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "description": "Unifold UI React - Deposit and onramp components for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -21,16 +21,7 @@
21
21
  "peerDependencies": {
22
22
  "react": "^18.2.0 || ^19.0.0",
23
23
  "react-dom": "^18.2.0 || ^19.0.0",
24
- "@solana/web3.js": "^1.87.0",
25
- "@solana/spl-token": "^0.3.8"
26
- },
27
- "peerDependenciesMeta": {
28
- "@solana/web3.js": {
29
- "optional": true
30
- },
31
- "@solana/spl-token": {
32
- "optional": true
33
- }
24
+ "@solana/web3.js": "^1.87.0"
34
25
  },
35
26
  "dependencies": {
36
27
  "@radix-ui/react-dialog": "^1.0.5",
@@ -43,10 +34,9 @@
43
34
  "lucide-react": "^0.454.0",
44
35
  "qr-code-styling": "^1.6.0-rc.1",
45
36
  "tailwind-merge": "^2.0.0",
46
- "@unifold/core": "0.1.47"
37
+ "@unifold/core": "0.1.49"
47
38
  },
48
39
  "devDependencies": {
49
- "@solana/spl-token": "^0.3.8",
50
40
  "@solana/web3.js": "^1.87.0",
51
41
  "@types/react": "^19.0.0",
52
42
  "@types/react-dom": "^19.0.0",