Skip to content

Commit

Permalink
feat: updated FAQ texts, added timestamp on request items in claim page
Browse files Browse the repository at this point in the history
  • Loading branch information
Tarens2 committed Nov 17, 2023
1 parent 020b498 commit 948e01a
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 41 deletions.
6 changes: 2 additions & 4 deletions features/home/stake-faq/list/how-can-i-unstake-steth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ export const HowCanIUnstakeSteth: FC = () => {
Withdrawals Request and Claim tabs
</a>
</LocalLink>{' '}
to unstake stETH and receive ETH at a 1:1 ratio. Under normal
circumstances, withdrawal period can take anywhere between 1-5 days.
After that, you can claim your ETH using the Claim tab. Also, you can
exchange stETH on{' '}
to unstake stETH and receive ETH at a 1:1 ratio. Also, you can exchange
stETH on{' '}
<OuterLink
href="https://lido.fi/lido-ecosystem?tokens=stETH&categories=Get"
data-matomo={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
import { Tooltip } from '@lidofinance/lido-ui';
import { useWaitingTime } from 'features/withdrawals/hooks/useWaitingTime';
import {
RequestsStatusStyled,
DesktopStatus,
MobileStatusIcon,
RequestInfoIcon,
StatusIcon,
MobileStatus,
} from './styles';
import { forwardRef } from 'react';
import { formatTimestamp } from '../../../utils/format-timestamp';

type RequestItemStatusProps = { status: 'ready' | 'pending' };

export const RequestStatus: React.FC<RequestItemStatusProps> = ({ status }) => {
if (status === 'pending') return <RequestStatusPending />;
return <RequestStatusBody status="ready" />;
type RequestItemStatusProps = {
status: 'ready' | 'pending';
finalizationAt: string | null;
};

const RequestStatusPending: React.FC = () => {
const waitingTime = useWaitingTime('');
return (
<Tooltip title={`Current withdrawal period is ${waitingTime.value}.`}>
<RequestStatusBody status="pending" />
</Tooltip>
);
export const RequestStatus: React.FC<RequestItemStatusProps> = (props) => {
return <RequestStatusBody {...props} />;
};

const RequestStatusBody = forwardRef<
HTMLDivElement,
RequestItemStatusProps & React.ComponentProps<'div'>
>(({ status, ...props }, ref) => {
const statusText = status === 'ready' ? 'Ready to claim' : 'Pending';
>(({ status, finalizationAt, ...props }, ref) => {
let statusText;
let statusTextMobile;

if (status === 'ready') {
statusText = 'Ready';
statusTextMobile = 'Ready';
} else if (finalizationAt) {
statusText = formatTimestamp(finalizationAt);
statusTextMobile = formatTimestamp(finalizationAt, true);
} else {
statusText = 'Pending';
statusTextMobile = 'Pending';
}

return (
<RequestsStatusStyled {...props} ref={ref} $variant={status}>
<StatusIcon $variant={status} />
<DesktopStatus>{statusText}</DesktopStatus>
<MobileStatusIcon $variant={status} />
{status === 'pending' && <RequestInfoIcon />}
<MobileStatus>{statusTextMobile}</MobileStatus>
</RequestsStatusStyled>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ export const RequestItem = forwardRef<HTMLInputElement, RequestItemProps>(
<RequestStyled $disabled={isDisabled}>
<Checkbox
{...props}
// TODO: Update Checkbox props in lido-ui
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
label={label}
disabled={isDisabled}
name={name}
ref={ref}
/>
<RequestStatus status={status.isFinalized ? 'ready' : 'pending'} />
<RequestStatus
status={status.isFinalized ? 'ready' : 'pending'}
finalizationAt={status.finalizationAt}
/>
<LinkStyled href={getNFTUrl(token_id, chainId)}>
<External />
</LinkStyled>
Expand Down
21 changes: 12 additions & 9 deletions features/withdrawals/claim/form/requests-list/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export const RequestsStatusStyled = styled.div<RequestProps>`
margin-right: 8px;
padding: 2px ${({ theme }) => theme.spaceMap.sm}px;
${({ theme }) => theme.mediaQueries.sm} {
padding: 4px;
min-width: 24px;
justify-content: center;
}
Expand Down Expand Up @@ -94,20 +93,24 @@ export const DesktopStatus = styled.span`
}
`;

export const MobileStatusIcon = styled.img.attrs<RequestProps>(
({ $variant }) => ({
alt: $variant,
src: $variant === 'ready' ? RequestReady : RequestPending,
}),
)<RequestProps>`
export const MobileStatus = styled.span`
font-size: 12px;
font-weight: 600;
display: none;
width: 16px;
height: 16px;
${({ theme }) => theme.mediaQueries.sm} {
display: block;
}
`;

export const StatusIcon = styled.img.attrs<RequestProps>(({ $variant }) => ({
alt: $variant,
src: $variant === 'ready' ? RequestReady : RequestPending,
}))<RequestProps>`
display: block;
width: 16px;
height: 16px;
`;

export const RequestInfoIcon = styled.img.attrs({
alt: 'info',
src: RequestInfo,
Expand Down
53 changes: 53 additions & 0 deletions features/withdrawals/hooks/contract/useWithdrawalsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,52 @@ import {
} from 'features/withdrawals/types/request-status';
import { MAX_SHOWN_REQUEST_PER_TYPE } from 'features/withdrawals/withdrawals-constants';
import { STRATEGY_LAZY } from 'utils/swrStrategies';
import { standardFetcher } from 'utils/standardFetcher';
import { dynamics } from 'config';
import { encodeURLQuery } from 'utils/encodeURLQuery';

// import { calcExpectedRequestEth } from 'features/withdrawals/utils/calc-expected-request-eth';

export type WithdrawalRequests = NonNullable<
ReturnType<typeof useWithdrawalRequests>['data']
>;

const getRequestTimeForWQRequestIds = async (ids: string[]) => {
const idsPages = [];
const pageSize = 20;

for (let i = 0; i < ids.length; i += pageSize) {
idsPages.push(ids.slice(i, i + pageSize));
}

const result = [];

for (const page of idsPages) {
const basePath = dynamics.wqAPIBasePath;
const params = encodeURLQuery({ ids: page.toString() });
const queryString = params ? `?${params}` : '';
const url = `${basePath}/v2/request-time${queryString}`;
const requests = (await standardFetcher(url)) as any;

for (const request of requests) {
if (!request || !request.requestInfo) continue;
const modifiedResult = {
id: request.requestInfo.requestId,
finalizationAt: request.requestInfo.finalizationAt,
};

result.push(modifiedResult);

if (idsPages.length > 1) {
// avoid backend spam
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
}

return result;
};

export const useWithdrawalRequests = () => {
const { contractRpc, account, chainId } = useWithdrawalsContract();
// const { data: currentShareRate } = useLidoShareRate();
Expand All @@ -42,6 +81,17 @@ export const useWithdrawalRequests = () => {

const claimableRequests: RequestStatus[] = [];
const pendingRequests: RequestStatusPending[] = [];
const pendingRequestsIds: string[] = [];

requestStatuses.forEach((request, index) => {
if (!request.isFinalized) {
pendingRequestsIds.push(requestIds[index].toString());
}
});

const wqRequests = await getRequestTimeForWQRequestIds(
pendingRequestsIds,
);

let pendingAmountOfStETH = BigNumber.from(0);
let claimableAmountOfStETH = BigNumber.from(0);
Expand All @@ -52,6 +102,7 @@ export const useWithdrawalRequests = () => {
...request,
id,
stringId: id.toString(),
finalizationAt: null,
};

if (request.isFinalized && !request.isClaimed) {
Expand All @@ -60,8 +111,10 @@ export const useWithdrawalRequests = () => {
request.amountOfStETH,
);
} else if (!request.isFinalized) {
const r = wqRequests.find((r) => r.id === id.toString());
pendingRequests.push({
...req,
finalizationAt: r?.finalizationAt,
expectedEth: req.amountOfStETH, // TODO: replace with calcExpectedRequestEth(req, currentShareRate),
});
pendingAmountOfStETH = pendingAmountOfStETH.add(
Expand Down
1 change: 1 addition & 0 deletions features/withdrawals/types/request-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type RequestStatus = {
isClaimed: boolean;
id: BigNumber;
stringId: string;
finalizationAt: string | null;
};

export type RequestStatusClaimable = RequestStatus & {
Expand Down
15 changes: 15 additions & 0 deletions features/withdrawals/utils/format-timestamp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const formatTimestamp = (timestamp: string, short = false): string => {
const diff = new Date(timestamp).getTime() - Date.now();
const hours = Math.ceil(diff / (1000 * 60 * 60));
const h = short ? 'h' : 'hour';

if (hours < 24) {
const plural = hours === 1 || short ? '' : 's';
return `~${hours} ${h}${plural}`;
}

const days = Math.ceil(hours / 24);
const d = short ? 'd' : 'day';
const plural = days === 1 || short ? '' : 's';
return `~${days} ${d}${plural}`;
};
1 change: 1 addition & 0 deletions features/withdrawals/withdrawals-constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const DEFAULT_CLAIM_REQUEST_SELECTED = 80;
export const MAX_SHOWN_REQUEST_PER_TYPE = 1024;

export const WITHDRAWAL_REQUEST_PATH = '/withdrawals/request';
export const WITHDRAWAL_PERIOD_PATH = '/withdrawals/request#withdrawalsPeriod';
export const WITHDRAWAL_CLAIM_PATH = '/withdrawals/claim';

// time that validation function waits for context data to resolve
Expand Down
15 changes: 13 additions & 2 deletions features/withdrawals/withdrawals-faq/list/how-long-to-withdraw.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { NoBr } from '../styles';
import { Accordion } from '@lidofinance/lido-ui';
import { LocalLink } from 'shared/components/local-link';
import { WITHDRAWAL_CLAIM_PATH } from 'features/withdrawals/withdrawals-constants';
import {
WITHDRAWAL_CLAIM_PATH,
WITHDRAWAL_PERIOD_PATH,
WITHDRAWAL_REQUEST_PATH,
} from 'features/withdrawals/withdrawals-constants';

export const HowLongToWithdraw: React.FC = () => {
return (
Expand All @@ -10,7 +14,14 @@ export const HowLongToWithdraw: React.FC = () => {
Under normal circumstances, the stETH/wstETH withdrawal period can take
anywhere between <NoBr>1-5 days</NoBr>. After that, you can claim your
ETH using the&nbsp;
<LocalLink href={WITHDRAWAL_CLAIM_PATH}>Claim&nbsp;tab</LocalLink>.
<LocalLink href={WITHDRAWAL_CLAIM_PATH}>Claim&nbsp;tab</LocalLink>. On{' '}
<LocalLink href={WITHDRAWAL_REQUEST_PATH}>
Request&nbsp;tabtab
</LocalLink>{' '}
interface, you can see the current estimation of the withdrawal waiting
time for new requests. The withdrawal request time depends on the
requested amount, the overall amount of stETH in the queue, and{' '}
<LocalLink href={WITHDRAWAL_PERIOD_PATH}>other&nbsp;factors</LocalLink>.
</p>
</Accordion>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Accordion } from '@lidofinance/lido-ui';
import { WITHDRAWAL_PERIOD_PATH } from '../../withdrawals-constants';
import { LocalLink } from '../../../../shared/components/local-link';

export const WhyWaitingTimeChanged: React.FC = () => {
return (
<Accordion summary="Why my waiting time changed after I submitted the withdrawal request?">
<p>
The waiting time could be changed due to{' '}
<LocalLink href={WITHDRAWAL_PERIOD_PATH}>
several&nbsp;factors
</LocalLink>
affecting waiting time. That&apos;s why it may either increase or
decrease.
</p>
</Accordion>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ export const WithdrawalPeriodCircumstances: React.FC = () => {
id="withdrawalsPeriod"
>
<ul>
<li>Demand for staking and unstaking.</li>
<li>The amount of stETH in the queue.</li>
<li>Perfomance of the validator poolside.</li>
<li>Protocols rules of finalization of requests.</li>
<li>Exit queue on the Beacon chain.</li>
<li>Demand for staking and unstaking.</li>
<li>Performance of the validator poolside.</li>
<li>
The protocol mode (Turbo mode [link to &quot;What is Turbo mode&quot;]
or Bunker mode [link to &quot;What is Bunker mode?&quot;)
</li>
</ul>
</Accordion>
);
Expand Down
2 changes: 2 additions & 0 deletions features/withdrawals/withdrawals-faq/request-faq.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { UnstakeAmountBoundaries } from './list/unstake-amount-boundaries';
import { LidoNFT } from './list/lido-nft';
import { HowToAddNFT } from './list/add-nft';
import { NFTNotChange } from './list/nft-not-change';
import { WhyWaitingTimeChanged } from './list/why-waiting-time-changed';

// TODO: Replace this link when it will be finalized
// const LEARN_MORE_LINK =
Expand All @@ -44,6 +45,7 @@ export const RequestFaq: React.FC = () => {
<WithdrawalPeriodCircumstances />
<RewardsAfterWithdraw />
<WithdrawalFee />
<WhyWaitingTimeChanged />
<ClaimableAmountDifference title="Why is the claimable amount may differ from my requested amount?" />
<TurboMode />
<BunkerMode />
Expand Down

0 comments on commit 948e01a

Please sign in to comment.