@tonappchain/sdk 0.7.2-alpha-20 → 0.7.2-alpha-22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/adapters/BaseContractOpener.d.ts +2 -2
- package/dist/src/adapters/BaseContractOpener.js +40 -43
- package/dist/src/adapters/RetryableContractOpener.js +17 -14
- package/dist/src/errors/instances.js +8 -4
- package/dist/src/interfaces/IOperationTracker.d.ts +22 -22
- package/dist/src/sdk/Consts.d.ts +6 -3
- package/dist/src/sdk/Consts.js +7 -4
- package/dist/src/sdk/OperationTracker.d.ts +11 -11
- package/dist/src/sdk/OperationTracker.js +33 -82
- package/dist/src/sdk/TacSdk.js +1 -1
- package/dist/src/sdk/Utils.js +9 -7
- package/dist/src/structs/Struct.d.ts +18 -6
- package/dist/src/structs/Struct.js +4 -3
- package/package.json +1 -1
|
@@ -62,9 +62,9 @@ export declare abstract class BaseContractOpener implements ContractOpener {
|
|
|
62
62
|
*/
|
|
63
63
|
private findTransactionByHashType;
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
65
|
+
* Find transaction with retry logic
|
|
66
66
|
*/
|
|
67
|
-
private
|
|
67
|
+
private findTransactionWithRetry;
|
|
68
68
|
/**
|
|
69
69
|
* Track transaction tree and validate all transactions
|
|
70
70
|
*/
|
|
@@ -293,46 +293,31 @@ class BaseContractOpener {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
/**
|
|
296
|
-
*
|
|
296
|
+
* Find transaction with retry logic
|
|
297
297
|
*/
|
|
298
|
-
async
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const firstTx = await this.findTransactionByHashType(address, hash, hashType, broadSearchOpts);
|
|
312
|
-
if (firstTx) {
|
|
313
|
-
this.logger?.debug(`Root transaction found on attempt 1/${attempts}`);
|
|
314
|
-
return firstTx;
|
|
315
|
-
}
|
|
316
|
-
this.logger?.debug(`Root transaction not found yet (attempt 1/${attempts}), retrying in ${Consts_1.DEFAULT_WAIT_FOR_ROOT_TRANSACTION_RETRY_DELAY_MS}ms`);
|
|
317
|
-
await (0, Utils_1.sleep)(Consts_1.DEFAULT_WAIT_FOR_ROOT_TRANSACTION_RETRY_DELAY_MS);
|
|
318
|
-
for (let attempt = 2; attempt <= attempts; attempt++) {
|
|
319
|
-
const info = await this.getAddressInformation(address);
|
|
320
|
-
const currentLt = info.lastTransaction.lt || undefined;
|
|
321
|
-
if (!currentLt || currentLt === seenLt) {
|
|
322
|
-
this.logger?.debug(`Root transaction not found yet (attempt ${attempt}/${attempts}), lastTx unchanged, retrying in ${Consts_1.DEFAULT_WAIT_FOR_ROOT_TRANSACTION_RETRY_DELAY_MS}ms`);
|
|
323
|
-
await (0, Utils_1.sleep)(Consts_1.DEFAULT_WAIT_FOR_ROOT_TRANSACTION_RETRY_DELAY_MS);
|
|
324
|
-
continue;
|
|
298
|
+
async findTransactionWithRetry(address, hash, hashType, opts, depth) {
|
|
299
|
+
const retryDelayMs = opts.retryDelayMs ?? Consts_1.DEFAULT_RETRY_ON_NOT_FOUND_DELAY_MS;
|
|
300
|
+
const maxRetries = opts.retries ?? Consts_1.DEFAULT_RETRY_ON_NOT_FOUND_RETRIES;
|
|
301
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
302
|
+
let errorMsg;
|
|
303
|
+
try {
|
|
304
|
+
const tx = await this.findTransactionByHashType(address, hash, hashType, opts);
|
|
305
|
+
if (tx) {
|
|
306
|
+
return tx;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
errorMsg = error instanceof Error ? error.message : String(error);
|
|
325
311
|
}
|
|
326
|
-
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
312
|
+
const isLastAttempt = attempt >= maxRetries;
|
|
313
|
+
const reason = errorMsg ?? 'not found';
|
|
314
|
+
const retryInfo = isLastAttempt ? '' : `, retrying in ${retryDelayMs}ms`;
|
|
315
|
+
this.logger?.debug(`Transaction not found at depth ${depth} (attempt ${attempt + 1}/${maxRetries + 1}): ${reason}${retryInfo}`);
|
|
316
|
+
if (isLastAttempt) {
|
|
317
|
+
return null;
|
|
331
318
|
}
|
|
332
|
-
|
|
333
|
-
await (0, Utils_1.sleep)(Consts_1.DEFAULT_WAIT_FOR_ROOT_TRANSACTION_RETRY_DELAY_MS);
|
|
319
|
+
await (0, Utils_1.sleep)(retryDelayMs);
|
|
334
320
|
}
|
|
335
|
-
this.logger?.debug(`Root transaction not found after ${attempts} attempts`);
|
|
336
321
|
return null;
|
|
337
322
|
}
|
|
338
323
|
/**
|
|
@@ -343,7 +328,7 @@ class BaseContractOpener {
|
|
|
343
328
|
ignoreOpcodeList: Consts_1.IGNORE_OPCODE,
|
|
344
329
|
limit: Consts_1.DEFAULT_FIND_TX_LIMIT,
|
|
345
330
|
direction: 'both',
|
|
346
|
-
|
|
331
|
+
retryOnNotFound: Consts_1.DEFAULT_RETRY_ON_NOT_FOUND,
|
|
347
332
|
}) {
|
|
348
333
|
const result = await this.trackTransactionTreeWithResult(address, hash, params);
|
|
349
334
|
if (this.logger && typeof result.checkedCount === 'number') {
|
|
@@ -354,7 +339,13 @@ class BaseContractOpener {
|
|
|
354
339
|
const context = reason === 'not_found'
|
|
355
340
|
? ` address=${errorAddress ?? 'unknown'} hashType=${hashType ?? 'unknown'}`
|
|
356
341
|
: '';
|
|
357
|
-
|
|
342
|
+
const message = `${txHash}: reason=${reason} (exitCode=${exitCode}, resultCode=${resultCode})${context}`;
|
|
343
|
+
if (reason === 'not_found') {
|
|
344
|
+
throw new Error(message);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
throw (0, errors_1.txFinalizationError)(message);
|
|
348
|
+
}
|
|
358
349
|
}
|
|
359
350
|
}
|
|
360
351
|
/**
|
|
@@ -365,15 +356,21 @@ class BaseContractOpener {
|
|
|
365
356
|
ignoreOpcodeList: Consts_1.IGNORE_OPCODE,
|
|
366
357
|
limit: Consts_1.DEFAULT_FIND_TX_LIMIT,
|
|
367
358
|
direction: 'both',
|
|
368
|
-
|
|
359
|
+
retryOnNotFound: Consts_1.DEFAULT_RETRY_ON_NOT_FOUND,
|
|
369
360
|
}) {
|
|
370
|
-
const { maxDepth = Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList = Consts_1.IGNORE_OPCODE, limit = Consts_1.DEFAULT_FIND_TX_LIMIT, maxScannedTransactions = Consts_1.DEFAULT_MAX_SCANNED_TRANSACTIONS, direction = 'both',
|
|
361
|
+
const { maxDepth = Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList = Consts_1.IGNORE_OPCODE, limit = Consts_1.DEFAULT_FIND_TX_LIMIT, maxScannedTransactions = Consts_1.DEFAULT_MAX_SCANNED_TRANSACTIONS, direction = 'both', retryOnNotFound = Consts_1.DEFAULT_RETRY_ON_NOT_FOUND, retryDelayMs, retries, } = params;
|
|
371
362
|
const parsedAddress = ton_1.Address.parse(address);
|
|
372
363
|
const normalizedRootHash = (0, Utils_1.normalizeHashToBase64)(hash);
|
|
373
364
|
const visitedSearchKeys = new Set();
|
|
374
365
|
const processedTxHashes = new Set();
|
|
375
366
|
let checkedCount = 0;
|
|
376
|
-
const searchOpts = {
|
|
367
|
+
const searchOpts = {
|
|
368
|
+
limit,
|
|
369
|
+
archival: true,
|
|
370
|
+
maxScannedTransactions,
|
|
371
|
+
retryDelayMs,
|
|
372
|
+
retries,
|
|
373
|
+
};
|
|
377
374
|
const queue = [
|
|
378
375
|
{ address: parsedAddress, hash: normalizedRootHash, depth: 0, hashType: 'unknown' },
|
|
379
376
|
];
|
|
@@ -383,8 +380,8 @@ class BaseContractOpener {
|
|
|
383
380
|
if (visitedSearchKeys.has(visitedKey))
|
|
384
381
|
continue;
|
|
385
382
|
visitedSearchKeys.add(visitedKey);
|
|
386
|
-
const tx =
|
|
387
|
-
? await this.
|
|
383
|
+
const tx = retryOnNotFound
|
|
384
|
+
? await this.findTransactionWithRetry(currentAddress, currentHash, hashType, searchOpts, currentDepth)
|
|
388
385
|
: await this.findTransactionByHashType(currentAddress, currentHash, hashType, searchOpts);
|
|
389
386
|
if (!tx) {
|
|
390
387
|
this.logger?.debug(`Transaction not found for hash: ${currentHash} (address=${currentAddress?.toString()}, hashType=${hashType ?? 'unknown'})`);
|
|
@@ -144,32 +144,35 @@ class RetryableContractOpener {
|
|
|
144
144
|
for (let index = 0; index < this.openerConfigs.length; index++) {
|
|
145
145
|
const config = this.openerConfigs[index];
|
|
146
146
|
const openerLabel = `opener ${index + 1}/${this.openerConfigs.length}`;
|
|
147
|
-
this.logger?.debug(`[RetryableContractOpener] ${operationName}: trying ${openerLabel}
|
|
147
|
+
this.logger?.debug(`[RetryableContractOpener] ${operationName}: trying ${openerLabel}`);
|
|
148
148
|
const result = useRetries
|
|
149
149
|
? await this.tryWithRetries(() => operation(config), config, `${operationName} ${openerLabel}`)
|
|
150
150
|
: await this.trySingleAttempt(() => operation(config));
|
|
151
151
|
if (result.success) {
|
|
152
|
-
this.logger?.debug(`[RetryableContractOpener] ${operationName}: ${openerLabel} succeeded`);
|
|
153
152
|
return { success: true, data: result.data };
|
|
154
153
|
}
|
|
155
154
|
lastError = result.lastError;
|
|
155
|
+
const isTransactionError = lastError instanceof errors_1.TransactionError;
|
|
156
|
+
const isContractExecutionError = !!lastError && this.isContractExecutionError(lastError);
|
|
157
|
+
const shouldStopOnNonTransportError = !!lastError && !!shouldFallbackOnError && !shouldFallbackOnError(lastError);
|
|
156
158
|
if (lastError) {
|
|
157
|
-
|
|
159
|
+
const stopReason = isTransactionError
|
|
160
|
+
? 'TransactionError'
|
|
161
|
+
: isContractExecutionError
|
|
162
|
+
? 'contract execution error'
|
|
163
|
+
: shouldStopOnNonTransportError
|
|
164
|
+
? 'non-transport error'
|
|
165
|
+
: undefined;
|
|
166
|
+
this.logger?.debug(`[RetryableContractOpener] ${operationName}: ${openerLabel} failed${stopReason ? ` (stopping fallback because of ${stopReason})` : ''}: ${lastError.message}`);
|
|
158
167
|
}
|
|
159
|
-
if (
|
|
160
|
-
this.logger?.debug(`[RetryableContractOpener] ${operationName}: stopping fallback because of TransactionError`);
|
|
168
|
+
if (isTransactionError) {
|
|
161
169
|
return { success: false, lastError };
|
|
162
170
|
}
|
|
163
|
-
if (
|
|
164
|
-
this.logger?.debug(`[RetryableContractOpener] ${operationName}: stopping fallback because of contract execution error`);
|
|
171
|
+
if (isContractExecutionError) {
|
|
165
172
|
return { success: false, lastError };
|
|
166
173
|
}
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
if (!shouldFallback) {
|
|
170
|
-
this.logger?.debug(`[RetryableContractOpener] ${operationName}: stopping fallback due to non-transport error`);
|
|
171
|
-
return { success: false, lastError };
|
|
172
|
-
}
|
|
174
|
+
if (shouldStopOnNonTransportError) {
|
|
175
|
+
return { success: false, lastError };
|
|
173
176
|
}
|
|
174
177
|
}
|
|
175
178
|
return { success: false, lastError };
|
|
@@ -196,7 +199,7 @@ class RetryableContractOpener {
|
|
|
196
199
|
return { success: false, lastError };
|
|
197
200
|
}
|
|
198
201
|
if (attempt < config.retries) {
|
|
199
|
-
this.logger?.debug(`[RetryableContractOpener] ${operationContext}: attempt ${attempt + 1}/${config.retries + 1} failed, retrying in ${config.retryDelay}ms`);
|
|
202
|
+
this.logger?.debug(`[RetryableContractOpener] ${operationContext}: attempt ${attempt + 1}/${config.retries + 1} failed (${lastError.message}), retrying in ${config.retryDelay}ms`);
|
|
200
203
|
await sleep(config.retryDelay);
|
|
201
204
|
}
|
|
202
205
|
}
|
|
@@ -37,8 +37,12 @@ function extractEndpoint(message) {
|
|
|
37
37
|
}
|
|
38
38
|
return match[0].replace(/[),.;]+$/, '');
|
|
39
39
|
}
|
|
40
|
-
function extractResponseMessage(data) {
|
|
40
|
+
function extractResponseMessage(data, includeFullTrace) {
|
|
41
41
|
if (typeof data === 'string' && data.length > 0) {
|
|
42
|
+
const isHtml = data.includes('<!doctype html>') || data.includes('<html');
|
|
43
|
+
if (isHtml && !includeFullTrace) {
|
|
44
|
+
return '[HTML response]';
|
|
45
|
+
}
|
|
42
46
|
return data;
|
|
43
47
|
}
|
|
44
48
|
if (!data || typeof data !== 'object') {
|
|
@@ -53,11 +57,11 @@ function extractResponseMessage(data) {
|
|
|
53
57
|
}
|
|
54
58
|
return undefined;
|
|
55
59
|
}
|
|
56
|
-
function buildInnerErrorSummary(inner) {
|
|
60
|
+
function buildInnerErrorSummary(inner, includeFullTrace) {
|
|
57
61
|
if (inner && typeof inner === 'object') {
|
|
58
62
|
const err = inner;
|
|
59
63
|
const parts = [];
|
|
60
|
-
const responseMessage = extractResponseMessage(err.response?.data);
|
|
64
|
+
const responseMessage = extractResponseMessage(err.response?.data, includeFullTrace);
|
|
61
65
|
const httpStatus = [err.httpStatus, err.status, err.response?.status].find((value) => typeof value === 'number');
|
|
62
66
|
const httpMessage = typeof err.innerMessage === 'string' && err.innerMessage.length > 0 ? err.innerMessage : responseMessage;
|
|
63
67
|
if (typeof httpStatus === 'number') {
|
|
@@ -81,7 +85,7 @@ function buildInnerErrorSummary(inner) {
|
|
|
81
85
|
}
|
|
82
86
|
return 'message=unknown error';
|
|
83
87
|
}
|
|
84
|
-
const allEndpointsFailedError = (inner, includeInnerStack = false) => new errors_1.FetchError(`All endpoints failed, last err: ${buildInnerErrorSummary(inner)}`, 117, inner, {
|
|
88
|
+
const allEndpointsFailedError = (inner, includeInnerStack = false) => new errors_1.FetchError(`All endpoints failed, last err: ${buildInnerErrorSummary(inner, includeInnerStack)}`, 117, inner, {
|
|
85
89
|
includeInnerStack,
|
|
86
90
|
});
|
|
87
91
|
exports.allEndpointsFailedError = allEndpointsFailedError;
|
|
@@ -3,55 +3,55 @@ export interface IOperationTracker {
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns the operation type for the given id, optionally waiting according to the provided policy.
|
|
5
5
|
* @param operationId Operation identifier.
|
|
6
|
-
* @param waitOptions Optional waiting and polling settings.
|
|
6
|
+
* @param waitOptions Optional waiting and polling settings. Pass `null` to disable retries and use a single attempt.
|
|
7
7
|
*/
|
|
8
|
-
getOperationType(operationId: string, waitOptions?: WaitOptions<OperationType>): Promise<OperationType>;
|
|
8
|
+
getOperationType(operationId: string, waitOptions?: WaitOptions<OperationType> | null): Promise<OperationType>;
|
|
9
9
|
/**
|
|
10
10
|
* Resolves an operation id for the given transaction linker, optionally waiting until available.
|
|
11
11
|
* @param transactionLinker Reference to originating transaction across chains.
|
|
12
|
-
* @param waitOptions Optional waiting settings.
|
|
12
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
13
13
|
*/
|
|
14
|
-
getOperationId(transactionLinker: TransactionLinker, waitOptions?: WaitOptions<string>): Promise<string>;
|
|
14
|
+
getOperationId(transactionLinker: TransactionLinker, waitOptions?: WaitOptions<string> | null): Promise<string>;
|
|
15
15
|
/**
|
|
16
16
|
* Resolves an operation id by a transaction hash, optionally waiting until available.
|
|
17
17
|
* @param transactionHash Hash of the originating transaction.
|
|
18
|
-
* @param waitOptions Optional waiting settings.
|
|
18
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
19
19
|
*/
|
|
20
|
-
getOperationIdByTransactionHash(transactionHash: string, waitOptions?: WaitOptions<string>): Promise<string>;
|
|
20
|
+
getOperationIdByTransactionHash(transactionHash: string, waitOptions?: WaitOptions<string> | null): Promise<string>;
|
|
21
21
|
/**
|
|
22
22
|
* Resolves operation ids by shard keys for a particular caller, with optional batching and waiting.
|
|
23
23
|
* @param shardsKeys List of shard keys.
|
|
24
24
|
* @param caller Human-readable identifier of the caller (for tracing/limits).
|
|
25
|
-
* @param waitOptions Optional waiting settings.
|
|
25
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
26
26
|
* @param chunkSize Optional batching size for network requests.
|
|
27
27
|
*/
|
|
28
|
-
getOperationIdsByShardsKeys(shardsKeys: string[], caller: string, waitOptions?: WaitOptions<OperationIdsByShardsKey
|
|
28
|
+
getOperationIdsByShardsKeys(shardsKeys: string[], caller: string, waitOptions?: WaitOptions<OperationIdsByShardsKey> | null, chunkSize?: number): Promise<OperationIdsByShardsKey>;
|
|
29
29
|
/**
|
|
30
30
|
* Gets detailed stage profiling for a single operation, optionally waiting until available.
|
|
31
31
|
* @param operationId Operation identifier.
|
|
32
|
-
* @param waitOptions Optional waiting settings.
|
|
32
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
33
33
|
*/
|
|
34
|
-
getStageProfiling(operationId: string, waitOptions?: WaitOptions<ExecutionStages>): Promise<ExecutionStages>;
|
|
34
|
+
getStageProfiling(operationId: string, waitOptions?: WaitOptions<ExecutionStages> | null): Promise<ExecutionStages>;
|
|
35
35
|
/**
|
|
36
36
|
* Gets stage profiling for multiple operations in bulk.
|
|
37
37
|
* @param operationIds Operation identifiers.
|
|
38
|
-
* @param waitOptions Optional waiting settings.
|
|
38
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
39
39
|
* @param chunkSize Optional batching size for requests.
|
|
40
40
|
*/
|
|
41
|
-
getStageProfilings(operationIds: string[], waitOptions?: WaitOptions<ExecutionStagesByOperationId
|
|
41
|
+
getStageProfilings(operationIds: string[], waitOptions?: WaitOptions<ExecutionStagesByOperationId> | null, chunkSize?: number): Promise<ExecutionStagesByOperationId>;
|
|
42
42
|
/**
|
|
43
43
|
* Gets statuses for multiple operations.
|
|
44
44
|
* @param operationIds Operation identifiers.
|
|
45
|
-
* @param waitOptions Optional waiting settings.
|
|
45
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
46
46
|
* @param chunkSize Optional batching size for requests.
|
|
47
47
|
*/
|
|
48
|
-
getOperationStatuses(operationIds: string[], waitOptions?: WaitOptions<StatusInfosByOperationId
|
|
48
|
+
getOperationStatuses(operationIds: string[], waitOptions?: WaitOptions<StatusInfosByOperationId> | null, chunkSize?: number): Promise<StatusInfosByOperationId>;
|
|
49
49
|
/**
|
|
50
50
|
* Gets a single operation status, optionally waiting according to policy.
|
|
51
51
|
* @param operationId Operation identifier.
|
|
52
|
-
* @param waitOptions Optional waiting settings.
|
|
52
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
53
53
|
*/
|
|
54
|
-
getOperationStatus(operationId: string, waitOptions?: WaitOptions<StatusInfo>): Promise<StatusInfo>;
|
|
54
|
+
getOperationStatus(operationId: string, waitOptions?: WaitOptions<StatusInfo> | null): Promise<StatusInfo>;
|
|
55
55
|
/**
|
|
56
56
|
* Returns a simplified status for the provided transaction linker.
|
|
57
57
|
* @param transactionLinker Reference to originating transaction across chains.
|
|
@@ -60,22 +60,22 @@ export interface IOperationTracker {
|
|
|
60
60
|
/**
|
|
61
61
|
* Converts currency using the tracker service, optionally waiting for completion.
|
|
62
62
|
* @param params Conversion parameters.
|
|
63
|
-
* @param waitOptions Optional waiting settings.
|
|
63
|
+
* @param waitOptions Optional waiting settings. Pass `null` to disable retries and use a single attempt.
|
|
64
64
|
*/
|
|
65
|
-
convertCurrency(params: ConvertCurrencyParams, waitOptions?: WaitOptions<ConvertedCurrencyResult>): Promise<ConvertedCurrencyResult>;
|
|
65
|
+
convertCurrency(params: ConvertCurrencyParams, waitOptions?: WaitOptions<ConvertedCurrencyResult> | null): Promise<ConvertedCurrencyResult>;
|
|
66
66
|
/**
|
|
67
67
|
* Simulates execution of a TAC message without broadcasting it, optionally waiting until the result is available.
|
|
68
68
|
* Useful to validate inputs and estimate effects before sending a real transaction.
|
|
69
69
|
* @param params Simulation parameters and context.
|
|
70
|
-
* @param waitOptions Optional waiting settings (polling/timeout policy).
|
|
70
|
+
* @param waitOptions Optional waiting settings (polling/timeout policy). Pass `null` to disable retries and use a single attempt.
|
|
71
71
|
* @returns Promise with detailed simulation result.
|
|
72
72
|
*/
|
|
73
|
-
simulateTACMessage(params: TACSimulationParams, waitOptions?: WaitOptions<TACSimulationResult>): Promise<TACSimulationResult>;
|
|
73
|
+
simulateTACMessage(params: TACSimulationParams, waitOptions?: WaitOptions<TACSimulationResult> | null): Promise<TACSimulationResult>;
|
|
74
74
|
/**
|
|
75
75
|
* Suggests/calculates a TVM executor fee for the provided parameters, optionally waiting for completion.
|
|
76
76
|
* @param params Parameters affecting fee calculation.
|
|
77
|
-
* @param waitOptions Optional waiting settings (polling/timeout policy).
|
|
77
|
+
* @param waitOptions Optional waiting settings (polling/timeout policy). Pass `null` to disable retries and use a single attempt.
|
|
78
78
|
* @returns Promise with suggested fee information.
|
|
79
79
|
*/
|
|
80
|
-
getTVMExecutorFee(params: GetTVMExecutorFeeParams, waitOptions?: WaitOptions<SuggestedTVMExecutorFee>): Promise<SuggestedTVMExecutorFee>;
|
|
80
|
+
getTVMExecutorFee(params: GetTVMExecutorFeeParams, waitOptions?: WaitOptions<SuggestedTVMExecutorFee> | null): Promise<SuggestedTVMExecutorFee>;
|
|
81
81
|
}
|
package/dist/src/sdk/Consts.d.ts
CHANGED
|
@@ -19,12 +19,15 @@ export declare const TON_BURN_ADDRESS = "EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
19
19
|
export declare const DEFAULT_HTTP_CLIENT_TIMEOUT_MS = 30000;
|
|
20
20
|
export declare const DEFAULT_RETRY_MAX_COUNT = 5;
|
|
21
21
|
export declare const DEFAULT_RETRY_DELAY_MS = 1000;
|
|
22
|
+
export declare const DEFAULT_WAIT_TIMEOUT_MS = 300000;
|
|
23
|
+
export declare const DEFAULT_WAIT_MAX_ATTEMPTS = 30;
|
|
24
|
+
export declare const DEFAULT_WAIT_DELAY_MS = 10000;
|
|
22
25
|
export declare const DEFAULT_FIND_TX_LIMIT = 100;
|
|
23
26
|
export declare const DEFAULT_MAX_SCANNED_TRANSACTIONS = 100;
|
|
24
27
|
export declare const DEFAULT_FIND_TX_ARCHIVAL = true;
|
|
25
28
|
export declare const DEFAULT_FIND_TX_MAX_DEPTH = 10;
|
|
26
|
-
export declare const
|
|
27
|
-
export declare const
|
|
28
|
-
export declare const
|
|
29
|
+
export declare const DEFAULT_RETRY_ON_NOT_FOUND = true;
|
|
30
|
+
export declare const DEFAULT_RETRY_ON_NOT_FOUND_RETRIES = 10;
|
|
31
|
+
export declare const DEFAULT_RETRY_ON_NOT_FOUND_DELAY_MS = 5000;
|
|
29
32
|
export declare const IGNORE_MSG_VALUE_1_NANO = 1n;
|
|
30
33
|
export declare const IGNORE_OPCODE: number[];
|
package/dist/src/sdk/Consts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IGNORE_OPCODE = exports.IGNORE_MSG_VALUE_1_NANO = exports.
|
|
3
|
+
exports.IGNORE_OPCODE = exports.IGNORE_MSG_VALUE_1_NANO = exports.DEFAULT_RETRY_ON_NOT_FOUND_DELAY_MS = exports.DEFAULT_RETRY_ON_NOT_FOUND_RETRIES = exports.DEFAULT_RETRY_ON_NOT_FOUND = exports.DEFAULT_FIND_TX_MAX_DEPTH = exports.DEFAULT_FIND_TX_ARCHIVAL = exports.DEFAULT_MAX_SCANNED_TRANSACTIONS = exports.DEFAULT_FIND_TX_LIMIT = exports.DEFAULT_WAIT_DELAY_MS = exports.DEFAULT_WAIT_MAX_ATTEMPTS = exports.DEFAULT_WAIT_TIMEOUT_MS = exports.DEFAULT_RETRY_DELAY_MS = exports.DEFAULT_RETRY_MAX_COUNT = exports.DEFAULT_HTTP_CLIENT_TIMEOUT_MS = exports.TON_BURN_ADDRESS = exports.MINUTE = exports.FIVE_MINUTES = exports.TAC_DECIMALS = exports.TON_DECIMALS = exports.ONE_YEAR_SECONDS = exports.FIFTEEN_MINUTES = exports.TAC_SYMBOL = exports.TON_SYMBOL = exports.MAX_MSG_DEPTH = exports.MAX_HIGHLOAD_GROUP_MSG_NUM = exports.MAX_EXT_MSG_SIZE = exports.SOLIDITY_METHOD_NAME_REGEX = exports.SOLIDITY_SIGNATURE_REGEX = exports.DEFAULT_DELAY = exports.MAX_ITERATION_COUNT = exports.NFT_TRANSFER_FORWARD_TON_AMOUNT = exports.JETTON_TRANSFER_FORWARD_TON_AMOUNT = void 0;
|
|
4
4
|
const ton_1 = require("@ton/ton");
|
|
5
5
|
exports.JETTON_TRANSFER_FORWARD_TON_AMOUNT = (0, ton_1.toNano)(0.2);
|
|
6
6
|
exports.NFT_TRANSFER_FORWARD_TON_AMOUNT = (0, ton_1.toNano)(0.3);
|
|
@@ -23,13 +23,16 @@ exports.TON_BURN_ADDRESS = 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c';
|
|
|
23
23
|
exports.DEFAULT_HTTP_CLIENT_TIMEOUT_MS = 30000;
|
|
24
24
|
exports.DEFAULT_RETRY_MAX_COUNT = 5;
|
|
25
25
|
exports.DEFAULT_RETRY_DELAY_MS = 1000;
|
|
26
|
+
exports.DEFAULT_WAIT_TIMEOUT_MS = 300000; // 5 minutes
|
|
27
|
+
exports.DEFAULT_WAIT_MAX_ATTEMPTS = 30;
|
|
28
|
+
exports.DEFAULT_WAIT_DELAY_MS = 10000; // 10 seconds
|
|
26
29
|
exports.DEFAULT_FIND_TX_LIMIT = 100;
|
|
27
30
|
exports.DEFAULT_MAX_SCANNED_TRANSACTIONS = 100;
|
|
28
31
|
exports.DEFAULT_FIND_TX_ARCHIVAL = true;
|
|
29
32
|
exports.DEFAULT_FIND_TX_MAX_DEPTH = 10;
|
|
30
|
-
exports.
|
|
31
|
-
exports.
|
|
32
|
-
exports.
|
|
33
|
+
exports.DEFAULT_RETRY_ON_NOT_FOUND = true;
|
|
34
|
+
exports.DEFAULT_RETRY_ON_NOT_FOUND_RETRIES = 10;
|
|
35
|
+
exports.DEFAULT_RETRY_ON_NOT_FOUND_DELAY_MS = 5000;
|
|
33
36
|
exports.IGNORE_MSG_VALUE_1_NANO = 1n;
|
|
34
37
|
exports.IGNORE_OPCODE = [
|
|
35
38
|
0xd53276db, // Excess
|
|
@@ -7,16 +7,16 @@ export declare class OperationTracker implements IOperationTracker {
|
|
|
7
7
|
private readonly clients;
|
|
8
8
|
private readonly logger;
|
|
9
9
|
constructor(network: Network, customLiteSequencerEndpoints?: string[], logger?: ILogger, clientFactory?: ILiteSequencerClientFactory);
|
|
10
|
-
getOperationIdByTransactionHash(transactionHash: string, waitOptions?: WaitOptions<string>): Promise<string>;
|
|
11
|
-
getOperationType(operationId: string, waitOptions?: WaitOptions<OperationType>): Promise<OperationType>;
|
|
12
|
-
getOperationId(transactionLinker: TransactionLinker, waitOptions?: WaitOptions<string>): Promise<string>;
|
|
13
|
-
getOperationIdsByShardsKeys(shardsKeys: string[], caller: string, waitOptions?: WaitOptions<OperationIdsByShardsKey
|
|
14
|
-
getStageProfiling(operationId: string, waitOptions?: WaitOptions<ExecutionStages>): Promise<ExecutionStages>;
|
|
15
|
-
getStageProfilings(operationIds: string[], waitOptions?: WaitOptions<ExecutionStagesByOperationId
|
|
16
|
-
getOperationStatuses(operationIds: string[], waitOptions?: WaitOptions<StatusInfosByOperationId
|
|
17
|
-
getOperationStatus(operationId: string, waitOptions?: WaitOptions<StatusInfo>): Promise<StatusInfo>;
|
|
10
|
+
getOperationIdByTransactionHash(transactionHash: string, waitOptions?: WaitOptions<string> | null): Promise<string>;
|
|
11
|
+
getOperationType(operationId: string, waitOptions?: WaitOptions<OperationType> | null): Promise<OperationType>;
|
|
12
|
+
getOperationId(transactionLinker: TransactionLinker, waitOptions?: WaitOptions<string> | null): Promise<string>;
|
|
13
|
+
getOperationIdsByShardsKeys(shardsKeys: string[], caller: string, waitOptions?: WaitOptions<OperationIdsByShardsKey> | null, chunkSize?: number): Promise<OperationIdsByShardsKey>;
|
|
14
|
+
getStageProfiling(operationId: string, waitOptions?: WaitOptions<ExecutionStages> | null): Promise<ExecutionStages>;
|
|
15
|
+
getStageProfilings(operationIds: string[], waitOptions?: WaitOptions<ExecutionStagesByOperationId> | null, chunkSize?: number): Promise<ExecutionStagesByOperationId>;
|
|
16
|
+
getOperationStatuses(operationIds: string[], waitOptions?: WaitOptions<StatusInfosByOperationId> | null, chunkSize?: number): Promise<StatusInfosByOperationId>;
|
|
17
|
+
getOperationStatus(operationId: string, waitOptions?: WaitOptions<StatusInfo> | null): Promise<StatusInfo>;
|
|
18
18
|
getSimplifiedOperationStatus(transactionLinker: TransactionLinker): Promise<SimplifiedStatuses>;
|
|
19
|
-
convertCurrency(params: ConvertCurrencyParams, waitOptions?: WaitOptions<ConvertedCurrencyResult>): Promise<ConvertedCurrencyResult>;
|
|
20
|
-
simulateTACMessage(params: TACSimulationParams, waitOptions?: WaitOptions<TACSimulationResult>): Promise<TACSimulationResult>;
|
|
21
|
-
getTVMExecutorFee(params: GetTVMExecutorFeeParams, waitOptions?: WaitOptions<SuggestedTVMExecutorFee>): Promise<SuggestedTVMExecutorFee>;
|
|
19
|
+
convertCurrency(params: ConvertCurrencyParams, waitOptions?: WaitOptions<ConvertedCurrencyResult> | null): Promise<ConvertedCurrencyResult>;
|
|
20
|
+
simulateTACMessage(params: TACSimulationParams, waitOptions?: WaitOptions<TACSimulationResult> | null): Promise<TACSimulationResult>;
|
|
21
|
+
getTVMExecutorFee(params: GetTVMExecutorFeeParams, waitOptions?: WaitOptions<SuggestedTVMExecutorFee> | null): Promise<SuggestedTVMExecutorFee>;
|
|
22
22
|
}
|
|
@@ -35,96 +35,78 @@ class OperationTracker {
|
|
|
35
35
|
this.logger = logger;
|
|
36
36
|
}
|
|
37
37
|
async getOperationIdByTransactionHash(transactionHash, waitOptions) {
|
|
38
|
-
this.logger.debug(`Getting operation ID for transactionHash: ${(0, Utils_1.formatObjectForLogging)(transactionHash)}`);
|
|
39
38
|
const requestFn = async () => {
|
|
40
39
|
let lastError;
|
|
41
40
|
for (const client of this.clients) {
|
|
42
41
|
try {
|
|
43
42
|
const id = await client.getOperationIdByTransactionHash(transactionHash);
|
|
44
|
-
this.logger.debug(`Operation ID ${id == '' ? 'does not exist' : 'retrieved successfully'}`);
|
|
45
43
|
return id;
|
|
46
44
|
}
|
|
47
45
|
catch (error) {
|
|
48
|
-
this.logger.warn(`Failed to get OperationId by transactionHash using one of the endpoints`);
|
|
49
46
|
lastError = error;
|
|
50
47
|
}
|
|
51
48
|
}
|
|
52
|
-
this.logger.error('All endpoints failed to get operation id by transactionHash');
|
|
53
49
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
54
50
|
};
|
|
55
|
-
return waitOptions
|
|
56
|
-
? await (
|
|
57
|
-
: await requestFn();
|
|
51
|
+
return waitOptions === null
|
|
52
|
+
? await requestFn()
|
|
53
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting operation ID by transaction hash ${(0, Utils_1.formatObjectForLogging)(transactionHash)}`);
|
|
58
54
|
}
|
|
59
55
|
async getOperationType(operationId, waitOptions) {
|
|
60
|
-
this.logger.debug(`Getting operation type for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
61
56
|
const requestFn = async () => {
|
|
62
57
|
let lastError;
|
|
63
58
|
for (const client of this.clients) {
|
|
64
59
|
try {
|
|
65
60
|
const type = await client.getOperationType(operationId);
|
|
66
|
-
this.logger.debug(`Operation retrieved successfully`);
|
|
67
61
|
return type;
|
|
68
62
|
}
|
|
69
63
|
catch (error) {
|
|
70
|
-
this.logger.warn(`Failed to get operationType using one of the endpoints`);
|
|
71
64
|
lastError = error;
|
|
72
65
|
}
|
|
73
66
|
}
|
|
74
|
-
this.logger.error('All endpoints failed to get operation type');
|
|
75
67
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
76
68
|
};
|
|
77
|
-
return waitOptions
|
|
78
|
-
? await (
|
|
79
|
-
: await requestFn();
|
|
69
|
+
return waitOptions === null
|
|
70
|
+
? await requestFn()
|
|
71
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting operation type for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
80
72
|
}
|
|
81
73
|
async getOperationId(transactionLinker, waitOptions) {
|
|
82
|
-
this.logger.debug(`Getting operation ID for transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
83
74
|
const requestFn = async () => {
|
|
84
75
|
let lastError;
|
|
85
76
|
for (const client of this.clients) {
|
|
86
77
|
try {
|
|
87
78
|
const id = await client.getOperationId(transactionLinker);
|
|
88
|
-
this.logger.debug(`Operation ID ${id == '' ? 'does not exist' : 'retrieved successfully'}`);
|
|
89
79
|
return id;
|
|
90
80
|
}
|
|
91
81
|
catch (error) {
|
|
92
|
-
this.logger.warn(`Failed to get OperationId using one of the endpoints`);
|
|
93
82
|
lastError = error;
|
|
94
83
|
}
|
|
95
84
|
}
|
|
96
|
-
this.logger.error('All endpoints failed to get operation id');
|
|
97
85
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
98
86
|
};
|
|
99
|
-
return waitOptions
|
|
100
|
-
? await (
|
|
101
|
-
: await requestFn();
|
|
87
|
+
return waitOptions === null
|
|
88
|
+
? await requestFn()
|
|
89
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting operation ID by transaction linker ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
102
90
|
}
|
|
103
91
|
async getOperationIdsByShardsKeys(shardsKeys, caller, waitOptions, chunkSize = 100) {
|
|
104
|
-
this.logger.debug(`Getting operation IDs for shards keys: ${(0, Utils_1.formatObjectForLogging)(shardsKeys)}`);
|
|
105
|
-
this.logger.debug(`Caller: ${caller}, Chunk size: ${chunkSize}`);
|
|
106
92
|
const requestFn = async () => {
|
|
107
93
|
let lastError;
|
|
108
94
|
for (const client of this.clients) {
|
|
109
95
|
try {
|
|
110
96
|
const result = await client.getOperationIdsByShardsKeys(shardsKeys, caller, chunkSize);
|
|
111
|
-
this.logger.debug(`Operation IDs by shards keys retrieved successfully`);
|
|
112
97
|
return result;
|
|
113
98
|
}
|
|
114
99
|
catch (error) {
|
|
115
|
-
this.logger.warn(`Failed to get OperationIds using one of the endpoints`);
|
|
116
100
|
lastError = error;
|
|
117
101
|
}
|
|
118
102
|
}
|
|
119
|
-
this.logger.error('All endpoints failed to get operation ids by shards keys');
|
|
120
103
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
121
104
|
};
|
|
122
|
-
return waitOptions
|
|
123
|
-
? await (
|
|
124
|
-
: await requestFn();
|
|
105
|
+
return waitOptions === null
|
|
106
|
+
? await requestFn()
|
|
107
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting operation IDs by shards keys ${(0, Utils_1.formatObjectForLogging)(shardsKeys)} caller=${caller} chunkSize=${chunkSize}`);
|
|
125
108
|
}
|
|
126
109
|
async getStageProfiling(operationId, waitOptions) {
|
|
127
|
-
this.logger.debug(`Getting stage profiling for operation ${operationId}`);
|
|
128
110
|
const requestFn = async () => {
|
|
129
111
|
let lastError;
|
|
130
112
|
for (const client of this.clients) {
|
|
@@ -132,72 +114,57 @@ class OperationTracker {
|
|
|
132
114
|
const map = await client.getStageProfilings([operationId]);
|
|
133
115
|
const result = map[operationId];
|
|
134
116
|
if (!result) {
|
|
135
|
-
this.logger.warn(`No stageProfiling data for operationId=${operationId}`);
|
|
136
117
|
throw new Error(`No stageProfiling data for operationId=${operationId}`);
|
|
137
118
|
}
|
|
138
|
-
this.logger.debug(`Stage profiling retrieved successfully`);
|
|
139
119
|
return result;
|
|
140
120
|
}
|
|
141
121
|
catch (error) {
|
|
142
|
-
this.logger.warn(`Failed to get stage profiling using one of the endpoints`);
|
|
143
122
|
lastError = error;
|
|
144
123
|
}
|
|
145
124
|
}
|
|
146
|
-
this.logger.error('All endpoints failed to get stage profiling');
|
|
147
125
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
148
126
|
};
|
|
149
|
-
return waitOptions
|
|
150
|
-
? await (
|
|
151
|
-
: await
|
|
127
|
+
return waitOptions === null
|
|
128
|
+
? await requestFn()
|
|
129
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting stage profiling for operation ${operationId}`);
|
|
152
130
|
}
|
|
153
131
|
async getStageProfilings(operationIds, waitOptions, chunkSize = 100) {
|
|
154
|
-
this.logger.debug(`Getting stage profilings for operations: ${operationIds.join(', ')}`);
|
|
155
|
-
this.logger.debug(`Chunk size: ${chunkSize}`);
|
|
156
132
|
const requestFn = async () => {
|
|
157
133
|
let lastError;
|
|
158
134
|
for (const client of this.clients) {
|
|
159
135
|
try {
|
|
160
136
|
const result = await client.getStageProfilings(operationIds, chunkSize);
|
|
161
|
-
this.logger.debug(`Stage profilings retrieved successfully`);
|
|
162
137
|
return result;
|
|
163
138
|
}
|
|
164
139
|
catch (error) {
|
|
165
|
-
this.logger.warn(`Failed to get stage profilings using one of the endpoints`);
|
|
166
140
|
lastError = error;
|
|
167
141
|
}
|
|
168
142
|
}
|
|
169
|
-
this.logger.error('All endpoints failed to get stage profilings');
|
|
170
143
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
171
144
|
};
|
|
172
|
-
return waitOptions
|
|
173
|
-
? await (
|
|
174
|
-
: await requestFn();
|
|
145
|
+
return waitOptions === null
|
|
146
|
+
? await requestFn()
|
|
147
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting stage profilings for operations: ${operationIds.join(', ')} chunkSize=${chunkSize}`);
|
|
175
148
|
}
|
|
176
149
|
async getOperationStatuses(operationIds, waitOptions, chunkSize = 100) {
|
|
177
|
-
this.logger.debug(`Getting operation statuses for operations: ${(0, Utils_1.formatObjectForLogging)(operationIds)}`);
|
|
178
|
-
this.logger.debug(`Chunk size: ${chunkSize}`);
|
|
179
150
|
const requestFn = async () => {
|
|
180
151
|
let lastError;
|
|
181
152
|
for (const client of this.clients) {
|
|
182
153
|
try {
|
|
183
154
|
const result = await client.getOperationStatuses(operationIds, chunkSize);
|
|
184
|
-
this.logger.debug(`Operation statuses retrieved successfully`);
|
|
185
155
|
return result;
|
|
186
156
|
}
|
|
187
157
|
catch (error) {
|
|
188
|
-
this.logger.warn(`Failed to get operation statuses using one of the endpoints`);
|
|
189
158
|
lastError = error;
|
|
190
159
|
}
|
|
191
160
|
}
|
|
192
|
-
this.logger.error('All endpoints failed to get operation statuses');
|
|
193
161
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
194
162
|
};
|
|
195
|
-
return waitOptions
|
|
196
|
-
? await (
|
|
197
|
-
: await requestFn();
|
|
163
|
+
return waitOptions === null
|
|
164
|
+
? await requestFn()
|
|
165
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting operation statuses for operations: ${(0, Utils_1.formatObjectForLogging)(operationIds)} chunkSize=${chunkSize}`);
|
|
198
166
|
}
|
|
199
167
|
async getOperationStatus(operationId, waitOptions) {
|
|
200
|
-
this.logger.debug(`Getting operation status for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
201
168
|
const requestFn = async () => {
|
|
202
169
|
let lastError;
|
|
203
170
|
for (const client of this.clients) {
|
|
@@ -205,27 +172,23 @@ class OperationTracker {
|
|
|
205
172
|
const map = await client.getOperationStatuses([operationId]);
|
|
206
173
|
const result = map[operationId];
|
|
207
174
|
if (!result) {
|
|
208
|
-
this.logger.warn(`No operation status for operationId=${operationId}`);
|
|
209
175
|
throw new Error(`No operation status for operationId=${operationId}`);
|
|
210
176
|
}
|
|
211
177
|
return result;
|
|
212
178
|
}
|
|
213
179
|
catch (error) {
|
|
214
|
-
this.logger.warn(`Failed to get operation status using one of the endpoints`);
|
|
215
180
|
lastError = error;
|
|
216
181
|
}
|
|
217
182
|
}
|
|
218
|
-
this.logger.error('All endpoints failed to get operation status');
|
|
219
183
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
220
184
|
};
|
|
221
|
-
const status = waitOptions
|
|
222
|
-
? await (
|
|
223
|
-
: await requestFn();
|
|
185
|
+
const status = waitOptions === null
|
|
186
|
+
? await requestFn()
|
|
187
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting operation status for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
224
188
|
this.logger.debug(`operation status resolved stage=${status.stage ?? 'unknown'} success=${(String(status.success))}`);
|
|
225
189
|
return status;
|
|
226
190
|
}
|
|
227
191
|
async getSimplifiedOperationStatus(transactionLinker) {
|
|
228
|
-
this.logger.debug(`Getting simplified operation status for transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
229
192
|
const operationId = await this.getOperationId(transactionLinker);
|
|
230
193
|
if (operationId == '') {
|
|
231
194
|
this.logger.warn('Operation ID not found');
|
|
@@ -244,71 +207,59 @@ class OperationTracker {
|
|
|
244
207
|
if (params.value <= 0n) {
|
|
245
208
|
throw instances_1.convertCurrencyNegativeOrZeroValueError;
|
|
246
209
|
}
|
|
247
|
-
this.logger.debug(`Converting currency: ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
248
210
|
const requestFn = async () => {
|
|
249
211
|
let lastError;
|
|
250
212
|
for (const client of this.clients) {
|
|
251
213
|
try {
|
|
252
214
|
const result = await client.convertCurrency(params);
|
|
253
|
-
this.logger.debug(`Conversion result retrieved successfully`);
|
|
254
215
|
return result;
|
|
255
216
|
}
|
|
256
217
|
catch (error) {
|
|
257
|
-
this.logger.warn(`Failed to convert currency using one of the endpoints`);
|
|
258
218
|
lastError = error;
|
|
259
219
|
}
|
|
260
220
|
}
|
|
261
|
-
this.logger.error('All endpoints failed to convert currency');
|
|
262
221
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
263
222
|
};
|
|
264
|
-
return waitOptions
|
|
265
|
-
? await (
|
|
266
|
-
: await requestFn();
|
|
223
|
+
return waitOptions === null
|
|
224
|
+
? await requestFn()
|
|
225
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Converting currency ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
267
226
|
}
|
|
268
227
|
async simulateTACMessage(params, waitOptions) {
|
|
269
228
|
Validator_1.Validator.validateTACSimulationParams(params);
|
|
270
|
-
this.logger.debug(`Simulating TAC message: ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
271
229
|
const requestFn = async () => {
|
|
272
230
|
let lastError;
|
|
273
231
|
for (const client of this.clients) {
|
|
274
232
|
try {
|
|
275
233
|
const result = await client.simulateTACMessage(params);
|
|
276
|
-
this.logger.debug(`Simulation result retrieved successfully`);
|
|
277
234
|
return result;
|
|
278
235
|
}
|
|
279
236
|
catch (error) {
|
|
280
|
-
this.logger.warn(`Failed to simulate TAC message using one of the endpoints`);
|
|
281
237
|
lastError = error;
|
|
282
238
|
}
|
|
283
239
|
}
|
|
284
|
-
this.logger.error('All endpoints failed to simulate TAC message');
|
|
285
240
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
286
241
|
};
|
|
287
|
-
return waitOptions
|
|
288
|
-
? await (
|
|
289
|
-
: await requestFn();
|
|
242
|
+
return waitOptions === null
|
|
243
|
+
? await requestFn()
|
|
244
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Simulating TAC message ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
290
245
|
}
|
|
291
246
|
async getTVMExecutorFee(params, waitOptions) {
|
|
292
|
-
this.logger.debug(`get TVM executor fee: ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
293
247
|
const requestFn = async () => {
|
|
294
248
|
let lastError;
|
|
295
249
|
for (const client of this.clients) {
|
|
296
250
|
try {
|
|
297
251
|
const result = await client.getTVMExecutorFee(params);
|
|
298
|
-
this.logger.debug(`Suggested TVM executor fee retrieved successfully`);
|
|
299
252
|
return result;
|
|
300
253
|
}
|
|
301
254
|
catch (error) {
|
|
302
|
-
this.logger.warn(`Failed to get TVM executor fee using one of the endpoints`);
|
|
303
255
|
lastError = error;
|
|
304
256
|
}
|
|
305
257
|
}
|
|
306
|
-
this.logger.error('All endpoints failed to get TVM executor fee');
|
|
307
258
|
throw (0, errors_1.allEndpointsFailedError)(lastError, waitOptions?.includeErrorTrace ?? false);
|
|
308
259
|
};
|
|
309
|
-
return waitOptions
|
|
310
|
-
? await (
|
|
311
|
-
: await requestFn();
|
|
260
|
+
return waitOptions === null
|
|
261
|
+
? await requestFn()
|
|
262
|
+
: await (0, Utils_1.waitUntilSuccess)({ logger: this.logger, ...waitOptions }, requestFn, `OperationTracker: Getting TVM executor fee ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
312
263
|
}
|
|
313
264
|
}
|
|
314
265
|
exports.OperationTracker = OperationTracker;
|
package/dist/src/sdk/TacSdk.js
CHANGED
|
@@ -42,7 +42,7 @@ class TacSdk {
|
|
|
42
42
|
throw new Error(`Unsupported network: ${network}`);
|
|
43
43
|
}
|
|
44
44
|
const config = await Configuration_1.Configuration.create(network, artifacts, sdkParams.TONParams, sdkParams.TACParams, sdkParams.customLiteSequencerEndpoints, delay, logger, passLoggerToOpeners);
|
|
45
|
-
const operationTracker = new OperationTracker_1.OperationTracker(network, config.liteSequencerEndpoints);
|
|
45
|
+
const operationTracker = new OperationTracker_1.OperationTracker(network, config.liteSequencerEndpoints, logger);
|
|
46
46
|
const explorerClient = new TacExplorerClient_1.TacExplorerClient(artifacts.TAC_EXPLORER_API_ENDPOINT);
|
|
47
47
|
const simulator = new Simulator_1.Simulator(config, operationTracker, logger);
|
|
48
48
|
const tonTransactionManager = new TONTransactionManager_1.TONTransactionManager(config, simulator, operationTracker, logger);
|
package/dist/src/sdk/Utils.js
CHANGED
|
@@ -151,13 +151,12 @@ const generateFeeData = (feeParams) => {
|
|
|
151
151
|
};
|
|
152
152
|
exports.generateFeeData = generateFeeData;
|
|
153
153
|
async function waitUntilSuccess(options = {}, operation, operationDescription, ...args) {
|
|
154
|
-
const timeout = options.timeout ??
|
|
155
|
-
const maxAttempts = options.maxAttempts ??
|
|
156
|
-
const delay = options.delay ??
|
|
154
|
+
const timeout = options.timeout ?? Struct_1.defaultWaitOptions.timeout;
|
|
155
|
+
const maxAttempts = options.maxAttempts ?? Struct_1.defaultWaitOptions.maxAttempts;
|
|
156
|
+
const delay = options.delay ?? Struct_1.defaultWaitOptions.delay;
|
|
157
157
|
const successCheck = options.successCheck;
|
|
158
158
|
const context = options.context;
|
|
159
159
|
const contextPrefix = operationDescription ? `[${operationDescription}] ` : '';
|
|
160
|
-
options.logger?.debug(`${contextPrefix}Starting wait for success with timeout=${timeout}ms, maxAttempts=${maxAttempts}, delay=${delay}ms`);
|
|
161
160
|
const startTime = Date.now();
|
|
162
161
|
let attempt = 1;
|
|
163
162
|
while (true) {
|
|
@@ -171,8 +170,7 @@ async function waitUntilSuccess(options = {}, operation, operationDescription, .
|
|
|
171
170
|
if (successCheck && !successCheck(result, context)) {
|
|
172
171
|
throw new Error(`Result is not successful: ${formatObjectForLogging(result)}`);
|
|
173
172
|
}
|
|
174
|
-
options.logger?.debug(`${contextPrefix}
|
|
175
|
-
// Execute custom onSuccess callback if provided
|
|
173
|
+
options.logger?.debug(`${contextPrefix}Success (attempt ${attempt}/${maxAttempts})`);
|
|
176
174
|
if (options.onSuccess) {
|
|
177
175
|
try {
|
|
178
176
|
await options.onSuccess(result, context);
|
|
@@ -197,7 +195,11 @@ async function waitUntilSuccess(options = {}, operation, operationDescription, .
|
|
|
197
195
|
options.logger?.debug(`${contextPrefix}${pendingMessage}`);
|
|
198
196
|
}
|
|
199
197
|
else {
|
|
200
|
-
|
|
198
|
+
let errorMessage = error instanceof Error ? error.message : String(error);
|
|
199
|
+
if (errorMessage.includes('<!doctype html>') || errorMessage.includes('<html')) {
|
|
200
|
+
errorMessage = errorMessage.replace(/<!doctype html>[\s\S]*?<\/html>/gi, '[HTML response]');
|
|
201
|
+
}
|
|
202
|
+
options.logger?.debug(`${contextPrefix}attempt=${attempt}/${maxAttempts} failed; retry_in=${delay}ms; error=${errorMessage}`);
|
|
201
203
|
}
|
|
202
204
|
await (0, exports.sleep)(delay);
|
|
203
205
|
attempt++;
|
|
@@ -353,17 +353,17 @@ export type BatchCrossChainTxWithAssetLike = Omit<BatchCrossChainTx, 'assets'> &
|
|
|
353
353
|
export interface WaitOptions<T = unknown, TContext = unknown> {
|
|
354
354
|
/**
|
|
355
355
|
* Timeout in milliseconds
|
|
356
|
-
* @default
|
|
356
|
+
* @default 30000 (5 minutes)
|
|
357
357
|
*/
|
|
358
358
|
timeout?: number;
|
|
359
359
|
/**
|
|
360
360
|
* Maximum number of attempts
|
|
361
|
-
* @default
|
|
361
|
+
* @default 10
|
|
362
362
|
*/
|
|
363
363
|
maxAttempts?: number;
|
|
364
364
|
/**
|
|
365
365
|
* Delay between attempts in milliseconds
|
|
366
|
-
* @default
|
|
366
|
+
* @default 1000 (1 seconds)
|
|
367
367
|
*/
|
|
368
368
|
delay?: number;
|
|
369
369
|
/**
|
|
@@ -496,11 +496,21 @@ export type TrackTransactionTreeParams = {
|
|
|
496
496
|
*/
|
|
497
497
|
direction?: 'forward' | 'backward' | 'both';
|
|
498
498
|
/**
|
|
499
|
-
*
|
|
500
|
-
* Useful
|
|
499
|
+
* Retry transaction lookup when `not_found` error occurs.
|
|
500
|
+
* Useful when transaction indexing has delays or when transactions appear gradually.
|
|
501
501
|
* @default true
|
|
502
502
|
*/
|
|
503
|
-
|
|
503
|
+
retryOnNotFound?: boolean;
|
|
504
|
+
/**
|
|
505
|
+
* Delay in milliseconds between retry attempts for transaction lookup
|
|
506
|
+
* @default 5000
|
|
507
|
+
*/
|
|
508
|
+
retryDelayMs?: number;
|
|
509
|
+
/**
|
|
510
|
+
* Number of retry attempts for transaction lookup
|
|
511
|
+
* @default 10
|
|
512
|
+
*/
|
|
513
|
+
retries?: number;
|
|
504
514
|
};
|
|
505
515
|
/**
|
|
506
516
|
* Details about a transaction validation error
|
|
@@ -570,6 +580,8 @@ export type GetTransactionsOptions = {
|
|
|
570
580
|
timeoutMs?: number;
|
|
571
581
|
/** Delay between retry attempts in milliseconds */
|
|
572
582
|
retryDelayMs?: number;
|
|
583
|
+
/** Number of retry attempts */
|
|
584
|
+
retries?: number;
|
|
573
585
|
/** Internal scan guard: maximum transactions to inspect while traversing history */
|
|
574
586
|
maxScannedTransactions?: number;
|
|
575
587
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Origin = exports.defaultWaitOptions = exports.TokenSymbol = exports.StageName = exports.NFTAddressType = exports.AssetType = exports.OperationType = exports.CurrencyType = exports.BlockchainType = exports.Network = exports.SimplifiedStatuses = void 0;
|
|
4
|
+
const Consts_1 = require("../sdk/Consts");
|
|
4
5
|
var SimplifiedStatuses;
|
|
5
6
|
(function (SimplifiedStatuses) {
|
|
6
7
|
SimplifiedStatuses["PENDING"] = "PENDING";
|
|
@@ -58,9 +59,9 @@ var TokenSymbol;
|
|
|
58
59
|
TokenSymbol["TON_SYMBOL"] = "TON";
|
|
59
60
|
})(TokenSymbol || (exports.TokenSymbol = TokenSymbol = {}));
|
|
60
61
|
exports.defaultWaitOptions = {
|
|
61
|
-
timeout:
|
|
62
|
-
maxAttempts:
|
|
63
|
-
delay:
|
|
62
|
+
timeout: Consts_1.DEFAULT_WAIT_TIMEOUT_MS,
|
|
63
|
+
maxAttempts: Consts_1.DEFAULT_WAIT_MAX_ATTEMPTS,
|
|
64
|
+
delay: Consts_1.DEFAULT_WAIT_DELAY_MS,
|
|
64
65
|
};
|
|
65
66
|
var Origin;
|
|
66
67
|
(function (Origin) {
|