@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.
Files changed (57) hide show
  1. package/README.md +7 -7
  2. package/dist/adapters/contractOpener.js +33 -4
  3. package/dist/adapters/retryableContractOpener.js +1 -1
  4. package/dist/assets/AssetFactory.js +1 -1
  5. package/dist/assets/FT.d.ts +8 -12
  6. package/dist/assets/FT.js +69 -36
  7. package/dist/assets/NFT.d.ts +4 -2
  8. package/dist/assets/NFT.js +14 -2
  9. package/dist/assets/TON.d.ts +4 -10
  10. package/dist/assets/TON.js +17 -15
  11. package/dist/errors/index.d.ts +1 -1
  12. package/dist/errors/index.js +7 -2
  13. package/dist/errors/instances.d.ts +8 -1
  14. package/dist/errors/instances.js +22 -16
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.js +5 -3
  17. package/dist/interfaces/Asset.d.ts +22 -17
  18. package/dist/interfaces/ILiteSequencerClient.d.ts +14 -1
  19. package/dist/interfaces/IOperationTracker.d.ts +16 -1
  20. package/dist/interfaces/ISimulator.d.ts +7 -36
  21. package/dist/interfaces/ITACTransactionManager.d.ts +15 -0
  22. package/dist/interfaces/ITONTransactionManager.d.ts +21 -0
  23. package/dist/interfaces/ITONTransactionManager.js +2 -0
  24. package/dist/interfaces/ITacSDK.d.ts +51 -13
  25. package/dist/interfaces/index.d.ts +2 -1
  26. package/dist/interfaces/index.js +2 -1
  27. package/dist/sdk/Configuration.d.ts +1 -0
  28. package/dist/sdk/Configuration.js +67 -14
  29. package/dist/sdk/Consts.d.ts +1 -0
  30. package/dist/sdk/Consts.js +5 -4
  31. package/dist/sdk/LiteSequencerClient.d.ts +5 -3
  32. package/dist/sdk/LiteSequencerClient.js +27 -4
  33. package/dist/sdk/OperationTracker.d.ts +3 -1
  34. package/dist/sdk/OperationTracker.js +51 -11
  35. package/dist/sdk/Simulator.d.ts +6 -12
  36. package/dist/sdk/Simulator.js +30 -124
  37. package/dist/sdk/TACTransactionManager.d.ts +10 -0
  38. package/dist/sdk/TACTransactionManager.js +92 -0
  39. package/dist/sdk/TONTransactionManager.d.ts +17 -0
  40. package/dist/sdk/TONTransactionManager.js +209 -0
  41. package/dist/sdk/TacSdk.d.ts +16 -10
  42. package/dist/sdk/TacSdk.js +52 -19
  43. package/dist/sdk/TxFinalizer.d.ts +3 -2
  44. package/dist/sdk/TxFinalizer.js +8 -8
  45. package/dist/sdk/Utils.d.ts +9 -4
  46. package/dist/sdk/Utils.js +86 -12
  47. package/dist/sdk/Validator.d.ts +2 -2
  48. package/dist/sdk/Validator.js +1 -1
  49. package/dist/structs/InternalStruct.d.ts +6 -2
  50. package/dist/structs/Struct.d.ts +70 -16
  51. package/dist/wrappers/Settings.d.ts +5 -1
  52. package/dist/wrappers/Settings.js +17 -0
  53. package/package.json +4 -3
  54. package/dist/interfaces/ITransactionManager.d.ts +0 -35
  55. package/dist/sdk/TransactionManager.d.ts +0 -22
  56. package/dist/sdk/TransactionManager.js +0 -272
  57. /package/dist/interfaces/{ITransactionManager.js → ITACTransactionManager.js} +0 -0
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TONTransactionManager = void 0;
4
+ const assets_1 = require("../assets");
5
+ const errors_1 = require("../errors");
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 TONTransactionManager {
11
+ constructor(config, simulator, operationTracker, logger = new Logger_1.NoopLogger()) {
12
+ this.config = config;
13
+ this.simulator = simulator;
14
+ this.operationTracker = operationTracker;
15
+ this.logger = logger;
16
+ }
17
+ async buildFeeParams(options, evmProxyMsg, sender, tx) {
18
+ const { withoutSimulation, protocolFee, evmExecutorFee, tvmExecutorFee, isRoundTrip } = options;
19
+ if (withoutSimulation) {
20
+ if (protocolFee === undefined || evmExecutorFee === undefined) {
21
+ throw errors_1.missingFeeParamsError;
22
+ }
23
+ if (isRoundTrip && tvmExecutorFee === undefined) {
24
+ throw errors_1.missingTvmExecutorFeeError;
25
+ }
26
+ if (!evmProxyMsg.gasLimit) {
27
+ throw errors_1.missingGasLimitError;
28
+ }
29
+ return {
30
+ protocolFee,
31
+ evmExecutorFee,
32
+ tvmExecutorFee: tvmExecutorFee || 0n,
33
+ gasLimit: evmProxyMsg.gasLimit,
34
+ isRoundTrip: isRoundTrip || false,
35
+ };
36
+ }
37
+ const simulationResult = await this.simulator.getSimulationInfo(sender, tx);
38
+ if (!evmProxyMsg.gasLimit)
39
+ evmProxyMsg.gasLimit = simulationResult.feeParams.gasLimit;
40
+ return {
41
+ protocolFee: protocolFee ?? simulationResult.feeParams.protocolFee,
42
+ evmExecutorFee: evmExecutorFee ?? simulationResult.feeParams.evmExecutorFee,
43
+ tvmExecutorFee: simulationResult.feeParams.isRoundTrip && tvmExecutorFee !== undefined
44
+ ? tvmExecutorFee
45
+ : simulationResult.feeParams.tvmExecutorFee,
46
+ gasLimit: evmProxyMsg.gasLimit ?? simulationResult.feeParams.gasLimit,
47
+ isRoundTrip: isRoundTrip ?? simulationResult.feeParams.isRoundTrip,
48
+ };
49
+ }
50
+ async prepareCrossChainTransaction(evmProxyMsg, sender, assets, options, skipAssetsBalanceValidation = false) {
51
+ this.logger.debug('Preparing cross-chain transaction');
52
+ const caller = sender.getSenderAddress();
53
+ const { allowSimulationError = false, isRoundTrip = undefined, calculateRollbackFee = true, validateAssetsBalance = true } = options || {};
54
+ const { evmValidExecutors = [], tvmValidExecutors = [] } = options || {};
55
+ Validator_1.Validator.validateEVMAddress(evmProxyMsg.evmTargetAddress);
56
+ const aggregatedData = await (0, Utils_1.aggregateTokens)(assets);
57
+ Validator_1.Validator.validateEVMAddresses(evmValidExecutors);
58
+ Validator_1.Validator.validateTVMAddresses(tvmValidExecutors);
59
+ const shouldValidateAssets = validateAssetsBalance && !skipAssetsBalanceValidation;
60
+ if (shouldValidateAssets) {
61
+ await Promise.all([
62
+ ...aggregatedData.jettons.map((jetton) => jetton.checkCanBeTransferredBy(caller)),
63
+ ...aggregatedData.nfts.map((nft) => nft.checkCanBeTransferredBy(caller)),
64
+ aggregatedData.ton?.checkCanBeTransferredBy(caller),
65
+ ].filter(Boolean));
66
+ }
67
+ const tokensLength = aggregatedData.jettons.length + aggregatedData.nfts.length;
68
+ const transactionLinker = (0, Utils_1.generateTransactionLinker)(caller, tokensLength || 1);
69
+ this.logger.debug(`Generated transaction linker: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
70
+ const tacExecutors = evmValidExecutors.length ? evmValidExecutors : this.config.getTrustedTACExecutors;
71
+ const tonExecutors = tvmValidExecutors.length ? tvmValidExecutors : this.config.getTrustedTONExecutors;
72
+ const tx = {
73
+ evmProxyMsg,
74
+ assets: assets ?? [],
75
+ options: {
76
+ allowSimulationError,
77
+ isRoundTrip,
78
+ evmValidExecutors: tacExecutors,
79
+ tvmValidExecutors: tonExecutors,
80
+ calculateRollbackFee,
81
+ },
82
+ };
83
+ const feeParams = await this.buildFeeParams(options || {}, evmProxyMsg, sender, tx);
84
+ this.logger.debug(`Resulting fee params: ${(0, Utils_1.formatObjectForLogging)(feeParams)}`);
85
+ const validExecutors = {
86
+ tac: tacExecutors,
87
+ ton: tonExecutors,
88
+ };
89
+ const evmData = (0, Utils_1.buildEvmDataCell)(transactionLinker, evmProxyMsg, validExecutors);
90
+ const messages = await this.generateCrossChainMessages(caller, evmData, aggregatedData, feeParams);
91
+ return {
92
+ transaction: {
93
+ validUntil: Date.now() + Consts_1.FIFTEEN_MINUTES,
94
+ messages,
95
+ network: this.config.network,
96
+ },
97
+ transactionLinker,
98
+ };
99
+ }
100
+ async generateCrossChainMessages(caller, evmData, aggregatedData, feeParams) {
101
+ this.logger.debug('Generating cross-chain messages');
102
+ const { jettons, nfts, ton = assets_1.TON.create(this.config) } = aggregatedData;
103
+ const totalAssets = [...jettons, ...nfts];
104
+ let crossChainTonAmount = ton.rawAmount;
105
+ let feeTonAmount = feeParams.protocolFee + feeParams.evmExecutorFee + feeParams.tvmExecutorFee;
106
+ this.logger.debug(`Crosschain ton amount: ${crossChainTonAmount}, Fee ton amount: ${feeTonAmount}`);
107
+ if (!totalAssets.length) {
108
+ return [
109
+ {
110
+ address: this.config.TONParams.crossChainLayerAddress,
111
+ value: crossChainTonAmount + feeTonAmount + Consts_1.TRANSACTION_TON_AMOUNT,
112
+ payload: await ton.generatePayload({ excessReceiver: caller, evmData, feeParams }),
113
+ },
114
+ ];
115
+ }
116
+ const messages = [];
117
+ let currentFeeParams = feeParams;
118
+ for (const asset of totalAssets) {
119
+ const payload = await asset.generatePayload({
120
+ excessReceiver: caller,
121
+ evmData,
122
+ crossChainTonAmount,
123
+ forwardFeeTonAmount: feeTonAmount,
124
+ feeParams: currentFeeParams,
125
+ });
126
+ const address = asset instanceof assets_1.FT ? await asset.getUserWalletAddress(caller) : asset.address;
127
+ messages.push({
128
+ address,
129
+ value: crossChainTonAmount + feeTonAmount + Consts_1.TRANSACTION_TON_AMOUNT,
130
+ payload,
131
+ });
132
+ crossChainTonAmount = 0n;
133
+ feeTonAmount = 0n;
134
+ currentFeeParams = undefined;
135
+ }
136
+ this.logger.debug('Cross-chain messages generated successfully');
137
+ return messages;
138
+ }
139
+ async sendCrossChainTransaction(evmProxyMsg, sender, tx, waitOptions) {
140
+ const { transaction, transactionLinker } = await this.prepareCrossChainTransaction(evmProxyMsg, sender, tx.assets, tx.options);
141
+ await assets_1.TON.checkBalance(sender, this.config, [transaction]);
142
+ this.logger.debug(`Sending transaction: ${(0, Utils_1.formatObjectForLogging)(transactionLinker)}`);
143
+ const sendTransactionResult = await sender.sendShardTransaction(transaction, this.config.network, this.config.TONParams.contractOpener);
144
+ if (!waitOptions) {
145
+ return { sendTransactionResult, ...transactionLinker };
146
+ }
147
+ const operationId = await this.operationTracker.getOperationId(transactionLinker, {
148
+ ...waitOptions,
149
+ successCheck: (id) => !!id,
150
+ logger: this.logger,
151
+ })
152
+ .catch((error) => {
153
+ this.logger.error(`Error while waiting for operation ID: ${error}`);
154
+ return undefined;
155
+ });
156
+ return { sendTransactionResult, operationId, ...transactionLinker };
157
+ }
158
+ async sendCrossChainTransactions(sender, txs, waitOptions) {
159
+ const caller = sender.getSenderAddress();
160
+ this.logger.debug(`Preparing ${txs.length} cross-chain transactions for ${caller}`);
161
+ const { transactions, transactionLinkers } = await this.prepareBatchTransactions(txs, sender);
162
+ await assets_1.TON.checkBalance(sender, this.config, transactions);
163
+ this.logger.debug(`Sending transactions: ${(0, Utils_1.formatObjectForLogging)(transactionLinkers)}`);
164
+ await sender.sendShardTransactions(transactions, this.config.network, this.config.TONParams.contractOpener);
165
+ return waitOptions
166
+ ? await this.waitForOperationIds(transactionLinkers, caller, waitOptions)
167
+ : transactionLinkers;
168
+ }
169
+ async prepareBatchTransactions(txs, sender) {
170
+ const caller = sender.getSenderAddress();
171
+ const txsRequiringValidation = txs.filter((tx) => tx.options?.validateAssetsBalance ?? true);
172
+ if (txsRequiringValidation.length) {
173
+ // Aggregate only assets from txs that require validation and validate once per unique asset
174
+ const assetsToValidate = txsRequiringValidation.flatMap((tx) => tx.assets ?? []);
175
+ const aggregatedData = await (0, Utils_1.aggregateTokens)(assetsToValidate);
176
+ await Promise.all([
177
+ ...aggregatedData.jettons.map((jetton) => jetton.checkCanBeTransferredBy(caller)),
178
+ ...aggregatedData.nfts.map((nft) => nft.checkCanBeTransferredBy(caller)),
179
+ aggregatedData.ton?.checkCanBeTransferredBy(caller),
180
+ ].filter(Boolean));
181
+ }
182
+ const results = await Promise.all(txs.map(({ evmProxyMsg, assets, options }) => this.prepareCrossChainTransaction(evmProxyMsg, sender, assets, options, true)));
183
+ return {
184
+ transactions: results.map((r) => r.transaction),
185
+ transactionLinkers: results.map((r) => r.transactionLinker),
186
+ };
187
+ }
188
+ async waitForOperationIds(transactionLinkers, caller, waitOptions) {
189
+ this.logger.debug(`Waiting for operation IDs`);
190
+ try {
191
+ const operationIds = await this.operationTracker.getOperationIdsByShardsKeys(transactionLinkers.map((linker) => linker.shardsKey), caller, {
192
+ ...waitOptions,
193
+ logger: this.logger,
194
+ successCheck: (operationIds) => Object.keys(operationIds).length == transactionLinkers.length &&
195
+ Object.values(operationIds).every((ids) => ids.operationIds.length > 0),
196
+ });
197
+ this.logger.debug(`Operation IDs: ${(0, Utils_1.formatObjectForLogging)(operationIds)}`);
198
+ return transactionLinkers.map((linker) => ({
199
+ ...linker,
200
+ operationId: operationIds[linker.shardsKey].operationIds.at(0),
201
+ }));
202
+ }
203
+ catch (error) {
204
+ this.logger.error(`Error while waiting for operation IDs: ${error}`);
205
+ return transactionLinkers;
206
+ }
207
+ }
208
+ }
209
+ exports.TONTransactionManager = TONTransactionManager;
@@ -1,28 +1,33 @@
1
+ import { AgnosticProxySDK } from '@tonappchain/agnostic-sdk';
1
2
  import { Wallet } from 'ethers';
2
3
  import { FT, NFT } from '../assets';
3
- import { Asset, IConfiguration, ILogger, ITacSDK } from '../interfaces';
4
+ import { IConfiguration, ILogger, IOperationTracker, ITacSDK } from '../interfaces';
4
5
  import type { SenderAbstraction } from '../sender';
5
- import { AssetFromFTArg, AssetFromNFTCollectionArg, AssetFromNFTItemArg, CrossChainTransactionOptions, CrosschainTx, EVMAddress, EvmProxyMsg, ExecutionFeeEstimationResult, NFTAddressType, NFTItemData, OperationIdsByShardsKey, SDKParams, SuggestedTONExecutorFee, TACSimulationRequest, TACSimulationResult, TransactionLinkerWithOperationId, TVMAddress, UserWalletBalanceExtended, WaitOptions } from '../structs/Struct';
6
+ import { AssetFromFTArg, AssetFromNFTCollectionArg, AssetFromNFTItemArg, AssetLike, CrossChainTransactionOptions, CrosschainTx, CrosschainTxWithAssetLike, EVMAddress, EvmProxyMsg, ExecutionFeeEstimationResult, NFTAddressType, NFTItemData, OperationIdsByShardsKey, SDKParams, SuggestedTVMExecutorFee, TACSimulationParams, TACSimulationResult, TransactionLinkerWithOperationId, TVMAddress, UserWalletBalanceExtended, WaitOptions } from '../structs/Struct';
6
7
  import { JettonMasterData } from '../wrappers/JettonMaster';
7
8
  export declare class TacSdk implements ITacSDK {
8
9
  readonly config: IConfiguration;
10
+ readonly operationTracker: IOperationTracker;
9
11
  private readonly simulator;
10
- private readonly transactionManager;
12
+ private readonly tonTransactionManager;
13
+ private readonly tacTransactionManager;
11
14
  private constructor();
12
15
  static create(sdkParams: SDKParams, logger?: ILogger): Promise<TacSdk>;
13
16
  closeConnections(): unknown;
14
17
  get nativeTONAddress(): string;
18
+ getAgnosticProxySDK(agnosticProxyAddress?: string, smartAccountFactoryAddress?: string): AgnosticProxySDK;
19
+ getSmartAccountAddressForTvmWallet(tvmWallet: string, applicationAddress: string): Promise<string>;
15
20
  nativeTACAddress(): Promise<string>;
16
21
  get getTrustedTACExecutors(): string[];
17
22
  get getTrustedTONExecutors(): string[];
18
- getTransactionSimulationInfo(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: Asset[]): Promise<ExecutionFeeEstimationResult>;
19
- getTVMExecutorFeeInfo(assets: Asset[], feeSymbol: string, tvmValidExecutors?: string[]): Promise<SuggestedTONExecutorFee>;
20
- sendCrossChainTransaction(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: Asset[], options?: CrossChainTransactionOptions, waitOptions?: WaitOptions<string>): Promise<TransactionLinkerWithOperationId>;
21
- sendCrossChainTransactions(sender: SenderAbstraction, txs: CrosschainTx[], waitOptions?: WaitOptions<OperationIdsByShardsKey>): Promise<TransactionLinkerWithOperationId[]>;
22
- bridgeTokensToTON(signer: Wallet, value: bigint, tonTarget: string, assets?: Asset[], tvmExecutorFee?: bigint, tvmValidExecutors?: string[]): Promise<string>;
23
+ getSimulationInfo(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: AssetLike[], options?: CrossChainTransactionOptions): Promise<ExecutionFeeEstimationResult>;
24
+ getTVMExecutorFeeInfo(assets: AssetLike[], feeSymbol: string, tvmValidExecutors?: string[]): Promise<SuggestedTVMExecutorFee>;
25
+ sendCrossChainTransaction(evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, assets?: AssetLike[], options?: CrossChainTransactionOptions, waitOptions?: WaitOptions<string>): Promise<TransactionLinkerWithOperationId>;
26
+ sendCrossChainTransactions(sender: SenderAbstraction, txs: CrosschainTxWithAssetLike[], waitOptions?: WaitOptions<OperationIdsByShardsKey>): Promise<TransactionLinkerWithOperationId[]>;
27
+ bridgeTokensToTON(signer: Wallet, value: bigint, tonTarget: string, assets?: AssetLike[], tvmExecutorFee?: bigint, tvmValidExecutors?: string[]): Promise<string>;
23
28
  isContractDeployedOnTVM(address: string): Promise<boolean>;
24
- simulateTACMessage(req: TACSimulationRequest): Promise<TACSimulationResult>;
25
- simulateTransactions(sender: SenderAbstraction, txs: CrosschainTx[]): Promise<TACSimulationResult[]>;
29
+ simulateTACMessage(req: TACSimulationParams): Promise<TACSimulationResult>;
30
+ simulateTransactions(sender: SenderAbstraction, txs: CrosschainTx[]): Promise<ExecutionFeeEstimationResult[]>;
26
31
  getAsset(args: AssetFromFTArg): Promise<FT>;
27
32
  getAsset(args: AssetFromNFTCollectionArg): Promise<NFT>;
28
33
  getAsset(args: AssetFromNFTItemArg): Promise<NFT>;
@@ -37,4 +42,5 @@ export declare class TacSdk implements ITacSDK {
37
42
  getTVMTokenAddress(evmTokenAddress: string): Promise<string>;
38
43
  getTVMNFTAddress(evmNFTAddress: string, tokenId?: number | bigint): Promise<string>;
39
44
  getEVMNFTAddress(tvmNFTAddress: string, addressType: NFTAddressType): Promise<string>;
45
+ getOperationTracker(): IOperationTracker;
40
46
  }
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.TacSdk = void 0;
37
+ const agnostic_sdk_1 = require("@tonappchain/agnostic-sdk");
37
38
  const assets_1 = require("../assets");
38
39
  const Struct_1 = require("../structs/Struct");
39
40
  const Configuration_1 = require("./Configuration");
@@ -41,12 +42,16 @@ const Consts_1 = require("./Consts");
41
42
  const Logger_1 = require("./Logger");
42
43
  const OperationTracker_1 = require("./OperationTracker");
43
44
  const Simulator_1 = require("./Simulator");
44
- const TransactionManager_1 = require("./TransactionManager");
45
+ const TACTransactionManager_1 = require("./TACTransactionManager");
46
+ const TONTransactionManager_1 = require("./TONTransactionManager");
47
+ const Utils_1 = require("./Utils");
45
48
  class TacSdk {
46
- constructor(config, simulator, transactionManager) {
49
+ constructor(config, simulator, tonTransactionManager, tacTransactionManager, operationTracker) {
47
50
  this.config = config;
48
51
  this.simulator = simulator;
49
- this.transactionManager = transactionManager;
52
+ this.tonTransactionManager = tonTransactionManager;
53
+ this.tacTransactionManager = tacTransactionManager;
54
+ this.operationTracker = operationTracker;
50
55
  }
51
56
  static async create(sdkParams, logger = new Logger_1.NoopLogger()) {
52
57
  const network = sdkParams.network;
@@ -54,10 +59,11 @@ class TacSdk {
54
59
  const { testnet, mainnet } = await Promise.resolve().then(() => __importStar(require('@tonappchain/artifacts')));
55
60
  const artifacts = network === Struct_1.Network.TESTNET ? testnet : mainnet;
56
61
  const config = await Configuration_1.Configuration.create(network, artifacts, sdkParams.TONParams, sdkParams.TACParams, sdkParams.customLiteSequencerEndpoints, delay);
57
- const simulator = new Simulator_1.Simulator(config, logger);
58
62
  const operationTracker = new OperationTracker_1.OperationTracker(network, config.liteSequencerEndpoints);
59
- const transactionManager = new TransactionManager_1.TransactionManager(config, simulator, operationTracker, logger);
60
- return new TacSdk(config, simulator, transactionManager);
63
+ const simulator = new Simulator_1.Simulator(config, operationTracker, logger);
64
+ const tonTransactionManager = new TONTransactionManager_1.TONTransactionManager(config, simulator, operationTracker, logger);
65
+ const tacTransactionManager = new TACTransactionManager_1.TACTransactionManager(config, operationTracker, logger);
66
+ return new TacSdk(config, simulator, tonTransactionManager, tacTransactionManager, operationTracker);
61
67
  }
62
68
  closeConnections() {
63
69
  return this.config.closeConnections();
@@ -65,6 +71,13 @@ class TacSdk {
65
71
  get nativeTONAddress() {
66
72
  return this.config.nativeTONAddress;
67
73
  }
74
+ getAgnosticProxySDK(agnosticProxyAddress, smartAccountFactoryAddress) {
75
+ return new agnostic_sdk_1.AgnosticProxySDK(smartAccountFactoryAddress ?? this.config.artifacts.TAC_SMART_ACCOUNT_FACTORY_ADDRESS, this.config.TACParams.provider, agnosticProxyAddress ?? this.config.artifacts.AGNOSTIC_PROXY_ADDRESS);
76
+ }
77
+ async getSmartAccountAddressForTvmWallet(tvmWallet, applicationAddress) {
78
+ const bouncedAddress = (0, Utils_1.getBouncedAddress)(tvmWallet);
79
+ return await this.config.TACParams.smartAccountFactory.getSmartAccountForApplication(bouncedAddress, applicationAddress);
80
+ }
68
81
  async nativeTACAddress() {
69
82
  return this.config.nativeTACAddress();
70
83
  }
@@ -74,29 +87,45 @@ class TacSdk {
74
87
  get getTrustedTONExecutors() {
75
88
  return this.config.getTrustedTONExecutors;
76
89
  }
77
- async getTransactionSimulationInfo(evmProxyMsg, sender, assets) {
78
- return this.simulator.getTransactionSimulationInfo(evmProxyMsg, sender, assets);
90
+ async getSimulationInfo(evmProxyMsg, sender, assets, options) {
91
+ const normalizedAssets = await (0, Utils_1.normalizeAssets)(this.config, assets);
92
+ const tx = { evmProxyMsg, assets: normalizedAssets, options };
93
+ return this.simulator.getSimulationInfo(sender, tx);
79
94
  }
80
95
  async getTVMExecutorFeeInfo(assets, feeSymbol, tvmValidExecutors) {
81
- return this.simulator.getTVMExecutorFeeInfo(assets, feeSymbol, tvmValidExecutors);
96
+ const normalized = await (0, Utils_1.normalizeAssets)(this.config, assets);
97
+ const params = {
98
+ tonAssets: (0, Utils_1.mapAssetsToTonAssets)(normalized),
99
+ feeSymbol: feeSymbol,
100
+ tvmValidExecutors: tvmValidExecutors ?? [],
101
+ };
102
+ return this.operationTracker.getTVMExecutorFee(params);
82
103
  }
83
- async sendCrossChainTransaction(evmProxyMsg, sender, assets, options, waitOptions) {
84
- return this.transactionManager.sendCrossChainTransaction(evmProxyMsg, sender, assets, options, waitOptions);
104
+ async sendCrossChainTransaction(evmProxyMsg, sender, assets = [], options, waitOptions) {
105
+ const normalizedAssets = await (0, Utils_1.normalizeAssets)(this.config, assets);
106
+ const tx = { evmProxyMsg, assets: normalizedAssets, options };
107
+ return this.tonTransactionManager.sendCrossChainTransaction(evmProxyMsg, sender, tx, waitOptions);
85
108
  }
86
109
  async sendCrossChainTransactions(sender, txs, waitOptions) {
87
- return this.transactionManager.sendCrossChainTransactions(sender, txs, waitOptions);
110
+ const normalizedTxs = await Promise.all(txs.map(async (tx) => ({
111
+ evmProxyMsg: tx.evmProxyMsg,
112
+ options: tx.options,
113
+ assets: await (0, Utils_1.normalizeAssets)(this.config, tx.assets),
114
+ })));
115
+ return this.tonTransactionManager.sendCrossChainTransactions(sender, normalizedTxs, waitOptions);
88
116
  }
89
117
  async bridgeTokensToTON(signer, value, tonTarget, assets, tvmExecutorFee, tvmValidExecutors) {
90
- return this.transactionManager.bridgeTokensToTON(signer, value, tonTarget, assets, tvmExecutorFee, tvmValidExecutors);
118
+ const normalizedAssets = await (0, Utils_1.normalizeAssets)(this.config, assets);
119
+ return this.tacTransactionManager.bridgeTokensToTON(signer, value, tonTarget, normalizedAssets, tvmExecutorFee, tvmValidExecutors);
91
120
  }
92
121
  async isContractDeployedOnTVM(address) {
93
122
  return this.config.isContractDeployedOnTVM(address);
94
123
  }
95
124
  async simulateTACMessage(req) {
96
- return this.simulator.simulateTACMessage(req);
125
+ return this.operationTracker.simulateTACMessage(req);
97
126
  }
98
127
  async simulateTransactions(sender, txs) {
99
- return this.simulator.simulateTransactions(sender, txs);
128
+ return this.simulator.getSimulationsInfo(sender, txs);
100
129
  }
101
130
  async getAsset(args) {
102
131
  return await assets_1.AssetFactory.from(this.config, args);
@@ -147,10 +176,11 @@ class TacSdk {
147
176
  }
148
177
  // Address conversion methods
149
178
  async getEVMTokenAddress(tvmTokenAddress) {
150
- if (tvmTokenAddress === this.nativeTONAddress || tvmTokenAddress === '') {
151
- return assets_1.TON.create(this.config).getEVMAddress();
152
- }
153
- return assets_1.FT.getEVMAddress(this.config, tvmTokenAddress);
179
+ const asset = await assets_1.AssetFactory.from(this.config, {
180
+ address: tvmTokenAddress,
181
+ tokenType: Struct_1.AssetType.FT,
182
+ });
183
+ return asset.getEVMAddress();
154
184
  }
155
185
  async getTVMTokenAddress(evmTokenAddress) {
156
186
  return assets_1.FT.getTVMAddress(this.config, evmTokenAddress);
@@ -168,5 +198,8 @@ class TacSdk {
168
198
  return nftCollection.getEVMAddress();
169
199
  }
170
200
  }
201
+ getOperationTracker() {
202
+ return this.operationTracker;
203
+ }
171
204
  }
172
205
  exports.TacSdk = TacSdk;
@@ -1,9 +1,10 @@
1
- import { ILogger } from '../interfaces';
1
+ import { IHttpClient, ILogger } from '../interfaces';
2
2
  import { TxFinalizerConfig } from '../structs/InternalStruct';
3
3
  export declare class TonTxFinalizer {
4
4
  private logger;
5
5
  private apiConfig;
6
- constructor(apiConfig: TxFinalizerConfig, logger?: ILogger);
6
+ private readonly httpClient;
7
+ constructor(apiConfig: TxFinalizerConfig, logger?: ILogger, httpClient?: IHttpClient);
7
8
  private logHashFormats;
8
9
  private fetchAdjacentTransactions;
9
10
  trackTransactionTree(hash: string, maxDepth?: number): Promise<void>;
@@ -1,10 +1,7 @@
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.TonTxFinalizer = void 0;
7
- const axios_1 = __importDefault(require("axios"));
4
+ const AxiosHttpClient_1 = require("./AxiosHttpClient");
8
5
  const Logger_1 = require("./Logger");
9
6
  const Utils_1 = require("./Utils");
10
7
  const IGNORE_OPCODE = [
@@ -12,9 +9,10 @@ const IGNORE_OPCODE = [
12
9
  '0x7362d09c', // Jetton Notify
13
10
  ];
14
11
  class TonTxFinalizer {
15
- constructor(apiConfig, logger = new Logger_1.NoopLogger()) {
12
+ constructor(apiConfig, logger = new Logger_1.NoopLogger(), httpClient = new AxiosHttpClient_1.AxiosHttpClient()) {
16
13
  this.apiConfig = apiConfig;
17
14
  this.logger = logger;
15
+ this.httpClient = httpClient;
18
16
  }
19
17
  logHashFormats(hash) {
20
18
  let hex, base64;
@@ -34,10 +32,9 @@ class TonTxFinalizer {
34
32
  // Fetches adjacent transactions from toncenter
35
33
  async fetchAdjacentTransactions(hash, retries = 5, delay = 1000) {
36
34
  for (let i = retries; i >= 0; i--) {
37
- await (0, Utils_1.sleep)(delay);
38
35
  try {
39
36
  const url = this.apiConfig.urlBuilder(hash);
40
- const response = await axios_1.default.get(url, {
37
+ const response = await this.httpClient.get(url, {
41
38
  headers: {
42
39
  [this.apiConfig.authorization.header]: this.apiConfig.authorization.value,
43
40
  },
@@ -57,6 +54,7 @@ class TonTxFinalizer {
57
54
  console.warn(`Failed to fetch adjacent transactions for ${hash}:`, logMessage);
58
55
  }
59
56
  }
57
+ await (0, Utils_1.sleep)(delay);
60
58
  }
61
59
  return [];
62
60
  }
@@ -91,7 +89,9 @@ class TonTxFinalizer {
91
89
  `action.result_code = ${action.resultCode}`);
92
90
  }
93
91
  if (currentDepth + 1 < maxDepth) {
94
- queue.push({ hash: tx.hash, depth: currentDepth + 1 });
92
+ if (tx.outMsgs.length > 0) {
93
+ queue.push({ hash: tx.hash, depth: currentDepth + 1 });
94
+ }
95
95
  }
96
96
  }
97
97
  else {
@@ -1,9 +1,9 @@
1
1
  import { Address, Cell } from '@ton/ton';
2
2
  import { AbiCoder } from 'ethers';
3
- import { FT, NFT, TON } from '../assets';
4
- import { Asset } from '../interfaces';
3
+ import type { FT, NFT, TON } from '../assets';
4
+ import { Asset, IConfiguration } from '../interfaces';
5
5
  import { RandomNumberByTimestamp } from '../structs/InternalStruct';
6
- import { EvmProxyMsg, FeeParams, TransactionLinker, ValidExecutors, WaitOptions } from '../structs/Struct';
6
+ import { AssetLike, EvmProxyMsg, FeeParams, TONAsset, TransactionLinker, ValidExecutors, WaitOptions } from '../structs/Struct';
7
7
  export declare const sleep: (ms: number) => Promise<unknown>;
8
8
  export declare function generateRandomNumber(interval: number): number;
9
9
  export declare function generateRandomNumberByTimestamp(): RandomNumberByTimestamp;
@@ -17,10 +17,15 @@ export declare const calculateRawAmount: (amount: number, decimals: number) => b
17
17
  export declare const calculateAmount: (rawAmount: bigint, decimals: number) => number;
18
18
  export declare const toCamelCaseTransformer: (data: string) => any;
19
19
  export declare const generateFeeData: (feeParams?: FeeParams) => Cell | undefined;
20
- export declare function waitUntilSuccess<T, A extends unknown[]>(options: WaitOptions<T> | undefined, operation: (...args: A) => Promise<T>, ...args: A): Promise<T>;
20
+ export declare function waitUntilSuccess<T, TContext = unknown, A extends unknown[] = unknown[]>(options: WaitOptions<T, TContext> | undefined, operation: (...args: A) => Promise<T>, operationDescription?: string, ...args: A): Promise<T>;
21
21
  export declare function formatObjectForLogging(obj: unknown): string;
22
+ export declare function getBouncedAddress(tvmAddress: string): string;
22
23
  export declare function aggregateTokens(assets?: Asset[]): Promise<{
23
24
  jettons: FT[];
24
25
  nfts: NFT[];
25
26
  ton?: TON;
26
27
  }>;
28
+ export declare function sha256toBigInt(ContractName: string): bigint;
29
+ export declare function mapAssetsToTonAssets(assets: Asset[]): TONAsset[];
30
+ export declare function normalizeAsset(config: IConfiguration, input: AssetLike): Promise<Asset>;
31
+ export declare function normalizeAssets(config: IConfiguration, assets?: AssetLike[]): Promise<Asset[]>;
package/dist/sdk/Utils.js CHANGED
@@ -10,9 +10,16 @@ exports.generateTransactionLinker = generateTransactionLinker;
10
10
  exports.calculateEVMTokenAddress = calculateEVMTokenAddress;
11
11
  exports.waitUntilSuccess = waitUntilSuccess;
12
12
  exports.formatObjectForLogging = formatObjectForLogging;
13
+ exports.getBouncedAddress = getBouncedAddress;
13
14
  exports.aggregateTokens = aggregateTokens;
15
+ exports.sha256toBigInt = sha256toBigInt;
16
+ exports.mapAssetsToTonAssets = mapAssetsToTonAssets;
17
+ exports.normalizeAsset = normalizeAsset;
18
+ exports.normalizeAssets = normalizeAssets;
14
19
  const ton_1 = require("@ton/ton");
15
20
  const ethers_1 = require("ethers");
21
+ const ton_crypto_1 = require("ton-crypto");
22
+ const assets_1 = require("../assets");
16
23
  const errors_1 = require("../errors");
17
24
  const Struct_1 = require("../structs/Struct");
18
25
  const Consts_1 = require("./Consts");
@@ -131,12 +138,14 @@ const generateFeeData = (feeParams) => {
131
138
  }
132
139
  };
133
140
  exports.generateFeeData = generateFeeData;
134
- async function waitUntilSuccess(options = {}, operation, ...args) {
141
+ async function waitUntilSuccess(options = {}, operation, operationDescription, ...args) {
135
142
  const timeout = options.timeout ?? 300000;
136
143
  const maxAttempts = options.maxAttempts ?? 30;
137
144
  const delay = options.delay ?? 10000;
138
145
  const successCheck = options.successCheck;
139
- options.logger?.debug(`Starting wait for success with timeout=${timeout}ms, maxAttempts=${maxAttempts}, delay=${delay}ms`);
146
+ const context = options.context;
147
+ const contextPrefix = operationDescription ? `[${operationDescription}] ` : '';
148
+ options.logger?.debug(`${contextPrefix}Starting wait for success with timeout=${timeout}ms, maxAttempts=${maxAttempts}, delay=${delay}ms`);
140
149
  const startTime = Date.now();
141
150
  let attempt = 1;
142
151
  while (true) {
@@ -144,27 +153,36 @@ async function waitUntilSuccess(options = {}, operation, ...args) {
144
153
  const elapsedTime = currentTime - startTime;
145
154
  try {
146
155
  const result = await operation(...args);
147
- if (!result) {
156
+ if (result === undefined || result === null) {
148
157
  throw new Error(`Empty result`);
149
158
  }
150
- options.logger?.debug(`Result: ${formatObjectForLogging(result)}`);
151
- if (successCheck && !successCheck(result)) {
159
+ options.logger?.debug(`${contextPrefix}Result: ${formatObjectForLogging(result)}`);
160
+ if (successCheck && !successCheck(result, context)) {
152
161
  throw new Error(`Result is not successful`);
153
162
  }
154
- options.logger?.debug(`Attempt ${attempt} successful`);
163
+ options.logger?.debug(`${contextPrefix}Attempt ${attempt} successful`);
164
+ // Execute custom onSuccess callback if provided
165
+ if (options.onSuccess) {
166
+ try {
167
+ await options.onSuccess(result, context);
168
+ }
169
+ catch (callbackError) {
170
+ options.logger?.warn(`${contextPrefix}onSuccess callback error: ${callbackError}`);
171
+ }
172
+ }
155
173
  return result;
156
174
  }
157
175
  catch (error) {
158
176
  if (elapsedTime >= timeout) {
159
- options.logger?.debug(`Timeout after ${elapsedTime}ms`);
177
+ options.logger?.debug(`${contextPrefix}Timeout after ${elapsedTime}ms`);
160
178
  throw error;
161
179
  }
162
180
  if (attempt >= maxAttempts) {
163
- options.logger?.debug(`Max attempts (${maxAttempts}) reached`);
181
+ options.logger?.debug(`${contextPrefix}Max attempts (${maxAttempts}) reached`);
164
182
  throw error;
165
183
  }
166
- options.logger?.debug(`Error on attempt ${attempt}: ${error}`);
167
- options.logger?.debug(`Waiting ${delay}ms before next attempt`);
184
+ options.logger?.debug(`${contextPrefix}Error on attempt ${attempt}: ${error}`);
185
+ options.logger?.debug(`${contextPrefix}Waiting ${delay}ms before next attempt`);
168
186
  await (0, exports.sleep)(delay);
169
187
  attempt++;
170
188
  }
@@ -173,6 +191,11 @@ async function waitUntilSuccess(options = {}, operation, ...args) {
173
191
  function formatObjectForLogging(obj) {
174
192
  return JSON.stringify(obj, (key, value) => (typeof value === 'bigint' ? value.toString() : value));
175
193
  }
194
+ function getBouncedAddress(tvmAddress) {
195
+ return ton_1.Address.parse(tvmAddress).toString({
196
+ bounceable: true,
197
+ });
198
+ }
176
199
  async function aggregateTokens(assets) {
177
200
  const uniqueAssetsMap = new Map();
178
201
  let ton;
@@ -180,7 +203,7 @@ async function aggregateTokens(assets) {
180
203
  if (asset.type !== Struct_1.AssetType.FT)
181
204
  continue;
182
205
  if (!asset.address) {
183
- ton = ton ? await ton.addAmount({ rawAmount: asset.rawAmount }) : asset.clone;
206
+ ton = ton ? ton.addRawAmount(asset.rawAmount) : asset.clone;
184
207
  continue;
185
208
  }
186
209
  let jetton = uniqueAssetsMap.get(asset.address);
@@ -188,7 +211,7 @@ async function aggregateTokens(assets) {
188
211
  jetton = asset.clone;
189
212
  }
190
213
  else {
191
- jetton = await jetton.addAmount({ rawAmount: asset.rawAmount });
214
+ jetton = jetton.addRawAmount(asset.rawAmount);
192
215
  }
193
216
  uniqueAssetsMap.set(asset.address, jetton);
194
217
  }
@@ -206,3 +229,54 @@ async function aggregateTokens(assets) {
206
229
  ton,
207
230
  };
208
231
  }
232
+ function sha256toBigInt(ContractName) {
233
+ const hash = (0, ton_crypto_1.sha256_sync)(ContractName);
234
+ return BigInt('0x' + hash.toString('hex'));
235
+ }
236
+ function mapAssetsToTonAssets(assets) {
237
+ return assets.map((asset) => ({
238
+ amount: asset.rawAmount.toString(),
239
+ tokenAddress: asset.address || '',
240
+ assetType: asset.type,
241
+ }));
242
+ }
243
+ async function normalizeAsset(config, input) {
244
+ if (typeof input.generatePayload === 'function') {
245
+ return input;
246
+ }
247
+ const address = 'address' in input && input.address ? input.address : '';
248
+ if ('itemIndex' in input) {
249
+ const args = {
250
+ address,
251
+ tokenType: Struct_1.AssetType.NFT,
252
+ addressType: Struct_1.NFTAddressType.COLLECTION,
253
+ index: BigInt(input.itemIndex),
254
+ };
255
+ return await assets_1.AssetFactory.from(config, args);
256
+ }
257
+ if ('rawAmount' in input || 'amount' in input) {
258
+ const ftArgs = {
259
+ address,
260
+ tokenType: Struct_1.AssetType.FT,
261
+ };
262
+ const asset = await assets_1.AssetFactory.from(config, ftArgs);
263
+ return 'rawAmount' in input
264
+ ? asset.withRawAmount(input.rawAmount)
265
+ : asset.withAmount(input.amount);
266
+ }
267
+ const itemArgs = {
268
+ address,
269
+ tokenType: Struct_1.AssetType.NFT,
270
+ addressType: Struct_1.NFTAddressType.ITEM,
271
+ };
272
+ return await assets_1.AssetFactory.from(config, itemArgs);
273
+ }
274
+ async function normalizeAssets(config, assets) {
275
+ if (!assets || assets.length === 0)
276
+ return [];
277
+ const normalized = [];
278
+ for (const a of assets) {
279
+ normalized.push(await normalizeAsset(config, a));
280
+ }
281
+ return normalized;
282
+ }