@aurora-is-near/intents-swap-widget 3.18.2 → 3.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Accordion.js +31 -32
- package/dist/components/Accordion.js.map +1 -1
- package/dist/components/AllNetworksIcon.js +11 -0
- package/dist/components/AllNetworksIcon.js.map +1 -0
- package/dist/components/Button.d.ts +8 -0
- package/dist/components/Button.js +53 -43
- package/dist/components/Button.js.map +1 -1
- package/dist/components/ChainShortcut.d.ts +15 -0
- package/dist/components/ChainShortcut.js +57 -0
- package/dist/components/ChainShortcut.js.map +1 -0
- package/dist/components/CopyButton.d.ts +5 -2
- package/dist/components/CopyButton.js +11 -7
- package/dist/components/CopyButton.js.map +1 -1
- package/dist/components/Notes.js +1 -1
- package/dist/components/Notes.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +21 -17
- package/dist/components/index.js.map +1 -1
- package/dist/{config-CgCb5P7j.js → config-C47AYcMK.js} +1006 -992
- package/dist/config-C47AYcMK.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +9 -10
- package/dist/config.js.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/ext/alchemy/index.js +1 -1
- package/dist/ext/index.js +1 -1
- package/dist/features/BalanceRpcLoader/TokenBalanceLoader.js +1 -1
- package/dist/features/BalanceRpcLoader/index.js +1 -1
- package/dist/features/BalanceRpcLoader/useTokenBalanceRpc.js +1 -1
- package/dist/features/ChainsDropdown/ChainItem.d.ts +1 -0
- package/dist/features/ChainsDropdown/ChainItem.js +23 -14
- package/dist/features/ChainsDropdown/ChainItem.js.map +1 -1
- package/dist/features/ChainsDropdown/index.js +61 -94
- package/dist/features/ChainsDropdown/index.js.map +1 -1
- package/dist/features/ChainsSelector/index.d.ts +15 -0
- package/dist/features/ChainsSelector/index.js +108 -0
- package/dist/features/ChainsSelector/index.js.map +1 -0
- package/dist/features/DepositMethodSwitcher.js +1 -1
- package/dist/features/ErrorBoundary.js +1 -1
- package/dist/features/ExternalDeposit.js +4 -3
- package/dist/features/ExternalDeposit.js.map +1 -1
- package/dist/features/SendAddress/index.js +1 -1
- package/dist/features/SendAddress/useNotification.js +1 -1
- package/dist/features/SubmitButton/index.js +1 -1
- package/dist/features/SuccessScreen/CopyableValue.d.ts +5 -0
- package/dist/features/SuccessScreen/CopyableValue.js +11 -0
- package/dist/features/SuccessScreen/CopyableValue.js.map +1 -0
- package/dist/features/SuccessScreen/TokenRow.d.ts +8 -0
- package/dist/features/SuccessScreen/TokenRow.js +20 -0
- package/dist/features/SuccessScreen/TokenRow.js.map +1 -0
- package/dist/features/SuccessScreen/index.d.ts +5 -4
- package/dist/features/SuccessScreen/index.js +151 -49
- package/dist/features/SuccessScreen/index.js.map +1 -1
- package/dist/features/SuccessScreen/useSummaryItemsCount.d.ts +1 -0
- package/dist/features/SuccessScreen/useSummaryItemsCount.js +14 -0
- package/dist/features/SuccessScreen/useSummaryItemsCount.js.map +1 -0
- package/dist/features/SwapDirectionSwitcher.js +1 -1
- package/dist/features/SwapQuote/SwapQuote.js +1 -1
- package/dist/features/SwapQuote/index.js +1 -1
- package/dist/features/TokenInput/TokenInput.js +1 -1
- package/dist/features/TokenInput/TokenInputEmpty.js +1 -1
- package/dist/features/TokenInput/TokenInputSource.js +1 -1
- package/dist/features/TokenInput/TokenInputTarget.js +2 -2
- package/dist/features/TokenInput/WalletBalance.js +1 -1
- package/dist/features/TokenInput/hooks/index.js +1 -1
- package/dist/features/TokenInput/hooks/useTokenInputBalance.js +1 -1
- package/dist/features/TokenInput/index.js +1 -1
- package/dist/features/TokensList/TokenItem.js +2 -2
- package/dist/features/TokensList/TokensList.js +1 -1
- package/dist/features/TokensList/index.js +1 -1
- package/dist/features/TokensModal.js +62 -64
- package/dist/features/TokensModal.js.map +1 -1
- package/dist/features/WalletCompatibilityCheck/WalletCompatibilityModal.js +5 -4
- package/dist/features/WalletCompatibilityCheck/WalletCompatibilityModal.js.map +1 -1
- package/dist/features/WalletCompatibilityCheck/index.js +1 -1
- package/dist/features/index.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useAllTokens.js +1 -1
- package/dist/hooks/useChains.js +1 -1
- package/dist/hooks/useCompatibilityCheck.js +1 -1
- package/dist/hooks/useDefaultToken.js +1 -1
- package/dist/hooks/useExternalDepositStatus/index.js +1 -1
- package/dist/hooks/useExternalDepositStatus/usePoaExternalDepositStatus.js +1 -1
- package/dist/hooks/useIntentsBalance.js +1 -1
- package/dist/hooks/useIsCompatibilityCheckRequired.js +1 -1
- package/dist/hooks/useMakeDepositAddress.js +1 -1
- package/dist/hooks/useMakeIntentsTransfer.js +1 -1
- package/dist/hooks/useMakeNEARFtTransferCall.js +1 -1
- package/dist/hooks/useMakeQuote.js +1 -1
- package/dist/hooks/useMakeQuoteTransfer.js +1 -1
- package/dist/hooks/useMakeTransfer.js +1 -1
- package/dist/hooks/useMergedBalance.js +1 -1
- package/dist/hooks/useSwitchChain.js +1 -1
- package/dist/hooks/useTheme.js +1 -1
- package/dist/hooks/useTokenInputPair.js +1 -1
- package/dist/hooks/useTokens.js +1 -1
- package/dist/hooks/useTokensFiltered.d.ts +3 -1
- package/dist/hooks/useTokensFiltered.js +1 -1
- package/dist/hooks/useTokensIntentsUnique.js +1 -1
- package/dist/index.js +74 -70
- package/dist/index.js.map +1 -1
- package/dist/machine/effects/index.js +1 -1
- package/dist/machine/effects/useAlchemyBalanceEffect.js +1 -1
- package/dist/machine/effects/useBalancesUpdateEffect.js +1 -1
- package/dist/machine/effects/useMakeQuoteEffect.js +1 -1
- package/dist/machine/effects/useSelectedTokensEffect.js +1 -1
- package/dist/machine/effects/useSetTokenBalanceEffect.js +1 -1
- package/dist/machine/effects/useSetTokenIntentsTargetEffect.js +1 -1
- package/dist/machine/effects/useWalletConnEffect.js +1 -1
- package/dist/machine/events/index.js +1 -1
- package/dist/machine/events/reset.d.ts +1 -0
- package/dist/machine/events/reset.js +2 -2
- package/dist/machine/events/reset.js.map +1 -1
- package/dist/machine/events/tokenSelect.js +1 -1
- package/dist/machine/events/validateInputAndMoveTo.js +1 -1
- package/dist/machine/events/validateInputs.js +1 -1
- package/dist/machine/index.js +1 -1
- package/dist/machine/snap.js +1 -1
- package/dist/machine/subscriptions/checkers/isSendAddressAsConnected.js +1 -1
- package/dist/machine/subscriptions/index.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme/ThemeProvider.js +1 -1
- package/dist/types/config.d.ts +3 -0
- package/dist/types/localisation.d.ts +1 -1
- package/dist/utils/intents/signers/near.js +1 -1
- package/dist/utils/intents/signers/privy.js +1 -1
- package/dist/utils/near/getNearNep141StorageBalance.js +1 -1
- package/dist/utils/tokens/sort.d.ts +2 -1
- package/dist/utils/tokens/sort.js +55 -24
- package/dist/utils/tokens/sort.js.map +1 -1
- package/dist/widgets/WidgetDeposit/WidgetDepositContent.js +74 -73
- package/dist/widgets/WidgetDeposit/WidgetDepositContent.js.map +1 -1
- package/dist/widgets/WidgetDeposit/WidgetDepositSkeleton.js +1 -1
- package/dist/widgets/WidgetSwap/WidgetSwapContent.js +70 -68
- package/dist/widgets/WidgetSwap/WidgetSwapContent.js.map +1 -1
- package/dist/widgets/WidgetSwap/WidgetSwapSkeleton.js +1 -1
- package/dist/widgets/WidgetWithdraw/WidgetWithdrawContent.js +64 -62
- package/dist/widgets/WidgetWithdraw/WidgetWithdrawContent.js.map +1 -1
- package/dist/widgets/WidgetWithdraw/WidgetWithdrawSkeleton.js +1 -1
- package/package.json +1 -1
- package/src/components/Accordion.tsx +5 -6
- package/src/components/AllNetworksIcon.tsx +8 -0
- package/src/components/Button.tsx +17 -1
- package/src/components/ChainShortcut.tsx +67 -0
- package/src/components/CopyButton.tsx +12 -2
- package/src/components/Notes.tsx +1 -1
- package/src/components/index.ts +2 -0
- package/src/config.tsx +13 -0
- package/src/features/ChainsDropdown/ChainItem.tsx +17 -4
- package/src/features/ChainsDropdown/index.tsx +10 -41
- package/src/features/ChainsSelector/index.tsx +113 -0
- package/src/features/SuccessScreen/CopyableValue.tsx +13 -0
- package/src/features/SuccessScreen/TokenRow.tsx +26 -0
- package/src/features/SuccessScreen/index.tsx +161 -55
- package/src/features/SuccessScreen/useSummaryItemsCount.ts +33 -0
- package/src/features/TokensList/TokensList.tsx +2 -1
- package/src/features/TokensModal.tsx +29 -29
- package/src/hooks/useTokensFiltered.ts +4 -0
- package/src/machine/events/reset.ts +6 -3
- package/src/types/config.ts +8 -0
- package/src/types/localisation.ts +11 -3
- package/src/utils/tokens/sort.ts +107 -20
- package/src/widgets/WidgetDeposit/WidgetDepositContent.tsx +6 -4
- package/src/widgets/WidgetSwap/WidgetSwapContent.tsx +7 -4
- package/src/widgets/WidgetWithdraw/WidgetWithdrawContent.tsx +7 -4
- package/dist/config-CgCb5P7j.js.map +0 -1
- package/dist/features/ChainsDropdown/AllNetworksIcon.js +0 -7
- package/dist/features/ChainsDropdown/AllNetworksIcon.js.map +0 -1
- package/dist/features/SuccessScreen/CheckIcon.d.ts +0 -1
- package/dist/features/SuccessScreen/CheckIcon.js +0 -7
- package/dist/features/SuccessScreen/CheckIcon.js.map +0 -1
- package/dist/features/SuccessScreen/ExternalAction.d.ts +0 -5
- package/dist/features/SuccessScreen/ExternalAction.js +0 -16
- package/dist/features/SuccessScreen/ExternalAction.js.map +0 -1
- package/dist/features/SuccessScreen/SummaryItem.d.ts +0 -8
- package/dist/features/SuccessScreen/SummaryItem.js +0 -21
- package/dist/features/SuccessScreen/SummaryItem.js.map +0 -1
- package/src/features/ChainsDropdown/AllNetworksIcon.tsx +0 -7
- package/src/features/SuccessScreen/CheckIcon.tsx +0 -7
- package/src/features/SuccessScreen/ExternalAction.tsx +0 -15
- package/src/features/SuccessScreen/SummaryItem.tsx +0 -28
- /package/dist/{features/ChainsDropdown → components}/AllNetworksIcon.d.ts +0 -0
|
@@ -1,79 +1,185 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ArrowDownward,
|
|
3
|
+
Check,
|
|
4
|
+
OpenInNew,
|
|
5
|
+
} from '@material-symbols-svg/react-rounded/w700';
|
|
2
6
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
+
import { TokenRow } from './TokenRow';
|
|
8
|
+
import { CopyableValue } from './CopyableValue';
|
|
9
|
+
import { useSummaryItemsCount } from './useSummaryItemsCount';
|
|
10
|
+
|
|
11
|
+
import { Notes } from '@/components/Notes';
|
|
12
|
+
import { Button } from '@/components/Button';
|
|
7
13
|
import { CloseButton } from '@/components/CloseButton';
|
|
8
|
-
import
|
|
14
|
+
import { Accordion } from '@/components/Accordion';
|
|
9
15
|
|
|
10
|
-
import {
|
|
16
|
+
import { guardStates } from '@/machine/guards';
|
|
17
|
+
import { useUnsafeSnapshot } from '@/machine/snap';
|
|
18
|
+
import { formatUsdAmount } from '@/utils/formatters/formatUsdAmount';
|
|
19
|
+
import { formatTinyNumber } from '@/utils/formatters/formatTinyNumber';
|
|
20
|
+
import { formatBigToHuman } from '@/utils/formatters/formatBigToHuman';
|
|
11
21
|
import { useTypedTranslation } from '@/localisation';
|
|
22
|
+
import { useHandleKeyDown } from '@/hooks';
|
|
23
|
+
import { logger } from '@/logger';
|
|
24
|
+
|
|
25
|
+
import type { TransferResult } from '@/types/transfer';
|
|
26
|
+
|
|
27
|
+
const NOTES_ITEM_HEIGHT = 44;
|
|
12
28
|
|
|
13
29
|
type Msg = { type: 'on_dismiss_success' };
|
|
14
30
|
|
|
15
31
|
type Props = TransferResult & {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
title: string;
|
|
33
|
+
message?: string;
|
|
34
|
+
showTargetToken?: boolean;
|
|
35
|
+
onMsg: (msg: Msg) => void;
|
|
19
36
|
};
|
|
20
37
|
|
|
21
38
|
export const SuccessScreen = ({
|
|
22
|
-
|
|
23
|
-
transactionLink,
|
|
24
|
-
hash: txHash,
|
|
39
|
+
title,
|
|
25
40
|
message,
|
|
41
|
+
showTargetToken = true,
|
|
42
|
+
transactionLink,
|
|
26
43
|
onMsg,
|
|
27
|
-
|
|
44
|
+
...transferResult
|
|
28
45
|
}: Props) => {
|
|
29
|
-
const { ctx } = useUnsafeSnapshot();
|
|
30
46
|
const { t } = useTypedTranslation();
|
|
31
|
-
const
|
|
47
|
+
const { ctx } = useUnsafeSnapshot();
|
|
48
|
+
|
|
49
|
+
const isValidState = guardStates(ctx, ['transfer_success']);
|
|
50
|
+
const handleClose = () => onMsg({ type: 'on_dismiss_success' });
|
|
51
|
+
const summaryItemsCount = useSummaryItemsCount(!!transferResult.intent);
|
|
52
|
+
|
|
53
|
+
useHandleKeyDown('Escape', handleClose);
|
|
32
54
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
55
|
+
if (!isValidState) {
|
|
56
|
+
logger.warn(
|
|
57
|
+
'[WIDGET] Success screen can be rendered only in transfer_success state',
|
|
36
58
|
);
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const sourceAmount = formatBigToHuman(
|
|
64
|
+
ctx.quote?.amountIn ?? ctx.sourceTokenAmount,
|
|
65
|
+
ctx.sourceToken.decimals,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const targetAmount = formatBigToHuman(
|
|
69
|
+
ctx.quote?.amountOut ?? ctx.targetTokenAmount,
|
|
70
|
+
ctx.targetToken.decimals,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const sourceAmountUsd = ctx.quote?.amountInUsd
|
|
74
|
+
? parseFloat(ctx.quote.amountInUsd)
|
|
75
|
+
: ctx.sourceToken.price * parseFloat(sourceAmount);
|
|
76
|
+
|
|
77
|
+
const targetAmountUsd = ctx.quote?.amountOutUsd
|
|
78
|
+
? parseFloat(ctx.quote.amountOutUsd)
|
|
79
|
+
: ctx.targetToken.price * parseFloat(targetAmount);
|
|
80
|
+
|
|
81
|
+
const targetTokenUnitPrice = targetAmountUsd / parseFloat(targetAmount);
|
|
82
|
+
|
|
83
|
+
const sourceTokenUnitAmount = formatTinyNumber(
|
|
84
|
+
targetTokenUnitPrice / (parseFloat(sourceAmount) / sourceAmountUsd),
|
|
85
|
+
);
|
|
39
86
|
|
|
40
87
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
88
|
+
<div className="flex flex-col gap-sw-2xl w-full">
|
|
89
|
+
<header className="flex items-center gap-sw-lg">
|
|
90
|
+
<div className="flex items-center justify-center p-sw-md bg-sw-status-success rounded-sw-md">
|
|
91
|
+
<Check size={20} className="text-sw-gray-900" />
|
|
92
|
+
</div>
|
|
93
|
+
<span className="text-sw-label-lg text-sw-status-success mr-auto">
|
|
94
|
+
{title}
|
|
95
|
+
</span>
|
|
96
|
+
<CloseButton onClick={handleClose} />
|
|
97
|
+
</header>
|
|
98
|
+
|
|
99
|
+
{!!message && (
|
|
100
|
+
<p className="text-sw-body-md text-sw-gray-200">{message}</p>
|
|
52
101
|
)}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
))}
|
|
60
|
-
</p>
|
|
61
|
-
<Hr className="mt-sw-xl mb-sw-md" />
|
|
62
|
-
<ul className="mt-sw-xl flex flex-col">
|
|
63
|
-
<SummaryItem
|
|
64
|
-
hasCopyAction
|
|
65
|
-
value={txHash}
|
|
66
|
-
externalUrl={transactionLink}
|
|
67
|
-
label={t('transfer.success.hash.label', 'Transaction hash')}
|
|
102
|
+
|
|
103
|
+
<div className="flex flex-col">
|
|
104
|
+
<TokenRow
|
|
105
|
+
token={ctx.sourceToken}
|
|
106
|
+
amount={sourceAmount}
|
|
107
|
+
amountUsd={sourceAmountUsd}
|
|
68
108
|
/>
|
|
69
|
-
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
109
|
+
{showTargetToken && (
|
|
110
|
+
<>
|
|
111
|
+
<div className="flex items-center justify-center w-full h-[12px] z-1">
|
|
112
|
+
<div className="flex items-center justify-center p-sw-md bg-sw-gray-950 rounded-sw-md w-fit">
|
|
113
|
+
<ArrowDownward size={18} className="text-sw-gray-200" />
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
<TokenRow
|
|
117
|
+
token={ctx.targetToken}
|
|
118
|
+
amount={targetAmount}
|
|
119
|
+
amountUsd={targetAmountUsd}
|
|
120
|
+
/>
|
|
121
|
+
</>
|
|
75
122
|
)}
|
|
76
|
-
</
|
|
77
|
-
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<Accordion
|
|
126
|
+
expandedByDefault={false}
|
|
127
|
+
expandedHeightPx={summaryItemsCount * NOTES_ITEM_HEIGHT}
|
|
128
|
+
title={t('transfer.success.details.label', 'Transaction details')}>
|
|
129
|
+
<Notes>
|
|
130
|
+
{ctx.sourceToken.symbol !== ctx.targetToken.symbol && (
|
|
131
|
+
<Notes.Item
|
|
132
|
+
label={t('transfer.success.details.rate', 'Rate')}
|
|
133
|
+
value={
|
|
134
|
+
<span
|
|
135
|
+
className="text-sw-gray-50"
|
|
136
|
+
style={{ borderBottomWidth: '2px', borderStyle: 'dotted' }}>
|
|
137
|
+
{`1 ${ctx.targetToken.symbol} ≈ `} {sourceTokenUnitAmount}{' '}
|
|
138
|
+
{`${ctx.sourceToken.symbol}`}
|
|
139
|
+
<span>{` (${formatUsdAmount(targetTokenUnitPrice)})`}</span>
|
|
140
|
+
</span>
|
|
141
|
+
}
|
|
142
|
+
/>
|
|
143
|
+
)}
|
|
144
|
+
{/* send address is missing if target token is on intents */}
|
|
145
|
+
{!!ctx.sendAddress && (
|
|
146
|
+
<Notes.Item
|
|
147
|
+
label={t(
|
|
148
|
+
'transfer.success.details.recipient',
|
|
149
|
+
'Recipient address',
|
|
150
|
+
)}
|
|
151
|
+
value={<CopyableValue value={ctx.sendAddress} />}
|
|
152
|
+
/>
|
|
153
|
+
)}
|
|
154
|
+
{!!transferResult.intent && (
|
|
155
|
+
<Notes.Item
|
|
156
|
+
label={t('transfer.success.details.intent', 'Intent hash')}
|
|
157
|
+
value={<CopyableValue value={transferResult.intent} />}
|
|
158
|
+
/>
|
|
159
|
+
)}
|
|
160
|
+
<Notes.Item
|
|
161
|
+
label={t('transfer.success.details.hash', 'Transaction hash')}
|
|
162
|
+
value={<CopyableValue value={transferResult.hash} />}
|
|
163
|
+
/>
|
|
164
|
+
</Notes>
|
|
165
|
+
</Accordion>
|
|
166
|
+
|
|
167
|
+
<div className="flex flex-col gap-sw-lg">
|
|
168
|
+
<Button
|
|
169
|
+
fluid
|
|
170
|
+
as="a"
|
|
171
|
+
size="lg"
|
|
172
|
+
target="_blank"
|
|
173
|
+
variant="primary"
|
|
174
|
+
iconPosition="tail"
|
|
175
|
+
href={transactionLink}
|
|
176
|
+
icon={OpenInNew}>
|
|
177
|
+
{t('transfer.success.action.viewOnExplorer', 'View in explorer')}
|
|
178
|
+
</Button>
|
|
179
|
+
<Button fluid size="lg" variant="outlined" onClick={handleClose}>
|
|
180
|
+
{t('transfer.success.action.backToSwap', 'Back to swap')}
|
|
181
|
+
</Button>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
78
184
|
);
|
|
79
185
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { guardStates } from '@/machine/guards';
|
|
4
|
+
import { useUnsafeSnapshot } from '@/machine/snap';
|
|
5
|
+
|
|
6
|
+
export const useSummaryItemsCount = (hasIntentHash: boolean) => {
|
|
7
|
+
const { ctx } = useUnsafeSnapshot();
|
|
8
|
+
const isValidState = guardStates(ctx, ['transfer_success']);
|
|
9
|
+
|
|
10
|
+
const summaryItemsCount = useMemo(() => {
|
|
11
|
+
let count = 1;
|
|
12
|
+
|
|
13
|
+
if (!isValidState) {
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (ctx.sourceToken.symbol !== ctx.targetToken.symbol) {
|
|
18
|
+
count += 1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (ctx.sendAddress) {
|
|
22
|
+
count += 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (hasIntentHash) {
|
|
26
|
+
count += 1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return count;
|
|
30
|
+
}, [hasIntentHash, ctx.sendAddress, ctx.sourceToken, ctx.targetToken]);
|
|
31
|
+
|
|
32
|
+
return summaryItemsCount;
|
|
33
|
+
};
|
|
@@ -60,7 +60,7 @@ export const TokensList = ({
|
|
|
60
60
|
}: Props) => {
|
|
61
61
|
const { t } = useTypedTranslation();
|
|
62
62
|
const { ctx } = useUnsafeSnapshot();
|
|
63
|
-
const { walletSupportedChains, appName } = useConfig();
|
|
63
|
+
const { walletSupportedChains, appName, priorityAssets = [] } = useConfig();
|
|
64
64
|
const { mergedBalance } = useMergedBalance();
|
|
65
65
|
|
|
66
66
|
const filteredTokens = useTokensFiltered({
|
|
@@ -69,6 +69,7 @@ export const TokensList = ({
|
|
|
69
69
|
chainsFilter,
|
|
70
70
|
selectedChain,
|
|
71
71
|
walletSupportedChains,
|
|
72
|
+
priorityAssets,
|
|
72
73
|
});
|
|
73
74
|
|
|
74
75
|
const areTokensGrouped = ctx.walletAddress ? groupTokens : false;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { SearchW700 as Search } from '@material-symbols-svg/react-rounded/icons/search';
|
|
2
1
|
import { useRef, useState } from 'react';
|
|
2
|
+
import { SearchW700 as Search } from '@material-symbols-svg/react-rounded/icons/search';
|
|
3
3
|
|
|
4
|
-
import { TokensList } from './TokensList';
|
|
5
|
-
import { ChainsDropdown } from './ChainsDropdown';
|
|
6
4
|
import { useChains } from '../hooks';
|
|
5
|
+
import { TokensList } from './TokensList';
|
|
6
|
+
import { ChainsSelector } from './ChainsSelector';
|
|
7
|
+
|
|
7
8
|
import { Hr } from '@/components/Hr';
|
|
8
9
|
import { Card } from '@/components/Card';
|
|
9
10
|
import { Input } from '@/components/Input';
|
|
@@ -96,33 +97,32 @@ export const TokensModal = ({
|
|
|
96
97
|
<CloseButton onClick={handleClose} />
|
|
97
98
|
</header>
|
|
98
99
|
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
<Input
|
|
101
|
+
focusOnMount
|
|
102
|
+
icon={Search}
|
|
103
|
+
ref={searchInputRef}
|
|
104
|
+
defaultValue={search}
|
|
105
|
+
className="w-full"
|
|
106
|
+
placeholder="Search or paste address"
|
|
107
|
+
onChange={(e) => setSearch(e.target.value.trim())}
|
|
108
|
+
/>
|
|
109
|
+
|
|
110
|
+
{showChainsSelector && (
|
|
111
|
+
<ChainsSelector
|
|
112
|
+
variant={variant}
|
|
113
|
+
chainsFilter={chainsFilter}
|
|
114
|
+
selectedChain={selectedChain}
|
|
115
|
+
onMsg={(msg) => {
|
|
116
|
+
switch (msg.type) {
|
|
117
|
+
case 'on_select_chain':
|
|
118
|
+
setSelectedChain(msg.chain);
|
|
119
|
+
break;
|
|
120
|
+
default:
|
|
121
|
+
notReachable(msg.type);
|
|
122
|
+
}
|
|
123
|
+
}}
|
|
108
124
|
/>
|
|
109
|
-
|
|
110
|
-
<ChainsDropdown
|
|
111
|
-
variant={variant}
|
|
112
|
-
selected={selectedChain}
|
|
113
|
-
chainsFilter={chainsFilter}
|
|
114
|
-
onMsg={(msg) => {
|
|
115
|
-
switch (msg.type) {
|
|
116
|
-
case 'on_click_chain':
|
|
117
|
-
setSelectedChain(msg.chain);
|
|
118
|
-
break;
|
|
119
|
-
default:
|
|
120
|
-
notReachable(msg.type, { throwError: false });
|
|
121
|
-
}
|
|
122
|
-
}}
|
|
123
|
-
/>
|
|
124
|
-
)}
|
|
125
|
-
</div>
|
|
125
|
+
)}
|
|
126
126
|
|
|
127
127
|
{chainIsNotSupported && !!ctx.walletAddress && (
|
|
128
128
|
<>
|
|
@@ -8,6 +8,7 @@ import { createFilterByIntents } from '@/utils/tokens/filterByIntents';
|
|
|
8
8
|
import { createFilterBySearch } from '@/utils/tokens/filterBySearchString';
|
|
9
9
|
import { createFilterBySelectedChain } from '@/utils/tokens/filterBySelectedChain';
|
|
10
10
|
import type { Chains, ChainsFilter } from '@/types/chain';
|
|
11
|
+
import type { PriorityAssets } from '@/types/config';
|
|
11
12
|
|
|
12
13
|
export type TokensFilterOptions = {
|
|
13
14
|
variant: 'source' | 'target';
|
|
@@ -15,6 +16,7 @@ export type TokensFilterOptions = {
|
|
|
15
16
|
selectedChain: Chains | 'all' | 'intents';
|
|
16
17
|
chainsFilter: ChainsFilter;
|
|
17
18
|
walletSupportedChains: ReadonlyArray<Chains>;
|
|
19
|
+
priorityAssets: PriorityAssets;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
// TODO: memoize
|
|
@@ -24,6 +26,7 @@ export const useTokensFiltered = ({
|
|
|
24
26
|
selectedChain,
|
|
25
27
|
chainsFilter,
|
|
26
28
|
walletSupportedChains,
|
|
29
|
+
priorityAssets,
|
|
27
30
|
}: TokensFilterOptions) => {
|
|
28
31
|
const chains = useChains(variant);
|
|
29
32
|
const { tokens } = useTokens(variant);
|
|
@@ -35,6 +38,7 @@ export const useTokensFiltered = ({
|
|
|
35
38
|
mergedBalance,
|
|
36
39
|
walletSupportedChains,
|
|
37
40
|
search,
|
|
41
|
+
priorityAssets,
|
|
38
42
|
);
|
|
39
43
|
|
|
40
44
|
const filteredTokens = tokens
|
|
@@ -2,15 +2,13 @@ import type { Machine } from '@/machine';
|
|
|
2
2
|
import type { Context } from '@/machine/context';
|
|
3
3
|
|
|
4
4
|
export type ResetPayload = {
|
|
5
|
+
keepSelectedTokens?: boolean;
|
|
5
6
|
clearWalletAddress: boolean;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export const reset = (ctx: Context, payload: ResetPayload, m: Machine) => {
|
|
9
|
-
ctx.sourceToken = undefined;
|
|
10
10
|
ctx.sourceTokenBalance = undefined;
|
|
11
11
|
ctx.sourceTokenAmount = '';
|
|
12
|
-
|
|
13
|
-
ctx.targetToken = undefined;
|
|
14
12
|
ctx.targetTokenAmount = '';
|
|
15
13
|
|
|
16
14
|
ctx.sendAddress = undefined;
|
|
@@ -22,6 +20,11 @@ export const reset = (ctx: Context, payload: ResetPayload, m: Machine) => {
|
|
|
22
20
|
ctx.quoteStatus = 'idle';
|
|
23
21
|
ctx.transferStatus = { status: 'idle' };
|
|
24
22
|
|
|
23
|
+
if (!payload.keepSelectedTokens) {
|
|
24
|
+
ctx.sourceToken = undefined;
|
|
25
|
+
ctx.targetToken = undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
25
28
|
if (payload.clearWalletAddress) {
|
|
26
29
|
ctx.walletAddress = undefined;
|
|
27
30
|
}
|
package/src/types/config.ts
CHANGED
|
@@ -9,6 +9,10 @@ export type WalletAddresses = Partial<
|
|
|
9
9
|
|
|
10
10
|
export type IntentsAccountType = 'evm' | 'near' | 'sol';
|
|
11
11
|
|
|
12
|
+
export type PriorityAssets =
|
|
13
|
+
| ReadonlyArray<string>
|
|
14
|
+
| ReadonlyArray<readonly [Chains, string]>;
|
|
15
|
+
|
|
12
16
|
export type WidgetConfig = {
|
|
13
17
|
// Application metadata
|
|
14
18
|
appName: string;
|
|
@@ -38,6 +42,7 @@ export type WidgetConfig = {
|
|
|
38
42
|
allowedTokensList?: string[]; // assetIDs
|
|
39
43
|
allowedSourceTokensList?: string[];
|
|
40
44
|
allowedTargetTokensList?: string[];
|
|
45
|
+
priorityAssets?: PriorityAssets;
|
|
41
46
|
filterTokens: (token: Token) => boolean;
|
|
42
47
|
|
|
43
48
|
// Chains filtering
|
|
@@ -45,6 +50,9 @@ export type WidgetConfig = {
|
|
|
45
50
|
allowedChainsList?: Chains[];
|
|
46
51
|
allowedSourceChainsList?: Chains[];
|
|
47
52
|
allowedTargetChainsList?: Chains[];
|
|
53
|
+
topChainShortcuts?: (
|
|
54
|
+
intentsAccountType?: IntentsAccountType,
|
|
55
|
+
) => [Chains, Chains, Chains, Chains];
|
|
48
56
|
chainsFilter: {
|
|
49
57
|
source: ChainsFilter;
|
|
50
58
|
target: ChainsFilter;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type LocalisationKeys =
|
|
2
2
|
// chain
|
|
3
3
|
| 'chain.all.label'
|
|
4
|
+
| 'chain.more.label'
|
|
4
5
|
// wallet
|
|
5
6
|
| 'wallet.recipient.placeholder'
|
|
6
7
|
| 'wallet.recipient.info.selectToken'
|
|
@@ -14,9 +15,16 @@ export type LocalisationKeys =
|
|
|
14
15
|
| 'wallet.recipient.message.receiveFunds'
|
|
15
16
|
| 'wallet.connected.error.notSupportedChain'
|
|
16
17
|
// transfer
|
|
17
|
-
| 'transfer.success.title'
|
|
18
|
-
| 'transfer.success.
|
|
19
|
-
| 'transfer.success.
|
|
18
|
+
| 'transfer.success.swap.title'
|
|
19
|
+
| 'transfer.success.withdrawal.title'
|
|
20
|
+
| 'transfer.success.deposit.title'
|
|
21
|
+
| 'transfer.success.details.label'
|
|
22
|
+
| 'transfer.success.details.hash'
|
|
23
|
+
| 'transfer.success.details.rate'
|
|
24
|
+
| 'transfer.success.details.intent'
|
|
25
|
+
| 'transfer.success.details.recipient'
|
|
26
|
+
| 'transfer.success.action.viewOnExplorer'
|
|
27
|
+
| 'transfer.success.action.backToSwap'
|
|
20
28
|
// quote
|
|
21
29
|
| 'quote.result.maxSlippage.label'
|
|
22
30
|
| 'quote.result.processingTime.label'
|
package/src/utils/tokens/sort.ts
CHANGED
|
@@ -2,8 +2,73 @@ import { formatUnits } from 'ethers';
|
|
|
2
2
|
|
|
3
3
|
import { getTokenBalanceKey } from '../intents/getTokenBalanceKey';
|
|
4
4
|
import type { Token, TokenBalances } from '@/types/token';
|
|
5
|
+
import type { PriorityAssets } from '@/types/config';
|
|
5
6
|
import type { Chains } from '@/types/chain';
|
|
6
7
|
|
|
8
|
+
const compareByPriority = (
|
|
9
|
+
a: Token,
|
|
10
|
+
b: Token,
|
|
11
|
+
priorityAssets: PriorityAssets,
|
|
12
|
+
): number | null => {
|
|
13
|
+
if (a.isIntent || b.isIntent || priorityAssets.length === 0) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const isPriorityToken = (token: Token): boolean => {
|
|
18
|
+
// by assetId
|
|
19
|
+
if (typeof priorityAssets[0] === 'string') {
|
|
20
|
+
return (priorityAssets as ReadonlyArray<string>).includes(token.assetId);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// by blockchain and symbol
|
|
24
|
+
return (priorityAssets as ReadonlyArray<readonly [Chains, string]>).some(
|
|
25
|
+
([blockchain, symbol]) =>
|
|
26
|
+
token.blockchain === blockchain &&
|
|
27
|
+
token.symbol.toLowerCase() === symbol.toLowerCase(),
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const getPriorityIndex = (token: Token): number => {
|
|
32
|
+
// by assetId
|
|
33
|
+
if (typeof priorityAssets[0] === 'string') {
|
|
34
|
+
return (priorityAssets as ReadonlyArray<string>).indexOf(token.assetId);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// by blockchain and symbol
|
|
38
|
+
return (
|
|
39
|
+
priorityAssets as ReadonlyArray<readonly [Chains, string]>
|
|
40
|
+
).findIndex(
|
|
41
|
+
([blockchain, symbol]) =>
|
|
42
|
+
token.blockchain === blockchain &&
|
|
43
|
+
token.symbol.toLowerCase() === symbol.toLowerCase(),
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const aIsPriority = isPriorityToken(a);
|
|
48
|
+
const bIsPriority = isPriorityToken(b);
|
|
49
|
+
|
|
50
|
+
if (aIsPriority && !bIsPriority) {
|
|
51
|
+
return -1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!aIsPriority && bIsPriority) {
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// If both are priority tokens, maintain their relative order based on the priority list
|
|
59
|
+
if (aIsPriority && bIsPriority) {
|
|
60
|
+
const aIndex = getPriorityIndex(a);
|
|
61
|
+
const bIndex = getPriorityIndex(b);
|
|
62
|
+
|
|
63
|
+
if (aIndex !== bIndex) {
|
|
64
|
+
return aIndex - bIndex;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Return null to indicate no priority difference, continue with other sorting criteria
|
|
69
|
+
return null;
|
|
70
|
+
};
|
|
71
|
+
|
|
7
72
|
const compareWithSearch = (
|
|
8
73
|
a: Token,
|
|
9
74
|
b: Token,
|
|
@@ -73,8 +138,9 @@ const compareWithSearch = (
|
|
|
73
138
|
return a.chainName.toLowerCase().localeCompare(b.chainName.toLowerCase());
|
|
74
139
|
};
|
|
75
140
|
|
|
76
|
-
const
|
|
141
|
+
const sortTokens = (
|
|
77
142
|
walletSupportedChains: ReadonlyArray<Chains>,
|
|
143
|
+
priorityAssets: PriorityAssets,
|
|
78
144
|
usdBalanceA: number | undefined,
|
|
79
145
|
usdBalanceB: number | undefined,
|
|
80
146
|
searchStr: string | undefined,
|
|
@@ -82,42 +148,61 @@ const sortTokensByUsdBalance = (
|
|
|
82
148
|
b: Token,
|
|
83
149
|
): number => {
|
|
84
150
|
const isIntent = a.isIntent || b.isIntent;
|
|
151
|
+
const hasBalanceA = usdBalanceA !== undefined && usdBalanceA > 0;
|
|
152
|
+
const hasBalanceB = usdBalanceB !== undefined && usdBalanceB > 0;
|
|
85
153
|
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
const bSupported = walletSupportedChains.includes(b.blockchain);
|
|
89
|
-
|
|
90
|
-
if (!isIntent && aSupported && !bSupported) {
|
|
154
|
+
// 1. Tokens with balance always come first
|
|
155
|
+
if (hasBalanceA && !hasBalanceB) {
|
|
91
156
|
return -1;
|
|
92
157
|
}
|
|
93
158
|
|
|
94
|
-
if (!
|
|
159
|
+
if (!hasBalanceA && hasBalanceB) {
|
|
95
160
|
return 1;
|
|
96
161
|
}
|
|
97
162
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
163
|
+
// 2. If both have balance, sort by balance amount and other criteria
|
|
164
|
+
if (hasBalanceA && hasBalanceB) {
|
|
165
|
+
// Sort supported chains first
|
|
166
|
+
const aSupported = walletSupportedChains.includes(a.blockchain);
|
|
167
|
+
const bSupported = walletSupportedChains.includes(b.blockchain);
|
|
168
|
+
|
|
169
|
+
if (!isIntent && aSupported && !bSupported) {
|
|
170
|
+
return -1;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (!isIntent && !aSupported && bSupported) {
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Compare non-zero balances
|
|
178
|
+
if (usdBalanceA !== usdBalanceB) {
|
|
179
|
+
return (usdBalanceB ?? 0) - (usdBalanceA ?? 0);
|
|
180
|
+
}
|
|
101
181
|
|
|
102
|
-
|
|
103
|
-
if (!usdBalanceA && !usdBalanceB) {
|
|
182
|
+
// If balances equal, sort by search/name
|
|
104
183
|
return compareWithSearch(a, b, searchStr);
|
|
105
184
|
}
|
|
106
185
|
|
|
107
|
-
|
|
108
|
-
|
|
186
|
+
// 3. Both have no balance - prioritize by asset IDs or blockchain-symbol pairs (only for non-intent tokens)
|
|
187
|
+
const priorityComparison = compareByPriority(a, b, priorityAssets);
|
|
188
|
+
|
|
189
|
+
if (priorityComparison !== null) {
|
|
190
|
+
return priorityComparison;
|
|
109
191
|
}
|
|
110
192
|
|
|
111
|
-
|
|
193
|
+
// 4. For tokens without balance and not in priority list, sort by supported chains
|
|
194
|
+
const aSupported = walletSupportedChains.includes(a.blockchain);
|
|
195
|
+
const bSupported = walletSupportedChains.includes(b.blockchain);
|
|
196
|
+
|
|
197
|
+
if (!isIntent && aSupported && !bSupported) {
|
|
112
198
|
return -1;
|
|
113
199
|
}
|
|
114
200
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return (usdBalanceB ?? 0) - (usdBalanceA ?? 0);
|
|
201
|
+
if (!isIntent && !aSupported && bSupported) {
|
|
202
|
+
return 1;
|
|
118
203
|
}
|
|
119
204
|
|
|
120
|
-
//
|
|
205
|
+
// 5. Finally, sort alphabetically by search/name
|
|
121
206
|
return compareWithSearch(a, b, searchStr);
|
|
122
207
|
};
|
|
123
208
|
|
|
@@ -125,6 +210,7 @@ export const createTokenSorter = (
|
|
|
125
210
|
tokensBalance: TokenBalances,
|
|
126
211
|
walletSupportedChains: ReadonlyArray<Chains>,
|
|
127
212
|
searchStr?: string | undefined,
|
|
213
|
+
priorityAssets: PriorityAssets = [],
|
|
128
214
|
) => {
|
|
129
215
|
return (a: Token, b: Token) => {
|
|
130
216
|
const recordA = tokensBalance[getTokenBalanceKey(a)];
|
|
@@ -145,8 +231,9 @@ export const createTokenSorter = (
|
|
|
145
231
|
|
|
146
232
|
const searchLower = searchStr?.trim().toLowerCase() ?? undefined;
|
|
147
233
|
|
|
148
|
-
return
|
|
234
|
+
return sortTokens(
|
|
149
235
|
walletSupportedChains,
|
|
236
|
+
priorityAssets,
|
|
150
237
|
usdBalanceA,
|
|
151
238
|
usdBalanceB,
|
|
152
239
|
searchLower,
|