Commit 1d156764 authored by tom goriunov's avatar tom goriunov Committed by GitHub

"Claim funds" button for OP bridge (#1335)

* "Claim funds" button for OP bridge + minor adjustments

Fixes #1293

* review env

* fix layout

* rollback preview envs
parent a8c723ca
...@@ -68,6 +68,7 @@ frontend: ...@@ -68,6 +68,7 @@ frontend:
NEXT_PUBLIC_OPTIMISTIC_L2_WITHDRAWAL_URL: https://app.optimism.io/bridge/withdraw NEXT_PUBLIC_OPTIMISTIC_L2_WITHDRAWAL_URL: https://app.optimism.io/bridge/withdraw
NEXT_PUBLIC_L1_BASE_URL: https://blockscout-main.k8s-dev.blockscout.com NEXT_PUBLIC_L1_BASE_URL: https://blockscout-main.k8s-dev.blockscout.com
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62 NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
NEXT_PUBLIC_USE_NEXT_JS_PROXY: true
envFromSecret: envFromSecret:
NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN
SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI
......
...@@ -11,12 +11,15 @@ export type L2WithdrawalsItem = { ...@@ -11,12 +11,15 @@ export type L2WithdrawalsItem = {
'status': string; 'status': string;
} }
export type L2WithdrawalStatus = export const WITHDRAWAL_STATUSES = [
'In challenge period' | 'Waiting for state root',
'Ready for relay' | 'Ready to prove',
'Relayed' | 'In challenge period',
'Waiting for state root' | 'Ready for relay',
'Ready to prove'; 'Relayed',
] as const;
export type L2WithdrawalStatus = typeof WITHDRAWAL_STATUSES[number];
export type L2WithdrawalsResponse = { export type L2WithdrawalsResponse = {
items: Array<L2WithdrawalsItem>; items: Array<L2WithdrawalsItem>;
......
...@@ -2,6 +2,7 @@ import type { AddressParam } from './addressParams'; ...@@ -2,6 +2,7 @@ import type { AddressParam } from './addressParams';
import type { BlockTransactionsResponse } from './block'; import type { BlockTransactionsResponse } from './block';
import type { DecodedInput } from './decodedInput'; import type { DecodedInput } from './decodedInput';
import type { Fee } from './fee'; import type { Fee } from './fee';
import type { L2WithdrawalStatus } from './l2Withdrawals';
import type { TokenInfo } from './token'; import type { TokenInfo } from './token';
import type { TokenTransfer } from './tokenTransfer'; import type { TokenTransfer } from './tokenTransfer';
import type { TxAction } from './txAction'; import type { TxAction } from './txAction';
...@@ -52,6 +53,9 @@ export type Transaction = { ...@@ -52,6 +53,9 @@ export type Transaction = {
l1_gas_price?: string; l1_gas_price?: string;
l1_gas_used?: string; l1_gas_used?: string;
has_error_in_internal_txs: boolean | null; has_error_in_internal_txs: boolean | null;
// optimism fields
op_withdrawal_status?: L2WithdrawalStatus;
op_l1_transaction_hash?: string;
// SUAVE fields // SUAVE fields
execution_node?: AddressParam | null; execution_node?: AddressParam | null;
allowed_peekers?: Array<string>; allowed_peekers?: Array<string>;
......
import { Skeleton } from '@chakra-ui/react'; import { Skeleton, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import VerificationStep from './VerificationStep'; import VerificationStep from './VerificationStep';
...@@ -7,13 +7,16 @@ export interface Props<T extends string> { ...@@ -7,13 +7,16 @@ export interface Props<T extends string> {
step: T; step: T;
steps: Array<T>; steps: Array<T>;
isLoading?: boolean; isLoading?: boolean;
rightSlot?: React.ReactNode;
className?: string;
} }
const VerificationSteps = <T extends string>({ step, steps, isLoading }: Props<T>) => { const VerificationSteps = <T extends string>({ step, steps, isLoading, rightSlot, className }: Props<T>) => {
const currentStepIndex = steps.indexOf(step); const currentStepIndex = steps.indexOf(step);
return ( return (
<Skeleton <Skeleton
className={ className }
isLoaded={ !isLoading } isLoaded={ !isLoading }
display="flex" display="flex"
gap={ 2 } gap={ 2 }
...@@ -21,10 +24,11 @@ const VerificationSteps = <T extends string>({ step, steps, isLoading }: Props<T ...@@ -21,10 +24,11 @@ const VerificationSteps = <T extends string>({ step, steps, isLoading }: Props<T
flexWrap="wrap" flexWrap="wrap"
> >
{ steps.map((step, index) => ( { steps.map((step, index) => (
<VerificationStep step={ step } isLast={ index === steps.length - 1 } isPassed={ index <= currentStepIndex } key={ step }/> <VerificationStep step={ step } isLast={ index === steps.length - 1 && !rightSlot } isPassed={ index <= currentStepIndex } key={ step }/>
)) } )) }
{ rightSlot }
</Skeleton> </Skeleton>
); );
}; };
export default VerificationSteps; export default chakra(VerificationSteps);
...@@ -54,6 +54,7 @@ import TxDetailsFeePerGas from 'ui/tx/details/TxDetailsFeePerGas'; ...@@ -54,6 +54,7 @@ import TxDetailsFeePerGas from 'ui/tx/details/TxDetailsFeePerGas';
import TxDetailsGasPrice from 'ui/tx/details/TxDetailsGasPrice'; import TxDetailsGasPrice from 'ui/tx/details/TxDetailsGasPrice';
import TxDetailsOther from 'ui/tx/details/TxDetailsOther'; import TxDetailsOther from 'ui/tx/details/TxDetailsOther';
import TxDetailsTokenTransfers from 'ui/tx/details/TxDetailsTokenTransfers'; import TxDetailsTokenTransfers from 'ui/tx/details/TxDetailsTokenTransfers';
import TxDetailsWithdrawalStatus from 'ui/tx/details/TxDetailsWithdrawalStatus';
import TxRevertReason from 'ui/tx/details/TxRevertReason'; import TxRevertReason from 'ui/tx/details/TxRevertReason';
import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers'; import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers';
import TxSocketAlert from 'ui/tx/TxSocketAlert'; import TxSocketAlert from 'ui/tx/TxSocketAlert';
...@@ -156,6 +157,10 @@ const TxDetails = () => { ...@@ -156,6 +157,10 @@ const TxDetails = () => {
</Tag> </Tag>
) } ) }
</DetailsInfoItem> </DetailsInfoItem>
<TxDetailsWithdrawalStatus
status={ data.op_withdrawal_status }
l1TxHash={ data.op_l1_transaction_hash }
/>
{ data.zkevm_status && ( { data.zkevm_status && (
<DetailsInfoItem <DetailsInfoItem
title="Confirmation status" title="Confirmation status"
......
import { Button } from '@chakra-ui/react';
import React from 'react';
import type { L2WithdrawalStatus } from 'types/api/l2Withdrawals';
import { WITHDRAWAL_STATUSES } from 'types/api/l2Withdrawals';
import config from 'configs/app';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import VerificationSteps from 'ui/shared/verificationSteps/VerificationSteps';
interface Props {
status: L2WithdrawalStatus | undefined;
l1TxHash: string | undefined;
}
const TxDetailsWithdrawalStatus = ({ status, l1TxHash }: Props) => {
if (!config.features.optimisticRollup.isEnabled) {
return null;
}
if (!status || !WITHDRAWAL_STATUSES.includes(status)) {
return null;
}
const rightSlot = (() => {
if (status === 'Relayed' && l1TxHash) {
return <TxEntityL1 hash={ l1TxHash } truncation="constant"/>;
}
if (status === 'Ready for relay') {
return (
<Button
variant="outline"
size="sm"
as="a"
href="https://app.optimism.io/bridge/withdraw"
target="_blank"
>
Claim funds
</Button>
);
}
return null;
})();
return (
<DetailsInfoItem
title="Withdrawal status"
hint="Detailed status progress of the transaction"
>
<VerificationSteps
steps={ WITHDRAWAL_STATUSES as unknown as Array<L2WithdrawalStatus> }
step={ status }
rightSlot={ rightSlot }
my={ status === 'Ready for relay' ? '-6px' : 0 }
lineHeight={ status === 'Ready for relay' ? 8 : undefined }
/>
</DetailsInfoItem>
);
};
export default React.memo(TxDetailsWithdrawalStatus);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment