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
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export {
SmartTransactionMinedTx,
SmartTransactionCancellationReason,
SmartTransactionStatuses,
OriginalTransactionStatus,
ClientId,
Feature,
Kind,
Expand Down
24 changes: 24 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,29 @@ export enum ClientId {
Extension = 'extension',
}

export enum OriginalTransactionStatus {
PENDING = 'PENDING',
PENDING_CANCELLED = 'PENDING_CANCELLED',

VALIDATED = 'VALIDATED',
REVERTED = 'REVERTED',
NONCE_TOO_LOW = 'NONCE_TOO_LOW',
CANCELLED = 'CANCELLED',

FAILED = 'FAILED',
FAILED_WOULD_REVERT = 'FAILED_WOULD_REVERT',
FAILED_INSUFFICIENT_FUNDS = 'FAILED_INSUFFICIENT_FUNDS',
FAILED_UNKNOWN = 'FAILED_UNKNOWN',
FAILED_TIMEOUT = 'FAILED_TIMEOUT',
FAILED_GAS_TOO_LOW = 'FAILED_GAS_TOO_LOW',
FAILED_NONCE_TOO_HIGH = 'FAILED_NONCE_TOO_HIGH',

LEAKED_VALIDATED = 'LEAKED_VALIDATED',
LEAKED_REVERTED = 'LEAKED_REVERTED',
CANCELLED_LEAKED_VALIDATED = 'CANCELLED_LEAKED_VALIDATED',
CANCELLED_LEAKED_REVERTED = 'CANCELLED_LEAKED_REVERTED',
}

export const cancellationReasonToStatusMap = {
[SmartTransactionCancellationReason.WOULD_REVERT]:
SmartTransactionStatuses.CANCELLED,
Expand All @@ -93,6 +116,7 @@ export type SmartTransactionsStatus = {
error?: string;
cancellationFeeWei: number;
cancellationReason?: SmartTransactionCancellationReason;
originalTransactionStatus?: OriginalTransactionStatus;
deadlineRatio: number;
minedHash: string;
minedTx: SmartTransactionMinedTx;
Expand Down
89 changes: 89 additions & 0 deletions src/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
APIType,
SmartTransactionStatuses,
SmartTransactionCancellationReason,
OriginalTransactionStatus,
ClientId,
} from './types';
import * as utils from './utils';
Expand Down Expand Up @@ -578,6 +579,41 @@ describe('src/utils.js', () => {
);
});

it('includes originalTransactionStatus in error message when available', () => {
const updateTransactionMock = jest.fn();
const smartTransaction = {
...createSmartTransaction(SmartTransactionStatuses.CANCELLED),
statusMetadata: {
cancellationFeeWei: 0,
deadlineRatio: 0,
minedHash: '',
minedTx: SmartTransactionMinedTx.NOT_MINED,
isSettled: false,
originalTransactionStatus:
OriginalTransactionStatus.FAILED_WOULD_REVERT,
},
};

utils.markRegularTransactionsAsFailed({
smartTransaction,
getRegularTransactions: () => [mockTransaction],
updateTransaction: updateTransactionMock,
});

expect(updateTransactionMock).toHaveBeenCalledWith(
{
...mockTransaction,
status: TransactionStatus.failed,
error: {
name: 'SmartTransactionFailed',
message:
'Smart transaction failed with status: cancelled, originalTransactionStatus: FAILED_WOULD_REVERT',
},
},
'Smart transaction status: cancelled',
);
});

it('throws error if original transaction cannot be found', () => {
const updateTransactionMock = jest.fn();
const getRegularTransactionsMock = jest.fn(() => []);
Expand Down Expand Up @@ -665,4 +701,57 @@ describe('src/utils.js', () => {
);
});
});

describe('getSmartTransactionMetricsProperties', () => {
it('includes stx_original_transaction_status from statusMetadata', () => {
const smartTransaction = {
uuid: 'test-uuid',
status: SmartTransactionStatuses.SUCCESS,
time: Date.now(),
statusMetadata: {
cancellationFeeWei: 0,
deadlineRatio: 0.5,
minedHash: '0xabc',
minedTx: SmartTransactionMinedTx.SUCCESS,
isSettled: true,
duplicated: false,
timedOut: false,
proxied: false,
originalTransactionStatus: OriginalTransactionStatus.VALIDATED,
},
};

const result =
utils.getSmartTransactionMetricsProperties(smartTransaction);

expect(result).toStrictEqual(
expect.objectContaining({
stx_original_transaction_status: OriginalTransactionStatus.VALIDATED,
stx_duplicated: false,
stx_timed_out: false,
stx_proxied: false,
}),
);
});

it('returns undefined for stx_original_transaction_status when not in statusMetadata', () => {
const smartTransaction = {
uuid: 'test-uuid',
status: SmartTransactionStatuses.PENDING,
time: Date.now(),
statusMetadata: {
cancellationFeeWei: 0,
deadlineRatio: 0,
minedHash: '',
minedTx: SmartTransactionMinedTx.NOT_MINED,
isSettled: false,
},
};

const result =
utils.getSmartTransactionMetricsProperties(smartTransaction);

expect(result.stx_original_transaction_status).toBeUndefined();
});
});
});
11 changes: 9 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@
stx_duplicated: smartTransactionStatusMetadata?.duplicated,
stx_timed_out: smartTransactionStatusMetadata?.timedOut,
stx_proxied: smartTransactionStatusMetadata?.proxied,
stx_original_transaction_status:
smartTransactionStatusMetadata?.originalTransactionStatus,
};
};

Expand Down Expand Up @@ -275,7 +277,8 @@
getRegularTransactions: TransactionControllerGetTransactionsAction['handler'];
updateTransaction: TransactionControllerUpdateTransactionAction['handler'];
}) => {
const { transactionId, status, txHashes } = smartTransaction;
const { transactionId, status, statusMetadata, txHashes } = smartTransaction;
const originalTransactionStatus = statusMetadata?.originalTransactionStatus;

const transactionsToFail = getRegularTransactions().filter(
(tx) => (tx.hash && txHashes?.includes(tx.hash)) || tx.id === transactionId,
Expand All @@ -285,6 +288,10 @@
throw new Error('Cannot find regular transaction to mark it as failed');
}

const errorMessage = originalTransactionStatus
? `Smart transaction failed with status: ${status}, originalTransactionStatus: ${originalTransactionStatus}`

Check warning on line 292 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (20.x)

Invalid type "string | undefined" of template literal expression

Check warning on line 292 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (18.x)

Invalid type "string | undefined" of template literal expression
: `Smart transaction failed with status: ${status}`;

Check warning on line 293 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (20.x)

Invalid type "string | undefined" of template literal expression

Check warning on line 293 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (18.x)

Invalid type "string | undefined" of template literal expression

for (const tx of transactionsToFail) {
if (tx.status === TransactionStatus.failed) {
continue; // Already marked as failed.
Expand All @@ -294,13 +301,13 @@
status: TransactionStatus.failed,
error: {
name: 'SmartTransactionFailed',
message: `Smart transaction failed with status: ${status}`,
message: errorMessage,
},
};

updateTransaction(
updatedTransaction,
`Smart transaction status: ${status}`,

Check warning on line 310 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (20.x)

Invalid type "string | undefined" of template literal expression

Check warning on line 310 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (18.x)

Invalid type "string | undefined" of template literal expression
);
}
};
Loading