Skip to content

Commit

Permalink
feat: handle failed transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
JackHamer09 committed Feb 29, 2024
1 parent df1b6ea commit d974f2f
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 9 deletions.
66 changes: 63 additions & 3 deletions components/animations/TransactionProgress.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<template>
<div
class="transaction-progress-animation"
:class="{ 'transaction-completed': state === 'completed', 'stopped-in-the-end': state === 'stopped-in-the-end' }"
:class="{
'transaction-completed': state === 'completed',
'transaction-failed': state === 'failed',
'stopped-in-the-end': state === 'stopped-in-the-end',
}"
>
<div class="no-overflow-container">
<div class="lines-inner">
Expand All @@ -19,16 +23,19 @@
<div class="check-icon">
<CheckIcon aria-hidden="true" />
</div>
<div class="fail-icon">
<XMarkIcon aria-hidden="true" />
</div>
</div>
</div>
</template>

<script lang="ts" setup>
import { CheckIcon } from "@heroicons/vue/24/outline";
import { CheckIcon, XMarkIcon } from "@heroicons/vue/24/outline";
import type { PropType } from "vue";
export type AnimationState = "playing" | "stopped-in-the-end" | "completed";
export type AnimationState = "playing" | "stopped-in-the-end" | "failed" | "completed";
defineProps({
state: {
Expand Down Expand Up @@ -66,6 +73,19 @@ defineProps({
}
}
}
&.transaction-failed {
.no-overflow-container {
.lines-inner {
animation-play-state: paused;
}
.airplane {
@apply opacity-0;
}
.fail-icon {
animation: bounce-in 1s linear forwards;
}
}
}
&.stopped-in-the-end {
&::after {
@apply opacity-0;
Expand Down Expand Up @@ -161,6 +181,46 @@ defineProps({
}
}
}
.fail-icon {
@apply absolute left-1/2 top-1/2 h-9 w-9 origin-top-left transform rounded-full bg-red-400 p-1 text-black opacity-0 transition-opacity;
@keyframes bounce-in {
0% {
transform: scale(0) translate(-50%, -50%);
animation-timing-function: ease-in;
opacity: 0;
}
35% {
transform: scale(1) translate(-50%, -50%);
animation-timing-function: ease-out;
opacity: 1;
}
55% {
transform: scale(1.5) translate(-50%, -50%);
animation-timing-function: ease-in;
}
70% {
transform: scale(1) translate(-50%, -50%);
animation-timing-function: ease-out;
}
80% {
transform: scale(1.24) translate(-50%, -50%);
animation-timing-function: ease-in;
}
90% {
transform: scale(1) translate(-50%, -50%);
animation-timing-function: ease-out;
}
95% {
transform: scale(1.04) translate(-50%, -50%);
animation-timing-function: ease-in;
}
100% {
transform: scale(1) translate(-50%, -50%);
animation-timing-function: ease-out;
opacity: 1;
}
}
}
}
}
</style>
16 changes: 12 additions & 4 deletions components/transaction/TransactionProgress.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@
</div>
</template>

<AnimationsTransactionProgress
:state="animationState ?? (completed ? 'completed' : 'playing')"
class="transaction-animation"
/>
<AnimationsTransactionProgress :state="transactionProgressAnimationState" class="transaction-animation" />

<div v-if="fromExplorerLink || fromTransactionHash" class="info-column bottom-left mt-block-gap-1/2">
<TransactionHashButton :explorer-url="fromExplorerLink" :transaction-hash="fromTransactionHash" />
Expand Down Expand Up @@ -159,6 +156,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
failed: {
type: Boolean,
default: false,
},
animationState: {
type: String as PropType<AnimationState>,
},
Expand All @@ -168,6 +169,13 @@ const isSameAddress = computed(() => props.fromAddress === props.toAddress);
const isSameAddressDifferentDestination = computed(
() => isSameAddress.value && props.fromDestination.label !== props.toDestination.label
);
const transactionProgressAnimationState = computed<AnimationState>(() => {
if (props.animationState) return props.animationState;
if (props.failed) return "failed";
if (props.completed) return "completed";
return "playing";
});
</script>

<style lang="scss" scoped>
Expand Down
15 changes: 13 additions & 2 deletions store/zksync/transactionStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type TransactionInfo = {
toTransactionHash?: string;
expectedCompleteTimestamp?: string;
withdrawalFinalizationAvailable?: boolean;
failed?: boolean;
completed: boolean;
};
};
Expand Down Expand Up @@ -77,7 +78,7 @@ export const useZkSyncTransactionStatusStore = defineStore("zkSyncTransactionSta
}
throw new Error("No L2 transaction hash found");
};
const updateDepositStatus = async (transaction: TransactionInfo) => {
const getDepositStatus = async (transaction: TransactionInfo) => {
const transactionHash = await getDepositL2TransactionHash(transaction.transactionHash);
const transactionReceipt = await providerStore.requestProvider().getTransactionReceipt(transactionHash);
if (!transactionReceipt) return transaction;
Expand All @@ -90,6 +91,12 @@ export const useZkSyncTransactionStatusStore = defineStore("zkSyncTransactionSta
const transactionDetails = await providerStore
.requestProvider()
.getTransactionDetails(transaction.transactionHash);
if (transactionDetails.status === "failed") {
transaction.info.withdrawalFinalizationAvailable = false;
transaction.info.failed = true;
transaction.info.completed = true;
return transaction;
}
if (transactionDetails.status !== "verified") {
return transaction;
}
Expand All @@ -105,13 +112,17 @@ export const useZkSyncTransactionStatusStore = defineStore("zkSyncTransactionSta
const getTransferStatus = async (transaction: TransactionInfo) => {
const transactionReceipt = await providerStore.requestProvider().getTransactionReceipt(transaction.transactionHash);
if (!transactionReceipt) return transaction;
const transactionDetails = await providerStore.requestProvider().getTransactionDetails(transaction.transactionHash);
if (transactionDetails.status === "failed") {
transaction.info.failed = true;
}
transaction.info.completed = true;
return transaction;
};
const waitForCompletion = async (transaction: TransactionInfo) => {
if (transaction.info.completed) return transaction;
if (transaction.type === "deposit") {
transaction = await updateDepositStatus(transaction);
transaction = await getDepositStatus(transaction);
} else if (transaction.type === "withdrawal") {
transaction = await getWithdrawalStatus(transaction);
} else if (transaction.type === "transfer") {
Expand Down
1 change: 1 addition & 0 deletions views/transactions/DepositSubmitted.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
:expected-complete-timestamp="transaction.info.expectedCompleteTimestamp"
:token="transaction!.token"
:completed="transaction.info.completed"
:failed="transaction.info.failed"
/>

<EcosystemBlock v-if="eraNetwork.displaySettings?.showPartnerLinks" class="mt-block-gap" />
Expand Down
1 change: 1 addition & 0 deletions views/transactions/TransferSubmitted.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
:transaction-hash="transaction.transactionHash"
:token="transaction.token"
:completed="transaction.info.completed"
:failed="transaction.info.failed"
/>

<CommonButton as="RouterLink" :to="{ name: 'assets' }" class="mt-block-gap" variant="primary">
Expand Down
1 change: 1 addition & 0 deletions views/transactions/WithdrawalSubmitted.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
:to-explorer-link="finalizeTransactionHash || transaction.info.toTransactionHash ? l1BlockExplorerUrl : undefined"
:token="transaction.token"
:completed="transaction.info.completed"
:failed="transaction.info.failed"
:animation-state="withdrawalFinalizationAvailable ? 'stopped-in-the-end' : undefined"
:expected-complete-timestamp="
withdrawalFinalizationAvailable ? undefined : transaction.info.expectedCompleteTimestamp
Expand Down

0 comments on commit d974f2f

Please sign in to comment.