@qso-soft/shared
Version:
Shared library for QSO-soft
185 lines • 8.63 kB
JavaScript
import { AxiosError } from 'axios';
import { CRITICAL_ERRORS_MAP, NFT_HOLDING_ERROR, PASSED_ERROR_MAP, SUCCESS_MESSAGES_TO_STOP_WALLET, WARNING_ERRORS_MAP, } from '../../constants';
import { runAutoGas } from '../../managers';
import { getClientByNetwork } from '../clients';
import { waitGas } from '../gas';
import { updateSavedModulesCount } from '../modules/save-modules';
import { checkMultipleOf, createRandomProxyAgent, sleep, sleepByRange } from '../utils';
const DEFAULT_ERROR_MSG = 'Execution was not done successfully';
export const transactionWorker = async (props) => {
const { startLogMessage = 'Processing transaction', wallet, logger, baseNetwork, count: countTxRange, delay, transactionCallback, projectName, moduleIndex, proxyAgent, proxyObject, } = props;
if (countTxRange > 1) {
logger.success(`Total number of transactions for [${logger.meta.moduleName}] module: [${countTxRange}]`, {
action: 'transactionWorker',
});
}
const transactionsDelayRange = delay || QsoGlobal.settings.delay.betweenTransactions;
let currentProxyAgent = proxyAgent;
let currentProxyObject = proxyObject;
const currentNetwork = props.network ? props.network : baseNetwork;
const client = getClientByNetwork(currentNetwork, wallet.privKey, props.logger);
let workerResponse = {
status: 'success',
logTemplate: {},
};
for (let txIndex = 0; txIndex < countTxRange; txIndex++) {
let attempts = QsoGlobal.settings.txAttempts;
const logTemplate = {
txId: txIndex + 1,
action: 'transactionWorker',
status: 'in progress',
};
workerResponse = {
...workerResponse,
logTemplate,
};
while (attempts > 0) {
try {
logger.info(startLogMessage, logTemplate);
await waitGas({
logger,
maxGas: props.maxGas,
wallet,
sleepSeconds: 30,
});
const modulesWithoutAutogas = ['binance-withdraw', 'okx-withdraw'];
const moduleName = props.moduleName;
const shouldRunAutoGas = !modulesWithoutAutogas.includes(moduleName);
if (shouldRunAutoGas) {
await runAutoGas({
network: currentNetwork,
client,
wallet,
logger,
});
}
const response = await transactionCallback({
...props,
proxyAgent: currentProxyAgent,
proxyObject: currentProxyObject,
client,
});
workerResponse = {
...workerResponse,
status: response.status,
};
if (response.txHash && response.explorerLink) {
const txScanUrl = `${response.explorerLink}/tx/${response.txHash}`;
logger.success(`Check your transaction - ${txScanUrl}`, logTemplate);
updateSavedModulesCount({
wallet,
moduleIndex,
projectName,
});
}
if (response.status === 'success' || response.status === 'passed') {
const logMessage = response.message || 'Execution was done successfully';
logger.success(logMessage, logTemplate);
updateSavedModulesCount({
wallet,
moduleIndex,
projectName,
});
}
if (response.status === 'warning' || response.status === 'critical') {
return {
...workerResponse,
message: response.message || DEFAULT_ERROR_MSG,
};
}
if (response.status === 'error') {
throw new Error(response.message || DEFAULT_ERROR_MSG);
}
if (txIndex !== countTxRange) {
await sleepByRange(transactionsDelayRange, logTemplate, logger);
}
break;
}
catch (e) {
const error = e;
let errorMessage = error.message;
if (e instanceof AxiosError) {
errorMessage = e.response?.data.msg || e.response?.data.message || errorMessage;
}
const successMessage = SUCCESS_MESSAGES_TO_STOP_WALLET.find((error) => errorMessage.includes(error));
const isNftHoldingError = errorMessage.includes(NFT_HOLDING_ERROR);
if (errorMessage.includes('execution reverted') && !isNftHoldingError) {
errorMessage = 'Unable to execute transaction for unknown reason';
}
if (successMessage) {
throw new Error(errorMessage);
}
for (const [originalMessage, customMessage] of Object.entries(CRITICAL_ERRORS_MAP)) {
if (errorMessage.includes(originalMessage)) {
return {
...workerResponse,
status: 'critical',
message: customMessage,
};
}
}
attempts--;
for (const [originalMessage, customMessage] of Object.entries(WARNING_ERRORS_MAP)) {
if (errorMessage.includes(originalMessage)) {
if (!props.stopWalletOnError) {
updateSavedModulesCount({
wallet,
moduleIndex,
projectName,
setZeroCount: true,
});
}
return {
...workerResponse,
status: 'warning',
message: customMessage,
};
}
}
for (const [originalMessage, customMessage] of Object.entries(PASSED_ERROR_MAP)) {
if (errorMessage.includes(originalMessage)) {
updateSavedModulesCount({
wallet,
moduleIndex,
projectName,
setZeroCount: true,
});
logger.success(customMessage, {
...logTemplate,
status: 'succeeded',
});
return {
...workerResponse,
status: 'passed',
};
}
}
if (attempts > 0) {
logger.warning(`${errorMessage}. ${attempts} attempts left`, logTemplate);
await sleep(QsoGlobal.settings.delay.betweenRetries, logTemplate, logger);
const attemptsToChangeProxy = QsoGlobal.settings.txAttemptsToChangeProxy;
const currentRetryCount = QsoGlobal.settings.txAttempts - attempts;
const shouldUpdateProxy = checkMultipleOf(attemptsToChangeProxy, currentRetryCount);
if (QsoGlobal.settings.useProxy && shouldUpdateProxy) {
const newProxyData = await createRandomProxyAgent(logger);
if (newProxyData) {
const { proxyAgent: newProxyAgent, ...newProxyObject } = newProxyData;
currentProxyAgent = newProxyAgent || proxyAgent;
currentProxyObject = newProxyObject || proxyObject;
}
}
}
else {
logger.warning(`The attempts are over. ${attempts} attempts left`, logTemplate);
return {
...workerResponse,
status: 'error',
message: errorMessage,
};
}
}
}
}
return workerResponse;
};
//# sourceMappingURL=transaction-worker.js.map