Skip to content
Closed
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
19 changes: 17 additions & 2 deletions services/blockchain-service/blockchain-service-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,28 @@ export default class BlockchainServiceBase {
// Guaranteed to be defined for OTP chains
const polling = blockchain.transactionFinalityPollingInterval;
const reminingPollingInterval = blockchain.transactionReminingPollingInterval;
const maxWaitTime = blockchain.transactionFinalityMaxWaitTime || 60_000; // Default 60 seconds

let receipt = initialReceipt;
const startTime = Date.now();

// eslint-disable-next-line no-constant-condition
while (true) {
// Check for timeout
if (Date.now() - startTime >= maxWaitTime) {
throw new Error(
`Timeout: Operation exceeded maximum wait time`
);
}

// 1. Wait until the block containing the tx is at the required depth
while (await web3Instance.eth.getBlockNumber() < receipt.blockNumber + confirmations) {
// Check for timeout during block waiting
if (Date.now() - startTime >= maxWaitTime) {
throw new Error(
`Timeout: Operation exceeded maximum wait time`
);
}
await sleepForMilliseconds(polling);
}

Expand Down Expand Up @@ -361,11 +376,11 @@ export default class BlockchainServiceBase {

// 3. Re-org detected: wait for tx to appear again
const timeoutMs = 60 * 1000; // 1 minute
const startTime = Date.now();
const reorgStartTime = Date.now();
let newReceipt = null;
// eslint-disable-next-line no-await-in-loop
while (!newReceipt) {
if (Date.now() - startTime >= timeoutMs) {
if (Date.now() - reorgStartTime >= timeoutMs) {
throw new Error(
`Timeout: Transaction receipt for ${receipt.transactionHash} not found after 1 minute of re-mining polling.`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,17 @@ export default class NodeBlockchainService extends BlockchainServiceBase {
let previousTxGasPrice;
let simulationSucceeded = false;
let transactionRetried = false;
const startTime = Date.now();
const maxWaitTime = 300_000; // 5 minutes total timeout

while (receipt === undefined) {
// Check for timeout
if (Date.now() - startTime >= maxWaitTime) {
throw new Error(
`Timeout: Operation exceeded maximum wait time`
);
}

try {
const tx = await this.prepareTransaction(
contractInstance,
Expand Down
30 changes: 28 additions & 2 deletions services/node-api-service/implementations/http-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ export default class HttpService {
) {
let retries = 0;
let finality = 0;
const startTime = Date.now();
const maxTotalTime = 300_000; // 5 minutes total timeout

const axios_config = {
method: 'get',
Expand All @@ -185,9 +187,16 @@ export default class HttpService {
};

do {
// Check for total timeout
if (Date.now() - startTime >= maxTotalTime) {
throw Error(
`Timeout: Operation exceeded maximum wait time`
);
}

if (retries > maxNumberOfRetries) {
throw Error(
`Unable to achieve required confirmations. Max number of retries (${maxNumberOfRetries}) reached.`,
`Unable to achieve required confirmations. Max number of retries (${maxNumberOfRetries}) reached. Last finality: ${finality}, Required: ${requiredConfirmations}`,
);
}

Expand All @@ -201,7 +210,10 @@ export default class HttpService {
const response = await axios(axios_config);
finality = response.data.finality || 0;
} catch (e) {
finality = 0;
// Don't reset finality to 0 on network errors, keep the last known value
// Only reset if we get a successful response with 0 finality
console.warn(`Warning: Network error during finality check for ${ual}: ${e.message}`);
// Don't increment finality, keep the last known value
}
} while (finality < requiredConfirmations && retries <= maxNumberOfRetries);

Expand All @@ -221,13 +233,27 @@ export default class HttpService {
status: OPERATION_STATUSES.PENDING,
};
let retries = 0;
const startTime = Date.now();
const maxTotalTime = 300_000; // 5 minutes total timeout

const axios_config = {
method: 'get',
url: `${this.getBaseUrl(endpoint, port)}/${operation}/${operationId}`,
headers: this.prepareRequestConfig(authToken),
};
do {
// Check for total timeout
if (Date.now() - startTime >= maxTotalTime) {
response.data = {
...response.data,
data: {
errorType: 'DKG_CLIENT_ERROR',
errorMessage: `Timeout: Operation exceeded maximum wait time`,
},
};
break;
}

if (retries > maxNumberOfRetries) {
response.data = {
...response.data,
Expand Down