Skip to content

Commit

Permalink
Add support for cancelling smart account transactions (#374)
Browse files Browse the repository at this point in the history
* Add support for cancelling smart account transactions

* Update

* Update
  • Loading branch information
adam-maj authored Jan 12, 2024
1 parent a699049 commit 0cb0da0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 82 deletions.
6 changes: 0 additions & 6 deletions src/server/routes/transaction/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,9 @@ export async function cancelTransaction(fastify: FastifyInstance) {
},
handler: async (request, reply) => {
const { queueId } = request.body;
const walletAddress = request.headers[
"x-backend-wallet-address"
] as string;
const accountAddress = request.headers["x-account-address"] as string;

const { message, transactionHash } = await cancelTransactionAndUpdate({
queueId,
walletAddress,
accountAddress,
});

return reply.status(StatusCodes.OK).send({
Expand Down
184 changes: 108 additions & 76 deletions src/server/utils/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,10 @@ import { TransactionStatusEnum } from "../schemas/transaction";

interface CancelTransactionAndUpdateParams {
queueId: string;
walletAddress: string;
accountAddress: string;
}

export const cancelTransactionAndUpdate = async ({
queueId,
walletAddress,
accountAddress,
}: CancelTransactionAndUpdateParams) => {
const txData = await getTxById({ queueId });
if (!txData) {
Expand All @@ -26,87 +22,123 @@ export const cancelTransactionAndUpdate = async ({
};
}

let message = "";
let error = null;
let transferTransactionResult: TransactionResponse | null = null;

let message = "";

switch (txData.status) {
case TransactionStatusEnum.Errored:
error = createCustomError(
`Cannot cancel errored transaction with queueId ${queueId}. Error: ${txData.errorMessage}`,
StatusCodes.BAD_REQUEST,
"TransactionErrored",
);
break;
case TransactionStatusEnum.Cancelled:
error = createCustomError(
`Transaction already cancelled with queueId ${queueId}`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadyCancelled",
);
break;
case TransactionStatusEnum.Queued:
await updateTx({
queueId,
data: {
status: TransactionStatusEnum.Cancelled,
},
});
message = "Transaction cancelled on-database successfully.";
break;
case TransactionStatusEnum.Mined:
error = createCustomError(
`Transaction already mined with queueId ${queueId}`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadyMined",
);
break;
case TransactionStatusEnum.Processed:
case TransactionStatusEnum.Submitted: {
const sdk = await getSdk({
chainId: parseInt(txData.chainId!),
walletAddress: txData.fromAddress!,
accountAddress,
});
if (txData.signerAddress && txData.accountAddress) {
switch (txData.status) {
case TransactionStatusEnum.Errored:
throw createCustomError(
`Cannot cancel user operation because it already errored`,
StatusCodes.BAD_REQUEST,
"TransactionErrored",
);
case TransactionStatusEnum.Cancelled:
throw createCustomError(
`User operation was already cancelled`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadyCancelled",
);
case TransactionStatusEnum.Mined:
throw createCustomError(
`Cannot cancel user operation because it was already mined`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadyMined",
);
case TransactionStatusEnum.Submitted:
case TransactionStatusEnum.Processed:
throw createCustomError(
`Cannot cancel user operation because it was already processed.`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadySubmitted",
);
case TransactionStatusEnum.Queued:
await updateTx({
queueId,
data: {
status: TransactionStatusEnum.Cancelled,
},
});
message = "Transaction cancelled on-database successfully.";
break;
}
} else {
switch (txData.status) {
case TransactionStatusEnum.Errored:
error = createCustomError(
`Cannot cancel errored transaction with queueId ${queueId}. Error: ${txData.errorMessage}`,
StatusCodes.BAD_REQUEST,
"TransactionErrored",
);
break;
case TransactionStatusEnum.Cancelled:
error = createCustomError(
`Transaction already cancelled with queueId ${queueId}`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadyCancelled",
);
break;
case TransactionStatusEnum.Queued:
await updateTx({
queueId,
data: {
status: TransactionStatusEnum.Cancelled,
},
});
message = "Transaction cancelled on-database successfully.";
break;
case TransactionStatusEnum.Mined:
error = createCustomError(
`Transaction already mined with queueId ${queueId}`,
StatusCodes.BAD_REQUEST,
"TransactionAlreadyMined",
);
break;
case TransactionStatusEnum.Processed:
case TransactionStatusEnum.Submitted: {
const sdk = await getSdk({
chainId: parseInt(txData.chainId!),
walletAddress: txData.fromAddress!,
});

const txReceipt = await sdk
.getProvider()
.getTransactionReceipt(txData.transactionHash!);
const txReceipt = await sdk
.getProvider()
.getTransactionReceipt(txData.transactionHash!);

if (txReceipt) {
message =
"Transaction already mined. Cannot cancel transaction on-chain.";
break;
}
if (txReceipt) {
message =
"Transaction already mined. Cannot cancel transaction on-chain.";
break;
}

const gasOverrides = await getDefaultGasOverrides(sdk.getProvider());
transferTransactionResult = await sdk.wallet.sendRawTransaction({
to: txData.fromAddress!,
from: txData.fromAddress!,
data: "0x",
value: "0x00",
nonce: txData.nonce!,
...gasOverrides,
maxFeePerGas: BigNumber.from(gasOverrides.maxFeePerGas).mul(2),
maxPriorityFeePerGas: BigNumber.from(
gasOverrides.maxPriorityFeePerGas,
).mul(2),
});
const gasOverrides = await getDefaultGasOverrides(sdk.getProvider());
transferTransactionResult = await sdk.wallet.sendRawTransaction({
to: txData.fromAddress!,
from: txData.fromAddress!,
data: "0x",
value: "0x00",
nonce: txData.nonce!,
...gasOverrides,
maxFeePerGas: BigNumber.from(gasOverrides.maxFeePerGas).mul(2),
maxPriorityFeePerGas: BigNumber.from(
gasOverrides.maxPriorityFeePerGas,
).mul(2),
});

message = "Cancellation Transaction sent on chain successfully.";
message = "Cancellation Transaction sent on chain successfully.";

await updateTx({
queueId,
data: {
status: TransactionStatusEnum.Cancelled,
},
});
break;
await updateTx({
queueId,
data: {
status: TransactionStatusEnum.Cancelled,
},
});
break;
}
default:
break;
}

default:
break;
}

if (error) {
Expand Down

0 comments on commit 0cb0da0

Please sign in to comment.