@tonappchain/sdk 0.6.6-mainnet-alpha → 0.7.0-rc10
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/LICENSE +20 -20
- package/README.md +191 -191
- package/dist/adapters/contractOpener.d.ts +6 -5
- package/dist/adapters/contractOpener.js +6 -6
- package/dist/adapters/retryableContractOpener.d.ts +9 -5
- package/dist/adapters/retryableContractOpener.js +2 -2
- package/dist/assets/AssetCache.d.ts +23 -0
- package/dist/assets/AssetCache.js +36 -0
- package/dist/assets/AssetFactory.d.ts +7 -0
- package/dist/assets/AssetFactory.js +46 -0
- package/dist/assets/FT.d.ts +58 -0
- package/dist/assets/FT.js +231 -0
- package/dist/assets/NFT.d.ts +65 -0
- package/dist/assets/NFT.js +210 -0
- package/dist/assets/TON.d.ts +38 -0
- package/dist/assets/TON.js +91 -0
- package/dist/assets/index.d.ts +4 -0
- package/dist/assets/index.js +11 -0
- package/dist/errors/errors.d.ts +6 -0
- package/dist/errors/errors.js +15 -1
- package/dist/errors/index.d.ts +2 -2
- package/dist/errors/index.js +26 -22
- package/dist/errors/instances.d.ts +4 -1
- package/dist/errors/instances.js +11 -2
- package/dist/index.d.ts +7 -0
- package/dist/index.js +14 -1
- package/dist/interfaces/IAsset.d.ts +73 -0
- package/dist/interfaces/IAsset.js +2 -0
- package/dist/interfaces/IConfiguration.d.ts +35 -0
- package/dist/interfaces/IConfiguration.js +2 -0
- package/dist/interfaces/IContractOpener.d.ts +21 -0
- package/dist/interfaces/IContractOpener.js +2 -0
- package/dist/interfaces/IHttpClient.d.ts +16 -0
- package/dist/interfaces/IHttpClient.js +2 -0
- package/dist/interfaces/ILiteSequencerClient.d.ts +30 -0
- package/dist/interfaces/ILiteSequencerClient.js +2 -0
- package/dist/interfaces/ILiteSequencerClientFactory.d.ts +9 -0
- package/dist/interfaces/ILiteSequencerClientFactory.js +2 -0
- package/dist/interfaces/ILogger.d.ts +10 -0
- package/dist/interfaces/ILogger.js +2 -0
- package/dist/interfaces/IOperationTracker.d.ts +66 -0
- package/dist/interfaces/IOperationTracker.js +2 -0
- package/dist/interfaces/ISender.d.ts +35 -0
- package/dist/interfaces/ISender.js +2 -0
- package/dist/interfaces/ISimulator.d.ts +47 -0
- package/dist/interfaces/ISimulator.js +2 -0
- package/dist/interfaces/ITacSDK.d.ts +147 -0
- package/dist/interfaces/ITacSDK.js +2 -0
- package/dist/interfaces/ITransactionManager.d.ts +35 -0
- package/dist/interfaces/ITransactionManager.js +2 -0
- package/dist/interfaces/IWallet.d.ts +20 -0
- package/dist/interfaces/IWallet.js +2 -0
- package/dist/interfaces/index.d.ts +13 -0
- package/dist/interfaces/index.js +29 -0
- package/dist/sdk/AxiosHttpClient.d.ts +12 -0
- package/dist/sdk/AxiosHttpClient.js +23 -0
- package/dist/sdk/Configuration.d.ts +21 -0
- package/dist/sdk/Configuration.js +90 -0
- package/dist/sdk/LiteSequencerClient.d.ts +6 -2
- package/dist/sdk/LiteSequencerClient.js +58 -14
- package/dist/sdk/Logger.d.ts +13 -0
- package/dist/sdk/Logger.js +25 -0
- package/dist/sdk/OperationTracker.d.ts +10 -5
- package/dist/sdk/OperationTracker.js +87 -45
- package/dist/sdk/Simulator.d.ts +17 -0
- package/dist/sdk/Simulator.js +163 -0
- package/dist/sdk/StartTracking.d.ts +6 -0
- package/dist/sdk/StartTracking.js +69 -32
- package/dist/sdk/TacSdk.d.ts +27 -44
- package/dist/sdk/TacSdk.js +121 -816
- package/dist/sdk/TransactionManager.d.ts +22 -0
- package/dist/sdk/TransactionManager.js +272 -0
- package/dist/sdk/TxFinalizer.d.ts +10 -0
- package/dist/sdk/TxFinalizer.js +104 -0
- package/dist/sdk/Utils.d.ts +7 -2
- package/dist/sdk/Utils.js +43 -24
- package/dist/sdk/Validator.d.ts +9 -0
- package/dist/sdk/Validator.js +43 -0
- package/dist/sender/BatchSender.d.ts +7 -5
- package/dist/sender/BatchSender.js +18 -6
- package/dist/sender/RawSender.d.ts +11 -6
- package/dist/sender/RawSender.js +46 -18
- package/dist/sender/SenderFactory.d.ts +2 -2
- package/dist/sender/SenderFactory.js +5 -4
- package/dist/sender/TonConnectSender.d.ts +7 -5
- package/dist/sender/TonConnectSender.js +14 -10
- package/dist/sender/index.d.ts +2 -2
- package/dist/sender/index.js +2 -2
- package/dist/structs/InternalStruct.d.ts +52 -33
- package/dist/structs/Struct.d.ts +92 -94
- package/dist/structs/Struct.js +11 -1
- package/dist/wrappers/HighloadQueryId.js +0 -1
- package/dist/wrappers/HighloadWalletV3.d.ts +4 -3
- package/dist/wrappers/HighloadWalletV3.js +5 -2
- package/package.json +67 -67
- package/dist/sender/SenderAbstraction.d.ts +0 -20
- package/dist/sender/SenderAbstraction.js +0 -5
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.LiteSequencerClient = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
4
|
const errors_1 = require("../errors");
|
|
9
5
|
const Utils_1 = require("./Utils");
|
|
6
|
+
const AxiosHttpClient_1 = require("./AxiosHttpClient");
|
|
10
7
|
class LiteSequencerClient {
|
|
11
|
-
constructor(endpoint, maxChunkSize = 100) {
|
|
8
|
+
constructor(endpoint, maxChunkSize = 100, httpClient = new AxiosHttpClient_1.AxiosHttpClient()) {
|
|
12
9
|
this.endpoint = endpoint;
|
|
13
10
|
this.maxChunkSize = maxChunkSize;
|
|
11
|
+
this.httpClient = httpClient;
|
|
12
|
+
}
|
|
13
|
+
async getOperationIdByTransactionHash(transactionHash) {
|
|
14
|
+
const isEthHash = /^0x[a-fA-F0-9]{64}$/.test(transactionHash);
|
|
15
|
+
const path = isEthHash ? 'tac/operation-id' : 'ton/operation-id';
|
|
16
|
+
try {
|
|
17
|
+
const response = await this.httpClient.get(new URL(path, this.endpoint).toString(), {
|
|
18
|
+
params: { transactionHash },
|
|
19
|
+
});
|
|
20
|
+
return response.data.response || '';
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error?.response?.status === 404) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
throw (0, errors_1.operationFetchError)(`endpoint ${this.endpoint} failed to complete request`, error);
|
|
27
|
+
}
|
|
14
28
|
}
|
|
15
29
|
async getOperationType(operationId) {
|
|
16
30
|
try {
|
|
17
|
-
const response = await
|
|
31
|
+
const response = await this.httpClient.get(new URL('operation-type', this.endpoint).toString(), {
|
|
18
32
|
params: {
|
|
19
33
|
operationId,
|
|
20
34
|
},
|
|
@@ -33,14 +47,12 @@ class LiteSequencerClient {
|
|
|
33
47
|
timestamp: transactionLinker.timestamp,
|
|
34
48
|
};
|
|
35
49
|
try {
|
|
36
|
-
const response = await
|
|
50
|
+
const response = await this.httpClient.post(new URL('ton/operation-id', this.endpoint).toString(), requestBody);
|
|
37
51
|
return response.data.response || '';
|
|
38
52
|
}
|
|
39
53
|
catch (error) {
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
return '';
|
|
43
|
-
}
|
|
54
|
+
if (error?.response?.status === 404) {
|
|
55
|
+
return '';
|
|
44
56
|
}
|
|
45
57
|
throw (0, errors_1.operationFetchError)(`endpoint ${this.endpoint} failed to complete request`, error);
|
|
46
58
|
}
|
|
@@ -51,7 +63,7 @@ class LiteSequencerClient {
|
|
|
51
63
|
}
|
|
52
64
|
try {
|
|
53
65
|
const response = await this.processChunkedRequest(shardsKeys, async (chunk) => {
|
|
54
|
-
const response = await
|
|
66
|
+
const response = await this.httpClient.post(new URL('operation-ids-by-shards-keys', this.endpoint).toString(), {
|
|
55
67
|
shardsKeys: chunk,
|
|
56
68
|
caller: caller,
|
|
57
69
|
});
|
|
@@ -69,7 +81,7 @@ class LiteSequencerClient {
|
|
|
69
81
|
}
|
|
70
82
|
try {
|
|
71
83
|
const response = await this.processChunkedRequest(operationIds, async (chunk) => {
|
|
72
|
-
const response = await
|
|
84
|
+
const response = await this.httpClient.post(new URL('stage-profiling', this.endpoint).toString(), {
|
|
73
85
|
operationIds: chunk,
|
|
74
86
|
}, {
|
|
75
87
|
transformResponse: [Utils_1.toCamelCaseTransformer],
|
|
@@ -88,7 +100,7 @@ class LiteSequencerClient {
|
|
|
88
100
|
}
|
|
89
101
|
try {
|
|
90
102
|
const response = await this.processChunkedRequest(operationIds, async (chunk) => {
|
|
91
|
-
const response = await
|
|
103
|
+
const response = await this.httpClient.post(new URL('status', this.endpoint).toString(), {
|
|
92
104
|
operationIds: chunk,
|
|
93
105
|
}, {
|
|
94
106
|
transformResponse: [Utils_1.toCamelCaseTransformer],
|
|
@@ -101,6 +113,38 @@ class LiteSequencerClient {
|
|
|
101
113
|
throw (0, errors_1.statusFetchError)(`endpoint ${this.endpoint} failed to complete request`, error);
|
|
102
114
|
}
|
|
103
115
|
}
|
|
116
|
+
async convertCurrency(params) {
|
|
117
|
+
try {
|
|
118
|
+
const payload = {
|
|
119
|
+
currencyType: params.currencyType,
|
|
120
|
+
rawValue: params.rawValue.toString(),
|
|
121
|
+
};
|
|
122
|
+
const response = await this.httpClient.post(new URL('convert_currency', this.endpoint).toString(), payload, {
|
|
123
|
+
transformResponse: [Utils_1.toCamelCaseTransformer],
|
|
124
|
+
});
|
|
125
|
+
const raw = response.data.response;
|
|
126
|
+
return {
|
|
127
|
+
spotRawValue: BigInt(raw.spotRawValue),
|
|
128
|
+
spotFriendlyValue: raw.spotFriendlyValue,
|
|
129
|
+
emaValue: BigInt(raw.emaValue),
|
|
130
|
+
emaFriendlyValue: raw.emaFriendlyValue,
|
|
131
|
+
spotValueInUSD: Number(raw.spotValueInUSD),
|
|
132
|
+
emaValueInUSD: Number(raw.emaValueInUSD),
|
|
133
|
+
currencyType: raw.currencyType,
|
|
134
|
+
tacPrice: {
|
|
135
|
+
spot: BigInt(raw.tacPrice.spot),
|
|
136
|
+
ema: BigInt(raw.tacPrice.ema),
|
|
137
|
+
},
|
|
138
|
+
tonPrice: {
|
|
139
|
+
spot: BigInt(raw.tonPrice.spot),
|
|
140
|
+
ema: BigInt(raw.tonPrice.ema),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
throw (0, errors_1.operationFetchError)(`endpoint ${this.endpoint} failed to complete request`, error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
104
148
|
async processChunkedRequest(identificators, requestFn, chunkSize = this.maxChunkSize) {
|
|
105
149
|
const results = [];
|
|
106
150
|
for (let i = 0; i < identificators.length; i += chunkSize) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ILogger } from '../interfaces';
|
|
2
|
+
export declare class ConsoleLogger implements ILogger {
|
|
3
|
+
debug(...arg: unknown[]): void;
|
|
4
|
+
info(...arg: unknown[]): void;
|
|
5
|
+
warn(...arg: unknown[]): void;
|
|
6
|
+
error(...arg: unknown[]): void;
|
|
7
|
+
}
|
|
8
|
+
export declare class NoopLogger implements ILogger {
|
|
9
|
+
debug(): void;
|
|
10
|
+
info(): void;
|
|
11
|
+
warn(): void;
|
|
12
|
+
error(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoopLogger = exports.ConsoleLogger = void 0;
|
|
4
|
+
class ConsoleLogger {
|
|
5
|
+
debug(...arg) {
|
|
6
|
+
console.debug(`[DEBUG]`, ...arg);
|
|
7
|
+
}
|
|
8
|
+
info(...arg) {
|
|
9
|
+
console.info(`[INFO]`, ...arg);
|
|
10
|
+
}
|
|
11
|
+
warn(...arg) {
|
|
12
|
+
console.warn(`[WARN]`, ...arg);
|
|
13
|
+
}
|
|
14
|
+
error(...arg) {
|
|
15
|
+
console.error(`[ERROR]`, ...arg);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.ConsoleLogger = ConsoleLogger;
|
|
19
|
+
class NoopLogger {
|
|
20
|
+
debug() { }
|
|
21
|
+
info() { }
|
|
22
|
+
warn() { }
|
|
23
|
+
error() { }
|
|
24
|
+
}
|
|
25
|
+
exports.NoopLogger = NoopLogger;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ILogger, IOperationTracker, ILiteSequencerClientFactory, ILiteSequencerClient } from '../interfaces';
|
|
2
|
+
import { ConvertCurrencyParams, ConvertedCurrencyResult, ExecutionStages, ExecutionStagesByOperationId, Network, OperationIdsByShardsKey, OperationType, SimplifiedStatuses, StatusInfo, StatusInfosByOperationId, TransactionLinker, WaitOptions } from '../structs/Struct';
|
|
3
|
+
export declare class DefaultLiteSequencerClientFactory implements ILiteSequencerClientFactory {
|
|
4
|
+
createClients(endpoints: string[]): ILiteSequencerClient[];
|
|
5
|
+
}
|
|
6
|
+
export declare class OperationTracker implements IOperationTracker {
|
|
3
7
|
private readonly clients;
|
|
4
|
-
private readonly
|
|
5
|
-
constructor(network: Network, customLiteSequencerEndpoints?: string[],
|
|
6
|
-
|
|
8
|
+
private readonly logger;
|
|
9
|
+
constructor(network: Network, customLiteSequencerEndpoints?: string[], logger?: ILogger, clientFactory?: ILiteSequencerClientFactory);
|
|
10
|
+
getOperationIdByTransactionHash(transactionHash: string, waitOptions?: WaitOptions<string>): Promise<string>;
|
|
7
11
|
getOperationType(operationId: string, waitOptions?: WaitOptions<OperationType>): Promise<OperationType>;
|
|
8
12
|
getOperationId(transactionLinker: TransactionLinker, waitOptions?: WaitOptions<string>): Promise<string>;
|
|
9
13
|
getOperationIdsByShardsKeys(shardsKeys: string[], caller: string, waitOptions?: WaitOptions<OperationIdsByShardsKey>, chunkSize?: number): Promise<OperationIdsByShardsKey>;
|
|
@@ -12,4 +16,5 @@ export declare class OperationTracker {
|
|
|
12
16
|
getOperationStatuses(operationIds: string[], waitOptions?: WaitOptions<StatusInfosByOperationId>, chunkSize?: number): Promise<StatusInfosByOperationId>;
|
|
13
17
|
getOperationStatus(operationId: string, waitOptions?: WaitOptions<StatusInfo>): Promise<StatusInfo>;
|
|
14
18
|
getSimplifiedOperationStatus(transactionLinker: TransactionLinker): Promise<SimplifiedStatuses>;
|
|
19
|
+
convertCurrency(params: ConvertCurrencyParams, waitOptions?: WaitOptions<ConvertedCurrencyResult>): Promise<ConvertedCurrencyResult>;
|
|
15
20
|
}
|
|
@@ -1,88 +1,110 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OperationTracker = void 0;
|
|
3
|
+
exports.OperationTracker = exports.DefaultLiteSequencerClientFactory = void 0;
|
|
4
4
|
const artifacts_1 = require("@tonappchain/artifacts");
|
|
5
5
|
const errors_1 = require("../errors");
|
|
6
6
|
const Struct_1 = require("../structs/Struct");
|
|
7
7
|
const LiteSequencerClient_1 = require("./LiteSequencerClient");
|
|
8
|
+
const Logger_1 = require("./Logger");
|
|
8
9
|
const Utils_1 = require("./Utils");
|
|
10
|
+
class DefaultLiteSequencerClientFactory {
|
|
11
|
+
createClients(endpoints) {
|
|
12
|
+
return endpoints.map((endpoint) => new LiteSequencerClient_1.LiteSequencerClient(endpoint));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.DefaultLiteSequencerClientFactory = DefaultLiteSequencerClientFactory;
|
|
9
16
|
class OperationTracker {
|
|
10
|
-
constructor(network, customLiteSequencerEndpoints,
|
|
17
|
+
constructor(network, customLiteSequencerEndpoints, logger = new Logger_1.NoopLogger(), clientFactory = new DefaultLiteSequencerClientFactory()) {
|
|
11
18
|
const endpoints = customLiteSequencerEndpoints ??
|
|
12
19
|
(network === Struct_1.Network.TESTNET
|
|
13
20
|
? artifacts_1.testnet.PUBLIC_LITE_SEQUENCER_ENDPOINTS
|
|
14
21
|
: artifacts_1.mainnet.PUBLIC_LITE_SEQUENCER_ENDPOINTS);
|
|
15
|
-
this.clients =
|
|
16
|
-
this.
|
|
22
|
+
this.clients = clientFactory.createClients(endpoints);
|
|
23
|
+
this.logger = logger;
|
|
17
24
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
async getOperationIdByTransactionHash(transactionHash, waitOptions) {
|
|
26
|
+
this.logger.debug(`Getting operation ID for transactionHash: ${(0, Utils_1.formatObjectForLogging)(transactionHash)}`);
|
|
27
|
+
const requestFn = async () => {
|
|
28
|
+
let lastError;
|
|
29
|
+
for (const client of this.clients) {
|
|
30
|
+
try {
|
|
31
|
+
const id = await client.getOperationIdByTransactionHash(transactionHash);
|
|
32
|
+
this.logger.debug(`Operation ID ${id == '' ? 'does not exist' : 'retrieved successfully'}`);
|
|
33
|
+
return id;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
this.logger.warn(`Failed to get OperationId by transactionHash using one of the endpoints`);
|
|
37
|
+
lastError = error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
this.logger.error('All endpoints failed to get operation id by transactionHash');
|
|
41
|
+
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
42
|
+
};
|
|
43
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
22
44
|
}
|
|
23
45
|
async getOperationType(operationId, waitOptions) {
|
|
24
|
-
this.
|
|
46
|
+
this.logger.debug(`Getting operation type for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
25
47
|
const requestFn = async () => {
|
|
26
48
|
let lastError;
|
|
27
49
|
for (const client of this.clients) {
|
|
28
50
|
try {
|
|
29
51
|
const type = await client.getOperationType(operationId);
|
|
30
|
-
this.
|
|
52
|
+
this.logger.debug(`Operation retrieved successfully`);
|
|
31
53
|
return type;
|
|
32
54
|
}
|
|
33
55
|
catch (error) {
|
|
34
|
-
this.
|
|
56
|
+
this.logger.warn(`Failed to get operationType using one of the endpoints`);
|
|
35
57
|
lastError = error;
|
|
36
58
|
}
|
|
37
59
|
}
|
|
38
|
-
this.
|
|
60
|
+
this.logger.error('All endpoints failed to get operation type');
|
|
39
61
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
40
62
|
};
|
|
41
63
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
42
64
|
}
|
|
43
65
|
async getOperationId(transactionLinker, waitOptions) {
|
|
44
|
-
this.
|
|
66
|
+
this.logger.debug(`Getting operation ID for transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
45
67
|
const requestFn = async () => {
|
|
46
68
|
let lastError;
|
|
47
69
|
for (const client of this.clients) {
|
|
48
70
|
try {
|
|
49
71
|
const id = await client.getOperationId(transactionLinker);
|
|
50
|
-
this.
|
|
72
|
+
this.logger.debug(`Operation ID ${id == '' ? 'does not exist' : 'retrieved successfully'}`);
|
|
51
73
|
return id;
|
|
52
74
|
}
|
|
53
75
|
catch (error) {
|
|
54
|
-
this.
|
|
76
|
+
this.logger.warn(`Failed to get OperationId using one of the endpoints`);
|
|
55
77
|
lastError = error;
|
|
56
78
|
}
|
|
57
79
|
}
|
|
58
|
-
this.
|
|
80
|
+
this.logger.error('All endpoints failed to get operation id');
|
|
59
81
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
60
82
|
};
|
|
61
83
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
62
84
|
}
|
|
63
85
|
async getOperationIdsByShardsKeys(shardsKeys, caller, waitOptions, chunkSize = 100) {
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
86
|
+
this.logger.debug(`Getting operation IDs for shards keys: ${(0, Utils_1.formatObjectForLogging)(shardsKeys)}`);
|
|
87
|
+
this.logger.debug(`Caller: ${caller}, Chunk size: ${chunkSize}`);
|
|
66
88
|
const requestFn = async () => {
|
|
67
89
|
let lastError;
|
|
68
90
|
for (const client of this.clients) {
|
|
69
91
|
try {
|
|
70
92
|
const result = await client.getOperationIdsByShardsKeys(shardsKeys, caller, chunkSize);
|
|
71
|
-
this.
|
|
93
|
+
this.logger.debug(`Operation IDs by shards keys retrieved successfully`);
|
|
72
94
|
return result;
|
|
73
95
|
}
|
|
74
96
|
catch (error) {
|
|
75
|
-
this.
|
|
97
|
+
this.logger.warn(`Failed to get OperationIds using one of the endpoints`);
|
|
76
98
|
lastError = error;
|
|
77
99
|
}
|
|
78
100
|
}
|
|
79
|
-
this.
|
|
101
|
+
this.logger.error('All endpoints failed to get operation ids by shards keys');
|
|
80
102
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
81
103
|
};
|
|
82
104
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
83
105
|
}
|
|
84
106
|
async getStageProfiling(operationId, waitOptions) {
|
|
85
|
-
this.
|
|
107
|
+
this.logger.debug(`Getting stage profiling for operation ${operationId}`);
|
|
86
108
|
const requestFn = async () => {
|
|
87
109
|
let lastError;
|
|
88
110
|
for (const client of this.clients) {
|
|
@@ -90,66 +112,66 @@ class OperationTracker {
|
|
|
90
112
|
const map = await client.getStageProfilings([operationId]);
|
|
91
113
|
const result = map[operationId];
|
|
92
114
|
if (!result) {
|
|
93
|
-
this.
|
|
115
|
+
this.logger.warn(`No stageProfiling data for operationId=${operationId}`);
|
|
94
116
|
throw new Error(`No stageProfiling data for operationId=${operationId}`);
|
|
95
117
|
}
|
|
96
|
-
this.
|
|
118
|
+
this.logger.debug(`Stage profiling retrieved successfully`);
|
|
97
119
|
return result;
|
|
98
120
|
}
|
|
99
121
|
catch (error) {
|
|
100
|
-
this.
|
|
122
|
+
this.logger.warn(`Failed to get stage profiling using one of the endpoints`);
|
|
101
123
|
lastError = error;
|
|
102
124
|
}
|
|
103
125
|
}
|
|
104
|
-
this.
|
|
126
|
+
this.logger.error('All endpoints failed to get stage profiling');
|
|
105
127
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
106
128
|
};
|
|
107
129
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
108
130
|
}
|
|
109
131
|
async getStageProfilings(operationIds, waitOptions, chunkSize = 100) {
|
|
110
|
-
this.
|
|
111
|
-
this.
|
|
132
|
+
this.logger.debug(`Getting stage profilings for operations: ${operationIds.join(', ')}`);
|
|
133
|
+
this.logger.debug(`Chunk size: ${chunkSize}`);
|
|
112
134
|
const requestFn = async () => {
|
|
113
135
|
let lastError;
|
|
114
136
|
for (const client of this.clients) {
|
|
115
137
|
try {
|
|
116
138
|
const result = await client.getStageProfilings(operationIds, chunkSize);
|
|
117
|
-
this.
|
|
139
|
+
this.logger.debug(`Stage profilings retrieved successfully`);
|
|
118
140
|
return result;
|
|
119
141
|
}
|
|
120
142
|
catch (error) {
|
|
121
|
-
this.
|
|
143
|
+
this.logger.warn(`Failed to get stage profilings using one of the endpoints`);
|
|
122
144
|
lastError = error;
|
|
123
145
|
}
|
|
124
146
|
}
|
|
125
|
-
this.
|
|
147
|
+
this.logger.error('All endpoints failed to get stage profilings');
|
|
126
148
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
127
149
|
};
|
|
128
150
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
129
151
|
}
|
|
130
152
|
async getOperationStatuses(operationIds, waitOptions, chunkSize = 100) {
|
|
131
|
-
this.
|
|
132
|
-
this.
|
|
153
|
+
this.logger.debug(`Getting operation statuses for operations: ${(0, Utils_1.formatObjectForLogging)(operationIds)}`);
|
|
154
|
+
this.logger.debug(`Chunk size: ${chunkSize}`);
|
|
133
155
|
const requestFn = async () => {
|
|
134
156
|
let lastError;
|
|
135
157
|
for (const client of this.clients) {
|
|
136
158
|
try {
|
|
137
159
|
const result = await client.getOperationStatuses(operationIds, chunkSize);
|
|
138
|
-
this.
|
|
160
|
+
this.logger.debug(`Operation statuses retrieved successfully`);
|
|
139
161
|
return result;
|
|
140
162
|
}
|
|
141
163
|
catch (error) {
|
|
142
|
-
this.
|
|
164
|
+
this.logger.warn(`Failed to get operation statuses using one of the endpoints`);
|
|
143
165
|
lastError = error;
|
|
144
166
|
}
|
|
145
167
|
}
|
|
146
|
-
this.
|
|
168
|
+
this.logger.error('All endpoints failed to get operation statuses');
|
|
147
169
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
148
170
|
};
|
|
149
171
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
150
172
|
}
|
|
151
173
|
async getOperationStatus(operationId, waitOptions) {
|
|
152
|
-
this.
|
|
174
|
+
this.logger.debug(`Getting operation status for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
153
175
|
const requestFn = async () => {
|
|
154
176
|
let lastError;
|
|
155
177
|
for (const client of this.clients) {
|
|
@@ -157,32 +179,32 @@ class OperationTracker {
|
|
|
157
179
|
const map = await client.getOperationStatuses([operationId]);
|
|
158
180
|
const result = map[operationId];
|
|
159
181
|
if (!result) {
|
|
160
|
-
this.
|
|
182
|
+
this.logger.warn(`No operation status for operationId=${operationId}`);
|
|
161
183
|
throw new Error(`No operation status for operationId=${operationId}`);
|
|
162
184
|
}
|
|
163
|
-
this.
|
|
185
|
+
this.logger.debug(`Operation status retrieved successfully`);
|
|
164
186
|
return result;
|
|
165
187
|
}
|
|
166
188
|
catch (error) {
|
|
167
|
-
this.
|
|
189
|
+
this.logger.warn(`Failed to get operation status using one of the endpoints`);
|
|
168
190
|
lastError = error;
|
|
169
191
|
}
|
|
170
192
|
}
|
|
171
|
-
this.
|
|
193
|
+
this.logger.error('All endpoints failed to get operation status');
|
|
172
194
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
173
195
|
};
|
|
174
196
|
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
175
197
|
}
|
|
176
198
|
async getSimplifiedOperationStatus(transactionLinker) {
|
|
177
|
-
this.
|
|
199
|
+
this.logger.debug(`Getting simplified operation status for transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
178
200
|
const operationId = await this.getOperationId(transactionLinker);
|
|
179
201
|
if (operationId == '') {
|
|
180
|
-
this.
|
|
202
|
+
this.logger.warn('Operation ID not found');
|
|
181
203
|
return Struct_1.SimplifiedStatuses.OPERATION_ID_NOT_FOUND;
|
|
182
204
|
}
|
|
183
|
-
this.
|
|
205
|
+
this.logger.debug(`Operation ID: ${operationId}`);
|
|
184
206
|
const operationType = await this.getOperationType(operationId);
|
|
185
|
-
this.
|
|
207
|
+
this.logger.debug(`Operation type: ${operationType}`);
|
|
186
208
|
if (operationType == Struct_1.OperationType.PENDING || operationType == Struct_1.OperationType.UNKNOWN) {
|
|
187
209
|
return Struct_1.SimplifiedStatuses.PENDING;
|
|
188
210
|
}
|
|
@@ -191,5 +213,25 @@ class OperationTracker {
|
|
|
191
213
|
}
|
|
192
214
|
return Struct_1.SimplifiedStatuses.SUCCESSFUL;
|
|
193
215
|
}
|
|
216
|
+
async convertCurrency(params, waitOptions) {
|
|
217
|
+
this.logger.debug(`Converting currency: ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
218
|
+
const requestFn = async () => {
|
|
219
|
+
let lastError;
|
|
220
|
+
for (const client of this.clients) {
|
|
221
|
+
try {
|
|
222
|
+
const result = await client.convertCurrency(params);
|
|
223
|
+
this.logger.debug(`Conversion result retrieved successfully`);
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
this.logger.warn(`Failed to convert currency using one of the endpoints`);
|
|
228
|
+
lastError = error;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
this.logger.error('All endpoints failed to convert currency');
|
|
232
|
+
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
233
|
+
};
|
|
234
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
235
|
+
}
|
|
194
236
|
}
|
|
195
237
|
exports.OperationTracker = OperationTracker;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ISender } from '../sender';
|
|
2
|
+
import { IConfiguration, ILogger, ISimulator } from '../interfaces';
|
|
3
|
+
import { IAsset, CrosschainTx, EvmProxyMsg, ExecutionFeeEstimationResult, SuggestedTONExecutorFee, TACSimulationRequest, TACSimulationResult, TransactionLinker } from '../structs/Struct';
|
|
4
|
+
import { IHttpClient } from '../interfaces';
|
|
5
|
+
export declare class Simulator implements ISimulator {
|
|
6
|
+
private readonly config;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private readonly httpClient;
|
|
9
|
+
constructor(config: IConfiguration, logger?: ILogger, httpClient?: IHttpClient);
|
|
10
|
+
simulateTACMessage(req: TACSimulationRequest): Promise<TACSimulationResult>;
|
|
11
|
+
simulateTransactions(sender: ISender, txs: CrosschainTx[]): Promise<TACSimulationResult[]>;
|
|
12
|
+
private buildTACSimulationRequest;
|
|
13
|
+
getTVMExecutorFeeInfo(assets: IAsset[], feeSymbol: string, tvmValidExecutors?: string[]): Promise<SuggestedTONExecutorFee>;
|
|
14
|
+
private getFeeInfo;
|
|
15
|
+
getTransactionSimulationInfo(evmProxyMsg: EvmProxyMsg, sender: ISender, assets?: IAsset[]): Promise<ExecutionFeeEstimationResult>;
|
|
16
|
+
getSimulationInfoForTransaction(evmProxyMsg: EvmProxyMsg, transactionLinker: TransactionLinker, assets: IAsset[], allowSimulationError?: boolean, isRoundTrip?: boolean, evmValidExecutors?: string[], tvmValidExecutors?: string[], calculateRollbackFee?: boolean): Promise<ExecutionFeeEstimationResult>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Simulator = void 0;
|
|
4
|
+
const ton_1 = require("@ton/ton");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const Logger_1 = require("./Logger");
|
|
7
|
+
const Utils_1 = require("./Utils");
|
|
8
|
+
const Validator_1 = require("./Validator");
|
|
9
|
+
const AxiosHttpClient_1 = require("./AxiosHttpClient");
|
|
10
|
+
class Simulator {
|
|
11
|
+
constructor(config, logger = new Logger_1.NoopLogger(), httpClient = new AxiosHttpClient_1.AxiosHttpClient()) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
this.httpClient = httpClient;
|
|
15
|
+
}
|
|
16
|
+
async simulateTACMessage(req) {
|
|
17
|
+
Validator_1.Validator.validateTACSimulationRequest(req);
|
|
18
|
+
this.logger.debug('Simulating TAC message');
|
|
19
|
+
let lastError;
|
|
20
|
+
for (const endpoint of this.config.liteSequencerEndpoints) {
|
|
21
|
+
try {
|
|
22
|
+
const response = await this.httpClient.post(new URL('tac/simulator/simulate-message', endpoint).toString(), req, {
|
|
23
|
+
transformResponse: [Utils_1.toCamelCaseTransformer],
|
|
24
|
+
});
|
|
25
|
+
this.logger.debug('TAC message simulation success');
|
|
26
|
+
return response.data.response;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
this.logger.error(`Error while simulating with ${endpoint}: ${error}`);
|
|
30
|
+
lastError = error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
throw (0, errors_1.simulationError)(lastError);
|
|
34
|
+
}
|
|
35
|
+
async simulateTransactions(sender, txs) {
|
|
36
|
+
this.logger.debug(`Simulating ${txs.length} TAC messages`);
|
|
37
|
+
const results = [];
|
|
38
|
+
for (const tx of txs) {
|
|
39
|
+
const req = await this.buildTACSimulationRequest(sender, tx);
|
|
40
|
+
const result = await this.simulateTACMessage(req);
|
|
41
|
+
results.push(result);
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
async buildTACSimulationRequest(sender, tx) {
|
|
46
|
+
const { evmProxyMsg, assets = [], options = {} } = tx;
|
|
47
|
+
const { evmValidExecutors = this.config.TACParams.trustedTACExecutors, tvmValidExecutors = this.config.TACParams.trustedTONExecutors, calculateRollbackFee = true, } = options;
|
|
48
|
+
Validator_1.Validator.validateEVMAddresses(evmValidExecutors);
|
|
49
|
+
Validator_1.Validator.validateTVMAddresses(tvmValidExecutors);
|
|
50
|
+
const aggregatedData = await (0, Utils_1.aggregateTokens)(assets);
|
|
51
|
+
const transactionLinkerShardCount = aggregatedData.jettons.length == 0 ? 1 : aggregatedData.jettons.length;
|
|
52
|
+
const transactionLinker = (0, Utils_1.generateTransactionLinker)(sender.getSenderAddress(), transactionLinkerShardCount);
|
|
53
|
+
return {
|
|
54
|
+
tacCallParams: {
|
|
55
|
+
arguments: evmProxyMsg.encodedParameters ?? '0x',
|
|
56
|
+
methodName: (0, Utils_1.formatSolidityMethodName)(evmProxyMsg.methodName),
|
|
57
|
+
target: evmProxyMsg.evmTargetAddress,
|
|
58
|
+
},
|
|
59
|
+
evmValidExecutors: evmValidExecutors,
|
|
60
|
+
tvmValidExecutors: tvmValidExecutors,
|
|
61
|
+
extraData: '0x',
|
|
62
|
+
shardsKey: transactionLinker.shardsKey,
|
|
63
|
+
tonAssets: assets.map((asset) => ({
|
|
64
|
+
amount: asset.rawAmount.toString(),
|
|
65
|
+
tokenAddress: asset.address || '',
|
|
66
|
+
assetType: asset.type,
|
|
67
|
+
})),
|
|
68
|
+
tonCaller: transactionLinker.caller,
|
|
69
|
+
calculateRollbackFee: calculateRollbackFee,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async getTVMExecutorFeeInfo(assets, feeSymbol, tvmValidExecutors = this.config.TACParams.trustedTONExecutors) {
|
|
73
|
+
this.logger.debug('Getting TVM executor fee info');
|
|
74
|
+
const requestBody = {
|
|
75
|
+
tonAssets: assets.map((asset) => ({
|
|
76
|
+
amount: asset.rawAmount.toString(),
|
|
77
|
+
tokenAddress: asset.address || '',
|
|
78
|
+
assetType: asset.type,
|
|
79
|
+
})),
|
|
80
|
+
feeSymbol: feeSymbol,
|
|
81
|
+
tvmValidExecutors: tvmValidExecutors,
|
|
82
|
+
};
|
|
83
|
+
let lastError;
|
|
84
|
+
for (const endpoint of this.config.liteSequencerEndpoints) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await this.httpClient.post(`${endpoint}/ton/calculator/ton-executor-fee`, requestBody);
|
|
87
|
+
return response.data.response;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
this.logger.error(`Error while calculating tvm executor fee ${endpoint}: ${error}`);
|
|
91
|
+
lastError = error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this.logger.error('Error while calculating tvm executor fee on all endpoints');
|
|
95
|
+
throw (0, errors_1.simulationError)(lastError);
|
|
96
|
+
}
|
|
97
|
+
async getFeeInfo(evmProxyMsg, transactionLinker, assets, allowSimulationError = false, isRoundTrip = true, evmValidExecutors = this.config.TACParams.trustedTACExecutors, tvmValidExecutors = this.config.TACParams.trustedTONExecutors, calculateRollbackFee = true) {
|
|
98
|
+
this.logger.debug('Getting fee info');
|
|
99
|
+
Validator_1.Validator.validateEVMAddress(evmProxyMsg.evmTargetAddress);
|
|
100
|
+
Validator_1.Validator.validateEVMAddresses(evmValidExecutors);
|
|
101
|
+
Validator_1.Validator.validateTVMAddresses(tvmValidExecutors);
|
|
102
|
+
const crossChainLayer = this.config.TONParams.contractOpener.open(this.config.artifacts.ton.wrappers.CrossChainLayer.createFromAddress(ton_1.Address.parse(this.config.TONParams.crossChainLayerAddress)));
|
|
103
|
+
const fullStateCCL = await crossChainLayer.getFullData();
|
|
104
|
+
this.logger.debug(`Full state CCL: ${(0, Utils_1.formatObjectForLogging)(fullStateCCL)}`);
|
|
105
|
+
const tacSimulationBody = {
|
|
106
|
+
tacCallParams: {
|
|
107
|
+
arguments: evmProxyMsg.encodedParameters ?? '0x',
|
|
108
|
+
methodName: (0, Utils_1.formatSolidityMethodName)(evmProxyMsg.methodName),
|
|
109
|
+
target: evmProxyMsg.evmTargetAddress,
|
|
110
|
+
},
|
|
111
|
+
evmValidExecutors: evmValidExecutors,
|
|
112
|
+
tvmValidExecutors: tvmValidExecutors,
|
|
113
|
+
extraData: '0x',
|
|
114
|
+
shardsKey: transactionLinker.shardsKey,
|
|
115
|
+
tonAssets: assets.map((asset) => ({
|
|
116
|
+
amount: asset.rawAmount.toString(),
|
|
117
|
+
tokenAddress: asset.address || '',
|
|
118
|
+
assetType: asset.type,
|
|
119
|
+
})),
|
|
120
|
+
tonCaller: transactionLinker.caller,
|
|
121
|
+
calculateRollbackFee: calculateRollbackFee,
|
|
122
|
+
};
|
|
123
|
+
isRoundTrip = isRoundTrip ?? assets.length != 0;
|
|
124
|
+
this.logger.debug(`Is round trip: ${isRoundTrip}`);
|
|
125
|
+
const tacSimulationResult = await this.simulateTACMessage(tacSimulationBody);
|
|
126
|
+
this.logger.debug(`TAC simulation ${tacSimulationResult.simulationStatus ? 'success' : 'failed'}`);
|
|
127
|
+
const protocolFee = BigInt((0, ton_1.toNano)(fullStateCCL.tacProtocolFee)) +
|
|
128
|
+
BigInt(isRoundTrip) * BigInt((0, ton_1.toNano)(fullStateCCL.tonProtocolFee));
|
|
129
|
+
const feeParams = {
|
|
130
|
+
isRoundTrip: isRoundTrip,
|
|
131
|
+
gasLimit: !tacSimulationResult.simulationStatus ? 0n : tacSimulationResult.estimatedGas,
|
|
132
|
+
protocolFee: protocolFee,
|
|
133
|
+
evmExecutorFee: BigInt(tacSimulationResult.suggestedTacExecutionFee),
|
|
134
|
+
tvmExecutorFee: BigInt(tacSimulationResult.suggestedTonExecutionFee) * BigInt(isRoundTrip),
|
|
135
|
+
};
|
|
136
|
+
if (!tacSimulationResult.simulationStatus) {
|
|
137
|
+
if (allowSimulationError) {
|
|
138
|
+
this.logger.info('Force send is true, returning fee params');
|
|
139
|
+
return {
|
|
140
|
+
feeParams,
|
|
141
|
+
simulation: tacSimulationResult,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
throw tacSimulationResult;
|
|
145
|
+
}
|
|
146
|
+
this.logger.debug(`Collected fee params: ${(0, Utils_1.formatObjectForLogging)(feeParams)}`);
|
|
147
|
+
return { feeParams, simulation: tacSimulationResult };
|
|
148
|
+
}
|
|
149
|
+
async getTransactionSimulationInfo(evmProxyMsg, sender, assets) {
|
|
150
|
+
this.logger.debug('Getting transaction simulation info');
|
|
151
|
+
Validator_1.Validator.validateEVMAddress(evmProxyMsg.evmTargetAddress);
|
|
152
|
+
const aggregatedData = await (0, Utils_1.aggregateTokens)(assets);
|
|
153
|
+
const transactionLinkerShardCount = aggregatedData.jettons.length == 0 ? 1 : aggregatedData.jettons.length;
|
|
154
|
+
this.logger.debug(`Transaction linker shard count: ${transactionLinkerShardCount}`);
|
|
155
|
+
const transactionLinker = (0, Utils_1.generateTransactionLinker)(sender.getSenderAddress(), transactionLinkerShardCount);
|
|
156
|
+
this.logger.debug(`Transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
157
|
+
return await this.getFeeInfo(evmProxyMsg, transactionLinker, assets ?? []);
|
|
158
|
+
}
|
|
159
|
+
async getSimulationInfoForTransaction(evmProxyMsg, transactionLinker, assets, allowSimulationError = false, isRoundTrip, evmValidExecutors, tvmValidExecutors, calculateRollbackFee) {
|
|
160
|
+
return await this.getFeeInfo(evmProxyMsg, transactionLinker, assets, allowSimulationError, isRoundTrip, evmValidExecutors, tvmValidExecutors, calculateRollbackFee);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.Simulator = Simulator;
|