Skip to content

Commit

Permalink
feat: add transaction error and revert reason (#110)
Browse files Browse the repository at this point in the history
# What ❔

- fetch and store tx error and revert reason;
- return tx error and revert reason via API;
- display tx error on UI;

## Why ❔

- fast way to see what's the reason of transaction failure;

## Checklist

- [+] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [+] Tests for the changes have been added / updated.
- [+] Documentation comments have been added / updated.
  • Loading branch information
Romsters committed Dec 5, 2023
1 parent bb89707 commit 845500d
Show file tree
Hide file tree
Showing 21 changed files with 411 additions and 12 deletions.
50 changes: 50 additions & 0 deletions packages/api/src/api/transaction/transaction.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,56 @@ describe("TransactionController", () => {
},
});
});

it("returns transaction error in errDescription when transaction is failed and transaction error is present", async () => {
jest.spyOn(transactionServiceMock, "findOne").mockResolvedValue({
status: TransactionStatus.Failed,
error: "Error",
revertReason: "Reverted",
} as TransactionDetails);

const response = await controller.getTransactionStatus(transactionHash);
expect(response).toEqual({
status: ResponseStatus.OK,
message: ResponseMessage.OK,
result: {
isError: "1",
errDescription: "Error",
},
});
});

it("returns transaction revert reason in errDescription when transaction is failed and transaction revert reason is present", async () => {
jest
.spyOn(transactionServiceMock, "findOne")
.mockResolvedValue({ status: TransactionStatus.Failed, revertReason: "Reverted" } as TransactionDetails);

const response = await controller.getTransactionStatus(transactionHash);
expect(response).toEqual({
status: ResponseStatus.OK,
message: ResponseMessage.OK,
result: {
isError: "1",
errDescription: "Reverted",
},
});
});

it("returns empty errDescription when transaction is failed and transaction error and revert reason are not present", async () => {
jest
.spyOn(transactionServiceMock, "findOne")
.mockResolvedValue({ status: TransactionStatus.Failed } as TransactionDetails);

const response = await controller.getTransactionStatus(transactionHash);
expect(response).toEqual({
status: ResponseStatus.OK,
message: ResponseMessage.OK,
result: {
isError: "1",
errDescription: "",
},
});
});
});

describe("getTransactionReceiptStatus", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/api/transaction/transaction.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class TransactionController {
message: ResponseMessage.OK,
result: {
isError: hasError ? ResponseStatus.OK : ResponseStatus.NOTOK,
errDescription: "",
errDescription: transaction?.error || transaction?.revertReason || "",
},
};
}
Expand Down
18 changes: 18 additions & 0 deletions packages/api/src/transaction/dtos/transaction.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,22 @@ export class TransactionDto {
examples: ["included", "committed", "proved", "verified", "failed"],
})
public readonly status: TransactionStatus;

@ApiProperty({
type: String,
description: "Transaction error",
example: "Some test error",
examples: ["Some test error", null],
nullable: true,
})
public readonly error?: string;

@ApiProperty({
type: String,
description: "Transaction revert reason",
example: "Some test revert reason",
examples: ["Some test revert reason", null],
nullable: true,
})
public readonly revertReason?: string;
}
6 changes: 6 additions & 0 deletions packages/api/src/transaction/entities/transaction.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ export class Transaction extends BaseEntity {
@OneToMany(() => Transfer, (transfer) => transfer.transaction)
public readonly transfers: Transfer[];

@Column({ nullable: true })
public readonly error?: string;

@Column({ nullable: true })
public readonly revertReason?: string;

public get status(): TransactionStatus {
if (this.receiptStatus === 0) {
return TransactionStatus.Failed;
Expand Down
46 changes: 46 additions & 0 deletions packages/api/test/transaction.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 9,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -282,6 +284,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 8,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa8",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab8",
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -308,6 +312,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 7,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa7",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab7",
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -334,6 +340,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 6,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa6",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -360,6 +368,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 5,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa5",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -386,6 +396,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 4,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa4",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -412,6 +424,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 3,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa3",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -438,6 +452,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -464,6 +480,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -490,6 +508,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -526,6 +546,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 8,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa8",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab8",
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -552,6 +574,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 7,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa7",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab7",
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -578,6 +602,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 6,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa6",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -660,6 +686,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -711,6 +739,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -762,6 +792,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 7,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa7",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab7",
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand All @@ -788,6 +820,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 6,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa6",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -875,6 +909,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 8,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa8",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab8",
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -910,6 +946,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 5,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa5",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -945,6 +983,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 3,
commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa3",
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -980,6 +1020,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -1015,6 +1057,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 9,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down Expand Up @@ -1050,6 +1094,8 @@ describe("TransactionController (e2e)", () => {
blockNumber: 1,
commitTxHash: null,
data: "0x000000000000000000000000000000000000000000000000016345785d8a0000",
error: null,
revertReason: null,
executeTxHash: null,
fee: "0x2386f26fc10000",
from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C",
Expand Down
19 changes: 16 additions & 3 deletions packages/app/src/components/transactions/infoTable/GeneralInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@
/>
</TableBodyColumn>
</tr>
<tr v-if="transaction?.status === 'failed'" class="transaction-table-row">
<TableBodyColumn class="transaction-table-label">
<span class="transaction-info-field-label transaction-reason-label">
{{ t("transactions.table.reason") }}
</span>
<InfoTooltip class="transaction-info-field-tooltip">
{{ t("transactions.table.reasonTooltip") }}
</InfoTooltip>
</TableBodyColumn>
<TableBodyColumn class="transaction-table-value transaction-reason-value">
{{ transaction.error || transaction.revertReason || "" }}
</TableBodyColumn>
</tr>
<tr class="transaction-table-row">
<TableBodyColumn class="transaction-table-label">
<span class="transaction-info-field-label">{{ t("transactions.table.block") }}</span>
Expand Down Expand Up @@ -233,9 +246,6 @@ const tokenTransfers = computed(() => {
<style lang="scss">
.transaction-info-table {
.table-body {
@apply md:overflow-visible;
}
.table-body-col {
@apply py-4;
}
Expand Down Expand Up @@ -285,5 +295,8 @@ const tokenTransfers = computed(() => {
.transaction-status-value {
@apply py-2;
}
.transaction-reason-value {
@apply text-error-600 whitespace-normal;
}
}
</style>
2 changes: 2 additions & 0 deletions packages/app/src/composables/common/Api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ declare namespace Api {
l1BatchNumber: number | null;
isL1BatchSealed: boolean;
status: "included" | "committed" | "proved" | "verified" | "failed";
error: string | null;
revertReason: string | null;
};

type Transfer = {
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/composables/useTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export type TransactionItem = {
status: TransactionStatus;
l1BatchNumber: number | null;
isL1BatchSealed: boolean;
error?: string | null;
revertReason?: string | null;
logs: TransactionLogEntry[];
transfers: TokenTransfer[];
};
Expand Down Expand Up @@ -222,6 +224,8 @@ export function mapTransaction(
status: transaction.status,
l1BatchNumber: transaction.l1BatchNumber,
isL1BatchSealed: transaction.isL1BatchSealed,
error: transaction.error,
revertReason: transaction.revertReason,

logs: logs.map((item) => ({
address: item.address,
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@
"table": {
"status": "Status",
"statusTooltip": "The status of the transaction",
"reason": "Reason",
"reasonTooltip": "The failure reason of the transaction",
"txnHash": "Txn hash",
"transactionHash": "Transaction Hash",
"transactionHashTooltip": "Transaction hash is a unique 66-character identifier that is generated whenever a transaction is executed",
Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/locales/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
},
"table": {
"status": "Статус",
"statusTooltip": "Статус транзакції",
"reason": "Причина",
"reasonTooltip": "Причина невиконання транзакції",
"transactionHash": "Хеш Транзакції",
"nonce": "Нонс",
"created": "Створено",
Expand Down
Loading

0 comments on commit 845500d

Please sign in to comment.