@orderly.network/ui-transfer 2.8.5 → 2.8.6-alpha.0

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
@@ -1,7 +1,7 @@
1
1
  import { useTranslation, i18n, Trans } from '@orderly.network/i18n';
2
- import { modal, useScreen, useModal, SimpleSheet, SimpleDialog, registerSimpleDialog, registerSimpleSheet, Tabs, TabPanel, ArrowDownSquareFillIcon, ArrowUpSquareFillIcon, toast, Box, ExtensionSlot, ExtensionPositionEnum, textVariants, Flex, Text, Button, cn, Divider, Spinner, Select, Input, inputFormatter, AlertDialog, EditIcon, Icon, TokenIcon, WalletIcon, DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuPortal, DropdownMenuContent, ScrollArea, Tooltip, ExclamationFillIcon, CloseCircleFillIcon, CheckedCircleFillIcon, ChainIcon, Badge, CloseIcon } from '@orderly.network/ui';
2
+ import { modal, useScreen, useModal, SimpleSheet, SimpleDialog, registerSimpleDialog, registerSimpleSheet, Tabs, TabPanel, ArrowDownSquareFillIcon, ArrowUpSquareFillIcon, toast, Box, ExtensionSlot, ExtensionPositionEnum, textVariants, Flex, Text, Button, cn, Divider, Spinner, Select, Input, inputFormatter, Tooltip, AlertDialog, EditIcon, Icon, TokenIcon, ArrowLeftRightIcon, WalletIcon, DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuPortal, DropdownMenuContent, ScrollArea, CloseCircleFillIcon, CheckedCircleFillIcon, ChainIcon, Badge, CaretDownIcon, InfoCircleIcon, ExclamationFillIcon, CloseIcon } from '@orderly.network/ui';
3
3
  import { forwardRef, useState, useMemo, useEffect, useCallback, useRef, createElement } from 'react';
4
- import { useEventEmitter, useConfig, useWalletConnector, useLocalStorage, useConvert, useOdosQuote, useComputedLTV, useBoolean, useAccountInstance, useAccount, useAppStore, useTransfer, useSubAccountDataObserver, useSubAccountMaxWithdrawal, useTokensInfo, usePositionStream, useIndexPricesStream, useDeposit, useAssetsHistory, useChains, useWithdraw, useMemoizedFn, useWalletTopic, useQuery, useTokenInfo, useIndexPrice, useInternalTransfer, useDebouncedCallback, useTransferHistory, useBalanceTopic } from '@orderly.network/hooks';
4
+ import { useEventEmitter, useConfig, useWalletConnector, useLocalStorage, useConvert, useOdosQuote, useComputedLTV, useBoolean, useAccountInstance, useAccount, useAppStore, useTransfer, useSubAccountDataObserver, useSubAccountMaxWithdrawal, useTokensInfo, usePositionStream, useIndexPricesStream, useDeposit, useAssetsHistory, useChains, useMemoizedFn, useWithdraw, useWalletTopic, useQuery, useTokenInfo, useIndexPrice, useHoldingStream, useInternalTransfer, useDebouncedCallback, useTransferHistory, useBalanceTopic } from '@orderly.network/hooks';
5
5
  import { Decimal, zero, praseChainIdToNumber, int2hex, toNonExponential, isSolana } from '@orderly.network/utils';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { WS_WalletStatusEnum, AccountStatusEnum, ChainNamespace, AssetHistoryStatusEnum, AssetHistorySideEnum, Arbitrum, isNativeTokenChecker as isNativeTokenChecker$1, ABSTRACT_CHAIN_ID_MAP, nativeTokenAddress as nativeTokenAddress$1 } from '@orderly.network/types';
@@ -223,9 +223,26 @@ var ActionButton = (props) => {
223
223
  }
224
224
  ) });
225
225
  };
226
+ var AvailableTooltipMessage = ({
227
+ tokenSymbol,
228
+ decimals
229
+ }) => {
230
+ const { t } = useTranslation();
231
+ const { maxAmount } = useWithdraw({
232
+ token: tokenSymbol,
233
+ decimals
234
+ });
235
+ const amountText = useMemo(() => {
236
+ if (maxAmount === void 0 || maxAmount === null)
237
+ return "--";
238
+ return maxAmount.toString();
239
+ }, [maxAmount]);
240
+ return /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 80, children: t("transfer.withdraw.available.tooltip", { amount: amountText }) });
241
+ };
226
242
  var AvailableQuantity = (props) => {
227
243
  const { amount, maxQuantity, token, loading } = props;
228
244
  const { t } = useTranslation();
245
+ const { isMobile } = useScreen();
229
246
  const { getIndexPrice } = useIndexPricesStream();
230
247
  const name = token?.display_name || token?.symbol || "";
231
248
  const dp = token?.precision ?? token?.decimals ?? 2;
@@ -242,7 +259,57 @@ var AvailableQuantity = (props) => {
242
259
  ] }),
243
260
  /* @__PURE__ */ jsxs(Flex, { gapX: 2, itemAlign: "center", className: "oui-ml-auto", children: [
244
261
  /* @__PURE__ */ jsxs(Flex, { gapX: 1, itemAlign: "center", children: [
245
- /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 36, children: `${t("common.available")}: ` }),
262
+ props.tooltipContent ? isMobile ? /* @__PURE__ */ jsx(
263
+ "button",
264
+ {
265
+ type: "button",
266
+ className: "oui-p-0",
267
+ onClick: () => {
268
+ if (token?.symbol) {
269
+ const anyToken = token;
270
+ modal.alert({
271
+ title: t("common.tips"),
272
+ message: /* @__PURE__ */ jsx(
273
+ AvailableTooltipMessage,
274
+ {
275
+ tokenSymbol: token.symbol,
276
+ decimals: anyToken?.token_decimal ?? token.decimals ?? token.precision
277
+ }
278
+ )
279
+ });
280
+ } else {
281
+ modal.alert({
282
+ title: t("common.tips"),
283
+ message: props.tooltipContent
284
+ });
285
+ }
286
+ },
287
+ children: /* @__PURE__ */ jsx(
288
+ Text,
289
+ {
290
+ size: "2xs",
291
+ intensity: 36,
292
+ className: "oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12",
293
+ children: `${t("common.available")}: `
294
+ }
295
+ )
296
+ }
297
+ ) : /* @__PURE__ */ jsx(
298
+ Tooltip,
299
+ {
300
+ content: props.tooltipContent,
301
+ className: "oui-max-w-[274px]",
302
+ children: /* @__PURE__ */ jsx(
303
+ Text,
304
+ {
305
+ size: "2xs",
306
+ intensity: 36,
307
+ className: "oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12",
308
+ children: `${t("common.available")}: `
309
+ }
310
+ )
311
+ }
312
+ ) : /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 36, children: `${t("common.available")}: ` }),
246
313
  loading ? /* @__PURE__ */ jsx(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx(
247
314
  Text.numeral,
248
315
  {
@@ -356,6 +423,9 @@ var ChainSelect = (props) => {
356
423
  }
357
424
  ) : /* @__PURE__ */ jsx(ChainIcon, { className: "oui-size-[18px]", chainId: value?.id });
358
425
  const chainName = wrongNetwork ? "Unknown" : value?.info?.network_infos?.name;
426
+ const currentChain = chains.find((chain) => chain.chain_id === value?.id);
427
+ const extendedCurrentChain = currentChain;
428
+ const isCurrentChainSupported = !currentChain || extendedCurrentChain?.isSupported !== false;
359
429
  const renderRightIcon = () => {
360
430
  if (loading) {
361
431
  return /* @__PURE__ */ jsx(Spinner, { size: "sm" });
@@ -379,9 +449,10 @@ var ChainSelect = (props) => {
379
449
  children: [
380
450
  /* @__PURE__ */ jsxs("div", { children: [
381
451
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 54, children: t("transfer.network") }) }),
382
- /* @__PURE__ */ jsxs(Flex, { gapX: 1, children: [
452
+ /* @__PURE__ */ jsxs(Flex, { gapX: 1, itemAlign: "center", children: [
383
453
  chainIcon,
384
- /* @__PURE__ */ jsx(Text, { size: "sm", intensity: 80, children: chainName })
454
+ /* @__PURE__ */ jsx(Text, { size: "sm", intensity: 80, children: chainName }),
455
+ !isCurrentChainSupported && /* @__PURE__ */ jsx(Badge, { color: "danger", size: "xs", children: t("common.notSupported") })
385
456
  ] })
386
457
  ] }),
387
458
  renderRightIcon()
@@ -389,27 +460,40 @@ var ChainSelect = (props) => {
389
460
  }
390
461
  );
391
462
  const content = chains.map((chain, index) => {
463
+ const extendedChain = chain;
392
464
  const isActive = chain.chain_id === value?.id;
465
+ const isSupported = extendedChain.isSupported !== false;
393
466
  return /* @__PURE__ */ jsxs(
394
467
  Flex,
395
468
  {
396
469
  px: 2,
397
470
  r: "base",
398
471
  justify: "between",
472
+ itemAlign: "center",
399
473
  className: cn(
400
474
  "oui-deposit-network-select-item",
401
- "hover:oui-bg-base-5 oui-h-[30px] oui-cursor-pointer",
475
+ "oui-h-[30px]",
476
+ isSupported ? "hover:oui-bg-base-5 oui-cursor-pointer" : "oui-cursor-not-allowed",
402
477
  isActive && "oui-bg-base-5",
403
478
  index !== 0 && "oui-mt-[2px]"
404
479
  ),
405
480
  onClick: async () => {
481
+ if (!isSupported)
482
+ return;
406
483
  setOpen(false);
407
484
  await props.onValueChange(chain);
408
485
  },
409
486
  children: [
410
487
  /* @__PURE__ */ jsxs(Flex, { gapX: 1, itemAlign: "center", children: [
411
- /* @__PURE__ */ jsx(ChainIcon, { className: "oui-size-[18px]", chainId: chain.chain_id }),
412
- /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 54, children: chain.name })
488
+ /* @__PURE__ */ jsx(
489
+ ChainIcon,
490
+ {
491
+ className: cn("oui-size-[18px]", !isSupported && "oui-opacity-50"),
492
+ chainId: chain.chain_id
493
+ }
494
+ ),
495
+ /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: isSupported ? 54 : 36, children: chain.name }),
496
+ !isSupported && /* @__PURE__ */ jsx(Badge, { color: "danger", size: "xs", children: t("common.notSupported") })
413
497
  ] }),
414
498
  isActive && /* @__PURE__ */ jsx(
415
499
  Box,
@@ -845,6 +929,7 @@ var QuantityInput = (props) => {
845
929
  label,
846
930
  status,
847
931
  hintMessage,
932
+ hintSuffix,
848
933
  value,
849
934
  onValueChange,
850
935
  fetchBalance,
@@ -855,6 +940,8 @@ var QuantityInput = (props) => {
855
940
  vaultBalanceList,
856
941
  displayType,
857
942
  tokenBalances,
943
+ tokenValueFormatter,
944
+ tokenShowCaret,
858
945
  ...rest
859
946
  } = props;
860
947
  const { t } = useTranslation();
@@ -920,6 +1007,8 @@ var QuantityInput = (props) => {
920
1007
  size: rest.size,
921
1008
  onValueChange: _onTokenChange,
922
1009
  showIcon: true,
1010
+ valueFormatter: tokenValueFormatter,
1011
+ showCaret: tokenShowCaret,
923
1012
  optionRenderer,
924
1013
  contentProps: {
925
1014
  onCloseAutoFocus: (event) => {
@@ -937,30 +1026,33 @@ var QuantityInput = (props) => {
937
1026
  }
938
1027
  }
939
1028
  ) });
940
- const message = /* @__PURE__ */ jsxs(Flex, { mt: 1, gapX: 1, px: 1, children: [
941
- /* @__PURE__ */ jsx(
942
- Box,
943
- {
944
- width: 4,
945
- height: 4,
946
- r: "full",
947
- className: cn(
948
- status === "error" && "oui-bg-danger-light",
949
- status === "warning" && "oui-bg-warning-light"
950
- )
951
- }
952
- ),
953
- /* @__PURE__ */ jsx(
954
- Text,
955
- {
956
- size: "2xs",
957
- className: cn(
958
- status === "error" && "oui-text-danger-light",
959
- status === "warning" && "oui-text-warning-light"
960
- ),
961
- children: hintMessage
962
- }
963
- )
1029
+ const message = /* @__PURE__ */ jsxs(Flex, { mt: 1, gapX: 1, px: 1, justify: "between", itemAlign: "center", children: [
1030
+ /* @__PURE__ */ jsxs(Flex, { gapX: 1, itemAlign: "center", children: [
1031
+ /* @__PURE__ */ jsx(
1032
+ Box,
1033
+ {
1034
+ width: 4,
1035
+ height: 4,
1036
+ r: "full",
1037
+ className: cn(
1038
+ status === "error" && "oui-bg-danger-light",
1039
+ status === "warning" && "oui-bg-warning-light"
1040
+ )
1041
+ }
1042
+ ),
1043
+ /* @__PURE__ */ jsx(
1044
+ Text,
1045
+ {
1046
+ size: "2xs",
1047
+ className: cn(
1048
+ status === "error" && "oui-text-danger-light",
1049
+ status === "warning" && "oui-text-warning-light"
1050
+ ),
1051
+ children: hintMessage
1052
+ }
1053
+ )
1054
+ ] }),
1055
+ hintSuffix && /* @__PURE__ */ jsx(Box, { className: "oui-flex oui-items-center oui-gap-1", children: hintSuffix })
964
1056
  ] });
965
1057
  const _placeholder = placeholder ?? (loading ? "" : "0");
966
1058
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -4527,8 +4619,6 @@ var useToken = (currentChain, filter = () => true) => {
4527
4619
  sourceTokenUpdatedRef
4528
4620
  };
4529
4621
  };
4530
-
4531
- // src/components/depositForm/depositForm.script.tsx
4532
4622
  var { collateralRatio, collateralContribution, calcMinimumReceived } = account;
4533
4623
  var SWAP_USDC_PRECISION = 3;
4534
4624
  var useDepositFormScript = (options2) => {
@@ -4586,6 +4676,23 @@ var useDepositFormScript = (options2) => {
4586
4676
  () => new Decimal(balance || 0).todp(sourceToken?.precision ?? 2, Decimal.ROUND_DOWN).toString(),
4587
4677
  [balance, sourceToken?.precision]
4588
4678
  );
4679
+ const maxDepositAmount = useMemo(() => {
4680
+ const balanceDecimal = new Decimal(balance || 0).todp(
4681
+ sourceToken?.precision ?? 2,
4682
+ Decimal.ROUND_DOWN
4683
+ );
4684
+ if (sourceToken?.user_max_qty === -1 || sourceToken?.user_max_qty === void 0) {
4685
+ return balanceDecimal.toString();
4686
+ }
4687
+ if (sourceToken?.user_max_qty === 0) {
4688
+ return "0";
4689
+ }
4690
+ const userMaxQty = new Decimal(sourceToken.user_max_qty).todp(
4691
+ sourceToken?.precision ?? 2,
4692
+ Decimal.ROUND_DOWN
4693
+ );
4694
+ return balanceDecimal.lt(userMaxQty) ? balanceDecimal.toString() : userMaxQty.toString();
4695
+ }, [balance, sourceToken?.precision, sourceToken?.user_max_qty]);
4589
4696
  const { inputStatus, hintMessage } = useInputStatus({
4590
4697
  quantity,
4591
4698
  maxQuantity
@@ -4640,13 +4747,31 @@ var useDepositFormScript = (options2) => {
4640
4747
  return "";
4641
4748
  }
4642
4749
  if (new Decimal(quantity).gt(sourceToken?.user_max_qty)) {
4643
- return t("transfer.deposit.userMaxQty.error", {
4644
- maxQty: sourceToken?.user_max_qty,
4645
- token: sourceToken?.symbol
4646
- });
4750
+ return /* @__PURE__ */ jsx(
4751
+ Trans,
4752
+ {
4753
+ i18nKey: "transfer.deposit.userMaxQty.error",
4754
+ values: {
4755
+ token: sourceToken?.symbol,
4756
+ chain: currentChain?.info?.network_infos?.name || ""
4757
+ },
4758
+ components: [
4759
+ /* @__PURE__ */ jsx(
4760
+ "a",
4761
+ {
4762
+ href: "https://orderly.network/docs/introduction/trade-on-orderly/multi-collateral#max-deposits-global",
4763
+ target: "_blank",
4764
+ rel: "noopener noreferrer",
4765
+ className: "oui-text-primary"
4766
+ },
4767
+ "0"
4768
+ )
4769
+ ]
4770
+ }
4771
+ );
4647
4772
  }
4648
4773
  return "";
4649
- }, [sourceToken, targetToken, quantity, t]);
4774
+ }, [sourceToken, targetToken, quantity, currentChain, t]);
4650
4775
  const loading = submitting || depositFeeRevalidating;
4651
4776
  const nativeSymbol = useMemo(() => {
4652
4777
  return currentChain?.info?.nativeToken?.symbol;
@@ -4732,6 +4857,9 @@ var useDepositFormScript = (options2) => {
4732
4857
  nativeBalance
4733
4858
  ]);
4734
4859
  const warningMessage = swapWarningMessage || userMaxQtyMessage || gasFeeMessage || feeWarningMessage || insufficientGasMessage;
4860
+ const hasUserMaxQtyError = !!userMaxQtyMessage;
4861
+ const finalInputStatus = hasUserMaxQtyError ? "error" : inputStatus;
4862
+ const finalHintMessage = hasUserMaxQtyError ? t("transfer.deposit.exceedCap") : hintMessage;
4735
4863
  const disabled = !quantity || Number(quantity) === 0 || !sourceToken || inputStatus === "error" || depositFeeRevalidating || swapRevalidating || // if exceed collateral cap, disable deposit
4736
4864
  !!userMaxQtyMessage || !!feeWarningMessage || !!insufficientGasMessage;
4737
4865
  const targetQuantity = useMemo(() => {
@@ -4780,10 +4908,11 @@ var useDepositFormScript = (options2) => {
4780
4908
  quantity,
4781
4909
  collateralContributionQuantity,
4782
4910
  maxQuantity,
4911
+ maxDepositAmount,
4783
4912
  indexPrice,
4784
4913
  onQuantityChange: setQuantity,
4785
- hintMessage,
4786
- inputStatus,
4914
+ hintMessage: finalHintMessage,
4915
+ inputStatus: finalInputStatus,
4787
4916
  chains,
4788
4917
  currentChain,
4789
4918
  settingChain,
@@ -4935,6 +5064,7 @@ var DepositForm = (props) => {
4935
5064
  quantity,
4936
5065
  collateralContributionQuantity,
4937
5066
  maxQuantity,
5067
+ maxDepositAmount,
4938
5068
  onQuantityChange,
4939
5069
  hintMessage,
4940
5070
  inputStatus,
@@ -4969,6 +5099,118 @@ var DepositForm = (props) => {
4969
5099
  targetQuantityLoading
4970
5100
  } = props;
4971
5101
  const { t } = useTranslation();
5102
+ const showRegularTokenRenderer = sourceToken?.user_max_qty !== void 0 && sourceToken?.user_max_qty === -1;
5103
+ const { isMobile } = useScreen();
5104
+ const renderDepositCapTooltipContent = (tokenLabel) => /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", children: [
5105
+ /* @__PURE__ */ jsxs(Text, { size: "2xs", weight: "semibold", intensity: 36, children: [
5106
+ t("transfer.depositCap.tooltip"),
5107
+ /* @__PURE__ */ jsxs(Text, { as: "span", size: "2xs", weight: "semibold", intensity: 80, children: [
5108
+ tokenLabel,
5109
+ "."
5110
+ ] })
5111
+ ] }),
5112
+ /* @__PURE__ */ jsx(
5113
+ "a",
5114
+ {
5115
+ href: "https://orderly.network/docs/introduction/trade-on-orderly/multi-collateral#max-deposits-user",
5116
+ target: "_blank",
5117
+ rel: "noopener noreferrer",
5118
+ className: "oui-text-2xs oui-text-primary",
5119
+ children: t("common.learnMore")
5120
+ }
5121
+ )
5122
+ ] });
5123
+ const tokenValueFormatter = (value) => /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "end", gapY: 1, children: [
5124
+ /* @__PURE__ */ jsxs(Flex, { gapX: 1, itemAlign: "center", children: [
5125
+ /* @__PURE__ */ jsx(TokenIcon, { name: value, className: "oui-size-[16px]" }),
5126
+ /* @__PURE__ */ jsx(Text, { weight: "semibold", intensity: 54, children: value }),
5127
+ /* @__PURE__ */ jsx(
5128
+ CaretDownIcon,
5129
+ {
5130
+ size: 12,
5131
+ className: "oui-text-base-contrast-54",
5132
+ opacity: 1
5133
+ }
5134
+ )
5135
+ ] }),
5136
+ /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", className: "oui-gap-[2px]", children: [
5137
+ /* @__PURE__ */ jsxs(
5138
+ Text,
5139
+ {
5140
+ size: "2xs",
5141
+ intensity: 36,
5142
+ weight: "regular",
5143
+ className: "oui-leading-[10px]",
5144
+ children: [
5145
+ t("transfer.depositCap", "Deposit cap"),
5146
+ " ",
5147
+ /* @__PURE__ */ jsx(
5148
+ Text.numeral,
5149
+ {
5150
+ as: "span",
5151
+ size: "2xs",
5152
+ intensity: 80,
5153
+ weight: "regular",
5154
+ className: "oui-leading-[10px]",
5155
+ dp: 0,
5156
+ children: sourceToken?.user_max_qty?.toString() || "0"
5157
+ }
5158
+ )
5159
+ ]
5160
+ }
5161
+ ),
5162
+ isMobile ? /* @__PURE__ */ jsx(
5163
+ "button",
5164
+ {
5165
+ type: "button",
5166
+ className: "oui-flex oui-items-center",
5167
+ onClick: (event) => {
5168
+ event.stopPropagation();
5169
+ modal.alert({
5170
+ title: t("common.tips"),
5171
+ message: /* @__PURE__ */ jsx(Box, { children: renderDepositCapTooltipContent(value) })
5172
+ });
5173
+ },
5174
+ onMouseDown: (event) => {
5175
+ event.stopPropagation();
5176
+ },
5177
+ onPointerDown: (event) => {
5178
+ event.stopPropagation();
5179
+ },
5180
+ children: /* @__PURE__ */ jsx(
5181
+ InfoCircleIcon,
5182
+ {
5183
+ className: "oui-size-3 oui-shrink-0 oui-cursor-pointer",
5184
+ opacity: 0.36
5185
+ }
5186
+ )
5187
+ }
5188
+ ) : /* @__PURE__ */ jsx(
5189
+ Tooltip,
5190
+ {
5191
+ content: /* @__PURE__ */ jsx(
5192
+ Box,
5193
+ {
5194
+ onMouseDown: (event) => {
5195
+ event.stopPropagation();
5196
+ },
5197
+ onPointerDown: (event) => {
5198
+ event.stopPropagation();
5199
+ },
5200
+ children: renderDepositCapTooltipContent(value)
5201
+ }
5202
+ ),
5203
+ children: /* @__PURE__ */ jsx(
5204
+ InfoCircleIcon,
5205
+ {
5206
+ className: "oui-size-3 oui-shrink-0 oui-cursor-pointer",
5207
+ opacity: 0.36
5208
+ }
5209
+ )
5210
+ }
5211
+ )
5212
+ ] })
5213
+ ] });
4972
5214
  const renderContent = () => {
4973
5215
  if (needSwap || needCrossSwap) {
4974
5216
  return /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", mt: 1, gapY: 1, children: [
@@ -5046,6 +5288,8 @@ var DepositForm = (props) => {
5046
5288
  hintMessage,
5047
5289
  fetchBalance,
5048
5290
  tokenBalances: props.tokenBalances,
5291
+ tokenShowCaret: showRegularTokenRenderer,
5292
+ tokenValueFormatter: showRegularTokenRenderer ? void 0 : tokenValueFormatter,
5049
5293
  "data-testId": "oui-testid-deposit-dialog-quantity-input",
5050
5294
  disabled: !props.isLoggedIn
5051
5295
  }
@@ -5059,7 +5303,7 @@ var DepositForm = (props) => {
5059
5303
  maxQuantity,
5060
5304
  loading: balanceRevalidating,
5061
5305
  onClick: () => {
5062
- onQuantityChange(maxQuantity);
5306
+ onQuantityChange(maxDepositAmount);
5063
5307
  }
5064
5308
  }
5065
5309
  ),
@@ -5207,6 +5451,13 @@ var UnsettlePnlInfo = (props) => {
5207
5451
  dialogContent
5208
5452
  } = props;
5209
5453
  const { t } = useTranslation();
5454
+ const { isMobile } = useScreen();
5455
+ const renderUnsettledLabel = () => {
5456
+ return /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "start", gap: 1, children: [
5457
+ /* @__PURE__ */ jsx(ExclamationFillIcon, { size: 14, className: "oui-text-warning-darken" }),
5458
+ /* @__PURE__ */ jsx(Text, { className: "oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12", children: `${t("settle.unsettled")}:` })
5459
+ ] });
5460
+ };
5210
5461
  if (unsettledPnl === 0 && !hasPositions) {
5211
5462
  return /* @__PURE__ */ jsx(Fragment, {});
5212
5463
  }
@@ -5221,23 +5472,27 @@ var UnsettlePnlInfo = (props) => {
5221
5472
  };
5222
5473
  return /* @__PURE__ */ jsxs(Flex, { justify: "between", className: "oui-text-2xs oui-text-base-contrast-36", children: [
5223
5474
  /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "start", gap: 1, children: [
5224
- /* @__PURE__ */ jsx(
5475
+ tooltipContent ? isMobile ? /* @__PURE__ */ jsx(
5476
+ "button",
5477
+ {
5478
+ type: "button",
5479
+ className: "oui-p-0",
5480
+ onClick: () => {
5481
+ modal.alert({
5482
+ title: t("common.tips"),
5483
+ message: tooltipContent
5484
+ });
5485
+ },
5486
+ children: renderUnsettledLabel()
5487
+ }
5488
+ ) : /* @__PURE__ */ jsx(
5225
5489
  Tooltip,
5226
5490
  {
5227
5491
  className: "oui-max-w-[274px] oui-font-semibold",
5228
5492
  content: tooltipContent,
5229
- children: /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "start", gap: 1, children: [
5230
- /* @__PURE__ */ jsx(
5231
- ExclamationFillIcon,
5232
- {
5233
- size: 14,
5234
- className: "oui-text-warning-darken"
5235
- }
5236
- ),
5237
- /* @__PURE__ */ jsx(Text, { className: "oui-cursor-pointer oui-border-b oui-border-dashed oui-border-line-12", children: `${t("settle.unsettled")}:` })
5238
- ] })
5493
+ children: renderUnsettledLabel()
5239
5494
  }
5240
- ),
5495
+ ) : renderUnsettledLabel(),
5241
5496
  /* @__PURE__ */ jsx(
5242
5497
  Text.numeral,
5243
5498
  {
@@ -5246,7 +5501,7 @@ var UnsettlePnlInfo = (props) => {
5246
5501
  weight: "semibold",
5247
5502
  dp: 6,
5248
5503
  "data-testid": "oui-testid-withdraw-dialog-unsettledPnl-value",
5249
- children: unsettledPnl
5504
+ children: unsettledPnl ?? "--"
5250
5505
  }
5251
5506
  ),
5252
5507
  /* @__PURE__ */ jsx(Text, { children: "USDC" })
@@ -5496,7 +5751,9 @@ var WithdrawForm = (props) => {
5496
5751
  sourceTokens,
5497
5752
  onSourceTokenChange,
5498
5753
  vaultBalanceList,
5499
- qtyGreaterThanMaxAmount
5754
+ qtyGreaterThanMaxAmount,
5755
+ isTokenUnsupported,
5756
+ onSwitchToSupportedNetwork
5500
5757
  } = props;
5501
5758
  const { t } = useTranslation();
5502
5759
  const internalWithdrawPanel = /* @__PURE__ */ jsxs(
@@ -5540,6 +5797,25 @@ var WithdrawForm = (props) => {
5540
5797
  onTokenChange: onSourceTokenChange,
5541
5798
  status: props.inputStatus,
5542
5799
  hintMessage: props.hintMessage,
5800
+ hintSuffix: isTokenUnsupported ? /* @__PURE__ */ jsxs(
5801
+ "button",
5802
+ {
5803
+ type: "button",
5804
+ onClick: onSwitchToSupportedNetwork,
5805
+ className: "oui-inline-flex oui-items-center oui-gap-1 oui-text-2xs oui-font-semibold oui-text-primary",
5806
+ children: [
5807
+ t("common.switch"),
5808
+ /* @__PURE__ */ jsx(
5809
+ ArrowLeftRightIcon,
5810
+ {
5811
+ size: 16,
5812
+ className: "oui-text-primary oui-mt-0.5",
5813
+ opacity: 1
5814
+ }
5815
+ )
5816
+ ]
5817
+ }
5818
+ ) : void 0,
5543
5819
  vaultBalanceList,
5544
5820
  testId: "oui-testid-withdraw-dialog-quantity-input",
5545
5821
  displayType: "vaultBalance",
@@ -5555,7 +5831,10 @@ var WithdrawForm = (props) => {
5555
5831
  loading: props.balanceRevalidating,
5556
5832
  onClick: () => {
5557
5833
  onQuantityChange(maxQuantity.toString());
5558
- }
5834
+ },
5835
+ tooltipContent: t("transfer.withdraw.available.tooltip", {
5836
+ amount: maxQuantity.toString()
5837
+ })
5559
5838
  }
5560
5839
  ),
5561
5840
  /* @__PURE__ */ jsx(Box, { mx: 2, mt: 1, children: /* @__PURE__ */ jsx(
@@ -5905,19 +6184,36 @@ function useWithdrawToken(params) {
5905
6184
  const [token, setToken] = useState();
5906
6185
  const [tokens, setTokens] = useState([]);
5907
6186
  const tokensInfo = useTokensInfo();
6187
+ const { data: holdings } = useHoldingStream();
5908
6188
  const { sourceToken, onSourceTokenChange, sourceTokens } = useToken(
5909
6189
  currentChain,
5910
6190
  (token2) => token2.symbol === "USDC" || token2.is_collateral
5911
6191
  );
5912
- useEffect(() => {
6192
+ const allTokens = useMemo(() => {
5913
6193
  if (!tokensInfo?.length)
5914
- return;
5915
- const list = tokensInfo.map((item) => ({
6194
+ return [];
6195
+ const holdingMap = /* @__PURE__ */ new Map();
6196
+ holdings?.forEach((item) => {
6197
+ holdingMap.set(item.token, item);
6198
+ });
6199
+ const mappedTokens = tokensInfo.map((item) => ({
5916
6200
  ...item,
5917
6201
  symbol: item.token,
5918
6202
  token_decimal: item.decimals,
5919
6203
  precision: item.decimals
5920
6204
  }));
6205
+ const list = mappedTokens.filter((token2) => {
6206
+ const holding = holdingMap.get(token2.symbol);
6207
+ if (!holdings)
6208
+ return true;
6209
+ return !!holding && holding.holding > 0;
6210
+ });
6211
+ if (list.length === 0) {
6212
+ const usdcToken = mappedTokens.find((t) => t.symbol === "USDC");
6213
+ if (usdcToken) {
6214
+ return [usdcToken];
6215
+ }
6216
+ }
5921
6217
  list.sort((a, b) => {
5922
6218
  if (a.symbol === "USDC")
5923
6219
  return -1;
@@ -5925,10 +6221,39 @@ function useWithdrawToken(params) {
5925
6221
  return 1;
5926
6222
  return 0;
5927
6223
  });
5928
- const usdcToken = getTokenByTokenList(tokens);
5929
- setToken(usdcToken || list?.[0]);
5930
- setTokens(list);
5931
- }, [tokensInfo]);
6224
+ return list;
6225
+ }, [tokensInfo, holdings]);
6226
+ useEffect(() => {
6227
+ if (!allTokens.length)
6228
+ return;
6229
+ const usdcToken = getTokenByTokenList(allTokens);
6230
+ setToken(usdcToken || allTokens?.[0]);
6231
+ setTokens(allTokens);
6232
+ }, [allTokens]);
6233
+ const isTokenSupportedOnChain = useMemoizedFn(
6234
+ (tokenSymbol) => {
6235
+ if (!currentChain?.info?.token_infos) {
6236
+ return false;
6237
+ }
6238
+ return currentChain.info.token_infos.some(
6239
+ (token2) => token2.symbol === tokenSymbol
6240
+ );
6241
+ }
6242
+ );
6243
+ const handleSourceTokenChange = useMemoizedFn((newToken) => {
6244
+ if (withdrawTo === "wallet" /* Wallet */ && currentChain && newToken.symbol) {
6245
+ const matchingToken = sourceTokens.find(
6246
+ (t) => t.symbol === newToken.symbol
6247
+ );
6248
+ if (matchingToken) {
6249
+ onSourceTokenChange(matchingToken);
6250
+ } else {
6251
+ onSourceTokenChange(newToken);
6252
+ }
6253
+ return;
6254
+ }
6255
+ onSourceTokenChange(newToken);
6256
+ });
5932
6257
  const syncToken = useMemoizedFn(() => {
5933
6258
  if (withdrawTo === "accountId" /* Account */) {
5934
6259
  const findToken = tokens.find(
@@ -5937,29 +6262,31 @@ function useWithdrawToken(params) {
5937
6262
  if (findToken) {
5938
6263
  setToken(findToken);
5939
6264
  }
5940
- } else {
5941
- const findToken = sourceTokens.find(
5942
- (item) => item.symbol === token?.symbol
5943
- );
5944
- if (findToken) {
5945
- onSourceTokenChange(findToken);
5946
- }
5947
6265
  }
5948
6266
  });
5949
6267
  useEffect(() => {
5950
6268
  syncToken();
5951
- }, [withdrawTo]);
6269
+ }, [
6270
+ withdrawTo,
6271
+ allTokens,
6272
+ sourceToken,
6273
+ sourceTokens,
6274
+ currentChain,
6275
+ syncToken
6276
+ ]);
5952
6277
  if (withdrawTo === "accountId" /* Account */) {
5953
6278
  return {
5954
6279
  sourceToken: token,
5955
6280
  onSourceTokenChange: setToken,
5956
- sourceTokens: tokens
6281
+ sourceTokens: tokens,
6282
+ isTokenSupportedOnChain
5957
6283
  };
5958
6284
  }
5959
6285
  return {
5960
6286
  sourceToken,
5961
- onSourceTokenChange,
5962
- sourceTokens
6287
+ onSourceTokenChange: handleSourceTokenChange,
6288
+ sourceTokens: allTokens,
6289
+ isTokenSupportedOnChain
5963
6290
  };
5964
6291
  }
5965
6292
 
@@ -6002,6 +6329,7 @@ var useWithdrawFormScript = (options2) => {
6002
6329
  settingChain
6003
6330
  } = useWalletConnector();
6004
6331
  const isLoggedIn = useAuthGuard();
6332
+ const [pendingTokenSymbol, setPendingTokenSymbol] = useState();
6005
6333
  const currentChain = useMemo(() => {
6006
6334
  const chainId = connectedChain ? praseChainIdToNumber(connectedChain.id) : Number.parseInt(linkDeviceStorage?.chainId);
6007
6335
  if (!chainId) {
@@ -6014,17 +6342,41 @@ var useWithdrawFormScript = (options2) => {
6014
6342
  info: chain
6015
6343
  };
6016
6344
  }, [findByChainId, connectedChain, linkDeviceStorage]);
6017
- const { sourceToken, onSourceTokenChange, sourceTokens } = useWithdrawToken({
6345
+ const {
6346
+ sourceToken,
6347
+ onSourceTokenChange: _OnSourceTokenChange,
6348
+ sourceTokens,
6349
+ isTokenSupportedOnChain
6350
+ } = useWithdrawToken({
6018
6351
  currentChain,
6019
6352
  withdrawTo
6020
6353
  });
6354
+ const onSourceTokenChange = useMemoizedFn((token) => {
6355
+ setQuantity("");
6356
+ _OnSourceTokenChange(token);
6357
+ setPendingTokenSymbol(token.symbol);
6358
+ });
6021
6359
  const tokenChains = useMemo(() => {
6022
- return chains.filter(
6023
- (chain) => chain.token_infos?.some(
6360
+ if (!chains)
6361
+ return [];
6362
+ const list = chains.map((chain) => {
6363
+ const isSupported = chain.token_infos?.some(
6024
6364
  (token) => token.symbol === sourceToken?.symbol
6025
- )
6026
- ).map((chain) => chain.network_infos);
6027
- }, [chains, networkId, sourceToken]);
6365
+ );
6366
+ return {
6367
+ ...chain.network_infos,
6368
+ isSupported
6369
+ };
6370
+ });
6371
+ list.sort((a, b) => {
6372
+ const aSupported = !!a.isSupported;
6373
+ const bSupported = !!b.isSupported;
6374
+ if (aSupported === bSupported)
6375
+ return 0;
6376
+ return aSupported ? -1 : 1;
6377
+ });
6378
+ return list;
6379
+ }, [chains, sourceToken?.symbol]);
6028
6380
  const { walletName, address } = useMemo(
6029
6381
  () => ({
6030
6382
  walletName: wallet?.label,
@@ -6113,6 +6465,17 @@ var useWithdrawFormScript = (options2) => {
6113
6465
  },
6114
6466
  [currentChain, switchChain, findByChainId, t]
6115
6467
  );
6468
+ useEffect(() => {
6469
+ if (!pendingTokenSymbol || !sourceTokens || sourceTokens.length === 0) {
6470
+ return;
6471
+ }
6472
+ const matchedToken = sourceTokens.find(
6473
+ (token) => token.symbol === pendingTokenSymbol
6474
+ );
6475
+ if (matchedToken) {
6476
+ onSourceTokenChange(matchedToken);
6477
+ }
6478
+ }, [pendingTokenSymbol, sourceTokens, onSourceTokenChange, currentChain]);
6116
6479
  const onWithdraw = async () => {
6117
6480
  if (loading) {
6118
6481
  return;
@@ -6177,7 +6540,20 @@ var useWithdrawFormScript = (options2) => {
6177
6540
  }
6178
6541
  return toNonExponential(value.toNumber());
6179
6542
  }, [fee, quantity]);
6543
+ const isTokenUnsupported = useMemo(() => {
6544
+ if (withdrawTo !== "wallet" /* Wallet */ || !currentChain || !sourceToken?.symbol) {
6545
+ return false;
6546
+ }
6547
+ return !isTokenSupportedOnChain(sourceToken.symbol);
6548
+ }, [withdrawTo, currentChain, sourceToken?.symbol, isTokenSupportedOnChain]);
6180
6549
  useEffect(() => {
6550
+ if (isTokenUnsupported && sourceToken?.symbol) {
6551
+ setInputStatus("error");
6552
+ setHintMessage(
6553
+ t("transfer.withdraw.unsupported.token", { token: sourceToken.symbol })
6554
+ );
6555
+ return;
6556
+ }
6181
6557
  if (!quantity) {
6182
6558
  setInputStatus("default");
6183
6559
  setHintMessage("");
@@ -6193,7 +6569,16 @@ var useWithdrawFormScript = (options2) => {
6193
6569
  setHintMessage("");
6194
6570
  }
6195
6571
  }
6196
- }, [quantity, maxAmount, unsettledPnL, crossChainTrans]);
6572
+ }, [
6573
+ quantity,
6574
+ maxAmount,
6575
+ unsettledPnL,
6576
+ crossChainTrans,
6577
+ isTokenUnsupported,
6578
+ sourceToken?.symbol,
6579
+ t
6580
+ ]);
6581
+ const disabled = crossChainTrans || !quantity || Number(quantity) === 0 || ["error", "warning"].includes(inputStatus) || withdrawTo === "accountId" /* Account */ && !withdrawAccountIdState.toAccountId || qtyGreaterThanMaxAmount || qtyGreaterThanVault || !!minAmountWarningMessage || isTokenUnsupported;
6197
6582
  useEffect(() => {
6198
6583
  setCrossChainTrans(!!assetHistory?.length);
6199
6584
  }, [assetHistory?.length]);
@@ -6215,8 +6600,21 @@ var useWithdrawFormScript = (options2) => {
6215
6600
  token: sourceToken?.symbol,
6216
6601
  quantity
6217
6602
  });
6218
- const disabled = crossChainTrans || !quantity || Number(quantity) === 0 || ["error", "warning"].includes(inputStatus) || withdrawTo === "accountId" /* Account */ && !withdrawAccountIdState.toAccountId || qtyGreaterThanMaxAmount || !!minAmountWarningMessage || qtyGreaterThanVault;
6219
- const warningMessage = minAmountWarningMessage || ltvWarningMessage || vaultBalanceMessage;
6603
+ const warningMessage = ltvWarningMessage || minAmountWarningMessage || vaultBalanceMessage;
6604
+ useMemo(() => {
6605
+ if (withdrawTo === "accountId" /* Account */) {
6606
+ return [];
6607
+ }
6608
+ return vaultBalanceList?.filter(
6609
+ (item) => Number.parseInt(item.chain_id) === currentChain?.id
6610
+ );
6611
+ }, [vaultBalanceList, currentChain, withdrawTo]);
6612
+ const onSwitchToSupportedNetwork = useMemoizedFn(async () => {
6613
+ if (!tokenChains || tokenChains.length === 0)
6614
+ return;
6615
+ const targetNetwork = tokenChains.find((item) => item.isSupported) ?? tokenChains[0];
6616
+ await onChainChange(targetNetwork);
6617
+ });
6220
6618
  return {
6221
6619
  walletName,
6222
6620
  address,
@@ -6256,7 +6654,9 @@ var useWithdrawFormScript = (options2) => {
6256
6654
  currentLTV,
6257
6655
  nextLTV,
6258
6656
  warningMessage,
6259
- isLoggedIn
6657
+ isLoggedIn,
6658
+ isTokenUnsupported,
6659
+ onSwitchToSupportedNetwork
6260
6660
  };
6261
6661
  };
6262
6662
  var WithdrawFormWidget = (props) => {
@@ -7670,7 +8070,7 @@ var DepositStatusContent = (props) => {
7670
8070
  estimatedTime
7671
8071
  ] });
7672
8072
  }
7673
- return /* @__PURE__ */ jsx(Badge2, { children: props.count });
8073
+ return /* @__PURE__ */ jsx(Badge3, { children: props.count });
7674
8074
  };
7675
8075
  return /* @__PURE__ */ jsxs(
7676
8076
  Flex,
@@ -7728,7 +8128,7 @@ var DepositStatusContent = (props) => {
7728
8128
  }
7729
8129
  );
7730
8130
  };
7731
- var Badge2 = (props) => {
8131
+ var Badge3 = (props) => {
7732
8132
  return /* @__PURE__ */ jsx(
7733
8133
  Flex,
7734
8134
  {