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