@tonappchain/sdk 0.6.5-mainnet-alpha → 0.6.6-mainnet-alpha

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.
@@ -1,8 +1,9 @@
1
+ import { mainnet, testnet } from '@tonappchain/artifacts';
1
2
  import { Wallet } from 'ethers';
2
3
  import type { SenderAbstraction } from '../sender';
3
- import { AssetBridgingData, EvmProxyMsg, Network, SDKParams, TransactionLinker, RawAssetBridgingData, UserWalletBalanceExtended, TACSimulationResult, TACSimulationRequest, SuggestedTONExecutorFee, CrossChainTransactionOptions, ExecutionFeeEstimationResult, CrosschainTx, WithAddressNFTCollectionItem, NFTAddressType, NFTItemData } from '../structs/Struct';
4
- import { InternalTONParams, InternalTACParams } from '../structs/InternalStruct';
5
- import { mainnet, testnet } from '@tonappchain/artifacts';
4
+ import { InternalTACParams, InternalTONParams } from '../structs/InternalStruct';
5
+ import { AssetBridgingData, CrossChainTransactionOptions, CrosschainTx, EvmProxyMsg, ExecutionFeeEstimationResult, Network, NFTAddressType, NFTItemData, OperationIdsByShardsKey, RawAssetBridgingData, SDKParams, SuggestedTONExecutorFee, TACSimulationRequest, TACSimulationResult, TransactionLinkerWithOperationId, UserWalletBalanceExtended, WaitOptions, WithAddressNFTCollectionItem } from '../structs/Struct';
6
+ import { OperationTracker } from './OperationTracker';
6
7
  export declare class TacSdk {
7
8
  readonly network: Network;
8
9
  readonly delay: number;
@@ -10,6 +11,8 @@ export declare class TacSdk {
10
11
  readonly TONParams: InternalTONParams;
11
12
  readonly TACParams: InternalTACParams;
12
13
  readonly liteSequencerEndpoints: string[];
14
+ readonly operationTracker: OperationTracker;
15
+ readonly debug: boolean;
13
16
  private constructor();
14
17
  static create(sdkParams: SDKParams): Promise<TacSdk>;
15
18
  private static prepareTONParams;
@@ -25,6 +28,7 @@ export declare class TacSdk {
25
28
  private getNFTBurnPayload;
26
29
  private getNFTTransferPayload;
27
30
  private getTonTransferPayload;
31
+ private debugLog;
28
32
  private getJettonOpType;
29
33
  private getNFTOpType;
30
34
  private getNFTItemAddressTON;
@@ -37,10 +41,10 @@ export declare class TacSdk {
37
41
  private convertAssetsToRawFormat;
38
42
  private getFeeInfo;
39
43
  getTransactionSimulationInfo(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: AssetBridgingData[]): Promise<ExecutionFeeEstimationResult>;
40
- getTVMExecutorFeeInfo(assets: AssetBridgingData[], feeSymbol: String): Promise<SuggestedTONExecutorFee>;
44
+ getTVMExecutorFeeInfo(assets: AssetBridgingData[], feeSymbol: string): Promise<SuggestedTONExecutorFee>;
41
45
  private prepareCrossChainTransaction;
42
- sendCrossChainTransaction(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: AssetBridgingData[], options?: CrossChainTransactionOptions): Promise<TransactionLinker>;
43
- sendCrossChainTransactions(sender: SenderAbstraction, txs: CrosschainTx[]): Promise<TransactionLinker[]>;
46
+ sendCrossChainTransaction(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: AssetBridgingData[], options?: CrossChainTransactionOptions, waitOptions?: WaitOptions<string>): Promise<TransactionLinkerWithOperationId>;
47
+ sendCrossChainTransactions(sender: SenderAbstraction, txs: CrosschainTx[], waitOptions?: WaitOptions<OperationIdsByShardsKey>): Promise<TransactionLinkerWithOperationId[]>;
44
48
  bridgeTokensToTON(signer: Wallet, value: bigint, tonTarget: string, assets?: RawAssetBridgingData<WithAddressNFTCollectionItem>[], tvmExecutorFee?: bigint): Promise<string>;
45
49
  get getTrustedTACExecutors(): string[];
46
50
  get getTrustedTONExecutors(): string[];
@@ -4,32 +4,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.TacSdk = void 0;
7
- const axios_1 = __importDefault(require("axios"));
8
7
  const ton_1 = require("@ton/ton");
8
+ const artifacts_1 = require("@tonappchain/artifacts");
9
+ const wrappers_1 = require("@tonappchain/artifacts/dist/src/ton/wrappers");
10
+ const axios_1 = __importDefault(require("axios"));
9
11
  const ethers_1 = require("ethers");
10
- // import structs
11
- const Struct_1 = require("../structs/Struct");
12
+ const errors_1 = require("../errors");
13
+ const instances_1 = require("../errors/instances");
14
+ const retryableContractOpener_1 = require("../adapters/retryableContractOpener");
12
15
  // import internal structs
13
16
  const InternalStruct_1 = require("../structs/InternalStruct");
17
+ // import structs
18
+ const Struct_1 = require("../structs/Struct");
14
19
  // jetton imports
15
20
  const JettonMaster_1 = require("../wrappers/JettonMaster");
16
21
  const JettonWallet_1 = require("../wrappers/JettonWallet");
17
22
  // ton settings
18
23
  const Settings_1 = require("../wrappers/Settings");
19
24
  const Consts_1 = require("./Consts");
25
+ const OperationTracker_1 = require("./OperationTracker");
20
26
  const Utils_1 = require("./Utils");
21
- const artifacts_1 = require("@tonappchain/artifacts");
22
- const errors_1 = require("../errors");
23
- const wrappers_1 = require("@tonappchain/artifacts/dist/src/ton/wrappers");
24
- const instances_1 = require("../errors/instances");
25
27
  class TacSdk {
26
- constructor(network, delay, artifacts, TONParams, TACParams, liteSequencerEndpoints) {
28
+ constructor(network, delay, artifacts, TONParams, TACParams, liteSequencerEndpoints, debug) {
27
29
  this.network = network;
28
30
  this.delay = delay;
29
31
  this.artifacts = artifacts;
30
32
  this.TONParams = TONParams;
31
33
  this.TACParams = TACParams;
32
34
  this.liteSequencerEndpoints = liteSequencerEndpoints;
35
+ this.debug = debug;
36
+ this.operationTracker = new OperationTracker_1.OperationTracker(network, liteSequencerEndpoints, debug);
33
37
  }
34
38
  static async create(sdkParams) {
35
39
  const network = sdkParams.network;
@@ -37,19 +41,16 @@ class TacSdk {
37
41
  const artifacts = network === Struct_1.Network.TESTNET ? artifacts_1.testnet : artifacts_1.mainnet;
38
42
  const TONParams = await this.prepareTONParams(delay, artifacts, sdkParams.TONParams);
39
43
  const TACParams = await this.prepareTACParams(artifacts, delay, sdkParams.TACParams);
44
+ const debug = sdkParams.debug ?? false;
40
45
  const liteSequencerEndpoints = sdkParams.customLiteSequencerEndpoints ??
41
46
  (network === Struct_1.Network.TESTNET
42
47
  ? artifacts_1.testnet.PUBLIC_LITE_SEQUENCER_ENDPOINTS
43
48
  : artifacts_1.mainnet.PUBLIC_LITE_SEQUENCER_ENDPOINTS);
44
- return new TacSdk(network, delay, artifacts, TONParams, TACParams, liteSequencerEndpoints);
49
+ return new TacSdk(network, delay, artifacts, TONParams, TACParams, liteSequencerEndpoints, debug);
45
50
  }
46
51
  static async prepareTONParams(delay, artifacts, TONParams) {
47
- const contractOpener = TONParams?.contractOpener ??
48
- new ton_1.TonClient({
49
- endpoint: new URL('api/v2/jsonRPC', artifacts.TON_RPC_ENDPOINT_BY_TAC).toString()
50
- });
51
- const settingsAddress = TONParams?.settingsAddress
52
- ?? artifacts.TON_SETTINGS_ADDRESS;
52
+ const contractOpener = TONParams?.contractOpener ?? (await (0, retryableContractOpener_1.createDefaultRetryableOpener)(artifacts));
53
+ const settingsAddress = TONParams?.settingsAddress ?? artifacts.TON_SETTINGS_ADDRESS;
53
54
  const settings = contractOpener.open(new Settings_1.Settings(ton_1.Address.parse(settingsAddress)));
54
55
  const jettonProxyAddress = await settings.getAddressSetting('JettonProxyAddress');
55
56
  await (0, Utils_1.sleep)(delay * 1000);
@@ -78,8 +79,7 @@ class TacSdk {
78
79
  }
79
80
  static async prepareTACParams(artifacts, delay, TACParams) {
80
81
  const provider = TACParams?.provider ?? ethers_1.ethers.getDefaultProvider(artifacts.TAC_RPC_ENDPOINT);
81
- const settingsAddress = TACParams?.settingsAddress?.toString()
82
- ?? artifacts.TAC_SETTINGS_ADDRESS;
82
+ const settingsAddress = TACParams?.settingsAddress?.toString() ?? artifacts.TAC_SETTINGS_ADDRESS;
83
83
  const settings = artifacts.tac.wrappers.SettingsFactoryTAC.connect(settingsAddress, provider);
84
84
  const crossChainLayerABI = TACParams?.crossChainLayerABI ?? artifacts.tac.compilationArtifacts.CrossChainLayer.abi;
85
85
  const crossChainLayerAddress = await settings.getAddressSetting((0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)('CrossChainLayerAddress')));
@@ -186,7 +186,13 @@ class TacSdk {
186
186
  .storeMaybeRef(evmData)
187
187
  .endCell();
188
188
  }
189
+ debugLog(message) {
190
+ if (this.debug) {
191
+ console.log(`[TacSdk Debug] ${message}`);
192
+ }
193
+ }
189
194
  async getJettonOpType(asset) {
195
+ this.debugLog(`Getting jetton op type for ${(0, Utils_1.formatObjectForLogging)(asset)}`);
190
196
  const { code: givenMinterCodeBOC } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(asset.address));
191
197
  if (!givenMinterCodeBOC) {
192
198
  throw errors_1.emptyContractError;
@@ -194,11 +200,13 @@ class TacSdk {
194
200
  const givenMinterCode = ton_1.Cell.fromBoc(givenMinterCodeBOC)[0];
195
201
  await (0, Utils_1.sleep)(this.delay * 1000);
196
202
  if (!this.TONParams.jettonMinterCode.equals(givenMinterCode)) {
203
+ this.debugLog(`Jetton ${(0, Utils_1.formatObjectForLogging)(asset)} requires JETTON_TRANSFER operation`);
197
204
  return InternalStruct_1.AssetOpType.JETTON_TRANSFER;
198
205
  }
199
206
  const givenMinter = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster((0, ton_1.address)(asset.address)));
200
207
  const evmAddress = await givenMinter.getEVMAddress();
201
208
  await (0, Utils_1.sleep)(this.delay * 1000);
209
+ this.debugLog(`Jetton ${(0, Utils_1.formatObjectForLogging)(asset)} has evm address ${evmAddress}`);
202
210
  const expectedMinterAddress = await (0, Utils_1.calculateContractAddress)(this.TONParams.jettonMinterCode, (0, ton_1.beginCell)()
203
211
  .storeCoins(0)
204
212
  .storeAddress((0, ton_1.address)(this.TONParams.crossChainLayerAddress))
@@ -208,11 +216,14 @@ class TacSdk {
208
216
  .storeStringTail(evmAddress)
209
217
  .endCell());
210
218
  if (!expectedMinterAddress.equals(givenMinter.address)) {
219
+ this.debugLog(`Jetton ${(0, Utils_1.formatObjectForLogging)(asset)} requires JETTON_TRANSFER operation`);
211
220
  return InternalStruct_1.AssetOpType.JETTON_TRANSFER;
212
221
  }
222
+ this.debugLog(`Jetton ${(0, Utils_1.formatObjectForLogging)(asset)} requires JETTON_BURN operation`);
213
223
  return InternalStruct_1.AssetOpType.JETTON_BURN;
214
224
  }
215
225
  async getNFTOpType(asset) {
226
+ this.debugLog(`Getting NFT op type for ${(0, Utils_1.formatObjectForLogging)(asset)}`);
216
227
  const { code: itemCodeBOC } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(asset.address));
217
228
  if (!itemCodeBOC) {
218
229
  throw errors_1.emptyContractError;
@@ -220,8 +231,10 @@ class TacSdk {
220
231
  const givenNFTItemCode = ton_1.Cell.fromBoc(itemCodeBOC)[0];
221
232
  await (0, Utils_1.sleep)(this.delay * 1000);
222
233
  if (!this.TONParams.nftItemCode.equals(givenNFTItemCode)) {
234
+ this.debugLog(`NFT ${(0, Utils_1.formatObjectForLogging)(asset)} requires NFT_TRANSFER operation`);
223
235
  return InternalStruct_1.AssetOpType.NFT_TRANSFER;
224
236
  }
237
+ this.debugLog(`NFT ${(0, Utils_1.formatObjectForLogging)(asset)} requires NFT_BURN operation`);
225
238
  return InternalStruct_1.AssetOpType.NFT_BURN;
226
239
  }
227
240
  async getNFTItemAddressTON(collectionAddress, itemIndex) {
@@ -235,6 +248,7 @@ class TacSdk {
235
248
  return await nftItem.getNFTData();
236
249
  }
237
250
  async aggregateTokens(assets) {
251
+ this.debugLog(`Aggregating tokens`);
238
252
  const uniqueAssetsMap = new Map();
239
253
  let crossChainTonAmount = 0n;
240
254
  for await (const asset of assets ?? []) {
@@ -255,6 +269,8 @@ class TacSdk {
255
269
  rawAmount,
256
270
  type: Struct_1.AssetType.FT,
257
271
  }));
272
+ this.debugLog(`Aggregated ${jettons.length} jettons`);
273
+ this.debugLog(`Crosschain ton amount: ${crossChainTonAmount}`);
258
274
  uniqueAssetsMap.clear();
259
275
  for await (const asset of assets ?? []) {
260
276
  if (asset.type !== Struct_1.AssetType.NFT)
@@ -267,6 +283,7 @@ class TacSdk {
267
283
  rawAmount,
268
284
  type: Struct_1.AssetType.NFT,
269
285
  }));
286
+ this.debugLog(`Aggregated ${nfts.length} nfts`);
270
287
  return {
271
288
  jettons,
272
289
  nfts,
@@ -274,9 +291,10 @@ class TacSdk {
274
291
  };
275
292
  }
276
293
  async generateJettonPayload(jetton, caller, evmData, crossChainTonAmount, forwardFeeTonAmount, feeParams) {
294
+ this.debugLog(`Generating jetton payload for ${(0, Utils_1.formatObjectForLogging)(jetton)}`);
277
295
  const opType = await this.getJettonOpType(jetton);
278
296
  await (0, Utils_1.sleep)(this.delay * 1000);
279
- console.log(`***** Jetton ${jetton.address} requires ${opType} operation`);
297
+ this.debugLog(`Generation fee data with params: ${(0, Utils_1.formatObjectForLogging)(feeParams)}`);
280
298
  const feeData = (0, Utils_1.generateFeeData)(feeParams);
281
299
  let payload;
282
300
  switch (opType) {
@@ -290,12 +308,14 @@ class TacSdk {
290
308
  payload = this.getJettonTransferPayload(jetton, caller, evmData, crossChainTonAmount, forwardFeeTonAmount, feeData);
291
309
  break;
292
310
  }
311
+ this.debugLog('Generating jetton payload success');
293
312
  return payload;
294
313
  }
295
314
  async generateNFTPayload(nft, caller, evmData, crossChainTonAmount, forwardFeeTonAmount, feeParams) {
315
+ this.debugLog(`Generating NFT payload for ${(0, Utils_1.formatObjectForLogging)(nft)}`);
296
316
  const opType = await this.getNFTOpType(nft);
297
317
  await (0, Utils_1.sleep)(this.delay * 1000);
298
- console.log(`***** NFT ${nft.address} requires ${opType} operation`);
318
+ this.debugLog(`Generation fee data with params: ${(0, Utils_1.formatObjectForLogging)(feeParams)}`);
299
319
  const feeData = (0, Utils_1.generateFeeData)(feeParams);
300
320
  let payload;
301
321
  switch (opType) {
@@ -319,11 +339,15 @@ class TacSdk {
319
339
  }, forwardFeeTonAmount);
320
340
  break;
321
341
  }
342
+ this.debugLog('Generating NFT payload success');
322
343
  return payload;
323
344
  }
324
345
  async generateCrossChainMessages(caller, evmData, aggregatedData, feeParams) {
346
+ this.debugLog(`Generating cross-chain messages`);
325
347
  let crossChainTonAmount = aggregatedData.crossChainTonAmount;
326
348
  let feeTonAmount = feeParams.protocolFee + feeParams.evmExecutorFee + feeParams.tvmExecutorFee;
349
+ this.debugLog(`Crosschain ton amount: ${crossChainTonAmount}`);
350
+ this.debugLog(`Fee ton amount: ${feeTonAmount}`);
327
351
  if (aggregatedData.jettons.length == 0 && aggregatedData.nfts.length == 0) {
328
352
  return [
329
353
  {
@@ -361,38 +385,51 @@ class TacSdk {
361
385
  feeTonAmount = 0n;
362
386
  currentFeeParams = undefined;
363
387
  }
388
+ this.debugLog('Generating cross-chain messages success');
364
389
  return messages;
365
390
  }
366
391
  async getRawAmount(asset, precalculatedAddress) {
392
+ this.debugLog(`Getting raw amount for ${(0, Utils_1.formatObjectForLogging)(precalculatedAddress ?? 'TON')}`);
367
393
  if ('rawAmount' in asset) {
368
- // User specified raw format amount
394
+ this.debugLog(`Provided raw amount: ${asset.rawAmount}`);
369
395
  return asset.rawAmount;
370
396
  }
371
397
  if (!precalculatedAddress) {
372
398
  // User specified TON Coin
373
- return (0, ton_1.toNano)(asset.amount);
399
+ const rawAmount = (0, ton_1.toNano)(asset.amount);
400
+ this.debugLog(`TON raw amount: ${rawAmount}`);
401
+ return rawAmount;
374
402
  }
375
403
  if (typeof asset.decimals === 'number') {
376
404
  // User manually set decimals
377
- return (0, Utils_1.calculateRawAmount)(asset.amount, asset.decimals);
405
+ const rawAmount = (0, Utils_1.calculateRawAmount)(asset.amount, asset.decimals);
406
+ this.debugLog(`Raw amount calculated from decimals: ${rawAmount}`);
407
+ return rawAmount;
378
408
  }
379
409
  // Get decimals from chain
380
410
  (0, Utils_1.validateTVMAddress)(precalculatedAddress);
411
+ this.debugLog('Getting decimals from chain');
381
412
  const contract = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster((0, ton_1.address)(precalculatedAddress)));
382
413
  const { content } = await contract.getJettonData();
383
414
  await (0, Utils_1.sleep)(this.delay * 1000);
384
415
  if (!content.metadata.decimals) {
385
416
  // if decimals not specified use default value 9
417
+ this.debugLog('Decimals not specified, using default value 9');
386
418
  return (0, ton_1.toNano)(asset.amount);
387
419
  }
388
- return (0, Utils_1.calculateRawAmount)(asset.amount, Number(content.metadata.decimals));
420
+ const rawAmount = (0, Utils_1.calculateRawAmount)(asset.amount, Number(content.metadata.decimals));
421
+ this.debugLog(`Raw amount calculated from decimals(${content.metadata.decimals}): ${rawAmount}`);
422
+ return rawAmount;
389
423
  }
390
424
  async convertAssetsToRawFormat(assets) {
425
+ this.debugLog(`Converting assets to raw format`);
391
426
  return await Promise.all((assets ?? []).map(async (asset) => {
427
+ this.debugLog(`Converting asset to raw format: ${(0, Utils_1.formatObjectForLogging)(asset)}`);
392
428
  if (asset.type === Struct_1.AssetType.FT) {
393
429
  const address = (0, ethers_1.isAddress)(asset.address)
394
430
  ? await this.getTVMTokenAddress(asset.address)
395
431
  : asset.address;
432
+ this.debugLog(`Token address on TON: ${address}`);
396
433
  return {
397
434
  address,
398
435
  rawAmount: await this.getRawAmount(asset, address),
@@ -404,6 +441,7 @@ class TacSdk {
404
441
  const address = (0, ethers_1.isAddress)(asset.collectionAddress)
405
442
  ? await this.getTVMNFTAddress(asset.collectionAddress, asset.itemIndex)
406
443
  : await this.getNFTItemAddressTON(asset.collectionAddress, asset.itemIndex);
444
+ this.debugLog(`NFT address on TON: ${address}`);
407
445
  await (0, Utils_1.sleep)(this.delay * 1000);
408
446
  return {
409
447
  address,
@@ -421,9 +459,12 @@ class TacSdk {
421
459
  throw instances_1.invalidAssetType;
422
460
  }));
423
461
  }
424
- async getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, forceSend = false, isRoundTrip = true, evmValidExecutors = this.TACParams.trustedTACExecutors) {
462
+ async getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, forceSend = false, isRoundTrip = true, evmValidExecutors = this.TACParams.trustedTACExecutors, tvmValidExecutors = this.TACParams.trustedTONExecutors) {
463
+ this.debugLog('Getting fee info');
425
464
  const crossChainLayer = this.TONParams.contractOpener.open(this.artifacts.ton.wrappers.CrossChainLayer.createFromAddress(ton_1.Address.parse(this.TONParams.crossChainLayerAddress)));
426
465
  const fullStateCCL = await crossChainLayer.getFullData();
466
+ await (0, Utils_1.sleep)(this.delay * 1000);
467
+ this.debugLog(`Full state CCL: ${(0, Utils_1.formatObjectForLogging)(fullStateCCL)}`);
427
468
  const tacSimulationBody = {
428
469
  tacCallParams: {
429
470
  arguments: evmProxyMsg.encodedParameters ?? '0x',
@@ -431,6 +472,7 @@ class TacSdk {
431
472
  target: evmProxyMsg.evmTargetAddress,
432
473
  },
433
474
  evmValidExecutors: evmValidExecutors,
475
+ tvmValidExecutors: tvmValidExecutors,
434
476
  extraData: '0x',
435
477
  shardsKey: transactionLinker.shardsKey,
436
478
  tonAssets: rawAssets.map((asset) => ({
@@ -440,10 +482,13 @@ class TacSdk {
440
482
  })),
441
483
  tonCaller: transactionLinker.caller,
442
484
  };
443
- isRoundTrip = isRoundTrip ?? (rawAssets.length != 0);
485
+ isRoundTrip = isRoundTrip ?? rawAssets.length != 0;
486
+ this.debugLog(`Is round trip: ${isRoundTrip}`);
444
487
  const tacSimulationResult = await this.simulateTACMessage(tacSimulationBody);
488
+ this.debugLog(`TAC simulation ${tacSimulationResult.simulationStatus ? 'success' : 'failed'}`);
445
489
  if (!tacSimulationResult.simulationStatus) {
446
490
  if (forceSend) {
491
+ this.debugLog('Force send is true, returning fee params');
447
492
  return {
448
493
  feeParams: {
449
494
  isRoundTrip,
@@ -467,16 +512,21 @@ class TacSdk {
467
512
  evmExecutorFee: BigInt(tacSimulationResult.suggestedTacExecutionFee),
468
513
  tvmExecutorFee: BigInt(tacSimulationResult.suggestedTonExecutionFee) * BigInt(isRoundTrip),
469
514
  };
515
+ this.debugLog(`Collected fee params: ${(0, Utils_1.formatObjectForLogging)(feeParams)}`);
470
516
  return { feeParams: feeParams, simulation: tacSimulationResult };
471
517
  }
472
518
  async getTransactionSimulationInfo(evmProxyMsg, sender, assets) {
519
+ this.debugLog('Getting transaction simulation info');
473
520
  const rawAssets = await this.convertAssetsToRawFormat(assets);
474
521
  const aggregatedData = await this.aggregateTokens(rawAssets);
475
522
  const transactionLinkerShardCount = aggregatedData.jettons.length == 0 ? 1 : aggregatedData.jettons.length;
523
+ this.debugLog(`Transaction linker shard count: ${transactionLinkerShardCount}`);
476
524
  const transactionLinker = (0, Utils_1.generateTransactionLinker)(sender.getSenderAddress(), transactionLinkerShardCount);
525
+ this.debugLog(`Transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
477
526
  return await this.getFeeInfo(evmProxyMsg, transactionLinker, rawAssets);
478
527
  }
479
528
  async getTVMExecutorFeeInfo(assets, feeSymbol) {
529
+ this.debugLog('Getting TVM executor fee info');
480
530
  const rawAssets = await this.convertAssetsToRawFormat(assets);
481
531
  const requestBody = {
482
532
  tonAssets: rawAssets.map((asset) => ({
@@ -493,26 +543,32 @@ class TacSdk {
493
543
  return response.data.response;
494
544
  }
495
545
  catch (error) {
496
- console.error(`Error while calculating tvm executor fee ${endpoint}:`, error);
546
+ this.debugLog(`Error while calculating tvm executor fee ${endpoint}: ${error}`);
497
547
  lastError = error;
498
548
  }
499
549
  }
550
+ this.debugLog('Error while calculating tvm executor fee on all endpoints');
500
551
  throw (0, errors_1.simulationError)(lastError);
501
552
  }
502
553
  async prepareCrossChainTransaction(evmProxyMsg, caller, assets, options) {
503
- let { forceSend = false, isRoundTrip = undefined, protocolFee = undefined, evmValidExecutors = [], evmExecutorFee = undefined, tvmValidExecutors = [], tvmExecutorFee = undefined, } = options || {};
554
+ this.debugLog('Preparing cross-chain transaction');
555
+ const { forceSend = false, isRoundTrip = undefined, protocolFee = undefined, evmExecutorFee = undefined, tvmExecutorFee = undefined, } = options || {};
556
+ let { evmValidExecutors = [], tvmValidExecutors = [] } = options || {};
504
557
  const rawAssets = await this.convertAssetsToRawFormat(assets);
505
558
  const aggregatedData = await this.aggregateTokens(rawAssets);
506
559
  const tokensLength = aggregatedData.jettons.length + aggregatedData.nfts.length;
507
- let transactionLinkerShardCount = tokensLength == 0 ? 1 : tokensLength;
560
+ this.debugLog(`Tokens length: ${tokensLength}`);
561
+ const transactionLinkerShardCount = tokensLength == 0 ? 1 : tokensLength;
562
+ this.debugLog(`Transaction linker shard count: ${transactionLinkerShardCount}`);
508
563
  const transactionLinker = (0, Utils_1.generateTransactionLinker)(caller, transactionLinkerShardCount);
564
+ this.debugLog(`Generated transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
509
565
  if (evmValidExecutors.length == 0) {
510
566
  evmValidExecutors = this.TACParams.trustedTACExecutors;
511
567
  }
512
568
  if (tvmValidExecutors.length == 0) {
513
569
  tvmValidExecutors = this.TACParams.trustedTONExecutors;
514
570
  }
515
- const { feeParams } = await this.getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, forceSend, isRoundTrip, evmValidExecutors);
571
+ const { feeParams } = await this.getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, forceSend, isRoundTrip, evmValidExecutors, tvmValidExecutors);
516
572
  if (evmProxyMsg.gasLimit == undefined) {
517
573
  evmProxyMsg.gasLimit = feeParams.gasLimit;
518
574
  }
@@ -525,10 +581,12 @@ class TacSdk {
525
581
  if (protocolFee != undefined) {
526
582
  feeParams.protocolFee = protocolFee;
527
583
  }
584
+ this.debugLog(`Resulting fee params: ${(0, Utils_1.formatObjectForLogging)(feeParams)}`);
528
585
  const validExecutors = {
529
586
  tac: evmValidExecutors,
530
587
  ton: tvmValidExecutors,
531
588
  };
589
+ this.debugLog(`Valid executors: ${(0, Utils_1.formatObjectForLogging)(validExecutors)}`);
532
590
  const evmData = (0, Utils_1.buildEvmDataCell)(transactionLinker, evmProxyMsg, validExecutors);
533
591
  const messages = await this.generateCrossChainMessages(caller, evmData, aggregatedData, feeParams);
534
592
  await (0, Utils_1.sleep)(this.delay * 1000);
@@ -537,34 +595,70 @@ class TacSdk {
537
595
  messages,
538
596
  network: this.network,
539
597
  };
598
+ this.debugLog('Transaction prepared');
540
599
  return { transaction, transactionLinker };
541
600
  }
542
- async sendCrossChainTransaction(evmProxyMsg, sender, assets, options) {
601
+ async sendCrossChainTransaction(evmProxyMsg, sender, assets, options, waitOptions) {
543
602
  const caller = sender.getSenderAddress();
603
+ this.debugLog(`Caller: ${caller}`);
544
604
  const { transaction, transactionLinker } = await this.prepareCrossChainTransaction(evmProxyMsg, caller, assets, options);
545
- console.log('*****Sending transaction: ', transaction);
605
+ this.debugLog(`*****Sending transaction: ${(0, Utils_1.formatObjectForLogging)(transaction)}`);
546
606
  const sendTransactionResult = await sender.sendShardTransaction(transaction, this.delay, this.network, this.TONParams.contractOpener);
547
- return { sendTransactionResult, ...transactionLinker };
607
+ return waitOptions
608
+ ? {
609
+ sendTransactionResult,
610
+ operationId: await this.operationTracker.getOperationId(transactionLinker, {
611
+ ...waitOptions,
612
+ successCheck: (operationId) => !!operationId,
613
+ log: this.debugLog.bind(this),
614
+ }),
615
+ ...transactionLinker,
616
+ }
617
+ : { sendTransactionResult, ...transactionLinker };
548
618
  }
549
- async sendCrossChainTransactions(sender, txs) {
619
+ async sendCrossChainTransactions(sender, txs, waitOptions) {
550
620
  const transactions = [];
551
621
  const transactionLinkers = [];
552
622
  const caller = sender.getSenderAddress();
623
+ this.debugLog(`Caller: ${caller}`);
624
+ this.debugLog('Preparing multiple cross-chain transactions');
553
625
  for (const { options, assets, evmProxyMsg } of txs) {
554
626
  const { transaction, transactionLinker } = await this.prepareCrossChainTransaction(evmProxyMsg, caller, assets, options);
555
627
  transactions.push(transaction);
556
628
  transactionLinkers.push(transactionLinker);
557
629
  }
558
- console.log('*****Sending transactions: ', transactions);
630
+ this.debugLog(`*****Sending transactions: ${(0, Utils_1.formatObjectForLogging)(transactions)}`);
559
631
  await sender.sendShardTransactions(transactions, this.delay, this.network, this.TONParams.contractOpener);
632
+ if (waitOptions) {
633
+ this.debugLog(`Waiting for operation IDs`);
634
+ try {
635
+ const operationIds = await this.operationTracker.getOperationIdsByShardsKeys(transactionLinkers.map((linker) => linker.shardsKey), caller, {
636
+ ...waitOptions,
637
+ log: this.debugLog.bind(this),
638
+ successCheck: (operationIds) => {
639
+ return (Object.keys(operationIds).length == transactionLinkers.length &&
640
+ Object.values(operationIds).every((ids) => ids.operationIds.length > 0));
641
+ },
642
+ });
643
+ this.debugLog(`Operation IDs: ${(0, Utils_1.formatObjectForLogging)(operationIds)}`);
644
+ return transactionLinkers.map((linker) => ({
645
+ ...linker,
646
+ operationId: operationIds[linker.shardsKey].operationIds.at(0),
647
+ }));
648
+ }
649
+ catch (error) {
650
+ this.debugLog(`Error while waiting for operation IDs: ${error}`);
651
+ }
652
+ }
560
653
  return transactionLinkers;
561
654
  }
562
655
  // TODO move to sdk.TAC, sdk.TON
563
656
  async bridgeTokensToTON(signer, value, tonTarget, assets, tvmExecutorFee) {
657
+ this.debugLog('Bridging tokens to TON');
564
658
  if (assets == undefined) {
565
659
  assets = [];
566
660
  }
567
- let tonAssets = [];
661
+ const tonAssets = [];
568
662
  for (const asset of assets) {
569
663
  if (asset.type == Struct_1.AssetType.FT) {
570
664
  const tvmAddress = await this.getTVMTokenAddress(asset.address);
@@ -583,7 +677,9 @@ class TacSdk {
583
677
  });
584
678
  }
585
679
  }
680
+ this.debugLog(`TON assets: ${(0, Utils_1.formatObjectForLogging)(tonAssets)}`);
586
681
  if (value > 0) {
682
+ this.debugLog('Adding native TAC to TON assets');
587
683
  const tvmAddress = await this.getTVMTokenAddress(await this.nativeTACAddress());
588
684
  tonAssets.push({
589
685
  address: tvmAddress,
@@ -592,21 +688,28 @@ class TacSdk {
592
688
  });
593
689
  }
594
690
  const suggestedTONExecutorFee = await this.getTVMExecutorFeeInfo(tonAssets, Consts_1.TAC_SYMBOL);
691
+ this.debugLog(`Suggested TON executor fee: ${(0, Utils_1.formatObjectForLogging)(suggestedTONExecutorFee)}`);
595
692
  const crossChainLayerAddress = await this.TACParams.crossChainLayer.getAddress();
596
693
  for (const asset of assets) {
597
694
  if (asset.type == Struct_1.AssetType.FT) {
695
+ this.debugLog(`Approving token ${asset.address} for ${crossChainLayerAddress}`);
598
696
  const tokenContract = this.artifacts.tac.wrappers.ERC20FactoryTAC.connect(asset.address, this.TACParams.provider);
599
697
  const tx = await tokenContract.connect(signer).approve(crossChainLayerAddress, asset.rawAmount);
600
698
  await tx.wait();
699
+ this.debugLog(`Approved ${asset.address} for ${crossChainLayerAddress}`);
601
700
  }
602
701
  if (asset.type == Struct_1.AssetType.NFT) {
702
+ this.debugLog(`Approving collection ${asset.collectionAddress} for ${crossChainLayerAddress}`);
603
703
  const tokenContract = this.artifacts.tac.wrappers.ERC721FactoryTAC.connect(asset.collectionAddress, this.TACParams.provider);
604
704
  const tx = await tokenContract.connect(signer).approve(crossChainLayerAddress, asset.itemIndex);
605
705
  await tx.wait();
706
+ this.debugLog(`Approved ${asset.collectionAddress} for ${crossChainLayerAddress}`);
606
707
  }
607
708
  }
608
709
  const shardsKey = BigInt(Math.round(Math.random() * 1e18));
710
+ this.debugLog(`Shards key: ${shardsKey}`);
609
711
  const protocolFee = await this.TACParams.crossChainLayer.getProtocolFee();
712
+ this.debugLog(`Protocol fee: ${protocolFee}`);
610
713
  const outMessage = {
611
714
  shardsKey: shardsKey,
612
715
  tvmTarget: tonTarget,
@@ -631,10 +734,12 @@ class TacSdk {
631
734
  const encodedOutMessage = this.artifacts.tac.utils.encodeOutMessageV1(outMessage);
632
735
  const outMsgVersion = 1n;
633
736
  const totalValue = value + BigInt(outMessage.tvmProtocolFee) + BigInt(outMessage.tvmExecutorFee);
737
+ this.debugLog(`Total value: ${totalValue}`);
634
738
  const tx = await this.TACParams.crossChainLayer
635
739
  .connect(signer)
636
740
  .sendMessage(outMsgVersion, encodedOutMessage, { value: totalValue });
637
741
  await tx.wait();
742
+ this.debugLog(`Transaction hash: ${tx.hash}`);
638
743
  return tx.hash;
639
744
  }
640
745
  get getTrustedTACExecutors() {
@@ -644,28 +749,34 @@ class TacSdk {
644
749
  return this.TACParams.trustedTONExecutors;
645
750
  }
646
751
  async getEVMTokenAddress(tvmTokenAddress) {
752
+ this.debugLog(`Getting EVM token address for ${tvmTokenAddress}`);
647
753
  if (tvmTokenAddress !== this.nativeTONAddress) {
648
754
  (0, Utils_1.validateTVMAddress)(tvmTokenAddress);
649
755
  tvmTokenAddress = ton_1.Address.parse(tvmTokenAddress).toString({ bounceable: true });
650
756
  const { code: givenMinterCodeBOC } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(tvmTokenAddress));
651
757
  await (0, Utils_1.sleep)(this.delay * 1000);
652
758
  if (givenMinterCodeBOC && this.TONParams.jettonMinterCode.equals(ton_1.Cell.fromBoc(givenMinterCodeBOC)[0])) {
759
+ this.debugLog(`Computing EVM token address using jetton minter`);
653
760
  const givenMinter = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster((0, ton_1.address)(tvmTokenAddress)));
654
761
  const evmAddress = await givenMinter.getEVMAddress();
655
762
  await (0, Utils_1.sleep)(this.delay * 1000);
656
763
  return evmAddress;
657
764
  }
658
765
  }
766
+ this.debugLog(`Computing EVM token address using token utils`);
659
767
  return this.TACParams.tokenUtils.computeAddress(tvmTokenAddress);
660
768
  }
661
769
  async getTVMTokenAddress(evmTokenAddress) {
770
+ this.debugLog(`Getting TVM token address for ${evmTokenAddress}`);
662
771
  (0, Utils_1.validateEVMAddress)(evmTokenAddress);
663
772
  const exists = await this.TACParams.tokenUtils['exists(address)'](evmTokenAddress);
664
773
  if (exists) {
774
+ this.debugLog(`Getting TVM token address using cross chain layer ERC20 factory`);
665
775
  const erc721Token = this.artifacts.tac.wrappers.CrossChainLayerERC20FactoryTAC.connect(evmTokenAddress, this.TACParams.provider);
666
776
  const info = await erc721Token.getInfo();
667
777
  return info.tvmAddress;
668
778
  }
779
+ this.debugLog(`Getting TVM token address using jetton minter`);
669
780
  const jettonMaster = JettonMaster_1.JettonMaster.createFromConfig({
670
781
  evmTokenAddress,
671
782
  crossChainLayerAddress: (0, ton_1.address)(this.TONParams.crossChainLayerAddress),
@@ -675,10 +786,12 @@ class TacSdk {
675
786
  return jettonMaster.address.toString();
676
787
  }
677
788
  async getTVMNFTAddress(evmNFTAddress, tokenId) {
789
+ this.debugLog(`Getting TVM NFT ${tokenId ? `item ${tokenId}` : 'collection'} address for ${evmNFTAddress}`);
678
790
  (0, Utils_1.validateEVMAddress)(evmNFTAddress);
679
791
  let nftCollection;
680
792
  const exists = await this.TACParams.tokenUtils['exists(address)'](evmNFTAddress);
681
793
  if (exists) {
794
+ this.debugLog(`Getting TVM NFT address using cross chain layer ERC721 factory`);
682
795
  const erc721Token = this.artifacts.tac.wrappers.CrossChainLayerERC721FactoryTAC.connect(evmNFTAddress, this.TACParams.provider);
683
796
  const info = await erc721Token.getInfo();
684
797
  nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromAddress((0, ton_1.address)(info.tvmAddress)));
@@ -687,9 +800,12 @@ class TacSdk {
687
800
  : (await nftCollection.getNFTAddressByIndex(tokenId)).toString();
688
801
  }
689
802
  else {
803
+ this.debugLog(`Getting TVM NFT address using TON NFT collection contract`);
690
804
  nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromConfig({
691
- ownerAddress: (0, ton_1.address)(this.TONParams.crossChainLayerAddress),
692
- content: (0, ton_1.beginCell)().endCell(),
805
+ adminAddress: (0, ton_1.address)(this.TONParams.crossChainLayerAddress),
806
+ newAdminAddress: null,
807
+ collectionContent: (0, ton_1.beginCell)().endCell(),
808
+ commonContent: (0, ton_1.beginCell)().endCell(),
693
809
  nftItemCode: this.TONParams.nftItemCode,
694
810
  originalAddress: evmNFTAddress,
695
811
  }, this.TONParams.nftCollectionCode));
@@ -698,43 +814,50 @@ class TacSdk {
698
814
  : wrappers_1.NFTItem.createFromConfig({
699
815
  collectionAddress: nftCollection.address,
700
816
  cclAddress: (0, ton_1.address)(this.TONParams.crossChainLayerAddress),
701
- // @ts-ignore // bigint can be used, wrapper is not typed properly
817
+ // @ts-expect-error // bigint can be used, wrapper is not typed properly
702
818
  index: tokenId,
703
819
  }, this.TONParams.nftItemCode).address.toString();
704
820
  }
705
821
  }
706
822
  async getEVMNFTAddress(tvmNFTAddress, addressType) {
823
+ this.debugLog(`Getting EVM NFT address for ${tvmNFTAddress}`);
707
824
  (0, Utils_1.validateTVMAddress)(tvmNFTAddress);
708
825
  tvmNFTAddress = ton_1.Address.parse(tvmNFTAddress).toString({ bounceable: true });
709
826
  if (addressType == Struct_1.NFTAddressType.ITEM) {
827
+ this.debugLog(`Retrieving collection address for item ${tvmNFTAddress}`);
710
828
  tvmNFTAddress = (await this.getNFTItemData(tvmNFTAddress)).collectionAddress.toString();
829
+ this.debugLog(`Collection address: ${tvmNFTAddress}`);
711
830
  addressType = Struct_1.NFTAddressType.COLLECTION;
712
831
  await (0, Utils_1.sleep)(this.delay * 1000);
713
832
  }
714
833
  const { code: givenNFTCollection } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(tvmNFTAddress));
715
834
  await (0, Utils_1.sleep)(this.delay * 1000);
716
835
  if (givenNFTCollection && this.TONParams.nftCollectionCode.equals(ton_1.Cell.fromBoc(givenNFTCollection)[0])) {
836
+ this.debugLog(`Getting EVM NFT address using TON NFT collection contract`);
717
837
  const nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromAddress((0, ton_1.address)(tvmNFTAddress)));
718
838
  const evmAddress = await nftCollection.getOriginalAddress();
719
839
  await (0, Utils_1.sleep)(this.delay * 1000);
720
840
  return evmAddress.toString();
721
841
  }
842
+ this.debugLog(`Computing EVM NFT address using token utils`);
722
843
  return this.TACParams.tokenUtils.computeAddressERC721(tvmNFTAddress);
723
844
  }
724
845
  async isContractDeployedOnTVM(address) {
725
846
  return (await this.TONParams.contractOpener.getContractState(ton_1.Address.parse(address))).state === 'active';
726
847
  }
727
848
  async simulateTACMessage(req) {
849
+ this.debugLog('Simulating TAC message');
728
850
  let lastError;
729
851
  for (const endpoint of this.liteSequencerEndpoints) {
730
852
  try {
731
853
  const response = await axios_1.default.post(new URL('tac/simulator/simulate-message', endpoint).toString(), req, {
732
854
  transformResponse: [Utils_1.toCamelCaseTransformer],
733
855
  });
856
+ this.debugLog('TAC message simulation success');
734
857
  return response.data.response;
735
858
  }
736
859
  catch (error) {
737
- console.error(`Error while simulating with ${endpoint}:`, error);
860
+ this.debugLog(`Error while simulating with ${endpoint}: ${error}`);
738
861
  lastError = error;
739
862
  }
740
863
  }