@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 +9 -0
- package/dist/index.css +7 -7
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +59 -94
- package/dist/index.mjs +58 -93
- package/package.json +1 -1
- package/src/components/TxConfigForm/Form.tsx +10 -11
- package/src/components/TxConfigForm/History.tsx +50 -101
- package/src/components/TxConfigForm/HistoryCard.tsx +3 -2
- package/src/components/TxConfigForm/TokenPicker.tsx +68 -65
- package/src/components/TxConfigForm/TopBar.tsx +17 -17
- package/src/constants/index.ts +2 -2
- package/tailwind.config.js +4 -0
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
|
|
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.
|
|
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,
|
|
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.
|
|
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,
|
|
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-
|
|
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) <
|
|
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 [
|
|
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
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
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
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
if (
|
|
2745
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
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)}` : `
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
3400
|
+
const defaultChain = supportedChains.find(
|
|
3435
3401
|
({ chainId }) => chainId === account.chainId?.toString()
|
|
3436
|
-
)
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
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-
|
|
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 ?
|
|
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-
|
|
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) <
|
|
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 [
|
|
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
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
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
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
if (
|
|
2675
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
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)}` : `
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
3330
|
+
const defaultChain = supportedChains.find(
|
|
3365
3331
|
({ chainId }) => chainId === account.chainId?.toString()
|
|
3366
|
-
)
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
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-
|
|
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 ?
|
|
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
|
@@ -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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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 ===
|
|
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-
|
|
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
|
-
|
|
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 [
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
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-[
|
|
135
|
-
{
|
|
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
|
-
{!
|
|
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
|
-
{
|
|
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) <
|
|
162
|
-
?
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
);
|
package/src/constants/index.ts
CHANGED
|
@@ -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.
|
|
10
|
+
export const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
|
|
11
|
+
export const DEFAULT_SOURCE_CHAIN_ID = "1";
|