Skip to content

Commit

Permalink
feat: refresh withdrawals ui to add clarity around fees (OTE-276) (#461)
Browse files Browse the repository at this point in the history
* [chore] refresh withdrawals ui to add clarity around fees

* add cctp file i forgot

* add space after comma

* cleanup

* use styled row with gap. rename ExchangeRate style to more descriptive generic RowWithGap

* address comments. add localization, use proper token by address detection

* cleanup

* replace more l8n stuff

* bump l10n package. localize lowest fees highlighted text

* removing unused code

* remove collapsible details and migrate styling

* exclude non mainnet chain

* address comment

* merge conflicts
  • Loading branch information
yogurtandjam authored Apr 26, 2024
1 parent e7c4cd4 commit ad56a5b
Show file tree
Hide file tree
Showing 8 changed files with 10,386 additions and 3,418 deletions.
13,517 changes: 10,238 additions & 3,279 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion public/configs/cctp.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
{
"chainId": "5",
"tokenAddress": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
"name": "Ethereum Goerli"
"name": "Ethereum Goerli",
"isTestnet": true
},
{
"chainId": "43114",
Expand Down
18 changes: 0 additions & 18 deletions src/components/SearchSelectMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import { Popover, TriggerType } from '@/components/Popover';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { WithLabel } from '@/components/WithLabel';

import cctpTokens from '../../public/configs/cctp.json';

type ElementProps = {
asChild?: boolean;
children: ReactNode;
Expand All @@ -36,17 +34,10 @@ type StyleProps = {

export type SearchSelectMenuProps = ElementProps & StyleProps;

type TokenInfo = {
chainId: string;
tokenAddress: string;
name: string;
};

export const SearchSelectMenu = ({
asChild,
children,
className,
disabled,
label,
items,
withSearch = true,
Expand All @@ -62,15 +53,6 @@ export const SearchSelectMenu = ({
ref: searchSelectMenuRef,
});

const cctpChainsById = cctpTokens.reduce((acc, token) => {
// Check if the key for this chainId already exists
if (!acc[token.chainId]) {
acc[token.chainId] = []; // Initialize it with an empty array if not existing
}
acc[token.chainId].push(token); // Push the current token into the corresponding array
return acc;
}, {} as Record<string, TokenInfo[]>);

const Trigger = asChild ? (
children
) : (
Expand Down
11 changes: 11 additions & 0 deletions src/constants/cctp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import cctpTokens from '../../public/configs/cctp.json';

const CCTP_MAINNET_CHAINS = cctpTokens.filter((token) => !token.isTestnet);
const CCTP_MAINNET_CHAINS_NAMES_LOWER_CASE = CCTP_MAINNET_CHAINS.map((token) =>
token.name.toLowerCase()
);

// TODO: make a general capitalize util fn
export const CCTP_MAINNET_CHAIN_NAMES_CAPITALIZED = CCTP_MAINNET_CHAINS_NAMES_LOWER_CASE.map(
(tokenName) => tokenName[0].toUpperCase() + tokenName.slice(1)
);
19 changes: 19 additions & 0 deletions src/constants/tooltips/withdraw.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { type TooltipStrings, TOOLTIP_STRING_KEYS } from '@/constants/localization';

import { CCTP_MAINNET_CHAIN_NAMES_CAPITALIZED } from '../cctp';

export const withdrawTooltips: TooltipStrings = {
'fast-withdraw-fee': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.FAST_WITHDRAW_FEE_TITLE }),
Expand All @@ -13,4 +15,21 @@ export const withdrawTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.WITHDRAW_TYPES_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.WITHDRAW_TYPES_BODY }),
}),
'gas-fees': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.GAS_FEES_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.GAS_FEES_BODY }),
}),
'bridge-fees': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.BRIDGE_FEES_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.BRIDGE_FEES_BODY }),
}),
'lowest-fees': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.LOWEST_FEE_WITHDRAWALS_TITLE }),
body: stringGetter({
key: TOOLTIP_STRING_KEYS.LOWEST_FEE_WITHDRAWALS_BODY,
params: {
LOWEST_FEE_TOKEN_NAMES: CCTP_MAINNET_CHAIN_NAMES_CAPITALIZED.join(', '),
},
}),
}),
} as const;
44 changes: 33 additions & 11 deletions src/views/forms/AccountManagementForms/TokenSelectMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ type ElementProps = {
isExchange?: boolean;
};

const cctpTokensByAddress = cctpTokens.reduce((acc, token) => {
if (!acc[token.tokenAddress]) {
acc[token.tokenAddress] = [];
}
acc[token.tokenAddress].push(token);
return acc;
}, {} as Record<string, TokenInfo[]>);

export const TokenSelectMenu = ({ selectedToken, onSelectToken, isExchange }: ElementProps) => {
const stringGetter = useStringGetter();
const { type, depositOptions, withdrawalOptions, resources } =
Expand All @@ -32,15 +40,6 @@ export const TokenSelectMenu = ({ selectedToken, onSelectToken, isExchange }: El

const tokens =
(type === TransferType.deposit ? depositOptions : withdrawalOptions)?.assets?.toArray() || [];

const cctpTokensByAddress = cctpTokens.reduce((acc, token) => {
if (!acc[token.tokenAddress]) {
acc[token.tokenAddress] = [];
}
acc[token.tokenAddress].push(token);
return acc;
}, {} as Record<string, TokenInfo[]>);

const tokenItems = Object.values(tokens)
.map((token) => ({
value: token.type,
Expand All @@ -50,11 +49,25 @@ export const TokenSelectMenu = ({ selectedToken, onSelectToken, isExchange }: El
selectedToken && onSelectToken(selectedToken);
},
slotBefore: <Styled.Img src={token.iconUrl} alt="" />,
slotAfter: !!cctpTokensByAddress[token.type] && (
<Styled.Text>
{stringGetter({
key: STRING_KEYS.LOWEST_FEES_WITH_USDC,
params: {
LOWEST_FEES_HIGHLIGHT_TEXT: (
<Styled.GreenHighlight>
{stringGetter({ key: STRING_KEYS.LOWEST_FEES_HIGHLIGHT_TEXT })}
</Styled.GreenHighlight>
),
},
})}
</Styled.Text>
),
tag: resources?.tokenResources?.get(token.type)?.symbol,
}))
.filter(
(chain) =>
type === TransferType.deposit || !!cctpTokensByAddress[chain.value] || !CCTPWithdrawalOnly
(token) =>
type === TransferType.deposit || !!cctpTokensByAddress[token.value] || !CCTPWithdrawalOnly
);

return (
Expand Down Expand Up @@ -102,6 +115,15 @@ export const TokenSelectMenu = ({ selectedToken, onSelectToken, isExchange }: El

const Styled: Record<string, AnyStyledComponent> = {};

Styled.Text = styled.div`
font: var(--font-small-regular);
color: var(--color-text-0);
`;

Styled.GreenHighlight = styled.span`
color: var(--color-green);
`;

Styled.AssetRow = styled.div`
${layoutMixins.row}
gap: 0.5rem;
Expand Down
20 changes: 19 additions & 1 deletion src/views/forms/AccountManagementForms/WithdrawForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { Link } from '@/components/Link';
import { OutputType } from '@/components/Output';
import { Tag } from '@/components/Tag';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { WithTooltip } from '@/components/WithTooltip';
import { SourceSelectMenu } from '@/views/forms/AccountManagementForms/SourceSelectMenu';

import { getSubaccount } from '@/state/accountSelectors';
Expand Down Expand Up @@ -437,7 +438,6 @@ export const WithdrawForm = () => {
}),
};
}

return {
errorMessage: undefined,
};
Expand Down Expand Up @@ -472,6 +472,20 @@ export const WithdrawForm = () => {

return (
<Styled.Form onSubmit={onSubmit}>
<Styled.Subheader>
{stringGetter({
key: STRING_KEYS.LOWEST_FEE_WITHDRAWALS,
params: {
LOWEST_FEE_TOKENS_TOOLTIP: (
<WithTooltip tooltip="lowest-fees">
{stringGetter({
key: STRING_KEYS.SELECT_CHAINS,
})}
</WithTooltip>
),
},
})}
</Styled.Subheader>
<Styled.DestinationRow>
<FormInput
type={InputType.Text}
Expand Down Expand Up @@ -535,6 +549,10 @@ export const WithdrawForm = () => {

const Styled: Record<string, AnyStyledComponent> = {};

Styled.Subheader = styled.div`
color: var(--color-text-0);
`;

Styled.Tag = styled(Tag)`
margin-left: 0.5ch;
`;
Expand Down
Loading

0 comments on commit ad56a5b

Please sign in to comment.