Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/transactions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
GenLayerTransaction,
GenLayerRawTransaction,
transactionsStatusNameToNumber,
isDecidedState,
} from "../types/transactions";
import {transactionsConfig} from "../config/transactions";
import {sleep} from "../utils/async";
Expand Down Expand Up @@ -37,11 +38,10 @@ export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClie
throw new Error("Transaction not found");
}
const transactionStatusString = String(transaction.status);
const transactionStatusFinalized = transactionsStatusNameToNumber[TransactionStatus.FINALIZED];
const requestedStatus = transactionsStatusNameToNumber[status];
if (
transactionStatusString === requestedStatus ||
(status === TransactionStatus.ACCEPTED && transactionStatusString === transactionStatusFinalized)
(status === TransactionStatus.ACCEPTED && isDecidedState(transactionStatusString))
) {
let finalTransaction = transaction;
if (client.chain.id === localnet.id) {
Expand Down
15 changes: 15 additions & 0 deletions src/types/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ export const transactionsStatusNameToNumber = {
[TransactionStatus.LEADER_TIMEOUT]: "13",
};

export const DECIDED_STATES = [
TransactionStatus.ACCEPTED,
TransactionStatus.UNDETERMINED,
TransactionStatus.LEADER_TIMEOUT,
TransactionStatus.VALIDATORS_TIMEOUT,
TransactionStatus.CANCELED,
TransactionStatus.FINALIZED
];

export function isDecidedState(status: string): boolean {
return DECIDED_STATES.some(state =>
transactionsStatusNameToNumber[state] === status
);
}

export const transactionResultNumberToName = {
"0": TransactionResult.IDLE,
"1": TransactionResult.AGREE,
Expand Down
142 changes: 142 additions & 0 deletions tests/transactions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { TransactionStatus, DECIDED_STATES, isDecidedState } from "../src/types/transactions";
import { receiptActions } from "../src/transactions/actions";
import { localnet } from "../src/chains/localnet";

const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);

describe("DECIDED_STATES constant", () => {
it("should contain all expected decided states", () => {
const expectedStates = [
TransactionStatus.ACCEPTED,
TransactionStatus.UNDETERMINED,
TransactionStatus.LEADER_TIMEOUT,
TransactionStatus.VALIDATORS_TIMEOUT,
TransactionStatus.CANCELED,
TransactionStatus.FINALIZED
];

expect(DECIDED_STATES).toEqual(expectedStates);
});
});

describe("isDecidedState utility function", () => {
it("should return true for all decided states", () => {
const decidedStatusNumbers = ["5", "6", "13", "12", "8", "7"]; // ACCEPTED, UNDETERMINED, LEADER_TIMEOUT, VALIDATORS_TIMEOUT, CANCELED, FINALIZED

decidedStatusNumbers.forEach(statusNum => {
expect(isDecidedState(statusNum)).toBe(true);
});
});

it("should return false for non-decided states", () => {
const nonDecidedStatusNumbers = ["0", "1", "2", "3", "4", "9", "10", "11"]; // UNINITIALIZED, PENDING, PROPOSING, COMMITTING, REVEALING, APPEAL_REVEALING, APPEAL_COMMITTING, READY_TO_FINALIZE

nonDecidedStatusNumbers.forEach(statusNum => {
expect(isDecidedState(statusNum)).toBe(false);
});
});

it("should return false for invalid statuses", () => {
const invalidStatuses = ["999", "invalid", ""];

invalidStatuses.forEach(status => {
expect(isDecidedState(status)).toBe(false);
});
});
});

describe("waitForTransactionReceipt with DECIDED_STATES", () => {
beforeEach(() => {
mockFetch.mockReset();
});

it("should accept all decided states when waiting for ACCEPTED", async () => {
const decidedStatusNumbers = ["5", "6", "13", "12", "8", "7"]; // All decided states

for (const statusNum of decidedStatusNumbers) {
const mockTransaction = {
hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6",
status: statusNum,
from_address: "0x123",
to_address: "0x456",
value: "0",
gaslimit: "1000000",
nonce: "1",
created_at: "2023-01-01T00:00:00Z",
};

const mockClient = {
chain: localnet,
getTransaction: vi.fn().mockResolvedValue(mockTransaction)
};

const mockPublicClient = {} as any;

const actions = receiptActions(mockClient as any, mockPublicClient);
const result = await actions.waitForTransactionReceipt({
hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" as any,
status: TransactionStatus.ACCEPTED,
});

expect(result).toEqual(mockTransaction);
}
});

it("should not affect waiting for specific non-ACCEPTED statuses", async () => {
const mockTransaction = {
hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6",
status: "7", // FINALIZED
from_address: "0x123",
to_address: "0x456",
value: "0",
gaslimit: "1000000",
nonce: "1",
created_at: "2023-01-01T00:00:00Z",
};

const mockClient = {
chain: localnet,
getTransaction: vi.fn().mockResolvedValue(mockTransaction)
};

const mockPublicClient = {} as any;

const actions = receiptActions(mockClient as any, mockPublicClient);
const result = await actions.waitForTransactionReceipt({
hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" as any,
status: TransactionStatus.FINALIZED,
});

expect(result).toEqual(mockTransaction);
});

it("should maintain backward compatibility", async () => {
const mockTransaction = {
hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6",
status: "5", // ACCEPTED
from_address: "0x123",
to_address: "0x456",
value: "0",
gaslimit: "1000000",
nonce: "1",
created_at: "2023-01-01T00:00:00Z",
};

const mockClient = {
chain: localnet,
getTransaction: vi.fn().mockResolvedValue(mockTransaction)
};

const mockPublicClient = {} as any;

const actions = receiptActions(mockClient as any, mockPublicClient);
const result = await actions.waitForTransactionReceipt({
hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" as any,
status: TransactionStatus.ACCEPTED,
});

expect(result).toEqual(mockTransaction);
});
});