zkverifyjs
Version:
Submit proofs to zkVerify and query proof state with ease using our npm package.
109 lines • 4.02 kB
JavaScript
import { TransactionStatus, ZkVerifyEvents } from "../../enums.js";
import { handleError } from "./errors/index.js";
import { safeEmit } from "../helpers/index.js";
import { initializeTransactionInfo } from "./transactionInfo/index.js";
import { handleFinalized, handleInBlock } from "./handlers/index.js";
/**
* Handles transaction execution, signing, and event handling.
*/
export const handleTransaction = async (api, submitExtrinsic, account, signer, emitter, options, transactionType, batchCount) => {
const transactionInfo = initializeTransactionInfo(transactionType, options, batchCount);
return new Promise((resolve, reject) => {
let unsubscribeFn;
const cancelTransaction = error => {
if (unsubscribeFn) {
try {
unsubscribeFn();
} catch (err) {
console.debug('Error during transaction cleanup:', err);
}
unsubscribeFn = undefined;
}
if (transactionInfo.status !== TransactionStatus.Error) {
transactionInfo.status = TransactionStatus.Error;
try {
const errObj = error instanceof Error ? error : new Error(String(error));
handleError(emitter, api, transactionInfo, errObj, true);
} catch (err) {
reject(err);
return;
}
}
reject(error);
};
const finalizeTransaction = async result => {
if (transactionInfo.status === TransactionStatus.Error) return;
try {
await handleFinalized(api, transactionInfo, result.dispatchError, emitter, transactionType);
if (unsubscribeFn) {
try {
unsubscribeFn();
} catch (err) {
console.debug('Error during transaction cleanup:', err);
}
unsubscribeFn = undefined;
}
resolve(transactionInfo);
} catch (error) {
cancelTransaction(error);
}
};
try {
const unsubscribeResult = performSignAndSend(submitExtrinsic, account, signer ? {
signer,
nonce: options.nonce
} : {
nonce: options.nonce
}, async result => {
if (transactionInfo.status === TransactionStatus.Error) return;
try {
if (result.status.isBroadcast) {
const txHash = result.txHash.toString();
transactionInfo.txHash = txHash;
safeEmit(emitter, ZkVerifyEvents.Broadcast, {
txHash
});
}
if (result.status.isInBlock) {
if (!transactionInfo.txHash) {
transactionInfo.txHash = result.txHash.toString();
}
transactionInfo.blockHash = result.status.asInBlock.toString();
await handleInBlock(api, result.events, transactionInfo, emitter, transactionType);
}
if (result.status.isFinalized) {
await finalizeTransaction(result);
} else if (result.status.isInvalid) {
throw new Error('Transaction is invalid.');
}
} catch (error) {
cancelTransaction(error);
}
});
if (typeof unsubscribeResult === 'function') {
unsubscribeFn = unsubscribeResult;
} else if (unsubscribeResult && typeof unsubscribeResult.then === 'function') {
unsubscribeResult.then(fn => {
if (typeof fn === 'function') {
unsubscribeFn = fn;
}
}).catch(error => {
cancelTransaction(error);
});
}
} catch (error) {
cancelTransaction(error);
}
});
};
/**
* Handles signing and sending transactions.
*/
export function performSignAndSend(submitExtrinsic, account, options, callback) {
if (typeof account === 'string' && options?.signer) {
return submitExtrinsic.signAndSend(account, options, callback);
} else if (typeof account !== 'string') {
return options ? submitExtrinsic.signAndSend(account, options, callback) : submitExtrinsic.signAndSend(account, callback);
}
throw new Error('Unsupported account or signer type.');
}