@tonappchain/sdk 0.7.0-rc13 → 0.7.0-rc15
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/README.md +7 -7
- package/dist/adapters/contractOpener.js +33 -4
- package/dist/adapters/retryableContractOpener.js +1 -1
- package/dist/assets/AssetFactory.js +1 -1
- package/dist/assets/FT.d.ts +8 -12
- package/dist/assets/FT.js +69 -36
- package/dist/assets/NFT.d.ts +4 -2
- package/dist/assets/NFT.js +14 -2
- package/dist/assets/TON.d.ts +4 -10
- package/dist/assets/TON.js +17 -15
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +7 -2
- package/dist/errors/instances.d.ts +8 -1
- package/dist/errors/instances.js +22 -16
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -3
- package/dist/interfaces/Asset.d.ts +22 -17
- package/dist/interfaces/ILiteSequencerClient.d.ts +14 -1
- package/dist/interfaces/IOperationTracker.d.ts +16 -1
- package/dist/interfaces/ISimulator.d.ts +7 -36
- package/dist/interfaces/ITACTransactionManager.d.ts +15 -0
- package/dist/interfaces/ITONTransactionManager.d.ts +21 -0
- package/dist/interfaces/ITONTransactionManager.js +2 -0
- package/dist/interfaces/ITacSDK.d.ts +51 -13
- package/dist/interfaces/index.d.ts +2 -1
- package/dist/interfaces/index.js +2 -1
- package/dist/sdk/Configuration.d.ts +1 -0
- package/dist/sdk/Configuration.js +67 -14
- package/dist/sdk/Consts.d.ts +1 -0
- package/dist/sdk/Consts.js +5 -4
- package/dist/sdk/LiteSequencerClient.d.ts +5 -3
- package/dist/sdk/LiteSequencerClient.js +27 -4
- package/dist/sdk/OperationTracker.d.ts +3 -1
- package/dist/sdk/OperationTracker.js +51 -11
- package/dist/sdk/Simulator.d.ts +6 -12
- package/dist/sdk/Simulator.js +30 -124
- package/dist/sdk/TACTransactionManager.d.ts +10 -0
- package/dist/sdk/TACTransactionManager.js +92 -0
- package/dist/sdk/TONTransactionManager.d.ts +17 -0
- package/dist/sdk/TONTransactionManager.js +209 -0
- package/dist/sdk/TacSdk.d.ts +16 -10
- package/dist/sdk/TacSdk.js +52 -19
- package/dist/sdk/TxFinalizer.d.ts +3 -2
- package/dist/sdk/TxFinalizer.js +8 -8
- package/dist/sdk/Utils.d.ts +9 -4
- package/dist/sdk/Utils.js +86 -12
- package/dist/sdk/Validator.d.ts +2 -2
- package/dist/sdk/Validator.js +1 -1
- package/dist/structs/InternalStruct.d.ts +6 -2
- package/dist/structs/Struct.d.ts +70 -16
- package/dist/wrappers/Settings.d.ts +5 -1
- package/dist/wrappers/Settings.js +17 -0
- package/package.json +4 -3
- package/dist/interfaces/ITransactionManager.d.ts +0 -35
- package/dist/sdk/TransactionManager.d.ts +0 -22
- package/dist/sdk/TransactionManager.js +0 -272
- /package/dist/interfaces/{ITransactionManager.js → ITACTransactionManager.js} +0 -0
|
@@ -7,6 +7,7 @@ const Struct_1 = require("../structs/Struct");
|
|
|
7
7
|
const LiteSequencerClient_1 = require("./LiteSequencerClient");
|
|
8
8
|
const Logger_1 = require("./Logger");
|
|
9
9
|
const Utils_1 = require("./Utils");
|
|
10
|
+
const Validator_1 = require("./Validator");
|
|
10
11
|
class DefaultLiteSequencerClientFactory {
|
|
11
12
|
createClients(endpoints) {
|
|
12
13
|
return endpoints.map((endpoint) => new LiteSequencerClient_1.LiteSequencerClient(endpoint));
|
|
@@ -40,7 +41,7 @@ class OperationTracker {
|
|
|
40
41
|
this.logger.error('All endpoints failed to get operation id by transactionHash');
|
|
41
42
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
42
43
|
};
|
|
43
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
44
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting operation ID by transaction hash") : await requestFn();
|
|
44
45
|
}
|
|
45
46
|
async getOperationType(operationId, waitOptions) {
|
|
46
47
|
this.logger.debug(`Getting operation type for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
@@ -60,7 +61,7 @@ class OperationTracker {
|
|
|
60
61
|
this.logger.error('All endpoints failed to get operation type');
|
|
61
62
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
62
63
|
};
|
|
63
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
64
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting operation type") : await requestFn();
|
|
64
65
|
}
|
|
65
66
|
async getOperationId(transactionLinker, waitOptions) {
|
|
66
67
|
this.logger.debug(`Getting operation ID for transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
@@ -80,7 +81,7 @@ class OperationTracker {
|
|
|
80
81
|
this.logger.error('All endpoints failed to get operation id');
|
|
81
82
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
82
83
|
};
|
|
83
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
84
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting operation ID by transaction linker") : await requestFn();
|
|
84
85
|
}
|
|
85
86
|
async getOperationIdsByShardsKeys(shardsKeys, caller, waitOptions, chunkSize = 100) {
|
|
86
87
|
this.logger.debug(`Getting operation IDs for shards keys: ${(0, Utils_1.formatObjectForLogging)(shardsKeys)}`);
|
|
@@ -101,7 +102,7 @@ class OperationTracker {
|
|
|
101
102
|
this.logger.error('All endpoints failed to get operation ids by shards keys');
|
|
102
103
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
103
104
|
};
|
|
104
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
105
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting operation IDs by shards keys") : await requestFn();
|
|
105
106
|
}
|
|
106
107
|
async getStageProfiling(operationId, waitOptions) {
|
|
107
108
|
this.logger.debug(`Getting stage profiling for operation ${operationId}`);
|
|
@@ -126,7 +127,7 @@ class OperationTracker {
|
|
|
126
127
|
this.logger.error('All endpoints failed to get stage profiling');
|
|
127
128
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
128
129
|
};
|
|
129
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
130
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting stage profiling") : await requestFn();
|
|
130
131
|
}
|
|
131
132
|
async getStageProfilings(operationIds, waitOptions, chunkSize = 100) {
|
|
132
133
|
this.logger.debug(`Getting stage profilings for operations: ${operationIds.join(', ')}`);
|
|
@@ -147,7 +148,7 @@ class OperationTracker {
|
|
|
147
148
|
this.logger.error('All endpoints failed to get stage profilings');
|
|
148
149
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
149
150
|
};
|
|
150
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
151
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting stage profilings") : await requestFn();
|
|
151
152
|
}
|
|
152
153
|
async getOperationStatuses(operationIds, waitOptions, chunkSize = 100) {
|
|
153
154
|
this.logger.debug(`Getting operation statuses for operations: ${(0, Utils_1.formatObjectForLogging)(operationIds)}`);
|
|
@@ -168,7 +169,7 @@ class OperationTracker {
|
|
|
168
169
|
this.logger.error('All endpoints failed to get operation statuses');
|
|
169
170
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
170
171
|
};
|
|
171
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
172
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting operation statuses") : await requestFn();
|
|
172
173
|
}
|
|
173
174
|
async getOperationStatus(operationId, waitOptions) {
|
|
174
175
|
this.logger.debug(`Getting operation status for ${(0, Utils_1.formatObjectForLogging)(operationId)}`);
|
|
@@ -193,7 +194,7 @@ class OperationTracker {
|
|
|
193
194
|
this.logger.error('All endpoints failed to get operation status');
|
|
194
195
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
195
196
|
};
|
|
196
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
197
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting operation status") : await requestFn();
|
|
197
198
|
}
|
|
198
199
|
async getSimplifiedOperationStatus(transactionLinker) {
|
|
199
200
|
this.logger.debug(`Getting simplified operation status for transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
|
|
@@ -202,9 +203,7 @@ class OperationTracker {
|
|
|
202
203
|
this.logger.warn('Operation ID not found');
|
|
203
204
|
return Struct_1.SimplifiedStatuses.OPERATION_ID_NOT_FOUND;
|
|
204
205
|
}
|
|
205
|
-
this.logger.debug(`Operation ID: ${operationId}`);
|
|
206
206
|
const operationType = await this.getOperationType(operationId);
|
|
207
|
-
this.logger.debug(`Operation type: ${operationType}`);
|
|
208
207
|
if (operationType == Struct_1.OperationType.PENDING || operationType == Struct_1.OperationType.UNKNOWN) {
|
|
209
208
|
return Struct_1.SimplifiedStatuses.PENDING;
|
|
210
209
|
}
|
|
@@ -231,7 +230,48 @@ class OperationTracker {
|
|
|
231
230
|
this.logger.error('All endpoints failed to convert currency');
|
|
232
231
|
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
233
232
|
};
|
|
234
|
-
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn) : await requestFn();
|
|
233
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Converting currency") : await requestFn();
|
|
234
|
+
}
|
|
235
|
+
async simulateTACMessage(params, waitOptions) {
|
|
236
|
+
Validator_1.Validator.validateTACSimulationParams(params);
|
|
237
|
+
this.logger.debug(`Simulating TAC message: ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
238
|
+
const requestFn = async () => {
|
|
239
|
+
let lastError;
|
|
240
|
+
for (const client of this.clients) {
|
|
241
|
+
try {
|
|
242
|
+
const result = await client.simulateTACMessage(params);
|
|
243
|
+
this.logger.debug(`Simulation result retrieved successfully`);
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
this.logger.warn(`Failed to simulate TAC message using one of the endpoints`);
|
|
248
|
+
lastError = error;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
this.logger.error('All endpoints failed to simulate TAC message');
|
|
252
|
+
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
253
|
+
};
|
|
254
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Simulating TAC message") : await requestFn();
|
|
255
|
+
}
|
|
256
|
+
async getTVMExecutorFee(params, waitOptions) {
|
|
257
|
+
this.logger.debug(`get TVM executor fee: ${(0, Utils_1.formatObjectForLogging)(params)}`);
|
|
258
|
+
const requestFn = async () => {
|
|
259
|
+
let lastError;
|
|
260
|
+
for (const client of this.clients) {
|
|
261
|
+
try {
|
|
262
|
+
const result = await client.getTVMExecutorFee(params);
|
|
263
|
+
this.logger.debug(`Suggested TVM executor fee retrieved successfully`);
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
this.logger.warn(`Failed to get TVM executor fee using one of the endpoints`);
|
|
268
|
+
lastError = error;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
this.logger.error('All endpoints failed to get TVM executor fee');
|
|
272
|
+
throw (0, errors_1.allEndpointsFailedError)(lastError);
|
|
273
|
+
};
|
|
274
|
+
return waitOptions ? await (0, Utils_1.waitUntilSuccess)(waitOptions, requestFn, "OperationTracker: Getting TVM executor fee") : await requestFn();
|
|
235
275
|
}
|
|
236
276
|
}
|
|
237
277
|
exports.OperationTracker = OperationTracker;
|
package/dist/sdk/Simulator.d.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IHttpClient } from '../interfaces';
|
|
1
|
+
import { IConfiguration, ILogger, IOperationTracker, ISimulator } from '../interfaces';
|
|
3
2
|
import type { SenderAbstraction } from '../sender';
|
|
4
|
-
import { CrosschainTx,
|
|
3
|
+
import { CrosschainTx, ExecutionFeeEstimationResult } from '../structs/Struct';
|
|
5
4
|
export declare class Simulator implements ISimulator {
|
|
6
5
|
private readonly config;
|
|
6
|
+
private readonly operationTracker;
|
|
7
7
|
private readonly logger;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
simulateTransactions(sender: SenderAbstraction, txs: CrosschainTx[]): Promise<TACSimulationResult[]>;
|
|
12
|
-
private buildTACSimulationRequest;
|
|
13
|
-
getTVMExecutorFeeInfo(assets: Asset[], feeSymbol: string, tvmValidExecutors?: string[]): Promise<SuggestedTONExecutorFee>;
|
|
14
|
-
private getFeeInfo;
|
|
15
|
-
getTransactionSimulationInfo(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: Asset[]): Promise<ExecutionFeeEstimationResult>;
|
|
16
|
-
getSimulationInfoForTransaction(evmProxyMsg: EvmProxyMsg, transactionLinker: TransactionLinker, assets: Asset[], allowSimulationError?: boolean, isRoundTrip?: boolean, evmValidExecutors?: string[], tvmValidExecutors?: string[], calculateRollbackFee?: boolean): Promise<ExecutionFeeEstimationResult>;
|
|
8
|
+
constructor(config: IConfiguration, operationTracker: IOperationTracker, logger?: ILogger);
|
|
9
|
+
getSimulationsInfo(sender: SenderAbstraction, txs: CrosschainTx[]): Promise<ExecutionFeeEstimationResult[]>;
|
|
10
|
+
getSimulationInfo(sender: SenderAbstraction, tx: CrosschainTx): Promise<ExecutionFeeEstimationResult>;
|
|
17
11
|
}
|
package/dist/sdk/Simulator.js
CHANGED
|
@@ -2,162 +2,68 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Simulator = void 0;
|
|
4
4
|
const ton_1 = require("@ton/ton");
|
|
5
|
-
const errors_1 = require("../errors");
|
|
6
|
-
const AxiosHttpClient_1 = require("./AxiosHttpClient");
|
|
7
5
|
const Logger_1 = require("./Logger");
|
|
8
6
|
const Utils_1 = require("./Utils");
|
|
9
7
|
const Validator_1 = require("./Validator");
|
|
10
8
|
class Simulator {
|
|
11
|
-
constructor(config, logger = new Logger_1.NoopLogger()
|
|
9
|
+
constructor(config, operationTracker, logger = new Logger_1.NoopLogger()) {
|
|
12
10
|
this.config = config;
|
|
11
|
+
this.operationTracker = operationTracker;
|
|
13
12
|
this.logger = logger;
|
|
14
|
-
this.httpClient = httpClient;
|
|
15
13
|
}
|
|
16
|
-
async
|
|
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) {
|
|
14
|
+
async getSimulationsInfo(sender, txs) {
|
|
36
15
|
this.logger.debug(`Simulating ${txs.length} TAC messages`);
|
|
37
16
|
const results = [];
|
|
38
17
|
for (const tx of txs) {
|
|
39
|
-
const
|
|
40
|
-
const result = await this.simulateTACMessage(req);
|
|
18
|
+
const result = await this.getSimulationInfo(sender, tx);
|
|
41
19
|
results.push(result);
|
|
42
20
|
}
|
|
43
21
|
return results;
|
|
44
22
|
}
|
|
45
|
-
async
|
|
23
|
+
async getSimulationInfo(sender, tx) {
|
|
24
|
+
this.logger.debug('Getting simulation info');
|
|
46
25
|
const { evmProxyMsg, assets = [], options = {} } = tx;
|
|
47
|
-
const { evmValidExecutors = this.config.TACParams.trustedTACExecutors, tvmValidExecutors = this.config.TACParams.trustedTONExecutors, calculateRollbackFee = true, } = options;
|
|
26
|
+
const { evmValidExecutors = this.config.TACParams.trustedTACExecutors, tvmValidExecutors = this.config.TACParams.trustedTONExecutors, calculateRollbackFee = true, allowSimulationError = false, } = options;
|
|
27
|
+
Validator_1.Validator.validateEVMAddress(evmProxyMsg.evmTargetAddress);
|
|
48
28
|
Validator_1.Validator.validateEVMAddresses(evmValidExecutors);
|
|
49
29
|
Validator_1.Validator.validateTVMAddresses(tvmValidExecutors);
|
|
50
30
|
const aggregatedData = await (0, Utils_1.aggregateTokens)(assets);
|
|
51
|
-
const
|
|
52
|
-
const transactionLinker = (0, Utils_1.generateTransactionLinker)(sender.getSenderAddress(),
|
|
53
|
-
|
|
31
|
+
const shardCount = aggregatedData.jettons.length || 1;
|
|
32
|
+
const transactionLinker = (0, Utils_1.generateTransactionLinker)(sender.getSenderAddress(), shardCount);
|
|
33
|
+
const tacSimulationParams = {
|
|
54
34
|
tacCallParams: {
|
|
55
35
|
arguments: evmProxyMsg.encodedParameters ?? '0x',
|
|
56
36
|
methodName: (0, Utils_1.formatSolidityMethodName)(evmProxyMsg.methodName),
|
|
57
37
|
target: evmProxyMsg.evmTargetAddress,
|
|
58
38
|
},
|
|
59
|
-
evmValidExecutors
|
|
60
|
-
tvmValidExecutors
|
|
39
|
+
evmValidExecutors,
|
|
40
|
+
tvmValidExecutors,
|
|
61
41
|
extraData: '0x',
|
|
62
42
|
shardsKey: transactionLinker.shardsKey,
|
|
63
|
-
tonAssets:
|
|
64
|
-
amount: asset.rawAmount.toString(),
|
|
65
|
-
tokenAddress: asset.address || '',
|
|
66
|
-
assetType: asset.type,
|
|
67
|
-
})),
|
|
43
|
+
tonAssets: (0, Utils_1.mapAssetsToTonAssets)(assets),
|
|
68
44
|
tonCaller: transactionLinker.caller,
|
|
69
|
-
calculateRollbackFee
|
|
45
|
+
calculateRollbackFee,
|
|
70
46
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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);
|
|
47
|
+
const simulation = await this.operationTracker.simulateTACMessage(tacSimulationParams);
|
|
48
|
+
this.logger.debug(`TAC simulation ${simulation.simulationStatus ? 'success' : 'failed'}`);
|
|
49
|
+
const isRoundTrip = options.isRoundTrip ?? assets.length !== 0;
|
|
102
50
|
const crossChainLayer = this.config.TONParams.contractOpener.open(this.config.artifacts.ton.wrappers.CrossChainLayer.createFromAddress(ton_1.Address.parse(this.config.TONParams.crossChainLayerAddress)));
|
|
103
51
|
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
52
|
const feeParams = {
|
|
130
|
-
isRoundTrip
|
|
131
|
-
gasLimit:
|
|
132
|
-
protocolFee:
|
|
133
|
-
|
|
134
|
-
|
|
53
|
+
isRoundTrip,
|
|
54
|
+
gasLimit: simulation.simulationStatus ? simulation.estimatedGas : 0n,
|
|
55
|
+
protocolFee: BigInt((0, ton_1.toNano)(fullStateCCL.tacProtocolFee)) +
|
|
56
|
+
BigInt(isRoundTrip) * BigInt((0, ton_1.toNano)(fullStateCCL.tonProtocolFee)),
|
|
57
|
+
evmExecutorFee: BigInt(simulation.suggestedTacExecutionFee),
|
|
58
|
+
tvmExecutorFee: BigInt(simulation.suggestedTonExecutionFee) * BigInt(isRoundTrip),
|
|
135
59
|
};
|
|
136
|
-
if (!
|
|
137
|
-
|
|
138
|
-
this.logger.info('Force send is true, returning fee params');
|
|
139
|
-
return {
|
|
140
|
-
feeParams,
|
|
141
|
-
simulation: tacSimulationResult,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
throw tacSimulationResult;
|
|
60
|
+
if (!simulation.simulationStatus && !allowSimulationError) {
|
|
61
|
+
throw simulation;
|
|
145
62
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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);
|
|
63
|
+
if (allowSimulationError && !simulation.simulationStatus) {
|
|
64
|
+
this.logger.info('Simulation failed but allowSimulationError is true, returning partial fee params');
|
|
65
|
+
}
|
|
66
|
+
return { feeParams, simulation };
|
|
161
67
|
}
|
|
162
68
|
}
|
|
163
69
|
exports.Simulator = Simulator;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Wallet } from 'ethers';
|
|
2
|
+
import { Asset, IConfiguration, ILogger, IOperationTracker, ITACTransactionManager } from '../interfaces';
|
|
3
|
+
export declare class TACTransactionManager implements ITACTransactionManager {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private readonly operationTracker;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
constructor(config: IConfiguration, operationTracker: IOperationTracker, logger?: ILogger);
|
|
8
|
+
private approveAsset;
|
|
9
|
+
bridgeTokensToTON(signer: Wallet, value: bigint, tonTarget: string, assets?: Asset[], tvmExecutorFee?: bigint, tvmValidExecutors?: string[]): Promise<string>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TACTransactionManager = void 0;
|
|
4
|
+
const assets_1 = require("../assets");
|
|
5
|
+
const Struct_1 = require("../structs/Struct");
|
|
6
|
+
const Consts_1 = require("./Consts");
|
|
7
|
+
const Logger_1 = require("./Logger");
|
|
8
|
+
const Utils_1 = require("./Utils");
|
|
9
|
+
const Validator_1 = require("./Validator");
|
|
10
|
+
class TACTransactionManager {
|
|
11
|
+
constructor(config, operationTracker, logger = new Logger_1.NoopLogger()) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.operationTracker = operationTracker;
|
|
14
|
+
this.logger = logger;
|
|
15
|
+
}
|
|
16
|
+
async approveAsset(asset, signer, spenderAddress) {
|
|
17
|
+
const evmAddress = await asset.getEVMAddress();
|
|
18
|
+
if (asset.type === Struct_1.AssetType.FT) {
|
|
19
|
+
this.logger.debug(`Approving FT ${evmAddress} for ${spenderAddress}`);
|
|
20
|
+
const contract = this.config.artifacts.tac.wrappers.ERC20FactoryTAC.connect(evmAddress, this.config.TACParams.provider);
|
|
21
|
+
const tx = await contract.connect(signer).approve(spenderAddress, asset.rawAmount);
|
|
22
|
+
await tx.wait();
|
|
23
|
+
}
|
|
24
|
+
else if (asset.type === Struct_1.AssetType.NFT) {
|
|
25
|
+
this.logger.debug(`Approving NFT ${evmAddress} for ${spenderAddress}`);
|
|
26
|
+
const contract = this.config.artifacts.tac.wrappers.ERC721FactoryTAC.connect(evmAddress, this.config.TACParams.provider);
|
|
27
|
+
const tx = await contract.connect(signer).approve(spenderAddress, asset.addresses.index);
|
|
28
|
+
await tx.wait();
|
|
29
|
+
}
|
|
30
|
+
this.logger.debug(`Approved ${evmAddress} for ${spenderAddress}`);
|
|
31
|
+
}
|
|
32
|
+
async bridgeTokensToTON(signer, value, tonTarget, assets = [], tvmExecutorFee, tvmValidExecutors) {
|
|
33
|
+
this.logger.debug('Bridging tokens to TON');
|
|
34
|
+
Validator_1.Validator.validateTVMAddress(tonTarget);
|
|
35
|
+
// Add native TAC asset if value > 0
|
|
36
|
+
if (value > 0n) {
|
|
37
|
+
const nativeTacAsset = (await assets_1.AssetFactory.from(this.config, {
|
|
38
|
+
address: await this.config.nativeTACAddress(),
|
|
39
|
+
tokenType: Struct_1.AssetType.FT,
|
|
40
|
+
})).withRawAmount(value);
|
|
41
|
+
assets = [...assets, nativeTacAsset];
|
|
42
|
+
}
|
|
43
|
+
// Calculate executor fee if not provided
|
|
44
|
+
if (!tvmExecutorFee) {
|
|
45
|
+
const feeParams = {
|
|
46
|
+
tonAssets: (0, Utils_1.mapAssetsToTonAssets)(assets),
|
|
47
|
+
feeSymbol: Consts_1.TAC_SYMBOL,
|
|
48
|
+
tvmValidExecutors: tvmValidExecutors ?? [],
|
|
49
|
+
};
|
|
50
|
+
const suggestedFee = await this.operationTracker.getTVMExecutorFee(feeParams);
|
|
51
|
+
this.logger.debug(`Suggested TON executor fee: ${(0, Utils_1.formatObjectForLogging)(suggestedFee)}`);
|
|
52
|
+
tvmExecutorFee = BigInt(suggestedFee.inTAC);
|
|
53
|
+
}
|
|
54
|
+
// Approve all assets
|
|
55
|
+
const crossChainLayerAddress = await this.config.TACParams.crossChainLayer.getAddress();
|
|
56
|
+
await Promise.all(assets.map(asset => this.approveAsset(asset, signer, crossChainLayerAddress)));
|
|
57
|
+
const protocolFee = await this.config.TACParams.crossChainLayer.getProtocolFee();
|
|
58
|
+
const shardsKey = BigInt(Math.round(Math.random() * 1e18));
|
|
59
|
+
this.logger.debug(`Shards key: ${shardsKey}, Protocol fee: ${protocolFee}`);
|
|
60
|
+
// Prepare bridge data
|
|
61
|
+
const [toBridge, toBridgeNFT] = await Promise.all([
|
|
62
|
+
Promise.all(assets.filter(a => a.type === Struct_1.AssetType.FT).map(async (a) => ({
|
|
63
|
+
evmAddress: await a.getEVMAddress(),
|
|
64
|
+
amount: a.rawAmount,
|
|
65
|
+
}))),
|
|
66
|
+
Promise.all(assets.filter(a => a.type === Struct_1.AssetType.NFT).map(async (a) => ({
|
|
67
|
+
evmAddress: await a.getEVMAddress(),
|
|
68
|
+
amount: 1n,
|
|
69
|
+
tokenId: a.addresses.index,
|
|
70
|
+
}))),
|
|
71
|
+
]);
|
|
72
|
+
const outMessage = {
|
|
73
|
+
shardsKey,
|
|
74
|
+
tvmTarget: tonTarget,
|
|
75
|
+
tvmPayload: '',
|
|
76
|
+
tvmProtocolFee: protocolFee,
|
|
77
|
+
tvmExecutorFee,
|
|
78
|
+
tvmValidExecutors: this.config.getTrustedTONExecutors,
|
|
79
|
+
toBridge,
|
|
80
|
+
toBridgeNFT,
|
|
81
|
+
};
|
|
82
|
+
const totalValue = value + BigInt(outMessage.tvmProtocolFee) + BigInt(outMessage.tvmExecutorFee);
|
|
83
|
+
this.logger.debug(`Total value: ${totalValue}`);
|
|
84
|
+
const tx = await this.config.TACParams.crossChainLayer
|
|
85
|
+
.connect(signer)
|
|
86
|
+
.sendMessage(1n, this.config.artifacts.tac.utils.encodeOutMessageV1(outMessage), { value: totalValue });
|
|
87
|
+
await tx.wait();
|
|
88
|
+
this.logger.debug(`Transaction hash: ${tx.hash}`);
|
|
89
|
+
return tx.hash;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.TACTransactionManager = TACTransactionManager;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IConfiguration, ILogger, IOperationTracker, ISimulator, ITONTransactionManager } from '../interfaces';
|
|
2
|
+
import type { SenderAbstraction } from '../sender';
|
|
3
|
+
import { CrosschainTx, EvmProxyMsg, OperationIdsByShardsKey, TransactionLinkerWithOperationId, WaitOptions } from '../structs/Struct';
|
|
4
|
+
export declare class TONTransactionManager implements ITONTransactionManager {
|
|
5
|
+
private readonly config;
|
|
6
|
+
private readonly simulator;
|
|
7
|
+
private readonly operationTracker;
|
|
8
|
+
private readonly logger;
|
|
9
|
+
constructor(config: IConfiguration, simulator: ISimulator, operationTracker: IOperationTracker, logger?: ILogger);
|
|
10
|
+
private buildFeeParams;
|
|
11
|
+
private prepareCrossChainTransaction;
|
|
12
|
+
private generateCrossChainMessages;
|
|
13
|
+
sendCrossChainTransaction(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, tx: CrosschainTx, waitOptions?: WaitOptions<string>): Promise<TransactionLinkerWithOperationId>;
|
|
14
|
+
sendCrossChainTransactions(sender: SenderAbstraction, txs: CrosschainTx[], waitOptions?: WaitOptions<OperationIdsByShardsKey>): Promise<TransactionLinkerWithOperationId[]>;
|
|
15
|
+
private prepareBatchTransactions;
|
|
16
|
+
private waitForOperationIds;
|
|
17
|
+
}
|