@xswap-link/sdk 0.1.1 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @xswap-link/xswap-sdk
2
2
 
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - e7dae6e: remove local storage usage from history
8
+ - 9a72993: define fallback source chain
9
+ - 8cf2f51: fix: show empty history with message instead of circular progress
10
+ - bef4486: fix custom width in tailwind config and form component
11
+
3
12
  ## 0.1.1
4
13
 
5
14
  ### Patch Changes
package/dist/index.css CHANGED
@@ -477,12 +477,12 @@ video {
477
477
  .h-\[2px\] {
478
478
  height: 2px;
479
479
  }
480
+ .h-\[30vh\] {
481
+ height: 30vh;
482
+ }
480
483
  .h-\[41px\] {
481
484
  height: 41px;
482
485
  }
483
- .h-\[50vh\] {
484
- height: 50vh;
485
- }
486
486
  .h-\[70\%\] {
487
487
  height: 70%;
488
488
  }
@@ -549,15 +549,15 @@ video {
549
549
  .w-\[310px\] {
550
550
  width: 310px;
551
551
  }
552
- .w-\[360px\] {
553
- width: 360px;
554
- }
555
552
  .w-\[452px\] {
556
553
  width: 452px;
557
554
  }
558
555
  .w-full {
559
556
  width: 100%;
560
557
  }
558
+ .w-x_mobile {
559
+ width: 356px;
560
+ }
561
561
  .min-w-\[26px\] {
562
562
  min-width: 26px;
563
563
  }
@@ -1102,7 +1102,7 @@ video {
1102
1102
  outline-offset: 2px;
1103
1103
  }
1104
1104
  @media (min-width: 640px) {
1105
- .sm\:w-\[600px\] {
1105
+ .sm\:w-x_desktop {
1106
1106
  width: 600px;
1107
1107
  }
1108
1108
  }
package/dist/index.d.mts CHANGED
@@ -262,9 +262,9 @@ declare const SLIPPAGE_PRESETS: number[];
262
262
  declare const DELIVERY_TIME: number;
263
263
  declare const EXPRESS_DELIVERY_TIME: number;
264
264
  declare const BALANCES_CHUNK_SIZE = 500;
265
- declare const BALANCE_DISPLAY_MIN_LIMIT = 0.0001;
266
265
  declare const ROUTE_TIMEOUT_MS = 5000;
267
- declare const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.00001;
266
+ declare const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
267
+ declare const DEFAULT_SOURCE_CHAIN_ID = "1";
268
268
 
269
269
  declare const BatchQueryAbi: ({
270
270
  inputs: {
@@ -519,4 +519,4 @@ declare const deepMergeObjects: (obj1: Record<string, any>, obj2: Record<string,
519
519
  };
520
520
  declare const chunkArray: (array: any[], chunkSize: number) => any[][];
521
521
 
522
- export { ADDRESSES, type AddReferralPayload, type Addresses, Alert, BALANCES_CHUNK_SIZE, BALANCE_DISPLAY_MIN_LIMIT, BatchQueryAbi, type BridgeToken, type Chain, type CoinTypeAddress, type CollectFees, type ContractCall, ContractName, type Contracts, DEFAULT_ECOSYSTEM, DELIVERY_TIME, ERC20Abi, EXPRESS_DELIVERY_TIME, Ecosystem, Environment, type GenerateStakingCallsParams, type GetPricesPayload, type GetRoutePayload, type GetSwapTxPayload, IERC20, MINIMUM_DISPLAYED_TOKEN_AMOUNT, NUMBER_INPUT_REGEX, type Prices, type Protocol, ROUTE_TIMEOUT_MS, type Referral, type ReferralInfo, type Route, SLIPPAGE_PRESETS, Skeleton, type Token, type TokenBalances, type TokenPrices, type Transaction, type TransactionHistory, type TransactionStatus, type Transactions, type TxConfigFormData, type TxConfigFormProps, Web3Environment, XSwapCallType, type XSwapConfig, type XSwapFee, type XSwapFees, XSwapRouterAbi, chunkArray, deepMergeObjects, findPlaceholderIndex, generateApproveTxData, generateRandomBigNumber, generateStakingCalls, generateUniqueRandomBigNumber, getBalanceOf, getBalances, getBridgeTokens, getChainData, getChains, getHistory, getPrices, getRoute, getSwapTx, getTokens, openTxConfigForm, replaceNull, safeBigNumberFrom, shortAddress, weiToHumanReadable };
522
+ export { ADDRESSES, type AddReferralPayload, type Addresses, Alert, BALANCES_CHUNK_SIZE, BatchQueryAbi, type BridgeToken, type Chain, type CoinTypeAddress, type CollectFees, type ContractCall, ContractName, type Contracts, DEFAULT_ECOSYSTEM, DEFAULT_SOURCE_CHAIN_ID, DELIVERY_TIME, ERC20Abi, EXPRESS_DELIVERY_TIME, Ecosystem, Environment, type GenerateStakingCallsParams, type GetPricesPayload, type GetRoutePayload, type GetSwapTxPayload, IERC20, MINIMUM_DISPLAYED_TOKEN_AMOUNT, NUMBER_INPUT_REGEX, type Prices, type Protocol, ROUTE_TIMEOUT_MS, type Referral, type ReferralInfo, type Route, SLIPPAGE_PRESETS, Skeleton, type Token, type TokenBalances, type TokenPrices, type Transaction, type TransactionHistory, type TransactionStatus, type Transactions, type TxConfigFormData, type TxConfigFormProps, Web3Environment, XSwapCallType, type XSwapConfig, type XSwapFee, type XSwapFees, XSwapRouterAbi, chunkArray, deepMergeObjects, findPlaceholderIndex, generateApproveTxData, generateRandomBigNumber, generateStakingCalls, generateUniqueRandomBigNumber, getBalanceOf, getBalances, getBridgeTokens, getChainData, getChains, getHistory, getPrices, getRoute, getSwapTx, getTokens, openTxConfigForm, replaceNull, safeBigNumberFrom, shortAddress, weiToHumanReadable };
package/dist/index.d.ts CHANGED
@@ -262,9 +262,9 @@ declare const SLIPPAGE_PRESETS: number[];
262
262
  declare const DELIVERY_TIME: number;
263
263
  declare const EXPRESS_DELIVERY_TIME: number;
264
264
  declare const BALANCES_CHUNK_SIZE = 500;
265
- declare const BALANCE_DISPLAY_MIN_LIMIT = 0.0001;
266
265
  declare const ROUTE_TIMEOUT_MS = 5000;
267
- declare const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.00001;
266
+ declare const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
267
+ declare const DEFAULT_SOURCE_CHAIN_ID = "1";
268
268
 
269
269
  declare const BatchQueryAbi: ({
270
270
  inputs: {
@@ -519,4 +519,4 @@ declare const deepMergeObjects: (obj1: Record<string, any>, obj2: Record<string,
519
519
  };
520
520
  declare const chunkArray: (array: any[], chunkSize: number) => any[][];
521
521
 
522
- export { ADDRESSES, type AddReferralPayload, type Addresses, Alert, BALANCES_CHUNK_SIZE, BALANCE_DISPLAY_MIN_LIMIT, BatchQueryAbi, type BridgeToken, type Chain, type CoinTypeAddress, type CollectFees, type ContractCall, ContractName, type Contracts, DEFAULT_ECOSYSTEM, DELIVERY_TIME, ERC20Abi, EXPRESS_DELIVERY_TIME, Ecosystem, Environment, type GenerateStakingCallsParams, type GetPricesPayload, type GetRoutePayload, type GetSwapTxPayload, IERC20, MINIMUM_DISPLAYED_TOKEN_AMOUNT, NUMBER_INPUT_REGEX, type Prices, type Protocol, ROUTE_TIMEOUT_MS, type Referral, type ReferralInfo, type Route, SLIPPAGE_PRESETS, Skeleton, type Token, type TokenBalances, type TokenPrices, type Transaction, type TransactionHistory, type TransactionStatus, type Transactions, type TxConfigFormData, type TxConfigFormProps, Web3Environment, XSwapCallType, type XSwapConfig, type XSwapFee, type XSwapFees, XSwapRouterAbi, chunkArray, deepMergeObjects, findPlaceholderIndex, generateApproveTxData, generateRandomBigNumber, generateStakingCalls, generateUniqueRandomBigNumber, getBalanceOf, getBalances, getBridgeTokens, getChainData, getChains, getHistory, getPrices, getRoute, getSwapTx, getTokens, openTxConfigForm, replaceNull, safeBigNumberFrom, shortAddress, weiToHumanReadable };
522
+ export { ADDRESSES, type AddReferralPayload, type Addresses, Alert, BALANCES_CHUNK_SIZE, BatchQueryAbi, type BridgeToken, type Chain, type CoinTypeAddress, type CollectFees, type ContractCall, ContractName, type Contracts, DEFAULT_ECOSYSTEM, DEFAULT_SOURCE_CHAIN_ID, DELIVERY_TIME, ERC20Abi, EXPRESS_DELIVERY_TIME, Ecosystem, Environment, type GenerateStakingCallsParams, type GetPricesPayload, type GetRoutePayload, type GetSwapTxPayload, IERC20, MINIMUM_DISPLAYED_TOKEN_AMOUNT, NUMBER_INPUT_REGEX, type Prices, type Protocol, ROUTE_TIMEOUT_MS, type Referral, type ReferralInfo, type Route, SLIPPAGE_PRESETS, Skeleton, type Token, type TokenBalances, type TokenPrices, type Transaction, type TransactionHistory, type TransactionStatus, type Transactions, type TxConfigFormData, type TxConfigFormProps, Web3Environment, XSwapCallType, type XSwapConfig, type XSwapFee, type XSwapFees, XSwapRouterAbi, chunkArray, deepMergeObjects, findPlaceholderIndex, generateApproveTxData, generateRandomBigNumber, generateStakingCalls, generateUniqueRandomBigNumber, getBalanceOf, getBalances, getBridgeTokens, getChainData, getChains, getHistory, getPrices, getRoute, getSwapTx, getTokens, openTxConfigForm, replaceNull, safeBigNumberFrom, shortAddress, weiToHumanReadable };
package/dist/index.js CHANGED
@@ -33,10 +33,10 @@ __export(src_exports, {
33
33
  ADDRESSES: () => ADDRESSES,
34
34
  Alert: () => Alert,
35
35
  BALANCES_CHUNK_SIZE: () => BALANCES_CHUNK_SIZE,
36
- BALANCE_DISPLAY_MIN_LIMIT: () => BALANCE_DISPLAY_MIN_LIMIT,
37
36
  BatchQueryAbi: () => BatchQueryAbi,
38
37
  ContractName: () => ContractName,
39
38
  DEFAULT_ECOSYSTEM: () => DEFAULT_ECOSYSTEM,
39
+ DEFAULT_SOURCE_CHAIN_ID: () => DEFAULT_SOURCE_CHAIN_ID,
40
40
  DELIVERY_TIME: () => DELIVERY_TIME,
41
41
  ERC20Abi: () => ERC20Abi,
42
42
  EXPRESS_DELIVERY_TIME: () => EXPRESS_DELIVERY_TIME,
@@ -1876,9 +1876,9 @@ var SLIPPAGE_PRESETS = [0.5, 1.5, 3];
1876
1876
  var DELIVERY_TIME = 30 * 1e3 * 60;
1877
1877
  var EXPRESS_DELIVERY_TIME = 30 * 1e3;
1878
1878
  var BALANCES_CHUNK_SIZE = 500;
1879
- var BALANCE_DISPLAY_MIN_LIMIT = 1e-4;
1880
1879
  var ROUTE_TIMEOUT_MS = 5e3;
1881
- var MINIMUM_DISPLAYED_TOKEN_AMOUNT = 1e-5;
1880
+ var MINIMUM_DISPLAYED_TOKEN_AMOUNT = 1e-4;
1881
+ var DEFAULT_SOURCE_CHAIN_ID = "1";
1882
1882
 
1883
1883
  // src/utils/contracts.ts
1884
1884
  var IERC20 = new import_ethers2.ethers.utils.Interface(ERC20Abi);
@@ -2641,7 +2641,7 @@ var HistoryCard = ({ transaction, supportedChains }) => {
2641
2641
  ] }),
2642
2642
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex items-center mb-2 last:mb-0", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-1 items-center flex-wrap text-xs text-[rgba(255,255,255,0.6)]", children: [
2643
2643
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center", children: [
2644
- Number(transferredAmount) < 1e-4 ? "<0.0001" : transferredAmount,
2644
+ Number(transferredAmount) < MINIMUM_DISPLAYED_TOKEN_AMOUNT ? `<${MINIMUM_DISPLAYED_TOKEN_AMOUNT}` : transferredAmount,
2645
2645
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "text-xs ml-1 text-rgba(255,255,255,0.6)", children: tokenData?.symbol }),
2646
2646
  tokenData?.image ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2647
2647
  "img",
@@ -2674,84 +2674,48 @@ var HistoryCard = ({ transaction, supportedChains }) => {
2674
2674
 
2675
2675
  // src/components/TxConfigForm/History.tsx
2676
2676
  var import_jsx_runtime23 = require("react/jsx-runtime");
2677
- var PENDING_TXS_LOCAL_STORAGE_KEY = "pending_transactions";
2678
2677
  var History = ({ signer, supportedChains }) => {
2679
- const [mappedHistory, setMappedHistory] = (0, import_react3.useState)();
2678
+ const [fetchedHistory, setFetchedHistory] = (0, import_react3.useState)();
2680
2679
  const [historyLoadedOnce, setHistoryLoadedOnce] = (0, import_react3.useState)(false);
2681
- const getLocalHistory = () => {
2682
- return JSON.parse(
2683
- localStorage.getItem(PENDING_TXS_LOCAL_STORAGE_KEY) || "{}"
2684
- );
2685
- };
2686
- const setLocalHistory = (data) => {
2687
- localStorage.setItem(PENDING_TXS_LOCAL_STORAGE_KEY, JSON.stringify(data));
2688
- };
2689
2680
  const fetchHistory = (0, import_react3.useCallback)(async () => {
2690
- const downloadedHistory = await getHistory({ walletAddress: signer });
2691
- const fetchedTransactions = [];
2692
- if (downloadedHistory) {
2693
- for (const entry of downloadedHistory.history) {
2694
- if (!entry.source) {
2695
- continue;
2696
- }
2697
- let status;
2698
- if (entry.failed)
2699
- status = "REVERTED";
2700
- if (!!entry.target) {
2701
- status = "DONE";
2702
- } else {
2703
- status = "IN_PROGRESS";
2704
- }
2705
- const blockTimestampMs = new Date(entry.source.blockTime).getTime();
2706
- const estimatedDeliveryTimestamp = new import_bignumber2.default(
2707
- entry.source.valueForInstantCcipRecieve
2708
- ).gt(0) ? blockTimestampMs + EXPRESS_DELIVERY_TIME : blockTimestampMs + DELIVERY_TIME;
2709
- fetchedTransactions.push({
2710
- hash: entry.source.transactionHash,
2711
- timestamp: blockTimestampMs / 1e3,
2712
- sourceChainId: entry.source.blockchainId,
2713
- targetChainId: entry.source.targetBlockchainId,
2714
- amountWei: entry.source.tokenAmount,
2715
- tokenAddress: entry.source.tokenAddress,
2716
- tokenOutAddress: entry.target?.tokenAddress || entry.source.tokenOutAddress,
2717
- tokenOutAmount: entry.target?.tokenAmount || entry.source.estimatedAmountOut,
2718
- estimatedDeliveryTimestamp,
2719
- status
2720
- });
2721
- }
2722
- const txHashToTxFromAPI = {};
2723
- for (const transaction of fetchedTransactions) {
2724
- txHashToTxFromAPI[transaction.hash] = transaction;
2725
- }
2726
- const localHistory = getLocalHistory();
2727
- const newLocalHistory = {};
2728
- for (const [walletAddress, transactions] of Object.entries(
2729
- localHistory
2730
- )) {
2731
- if (walletAddress.toLowerCase() !== signer.toLowerCase()) {
2732
- continue;
2733
- }
2734
- const newLocalHistoryForWallet = [];
2735
- for (const transaction of transactions) {
2736
- if (!txHashToTxFromAPI[transaction.hash]) {
2737
- fetchedTransactions.push(transaction);
2738
- newLocalHistoryForWallet.push(transaction);
2681
+ if (signer) {
2682
+ const downloadedHistory = await getHistory({ walletAddress: signer });
2683
+ const fetchedTransactions = [];
2684
+ if (downloadedHistory) {
2685
+ for (const entry of downloadedHistory.history) {
2686
+ if (!entry.source) {
2739
2687
  continue;
2740
2688
  }
2741
- if (txHashToTxFromAPI[transaction.hash] && transaction.status === "DONE" && txHashToTxFromAPI[transaction.hash]?.status === "IN_PROGRESS") {
2742
- txHashToTxFromAPI[transaction.hash].status = "DONE";
2743
- }
2744
- if (txHashToTxFromAPI[transaction.hash]?.status === "DONE" || txHashToTxFromAPI[transaction.hash]?.status === "REVERTED") {
2745
- continue;
2689
+ let status;
2690
+ if (entry.failed)
2691
+ status = "REVERTED";
2692
+ if (!!entry.target) {
2693
+ status = "DONE";
2694
+ } else {
2695
+ status = "IN_PROGRESS";
2746
2696
  }
2697
+ const blockTimestampMs = new Date(entry.source.blockTime).getTime();
2698
+ const estimatedDeliveryTimestamp = new import_bignumber2.default(
2699
+ entry.source.valueForInstantCcipRecieve
2700
+ ).gt(0) ? blockTimestampMs + EXPRESS_DELIVERY_TIME : blockTimestampMs + DELIVERY_TIME;
2701
+ fetchedTransactions.push({
2702
+ hash: entry.source.transactionHash,
2703
+ timestamp: blockTimestampMs / 1e3,
2704
+ sourceChainId: entry.source.blockchainId,
2705
+ targetChainId: entry.source.targetBlockchainId,
2706
+ amountWei: entry.source.tokenAmount,
2707
+ tokenAddress: entry.source.tokenAddress,
2708
+ tokenOutAddress: entry.target?.tokenAddress || entry.source.tokenOutAddress,
2709
+ tokenOutAmount: entry.target?.tokenAmount || entry.source.estimatedAmountOut,
2710
+ estimatedDeliveryTimestamp,
2711
+ status
2712
+ });
2747
2713
  }
2748
- newLocalHistory[walletAddress.toLowerCase()] = newLocalHistoryForWallet;
2714
+ setFetchedHistory(
2715
+ fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp)
2716
+ );
2717
+ setHistoryLoadedOnce(true);
2749
2718
  }
2750
- setLocalHistory(newLocalHistory);
2751
- setMappedHistory(
2752
- fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp)
2753
- );
2754
- setHistoryLoadedOnce(true);
2755
2719
  }
2756
2720
  }, [signer, getHistory]);
2757
2721
  (0, import_react3.useEffect)(() => {
@@ -2762,10 +2726,12 @@ var History = ({ signer, supportedChains }) => {
2762
2726
  }, 6e4);
2763
2727
  return () => clearInterval(timer);
2764
2728
  }, [signer, fetchHistory, getHistory, historyLoadedOnce]);
2765
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center w-full", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "w-full h-[50vh] overflow-scroll overflow-x-hidden", children: [
2766
- mappedHistory?.length === 0 && historyLoadedOnce && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full text-center py-4 px-0 text-[rgb(158,158,158)]", children: "Your history is empty..." }),
2767
- !mappedHistory && !historyLoadedOnce && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex w-full h-full items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CircularProgressIcon, {}) }),
2768
- mappedHistory?.map((transaction, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2729
+ if (!signer)
2730
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center w-full h-[30vh]", children: "Connect a wallet to browse history" });
2731
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center w-full", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "w-full h-[30vh] overflow-scroll overflow-x-hidden", children: [
2732
+ fetchedHistory?.length === 0 && historyLoadedOnce && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full text-center py-4 px-0 text-[rgb(158,158,158)]", children: "Your history is empty..." }),
2733
+ !fetchedHistory && !historyLoadedOnce && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex w-full h-full items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CircularProgressIcon, {}) }),
2734
+ fetchedHistory?.map((transaction, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2769
2735
  HistoryCard,
2770
2736
  {
2771
2737
  transaction,
@@ -2785,7 +2751,7 @@ var TopBar = ({
2785
2751
  historyTabShown
2786
2752
  }) => {
2787
2753
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex w-full justify-between mx-auto pl-4 pr-8 pt-2", children: [
2788
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "rounded-lg text-[rgba(255,255,255,0.6)] text-base whitespace-nowrap", children: signer ? `Connected wallet: ${shortAddress(signer)}` : `Disconnected` }),
2754
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "rounded-lg text-[rgba(255,255,255,0.6)] text-base whitespace-nowrap", children: signer ? `Connected wallet: ${shortAddress(signer)}` : `Wallet disconnected` }),
2789
2755
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-2", children: [
2790
2756
  !historyTabShown && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2791
2757
  "div",
@@ -2795,7 +2761,7 @@ var TopBar = ({
2795
2761
  children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "w-7 h-7 rounded-full bg-gradient-to-r from-x_blue_light to-x_blue_dark flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SettingsIcon, {}) })
2796
2762
  }
2797
2763
  ),
2798
- signer && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2764
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2799
2765
  "div",
2800
2766
  {
2801
2767
  onClick: () => setHistoryTabShown((x) => !x),
@@ -3067,6 +3033,8 @@ var TokenPicker = ({
3067
3033
  const isMatch = (value, searchValue2) => value.toLowerCase().indexOf(searchValue2.toLowerCase()) > -1;
3068
3034
  return tokens?.filter(
3069
3035
  (token) => isMatch(token.symbol, searchValue) || isMatch(token.name, searchValue) || token.address === searchValue.toLowerCase()
3036
+ ).sort(
3037
+ (a, b) => a.priority < b.priority ? 1 : balances && balances[a.address] && balances[b.address] && balances[a.address]?.lte(balances[b.address] || "0") ? 1 : -1
3070
3038
  );
3071
3039
  }, [searchValue, tokens]);
3072
3040
  return modalRoot ? (0, import_react_dom.createPortal)(
@@ -3113,9 +3081,7 @@ var TokenPicker = ({
3113
3081
  token.address
3114
3082
  )) }),
3115
3083
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "h-[2px] my-0 mx-[-24px] w-[100%+48px] px-12 bg-[rgba(255,255,255,0.1)]" }),
3116
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "overflow-y-scroll h-full mx-[-24px] w-[100%+48px] flex flex-col", children: filteredTokens && filteredTokens.length > 0 ? filteredTokens.sort(
3117
- (a, b) => balances && balances[a.address] && balances[b.address] && balances[a.address]?.lte(balances[b.address] || "0") ? 1 : -1
3118
- ).map((token, index) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3084
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "overflow-y-scroll h-full mx-[-24px] w-[100%+48px] flex flex-col", children: filteredTokens && filteredTokens.length > 0 ? filteredTokens.map((token, index) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3119
3085
  "div",
3120
3086
  {
3121
3087
  className: `flex gap-3 py-2 px-[24px] w-full items-center hover:bg-[rgb(25,25,25)] hover:cursor-pointer ${token.address === selectedToken?.address ? "bg-[rgb(35,35,35)]" : ""}`,
@@ -3431,15 +3397,14 @@ var Form = ({
3431
3397
  setSigner(account.address);
3432
3398
  }, [account.address]);
3433
3399
  (0, import_react8.useEffect)(() => {
3434
- if (supportedChains.some(
3400
+ const defaultChain = supportedChains.find(
3435
3401
  ({ chainId }) => chainId === account.chainId?.toString()
3436
- )) {
3437
- setSrcChain(
3438
- supportedChains.find(
3439
- ({ chainId }) => chainId === account.chainId?.toString()
3440
- )
3441
- );
3442
- }
3402
+ );
3403
+ setSrcChain(
3404
+ defaultChain ?? supportedChains.find(
3405
+ ({ chainId }) => chainId === DEFAULT_SOURCE_CHAIN_ID
3406
+ )
3407
+ );
3443
3408
  }, [account.chainId]);
3444
3409
  (0, import_react8.useEffect)(() => {
3445
3410
  setDstChain(supportedChains.find((chain) => chain.chainId === dstChainId));
@@ -3529,7 +3494,7 @@ var Form = ({
3529
3494
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
3530
3495
  "form",
3531
3496
  {
3532
- className: "flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-[360px] sm:w-[600px]",
3497
+ className: "flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-x_mobile sm:w-x_desktop",
3533
3498
  onSubmit: handleSubmit,
3534
3499
  children: [
3535
3500
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
@@ -3551,7 +3516,7 @@ var Form = ({
3551
3516
  setSlippage
3552
3517
  }
3553
3518
  ),
3554
- historyTabShown ? signer && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(History, { signer, supportedChains }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col gap-2", children: [
3519
+ historyTabShown ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(History, { signer, supportedChains }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col gap-2", children: [
3555
3520
  desc && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Description, { description: desc }),
3556
3521
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3557
3522
  SwapPanel,
@@ -3716,10 +3681,10 @@ var Skeleton = ({ w, h }) => {
3716
3681
  ADDRESSES,
3717
3682
  Alert,
3718
3683
  BALANCES_CHUNK_SIZE,
3719
- BALANCE_DISPLAY_MIN_LIMIT,
3720
3684
  BatchQueryAbi,
3721
3685
  ContractName,
3722
3686
  DEFAULT_ECOSYSTEM,
3687
+ DEFAULT_SOURCE_CHAIN_ID,
3723
3688
  DELIVERY_TIME,
3724
3689
  ERC20Abi,
3725
3690
  EXPRESS_DELIVERY_TIME,
package/dist/index.mjs CHANGED
@@ -1806,9 +1806,9 @@ var SLIPPAGE_PRESETS = [0.5, 1.5, 3];
1806
1806
  var DELIVERY_TIME = 30 * 1e3 * 60;
1807
1807
  var EXPRESS_DELIVERY_TIME = 30 * 1e3;
1808
1808
  var BALANCES_CHUNK_SIZE = 500;
1809
- var BALANCE_DISPLAY_MIN_LIMIT = 1e-4;
1810
1809
  var ROUTE_TIMEOUT_MS = 5e3;
1811
- var MINIMUM_DISPLAYED_TOKEN_AMOUNT = 1e-5;
1810
+ var MINIMUM_DISPLAYED_TOKEN_AMOUNT = 1e-4;
1811
+ var DEFAULT_SOURCE_CHAIN_ID = "1";
1812
1812
 
1813
1813
  // src/utils/contracts.ts
1814
1814
  var IERC20 = new ethers.utils.Interface(ERC20Abi);
@@ -2571,7 +2571,7 @@ var HistoryCard = ({ transaction, supportedChains }) => {
2571
2571
  ] }),
2572
2572
  /* @__PURE__ */ jsx21("div", { className: "flex items-center mb-2 last:mb-0", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-1 items-center flex-wrap text-xs text-[rgba(255,255,255,0.6)]", children: [
2573
2573
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center", children: [
2574
- Number(transferredAmount) < 1e-4 ? "<0.0001" : transferredAmount,
2574
+ Number(transferredAmount) < MINIMUM_DISPLAYED_TOKEN_AMOUNT ? `<${MINIMUM_DISPLAYED_TOKEN_AMOUNT}` : transferredAmount,
2575
2575
  /* @__PURE__ */ jsx21("div", { className: "text-xs ml-1 text-rgba(255,255,255,0.6)", children: tokenData?.symbol }),
2576
2576
  tokenData?.image ? /* @__PURE__ */ jsx21(
2577
2577
  "img",
@@ -2604,84 +2604,48 @@ var HistoryCard = ({ transaction, supportedChains }) => {
2604
2604
 
2605
2605
  // src/components/TxConfigForm/History.tsx
2606
2606
  import { jsx as jsx22, jsxs as jsxs7 } from "react/jsx-runtime";
2607
- var PENDING_TXS_LOCAL_STORAGE_KEY = "pending_transactions";
2608
2607
  var History = ({ signer, supportedChains }) => {
2609
- const [mappedHistory, setMappedHistory] = useState2();
2608
+ const [fetchedHistory, setFetchedHistory] = useState2();
2610
2609
  const [historyLoadedOnce, setHistoryLoadedOnce] = useState2(false);
2611
- const getLocalHistory = () => {
2612
- return JSON.parse(
2613
- localStorage.getItem(PENDING_TXS_LOCAL_STORAGE_KEY) || "{}"
2614
- );
2615
- };
2616
- const setLocalHistory = (data) => {
2617
- localStorage.setItem(PENDING_TXS_LOCAL_STORAGE_KEY, JSON.stringify(data));
2618
- };
2619
2610
  const fetchHistory = useCallback2(async () => {
2620
- const downloadedHistory = await getHistory({ walletAddress: signer });
2621
- const fetchedTransactions = [];
2622
- if (downloadedHistory) {
2623
- for (const entry of downloadedHistory.history) {
2624
- if (!entry.source) {
2625
- continue;
2626
- }
2627
- let status;
2628
- if (entry.failed)
2629
- status = "REVERTED";
2630
- if (!!entry.target) {
2631
- status = "DONE";
2632
- } else {
2633
- status = "IN_PROGRESS";
2634
- }
2635
- const blockTimestampMs = new Date(entry.source.blockTime).getTime();
2636
- const estimatedDeliveryTimestamp = new BigNumberJS2(
2637
- entry.source.valueForInstantCcipRecieve
2638
- ).gt(0) ? blockTimestampMs + EXPRESS_DELIVERY_TIME : blockTimestampMs + DELIVERY_TIME;
2639
- fetchedTransactions.push({
2640
- hash: entry.source.transactionHash,
2641
- timestamp: blockTimestampMs / 1e3,
2642
- sourceChainId: entry.source.blockchainId,
2643
- targetChainId: entry.source.targetBlockchainId,
2644
- amountWei: entry.source.tokenAmount,
2645
- tokenAddress: entry.source.tokenAddress,
2646
- tokenOutAddress: entry.target?.tokenAddress || entry.source.tokenOutAddress,
2647
- tokenOutAmount: entry.target?.tokenAmount || entry.source.estimatedAmountOut,
2648
- estimatedDeliveryTimestamp,
2649
- status
2650
- });
2651
- }
2652
- const txHashToTxFromAPI = {};
2653
- for (const transaction of fetchedTransactions) {
2654
- txHashToTxFromAPI[transaction.hash] = transaction;
2655
- }
2656
- const localHistory = getLocalHistory();
2657
- const newLocalHistory = {};
2658
- for (const [walletAddress, transactions] of Object.entries(
2659
- localHistory
2660
- )) {
2661
- if (walletAddress.toLowerCase() !== signer.toLowerCase()) {
2662
- continue;
2663
- }
2664
- const newLocalHistoryForWallet = [];
2665
- for (const transaction of transactions) {
2666
- if (!txHashToTxFromAPI[transaction.hash]) {
2667
- fetchedTransactions.push(transaction);
2668
- newLocalHistoryForWallet.push(transaction);
2611
+ if (signer) {
2612
+ const downloadedHistory = await getHistory({ walletAddress: signer });
2613
+ const fetchedTransactions = [];
2614
+ if (downloadedHistory) {
2615
+ for (const entry of downloadedHistory.history) {
2616
+ if (!entry.source) {
2669
2617
  continue;
2670
2618
  }
2671
- if (txHashToTxFromAPI[transaction.hash] && transaction.status === "DONE" && txHashToTxFromAPI[transaction.hash]?.status === "IN_PROGRESS") {
2672
- txHashToTxFromAPI[transaction.hash].status = "DONE";
2673
- }
2674
- if (txHashToTxFromAPI[transaction.hash]?.status === "DONE" || txHashToTxFromAPI[transaction.hash]?.status === "REVERTED") {
2675
- continue;
2619
+ let status;
2620
+ if (entry.failed)
2621
+ status = "REVERTED";
2622
+ if (!!entry.target) {
2623
+ status = "DONE";
2624
+ } else {
2625
+ status = "IN_PROGRESS";
2676
2626
  }
2627
+ const blockTimestampMs = new Date(entry.source.blockTime).getTime();
2628
+ const estimatedDeliveryTimestamp = new BigNumberJS2(
2629
+ entry.source.valueForInstantCcipRecieve
2630
+ ).gt(0) ? blockTimestampMs + EXPRESS_DELIVERY_TIME : blockTimestampMs + DELIVERY_TIME;
2631
+ fetchedTransactions.push({
2632
+ hash: entry.source.transactionHash,
2633
+ timestamp: blockTimestampMs / 1e3,
2634
+ sourceChainId: entry.source.blockchainId,
2635
+ targetChainId: entry.source.targetBlockchainId,
2636
+ amountWei: entry.source.tokenAmount,
2637
+ tokenAddress: entry.source.tokenAddress,
2638
+ tokenOutAddress: entry.target?.tokenAddress || entry.source.tokenOutAddress,
2639
+ tokenOutAmount: entry.target?.tokenAmount || entry.source.estimatedAmountOut,
2640
+ estimatedDeliveryTimestamp,
2641
+ status
2642
+ });
2677
2643
  }
2678
- newLocalHistory[walletAddress.toLowerCase()] = newLocalHistoryForWallet;
2644
+ setFetchedHistory(
2645
+ fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp)
2646
+ );
2647
+ setHistoryLoadedOnce(true);
2679
2648
  }
2680
- setLocalHistory(newLocalHistory);
2681
- setMappedHistory(
2682
- fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp)
2683
- );
2684
- setHistoryLoadedOnce(true);
2685
2649
  }
2686
2650
  }, [signer, getHistory]);
2687
2651
  useEffect2(() => {
@@ -2692,10 +2656,12 @@ var History = ({ signer, supportedChains }) => {
2692
2656
  }, 6e4);
2693
2657
  return () => clearInterval(timer);
2694
2658
  }, [signer, fetchHistory, getHistory, historyLoadedOnce]);
2695
- return /* @__PURE__ */ jsx22("div", { className: "flex items-center justify-center w-full", children: /* @__PURE__ */ jsxs7("div", { className: "w-full h-[50vh] overflow-scroll overflow-x-hidden", children: [
2696
- mappedHistory?.length === 0 && historyLoadedOnce && /* @__PURE__ */ jsx22("div", { className: "w-full text-center py-4 px-0 text-[rgb(158,158,158)]", children: "Your history is empty..." }),
2697
- !mappedHistory && !historyLoadedOnce && /* @__PURE__ */ jsx22("div", { className: "flex w-full h-full items-center justify-center", children: /* @__PURE__ */ jsx22(CircularProgressIcon, {}) }),
2698
- mappedHistory?.map((transaction, index) => /* @__PURE__ */ jsx22(
2659
+ if (!signer)
2660
+ return /* @__PURE__ */ jsx22("div", { className: "flex items-center justify-center w-full h-[30vh]", children: "Connect a wallet to browse history" });
2661
+ return /* @__PURE__ */ jsx22("div", { className: "flex items-center justify-center w-full", children: /* @__PURE__ */ jsxs7("div", { className: "w-full h-[30vh] overflow-scroll overflow-x-hidden", children: [
2662
+ fetchedHistory?.length === 0 && historyLoadedOnce && /* @__PURE__ */ jsx22("div", { className: "w-full text-center py-4 px-0 text-[rgb(158,158,158)]", children: "Your history is empty..." }),
2663
+ !fetchedHistory && !historyLoadedOnce && /* @__PURE__ */ jsx22("div", { className: "flex w-full h-full items-center justify-center", children: /* @__PURE__ */ jsx22(CircularProgressIcon, {}) }),
2664
+ fetchedHistory?.map((transaction, index) => /* @__PURE__ */ jsx22(
2699
2665
  HistoryCard,
2700
2666
  {
2701
2667
  transaction,
@@ -2715,7 +2681,7 @@ var TopBar = ({
2715
2681
  historyTabShown
2716
2682
  }) => {
2717
2683
  return /* @__PURE__ */ jsxs8("div", { className: "flex w-full justify-between mx-auto pl-4 pr-8 pt-2", children: [
2718
- /* @__PURE__ */ jsx23("div", { className: "rounded-lg text-[rgba(255,255,255,0.6)] text-base whitespace-nowrap", children: signer ? `Connected wallet: ${shortAddress(signer)}` : `Disconnected` }),
2684
+ /* @__PURE__ */ jsx23("div", { className: "rounded-lg text-[rgba(255,255,255,0.6)] text-base whitespace-nowrap", children: signer ? `Connected wallet: ${shortAddress(signer)}` : `Wallet disconnected` }),
2719
2685
  /* @__PURE__ */ jsxs8("div", { className: "flex gap-2", children: [
2720
2686
  !historyTabShown && /* @__PURE__ */ jsx23(
2721
2687
  "div",
@@ -2725,7 +2691,7 @@ var TopBar = ({
2725
2691
  children: /* @__PURE__ */ jsx23("div", { className: "w-7 h-7 rounded-full bg-gradient-to-r from-x_blue_light to-x_blue_dark flex items-center justify-center", children: /* @__PURE__ */ jsx23(SettingsIcon, {}) })
2726
2692
  }
2727
2693
  ),
2728
- signer && /* @__PURE__ */ jsx23(
2694
+ /* @__PURE__ */ jsx23(
2729
2695
  "div",
2730
2696
  {
2731
2697
  onClick: () => setHistoryTabShown((x) => !x),
@@ -2997,6 +2963,8 @@ var TokenPicker = ({
2997
2963
  const isMatch = (value, searchValue2) => value.toLowerCase().indexOf(searchValue2.toLowerCase()) > -1;
2998
2964
  return tokens?.filter(
2999
2965
  (token) => isMatch(token.symbol, searchValue) || isMatch(token.name, searchValue) || token.address === searchValue.toLowerCase()
2966
+ ).sort(
2967
+ (a, b) => a.priority < b.priority ? 1 : balances && balances[a.address] && balances[b.address] && balances[a.address]?.lte(balances[b.address] || "0") ? 1 : -1
3000
2968
  );
3001
2969
  }, [searchValue, tokens]);
3002
2970
  return modalRoot ? createPortal(
@@ -3043,9 +3011,7 @@ var TokenPicker = ({
3043
3011
  token.address
3044
3012
  )) }),
3045
3013
  /* @__PURE__ */ jsx27("div", { className: "h-[2px] my-0 mx-[-24px] w-[100%+48px] px-12 bg-[rgba(255,255,255,0.1)]" }),
3046
- /* @__PURE__ */ jsx27("div", { className: "overflow-y-scroll h-full mx-[-24px] w-[100%+48px] flex flex-col", children: filteredTokens && filteredTokens.length > 0 ? filteredTokens.sort(
3047
- (a, b) => balances && balances[a.address] && balances[b.address] && balances[a.address]?.lte(balances[b.address] || "0") ? 1 : -1
3048
- ).map((token, index) => /* @__PURE__ */ jsxs12(
3014
+ /* @__PURE__ */ jsx27("div", { className: "overflow-y-scroll h-full mx-[-24px] w-[100%+48px] flex flex-col", children: filteredTokens && filteredTokens.length > 0 ? filteredTokens.map((token, index) => /* @__PURE__ */ jsxs12(
3049
3015
  "div",
3050
3016
  {
3051
3017
  className: `flex gap-3 py-2 px-[24px] w-full items-center hover:bg-[rgb(25,25,25)] hover:cursor-pointer ${token.address === selectedToken?.address ? "bg-[rgb(35,35,35)]" : ""}`,
@@ -3361,15 +3327,14 @@ var Form = ({
3361
3327
  setSigner(account.address);
3362
3328
  }, [account.address]);
3363
3329
  useEffect5(() => {
3364
- if (supportedChains.some(
3330
+ const defaultChain = supportedChains.find(
3365
3331
  ({ chainId }) => chainId === account.chainId?.toString()
3366
- )) {
3367
- setSrcChain(
3368
- supportedChains.find(
3369
- ({ chainId }) => chainId === account.chainId?.toString()
3370
- )
3371
- );
3372
- }
3332
+ );
3333
+ setSrcChain(
3334
+ defaultChain ?? supportedChains.find(
3335
+ ({ chainId }) => chainId === DEFAULT_SOURCE_CHAIN_ID
3336
+ )
3337
+ );
3373
3338
  }, [account.chainId]);
3374
3339
  useEffect5(() => {
3375
3340
  setDstChain(supportedChains.find((chain) => chain.chainId === dstChainId));
@@ -3459,7 +3424,7 @@ var Form = ({
3459
3424
  return /* @__PURE__ */ jsxs16(
3460
3425
  "form",
3461
3426
  {
3462
- className: "flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-[360px] sm:w-[600px]",
3427
+ className: "flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-x_mobile sm:w-x_desktop",
3463
3428
  onSubmit: handleSubmit,
3464
3429
  children: [
3465
3430
  /* @__PURE__ */ jsx33(
@@ -3481,7 +3446,7 @@ var Form = ({
3481
3446
  setSlippage
3482
3447
  }
3483
3448
  ),
3484
- historyTabShown ? signer && /* @__PURE__ */ jsx33(History, { signer, supportedChains }) : /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-2", children: [
3449
+ historyTabShown ? /* @__PURE__ */ jsx33(History, { signer, supportedChains }) : /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-2", children: [
3485
3450
  desc && /* @__PURE__ */ jsx33(Description, { description: desc }),
3486
3451
  /* @__PURE__ */ jsx33(
3487
3452
  SwapPanel,
@@ -3645,10 +3610,10 @@ export {
3645
3610
  ADDRESSES,
3646
3611
  Alert,
3647
3612
  BALANCES_CHUNK_SIZE,
3648
- BALANCE_DISPLAY_MIN_LIMIT,
3649
3613
  BatchQueryAbi,
3650
3614
  ContractName,
3651
3615
  DEFAULT_ECOSYSTEM,
3616
+ DEFAULT_SOURCE_CHAIN_ID,
3652
3617
  DELIVERY_TIME,
3653
3618
  ERC20Abi,
3654
3619
  EXPRESS_DELIVERY_TIME,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xswap-link/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "JavaScript SDK for XSwap platform",
5
5
  "homepage": "https://github.com/xswap-link/xswap-sdk",
6
6
  "repository": {
@@ -17,6 +17,7 @@ import { Summary } from "./Summary";
17
17
  import { SwapPanel } from "./SwapPanel";
18
18
  import { ErrorField } from "./ErrorField";
19
19
  import { Description } from "./Description";
20
+ import { DEFAULT_SOURCE_CHAIN_ID } from "@src/constants";
20
21
 
21
22
  export const Form = ({
22
23
  dstChainId,
@@ -55,17 +56,15 @@ export const Form = ({
55
56
  }, [account.address]);
56
57
 
57
58
  useEffect(() => {
58
- if (
59
- supportedChains.some(
60
- ({ chainId }) => chainId === account.chainId?.toString(),
61
- )
62
- ) {
63
- setSrcChain(
59
+ const defaultChain = supportedChains.find(
60
+ ({ chainId }) => chainId === account.chainId?.toString(),
61
+ );
62
+ setSrcChain(
63
+ defaultChain ??
64
64
  supportedChains.find(
65
- ({ chainId }) => chainId === account.chainId?.toString(),
65
+ ({ chainId }) => chainId === DEFAULT_SOURCE_CHAIN_ID,
66
66
  ),
67
- );
68
- }
67
+ );
69
68
  }, [account.chainId]);
70
69
 
71
70
  useEffect(() => {
@@ -178,7 +177,7 @@ export const Form = ({
178
177
 
179
178
  return (
180
179
  <form
181
- className="flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-[360px] sm:w-[600px]"
180
+ className="flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-x_mobile sm:w-x_desktop"
182
181
  onSubmit={handleSubmit}
183
182
  >
184
183
  <TopBar
@@ -197,7 +196,7 @@ export const Form = ({
197
196
  />
198
197
  )}
199
198
  {historyTabShown ? (
200
- signer && <History signer={signer} supportedChains={supportedChains} />
199
+ <History signer={signer} supportedChains={supportedChains} />
201
200
  ) : (
202
201
  <div className="flex flex-col gap-2">
203
202
  {desc && <Description description={desc} />}
@@ -6,118 +6,60 @@ import BigNumberJS from "bignumber.js";
6
6
  import { HistoryCard } from "./HistoryCard";
7
7
  import { CircularProgressIcon } from "../icons";
8
8
 
9
- const PENDING_TXS_LOCAL_STORAGE_KEY = "pending_transactions";
10
-
11
- type LocalHistory = { [walletAddress: string]: Transaction[] };
12
-
13
9
  interface Props {
14
- signer: string;
10
+ signer: string | undefined;
15
11
  supportedChains: Chain[];
16
12
  }
17
13
 
18
14
  export const History: FC<Props> = ({ signer, supportedChains }) => {
19
- const [mappedHistory, setMappedHistory] = useState<Transaction[]>();
20
- // const [latestHistory, setLatestHistory] = useState<Transaction[]>();
15
+ const [fetchedHistory, setFetchedHistory] = useState<Transaction[]>();
21
16
  const [historyLoadedOnce, setHistoryLoadedOnce] = useState(false);
22
17
 
23
- const getLocalHistory = () => {
24
- return JSON.parse(
25
- localStorage.getItem(PENDING_TXS_LOCAL_STORAGE_KEY) || "{}",
26
- ) as LocalHistory;
27
- };
28
-
29
- const setLocalHistory = (data: LocalHistory) => {
30
- localStorage.setItem(PENDING_TXS_LOCAL_STORAGE_KEY, JSON.stringify(data));
31
- };
32
-
33
18
  const fetchHistory = useCallback(async () => {
34
- const downloadedHistory = await getHistory({ walletAddress: signer });
35
- const fetchedTransactions: Transaction[] = [];
36
- if (downloadedHistory) {
37
- for (const entry of downloadedHistory.history) {
38
- if (!entry.source) {
39
- continue;
40
- }
41
- let status: TransactionStatus;
42
- if (entry.failed) status = "REVERTED";
43
- if (!!entry.target) {
44
- status = "DONE";
45
- } else {
46
- status = "IN_PROGRESS";
47
- }
48
-
49
- const blockTimestampMs = new Date(entry.source.blockTime).getTime();
50
- const estimatedDeliveryTimestamp = new BigNumberJS(
51
- entry.source.valueForInstantCcipRecieve,
52
- ).gt(0)
53
- ? blockTimestampMs + EXPRESS_DELIVERY_TIME
54
- : blockTimestampMs + DELIVERY_TIME;
55
-
56
- fetchedTransactions.push({
57
- hash: entry.source.transactionHash,
58
- timestamp: blockTimestampMs / 1000,
59
- sourceChainId: entry.source.blockchainId,
60
- targetChainId: entry.source.targetBlockchainId,
61
- amountWei: entry.source.tokenAmount,
62
- tokenAddress: entry.source.tokenAddress,
63
- tokenOutAddress:
64
- entry.target?.tokenAddress || entry.source.tokenOutAddress,
65
- tokenOutAmount:
66
- entry.target?.tokenAmount || entry.source.estimatedAmountOut,
67
- estimatedDeliveryTimestamp,
68
- status,
69
- });
70
- }
71
-
72
- const txHashToTxFromAPI: Record<string, Transaction> = {};
73
- for (const transaction of fetchedTransactions) {
74
- txHashToTxFromAPI[transaction.hash] = transaction;
75
- }
76
-
77
- const localHistory = getLocalHistory();
78
- const newLocalHistory: Record<string, Transaction[]> = {};
79
-
80
- for (const [walletAddress, transactions] of Object.entries(
81
- localHistory,
82
- )) {
83
- if (walletAddress.toLowerCase() !== signer.toLowerCase()) {
84
- continue;
85
- }
86
- const newLocalHistoryForWallet: Transaction[] = [];
87
-
88
- for (const transaction of transactions) {
89
- if (!txHashToTxFromAPI[transaction.hash]) {
90
- // localStorage has fresher data.
91
- fetchedTransactions.push(transaction);
92
- newLocalHistoryForWallet.push(transaction);
19
+ if (signer) {
20
+ const downloadedHistory = await getHistory({ walletAddress: signer });
21
+ const fetchedTransactions: Transaction[] = [];
22
+ if (downloadedHistory) {
23
+ for (const entry of downloadedHistory.history) {
24
+ if (!entry.source) {
93
25
  continue;
94
26
  }
95
-
96
- if (
97
- txHashToTxFromAPI[transaction.hash] &&
98
- transaction.status === "DONE" &&
99
- txHashToTxFromAPI[transaction.hash]?.status === "IN_PROGRESS"
100
- ) {
101
- // If we know on the frontend that the tx is done we should update backend result
102
- txHashToTxFromAPI[transaction.hash]!.status = "DONE";
27
+ let status: TransactionStatus;
28
+ if (entry.failed) status = "REVERTED";
29
+ if (!!entry.target) {
30
+ status = "DONE";
31
+ } else {
32
+ status = "IN_PROGRESS";
103
33
  }
104
34
 
105
- if (
106
- txHashToTxFromAPI[transaction.hash]?.status === "DONE" ||
107
- txHashToTxFromAPI[transaction.hash]?.status === "REVERTED"
108
- ) {
109
- // API has the same or fresher data.
110
- continue;
111
- }
35
+ const blockTimestampMs = new Date(entry.source.blockTime).getTime();
36
+ const estimatedDeliveryTimestamp = new BigNumberJS(
37
+ entry.source.valueForInstantCcipRecieve,
38
+ ).gt(0)
39
+ ? blockTimestampMs + EXPRESS_DELIVERY_TIME
40
+ : blockTimestampMs + DELIVERY_TIME;
41
+
42
+ fetchedTransactions.push({
43
+ hash: entry.source.transactionHash,
44
+ timestamp: blockTimestampMs / 1000,
45
+ sourceChainId: entry.source.blockchainId,
46
+ targetChainId: entry.source.targetBlockchainId,
47
+ amountWei: entry.source.tokenAmount,
48
+ tokenAddress: entry.source.tokenAddress,
49
+ tokenOutAddress:
50
+ entry.target?.tokenAddress || entry.source.tokenOutAddress,
51
+ tokenOutAmount:
52
+ entry.target?.tokenAmount || entry.source.estimatedAmountOut,
53
+ estimatedDeliveryTimestamp,
54
+ status,
55
+ });
112
56
  }
113
57
 
114
- newLocalHistory[walletAddress.toLowerCase()] = newLocalHistoryForWallet;
58
+ setFetchedHistory(
59
+ fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp),
60
+ );
61
+ setHistoryLoadedOnce(true);
115
62
  }
116
- setLocalHistory(newLocalHistory);
117
- setMappedHistory(
118
- fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp),
119
- );
120
- setHistoryLoadedOnce(true);
121
63
  }
122
64
  }, [signer, getHistory]);
123
65
 
@@ -129,20 +71,27 @@ export const History: FC<Props> = ({ signer, supportedChains }) => {
129
71
  return () => clearInterval(timer);
130
72
  }, [signer, fetchHistory, getHistory, historyLoadedOnce]);
131
73
 
74
+ if (!signer)
75
+ return (
76
+ <div className="flex items-center justify-center w-full h-[30vh]">
77
+ Connect a wallet to browse history
78
+ </div>
79
+ );
80
+
132
81
  return (
133
82
  <div className="flex items-center justify-center w-full">
134
- <div className="w-full h-[50vh] overflow-scroll overflow-x-hidden">
135
- {mappedHistory?.length === 0 && historyLoadedOnce && (
83
+ <div className="w-full h-[30vh] overflow-scroll overflow-x-hidden">
84
+ {fetchedHistory?.length === 0 && historyLoadedOnce && (
136
85
  <div className="w-full text-center py-4 px-0 text-[rgb(158,158,158)]">
137
86
  Your history is empty...
138
87
  </div>
139
88
  )}
140
- {!mappedHistory && !historyLoadedOnce && (
89
+ {!fetchedHistory && !historyLoadedOnce && (
141
90
  <div className="flex w-full h-full items-center justify-center">
142
91
  <CircularProgressIcon />
143
92
  </div>
144
93
  )}
145
- {mappedHistory?.map((transaction, index) => (
94
+ {fetchedHistory?.map((transaction, index) => (
146
95
  <HistoryCard
147
96
  key={index}
148
97
  transaction={transaction}
@@ -9,6 +9,7 @@ import {
9
9
  HourGlassIcon,
10
10
  XMarkIcon,
11
11
  } from "@src/components/icons";
12
+ import { MINIMUM_DISPLAYED_TOKEN_AMOUNT } from "@src/constants";
12
13
 
13
14
  interface Props {
14
15
  transaction: Transaction;
@@ -158,8 +159,8 @@ export const HistoryCard: FC<Props> = ({ transaction, supportedChains }) => {
158
159
  <div className="flex items-center mb-2 last:mb-0">
159
160
  <div className="flex flex-1 items-center flex-wrap text-xs text-[rgba(255,255,255,0.6)]">
160
161
  <div className="flex items-center">
161
- {Number(transferredAmount) < 0.0001
162
- ? "<0.0001"
162
+ {Number(transferredAmount) < MINIMUM_DISPLAYED_TOKEN_AMOUNT
163
+ ? `<${MINIMUM_DISPLAYED_TOKEN_AMOUNT}`
163
164
  : transferredAmount}
164
165
  <div className="text-xs ml-1 text-rgba(255,255,255,0.6)">
165
166
  {tokenData?.symbol}
@@ -37,12 +37,24 @@ export const TokenPicker: FC<Props> = ({
37
37
  const filteredTokens = useMemo(() => {
38
38
  const isMatch = (value: string, searchValue: string) =>
39
39
  value.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
40
- return tokens?.filter(
41
- (token) =>
42
- isMatch(token.symbol, searchValue) ||
43
- isMatch(token.name, searchValue) ||
44
- token.address === searchValue.toLowerCase(),
45
- );
40
+
41
+ return tokens
42
+ ?.filter(
43
+ (token) =>
44
+ isMatch(token.symbol, searchValue) ||
45
+ isMatch(token.name, searchValue) ||
46
+ token.address === searchValue.toLowerCase(),
47
+ )
48
+ .sort((a, b) =>
49
+ a.priority < b.priority
50
+ ? 1
51
+ : balances &&
52
+ balances[a.address] &&
53
+ balances[b.address] &&
54
+ balances[a.address]?.lte(balances[b.address] || "0")
55
+ ? 1
56
+ : -1,
57
+ );
46
58
  }, [searchValue, tokens]);
47
59
 
48
60
  return modalRoot
@@ -94,69 +106,60 @@ export const TokenPicker: FC<Props> = ({
94
106
  <div className="h-[2px] my-0 mx-[-24px] w-[100%+48px] px-12 bg-[rgba(255,255,255,0.1)]" />
95
107
  <div className="overflow-y-scroll h-full mx-[-24px] w-[100%+48px] flex flex-col">
96
108
  {filteredTokens && filteredTokens.length > 0 ? (
97
- filteredTokens
98
- .sort((a, b) =>
99
- balances &&
100
- balances[a.address] &&
101
- balances[b.address] &&
102
- balances[a.address]?.lte(balances[b.address] || "0")
103
- ? 1
104
- : -1,
105
- )
106
- .map((token, index) => (
107
- <div
108
- key={`${index}_${token.address}`}
109
- className={`flex gap-3 py-2 px-[24px] w-full items-center hover:bg-[rgb(25,25,25)] hover:cursor-pointer ${
110
- token.address === selectedToken?.address
111
- ? "bg-[rgb(35,35,35)]"
112
- : ""
113
- }`}
114
- onClick={() => {
115
- setSelectedToken(token);
116
- onCloseClick();
117
- }}
118
- >
119
- {token.image ? (
120
- <img
121
- src={token.image}
122
- alt={token.name}
123
- className="token-picker__all__logo"
124
- />
125
- ) : (
126
- <div className="flex items-center justify-center w-9 h-9 text-[15px] ml-1 rounded-full bg-[#272e40] text-[#e0e7fa]">
127
- {token?.symbol.substring(0, 1)}
109
+ filteredTokens.map((token, index) => (
110
+ <div
111
+ key={`${index}_${token.address}`}
112
+ className={`flex gap-3 py-2 px-[24px] w-full items-center hover:bg-[rgb(25,25,25)] hover:cursor-pointer ${
113
+ token.address === selectedToken?.address
114
+ ? "bg-[rgb(35,35,35)]"
115
+ : ""
116
+ }`}
117
+ onClick={() => {
118
+ setSelectedToken(token);
119
+ onCloseClick();
120
+ }}
121
+ >
122
+ {token.image ? (
123
+ <img
124
+ src={token.image}
125
+ alt={token.name}
126
+ className="token-picker__all__logo"
127
+ />
128
+ ) : (
129
+ <div className="flex items-center justify-center w-9 h-9 text-[15px] ml-1 rounded-full bg-[#272e40] text-[#e0e7fa]">
130
+ {token?.symbol.substring(0, 1)}
131
+ </div>
132
+ )}
133
+ <div className="flex justify-between items-center gap-1 overflow-hidden grow">
134
+ <div className="flex flex-col leading-[16px]">
135
+ <div className="overflow-hidden whitespace-nowrap text-ellipsis text-[15px]">
136
+ {token.name}
128
137
  </div>
129
- )}
130
- <div className="flex justify-between items-center gap-1 overflow-hidden grow">
131
- <div className="flex flex-col leading-[16px]">
132
- <div className="overflow-hidden whitespace-nowrap text-ellipsis text-[15px]">
133
- {token.name}
134
- </div>
135
- <div className="text-[#888] text-[11px]">
136
- {token.symbol}
137
- </div>
138
+ <div className="text-[#888] text-[11px]">
139
+ {token.symbol}
138
140
  </div>
139
- {signer && (
140
- <>
141
- {balances &&
142
- balances[token.address] &&
143
- token.decimals ? (
144
- <div className="text-xs">
145
- {weiToHumanReadable({
146
- amount:
147
- balances[token.address]?.toString() || "0",
148
- decimals: token.decimals,
149
- precisionFractionalPlaces: 4,
150
- })}
151
- </div>
152
- ) : (
153
- <Skeleton w="w-12" h="h-3" />
154
- )}
155
- </>
156
- )}
157
141
  </div>
142
+ {signer && (
143
+ <>
144
+ {balances &&
145
+ balances[token.address] &&
146
+ token.decimals ? (
147
+ <div className="text-xs">
148
+ {weiToHumanReadable({
149
+ amount:
150
+ balances[token.address]?.toString() || "0",
151
+ decimals: token.decimals,
152
+ precisionFractionalPlaces: 4,
153
+ })}
154
+ </div>
155
+ ) : (
156
+ <Skeleton w="w-12" h="h-3" />
157
+ )}
158
+ </>
159
+ )}
158
160
  </div>
159
- ))
161
+ </div>
162
+ ))
160
163
  ) : (
161
164
  <div className="mt-4 flex justify-center">
162
165
  <p className="text-sm text-white">No tokens found.</p>
@@ -18,7 +18,9 @@ export const TopBar: FC<Props> = ({
18
18
  return (
19
19
  <div className="flex w-full justify-between mx-auto pl-4 pr-8 pt-2">
20
20
  <div className="rounded-lg text-[rgba(255,255,255,0.6)] text-base whitespace-nowrap">
21
- {signer ? `Connected wallet: ${shortAddress(signer)}` : `Disconnected`}
21
+ {signer
22
+ ? `Connected wallet: ${shortAddress(signer)}`
23
+ : `Wallet disconnected`}
22
24
  </div>
23
25
  <div className="flex gap-2">
24
26
  {!historyTabShown && (
@@ -31,22 +33,20 @@ export const TopBar: FC<Props> = ({
31
33
  </div>
32
34
  </div>
33
35
  )}
34
- {signer && (
35
- <div
36
- onClick={() => setHistoryTabShown((x) => !x)}
37
- className="flex items-center text-sm gap-1 cursor-pointer"
38
- >
39
- {!historyTabShown ? (
40
- <>
41
- <div className="w-7 h-7 rounded-full bg-gradient-to-r from-x_blue_light to-x_blue_dark flex items-center justify-center">
42
- <HistoryIcon />
43
- </div>
44
- </>
45
- ) : (
46
- <div>Back</div>
47
- )}
48
- </div>
49
- )}
36
+ <div
37
+ onClick={() => setHistoryTabShown((x) => !x)}
38
+ className="flex items-center text-sm gap-1 cursor-pointer"
39
+ >
40
+ {!historyTabShown ? (
41
+ <>
42
+ <div className="w-7 h-7 rounded-full bg-gradient-to-r from-x_blue_light to-x_blue_dark flex items-center justify-center">
43
+ <HistoryIcon />
44
+ </div>
45
+ </>
46
+ ) : (
47
+ <div>Back</div>
48
+ )}
49
+ </div>
50
50
  </div>
51
51
  </div>
52
52
  );
@@ -6,6 +6,6 @@ export const SLIPPAGE_PRESETS: number[] = [0.5, 1.5, 3.0];
6
6
  export const DELIVERY_TIME = 30 * 1000 * 60;
7
7
  export const EXPRESS_DELIVERY_TIME = 30 * 1000;
8
8
  export const BALANCES_CHUNK_SIZE = 500;
9
- export const BALANCE_DISPLAY_MIN_LIMIT = 0.0001;
10
9
  export const ROUTE_TIMEOUT_MS = 5000;
11
- export const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.00001;
10
+ export const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
11
+ export const DEFAULT_SOURCE_CHAIN_ID = "1";
@@ -13,6 +13,10 @@ module.exports = {
13
13
  x_blue_light: "rgba(54,129,198,1)",
14
14
  x_blue_dark: "rgba(43,74,157,1)",
15
15
  },
16
+ width: {
17
+ x_desktop: "600px",
18
+ x_mobile: "356px",
19
+ },
16
20
  },
17
21
  },
18
22
  plugins: [],