Skip to content
Open
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/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* This is the main entry point for all type exports
*/

export { TRANSACTION_STATUSES } from './transaction-status.ts';
export type { TransactionStatus } from './transaction-status.ts';
export { isPendingTransactionStatus, TRANSACTION_STATUSES } from './transaction-status.ts';
export type { PendingTransactionStatus, TransactionStatus } from './transaction-status.ts';

export type { Customer } from './customer.ts';

Expand Down
31 changes: 31 additions & 0 deletions src/types/transaction-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,34 @@ export const TRANSACTION_STATUSES = [

/** Union of all valid transaction statuses, pulled from the array above. */
export type TransactionStatus = (typeof TRANSACTION_STATUSES)[number];

/** Union of all pending transaction statuses. */
export type PendingTransactionStatus = Extract<TransactionStatus, `pending_${string}`>;

const PENDING_TRANSACTION_STATUSES: ReadonlySet<TransactionStatus> = new Set([
'pending_anchor',
'pending_user_transfer_start',
'pending_user_transfer_complete',
'pending_external',
'pending_trust',
'pending_user',
'pending_stellar',
]);

/**
* Returns whether a transaction is still in progress.
*
* Pending statuses are:
* - `pending_anchor`
* - `pending_user_transfer_start`
* - `pending_user_transfer_complete`
* - `pending_external`
* - `pending_trust`
* - `pending_user`
* - `pending_stellar`
*/
export function isPendingTransactionStatus(
status: TransactionStatus,
): status is PendingTransactionStatus {
return PENDING_TRANSACTION_STATUSES.has(status);
}
48 changes: 47 additions & 1 deletion tests/types/transaction-status.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { TRANSACTION_STATUSES, type TransactionStatus } from '@/types/index.ts';
import {
isPendingTransactionStatus,
type PendingTransactionStatus,
TRANSACTION_STATUSES,
type TransactionStatus,
} from '@/types/index.ts';

describe('TransactionStatus', () => {
// -- runtime checks on the status array --
Expand Down Expand Up @@ -30,6 +35,47 @@ describe('TransactionStatus', () => {
expect(unique.size).toBe(TRANSACTION_STATUSES.length);
});

it('returns true for every pending or in-progress status', () => {
const pendingStatuses: TransactionStatus[] = [
'pending_anchor',
'pending_user_transfer_start',
'pending_user_transfer_complete',
'pending_external',
'pending_trust',
'pending_user',
'pending_stellar',
];

expect(pendingStatuses.every((status) => isPendingTransactionStatus(status))).toBe(true);
});

it('returns false for every non-pending status', () => {
const nonPendingStatuses: TransactionStatus[] = [
'incomplete',
'completed',
'refunded',
'expired',
'error',
'no_market',
'too_small',
'too_large',
];

expect(nonPendingStatuses.every((status) => !isPendingTransactionStatus(status))).toBe(true);
});

it('narrows to PendingTransactionStatus when the helper returns true', () => {
const status: TransactionStatus = 'pending_anchor';

if (isPendingTransactionStatus(status)) {
const narrowed: PendingTransactionStatus = status;
expect(narrowed).toBe('pending_anchor');
return;
}

throw new Error('expected status to narrow to PendingTransactionStatus');
});

// -- compile-time checks (tsc catches these before tests even run) --

it('accepts every valid status', () => {
Expand Down
Loading