@tonappchain/sdk 0.7.2-alpha-11 → 0.7.2-alpha-13

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 (40) hide show
  1. package/dist/artifacts/dev/ton/internal/build/CrossChainLayer.compiled.json +1 -1
  2. package/dist/src/adapters/BaseContractOpener.d.ts +71 -0
  3. package/dist/src/adapters/BaseContractOpener.js +290 -0
  4. package/dist/src/adapters/LiteClientOpener.d.ts +33 -0
  5. package/dist/src/adapters/LiteClientOpener.js +117 -0
  6. package/dist/src/adapters/OpenerUtils.d.ts +3 -0
  7. package/dist/src/adapters/OpenerUtils.js +39 -0
  8. package/dist/src/adapters/RetryableContractOpener.d.ts +35 -0
  9. package/dist/src/adapters/{retryableContractOpener.js → RetryableContractOpener.js} +60 -12
  10. package/dist/src/adapters/SandboxOpener.d.ts +15 -0
  11. package/dist/src/adapters/SandboxOpener.js +35 -0
  12. package/dist/src/adapters/TonClient4Opener.d.ts +21 -0
  13. package/dist/src/adapters/TonClient4Opener.js +86 -0
  14. package/dist/src/adapters/TonClientOpener.d.ts +16 -0
  15. package/dist/src/adapters/TonClientOpener.js +70 -0
  16. package/dist/src/adapters/index.d.ts +7 -2
  17. package/dist/src/adapters/index.js +7 -2
  18. package/dist/src/index.d.ts +1 -1
  19. package/dist/src/index.js +3 -2
  20. package/dist/src/interfaces/ContractOpener.d.ts +69 -2
  21. package/dist/src/interfaces/ITacSDK.d.ts +5 -0
  22. package/dist/src/sdk/Configuration.js +1 -1
  23. package/dist/src/sdk/Consts.d.ts +5 -2
  24. package/dist/src/sdk/Consts.js +8 -4
  25. package/dist/src/sdk/StartTracking.d.ts +3 -4
  26. package/dist/src/sdk/StartTracking.js +7 -7
  27. package/dist/src/sdk/TONTransactionManager.d.ts +1 -3
  28. package/dist/src/sdk/TONTransactionManager.js +2 -3
  29. package/dist/src/sdk/TacSdk.d.ts +3 -1
  30. package/dist/src/sdk/TacSdk.js +5 -3
  31. package/dist/src/sdk/TxFinalizer.d.ts +1 -8
  32. package/dist/src/sdk/TxFinalizer.js +10 -122
  33. package/dist/src/sdk/Utils.d.ts +5 -0
  34. package/dist/src/sdk/Utils.js +24 -0
  35. package/dist/src/structs/InternalStruct.d.ts +1 -16
  36. package/dist/src/structs/Struct.d.ts +90 -5
  37. package/package.json +1 -1
  38. package/dist/src/adapters/contractOpener.d.ts +0 -24
  39. package/dist/src/adapters/contractOpener.js +0 -310
  40. package/dist/src/adapters/retryableContractOpener.d.ts +0 -29
@@ -9,7 +9,7 @@ const Logger_1 = require("./Logger");
9
9
  const OperationTracker_1 = require("./OperationTracker");
10
10
  const Utils_1 = require("./Utils");
11
11
  async function startTracking(transactionLinker, network, options) {
12
- const { customLiteSequencerEndpoints, delay = 10, maxIterationCount = Consts_1.MAX_ITERATION_COUNT, returnValue = false, tableView = true, logger = new Logger_1.NoopLogger(), txFinalizer, cclAddress, } = options || {};
12
+ const { customLiteSequencerEndpoints, delay = 10, maxIterationCount = Consts_1.MAX_ITERATION_COUNT, returnValue = false, tableView = true, logger = new Logger_1.NoopLogger(), contractOpener, cclAddress, } = options || {};
13
13
  const tracker = new OperationTracker_1.OperationTracker(network, customLiteSequencerEndpoints, logger);
14
14
  logger.debug(`Start tracking operation\n` +
15
15
  `caller: ${transactionLinker.caller}\n` +
@@ -63,15 +63,15 @@ async function startTracking(transactionLinker, network, options) {
63
63
  logger.debug(errorMessage);
64
64
  }
65
65
  const profilingData = await tracker.getStageProfiling(operationId);
66
- // Check if EXECUTED_IN_TON stage exists and use TxFinalizer to verify transaction success
66
+ // Check if EXECUTED_IN_TON stage exists and use ContractOpener to verify transaction success
67
67
  if (profilingData.executedInTON.exists && profilingData.executedInTON.stageData?.transactions) {
68
68
  logger.debug('EXECUTED_IN_TON stage found, verifying transaction success in TON...');
69
- if (txFinalizer && cclAddress) {
69
+ if (contractOpener && cclAddress) {
70
70
  const transactions = profilingData.executedInTON.stageData.transactions;
71
71
  for (const tx of transactions) {
72
72
  try {
73
73
  logger.debug(`Verifying transaction: ${tx.hash}`);
74
- await txFinalizer.trackTransactionTree(cclAddress, tx.hash, { maxDepth: Consts_1.DEFAULT_FIND_TX_MAX_DEPTH });
74
+ await contractOpener.trackTransactionTree(cclAddress, tx.hash, { maxDepth: Consts_1.DEFAULT_FIND_TX_MAX_DEPTH });
75
75
  logger.debug(`Transaction ${tx.hash} verified successfully in TON`);
76
76
  }
77
77
  catch (error) {
@@ -83,7 +83,7 @@ async function startTracking(transactionLinker, network, options) {
83
83
  }
84
84
  }
85
85
  else {
86
- logger.debug('TxFinalizer or CCL address is not provided, skipping TON transaction verification');
86
+ logger.debug('ContractOpener or CCL address is not provided, skipping TON transaction verification');
87
87
  }
88
88
  }
89
89
  if (returnValue) {
@@ -99,7 +99,7 @@ async function startTracking(transactionLinker, network, options) {
99
99
  }
100
100
  }
101
101
  async function startTrackingMultiple(transactionLinkers, network, options) {
102
- const { customLiteSequencerEndpoints, delay = 10, maxIterationCount = Consts_1.MAX_ITERATION_COUNT, returnValue = false, tableView = true, txFinalizer, logger = new Logger_1.NoopLogger(), } = options || {};
102
+ const { customLiteSequencerEndpoints, delay = 10, maxIterationCount = Consts_1.MAX_ITERATION_COUNT, returnValue = false, tableView = true, contractOpener, logger = new Logger_1.NoopLogger(), } = options || {};
103
103
  logger.debug(`Start tracking ${transactionLinkers.length} operations`);
104
104
  const results = await Promise.all(transactionLinkers.map((linker, index) => {
105
105
  logger.debug(`\nProcessing operation ${index + 1}/${transactionLinkers.length}`);
@@ -109,7 +109,7 @@ async function startTrackingMultiple(transactionLinkers, network, options) {
109
109
  maxIterationCount,
110
110
  returnValue: true,
111
111
  tableView: false,
112
- txFinalizer,
112
+ contractOpener,
113
113
  logger,
114
114
  });
115
115
  }));
@@ -1,5 +1,4 @@
1
1
  import { Asset, IConfiguration, ILogger, IOperationTracker, ISimulator, ITONTransactionManager } from '../interfaces';
2
- import { ITxFinalizer } from '../interfaces/ITxFinalizer';
3
2
  import { type SenderAbstraction } from '../sender';
4
3
  import { BatchCrossChainTx, CrossChainPayloadResult, CrossChainTransactionOptions, CrossChainTransactionsOptions, CrosschainTx, EvmProxyMsg, FeeParams, TransactionLinkerWithOperationId } from '../structs/Struct';
5
4
  export declare class TONTransactionManager implements ITONTransactionManager {
@@ -7,8 +6,7 @@ export declare class TONTransactionManager implements ITONTransactionManager {
7
6
  private readonly simulator;
8
7
  private readonly operationTracker;
9
8
  private readonly logger;
10
- private readonly txFinalizer;
11
- constructor(config: IConfiguration, simulator: ISimulator, operationTracker: IOperationTracker, logger: ILogger | undefined, txFinalizer: ITxFinalizer);
9
+ constructor(config: IConfiguration, simulator: ISimulator, operationTracker: IOperationTracker, logger?: ILogger);
12
10
  buildFeeParams(options: CrossChainTransactionOptions, evmProxyMsg: EvmProxyMsg, sender: SenderAbstraction, tx: CrosschainTx): Promise<FeeParams>;
13
11
  private prepareCrossChainTransaction;
14
12
  private generateCrossChainMessages;
@@ -11,12 +11,11 @@ const Logger_1 = require("./Logger");
11
11
  const Utils_1 = require("./Utils");
12
12
  const Validator_1 = require("./Validator");
13
13
  class TONTransactionManager {
14
- constructor(config, simulator, operationTracker, logger = new Logger_1.NoopLogger(), txFinalizer) {
14
+ constructor(config, simulator, operationTracker, logger = new Logger_1.NoopLogger()) {
15
15
  this.config = config;
16
16
  this.simulator = simulator;
17
17
  this.operationTracker = operationTracker;
18
18
  this.logger = logger;
19
- this.txFinalizer = txFinalizer;
20
19
  }
21
20
  async buildFeeParams(options, evmProxyMsg, sender, tx) {
22
21
  const { withoutSimulation, protocolFee, evmExecutorFee, tvmExecutorFee, isRoundTrip } = options;
@@ -175,7 +174,7 @@ class TONTransactionManager {
175
174
  if (waitOptions.ensureTxExecuted && sendTransactionResult.boc) {
176
175
  const hash = (0, Utils_1.getNormalizedExtMessageHash)((0, ton_1.loadMessage)(ton_1.Cell.fromBase64(sendTransactionResult.boc).beginParse()));
177
176
  this.logger.info(`Tracking transaction tree for hash: ${hash}`);
178
- await this.txFinalizer.trackTransactionTree(sender.getSenderAddress(), hash, {
177
+ await this.config.TONParams.contractOpener.trackTransactionTree(sender.getSenderAddress(), hash, {
179
178
  maxDepth: Consts_1.DEFAULT_FIND_TX_MAX_DEPTH,
180
179
  });
181
180
  this.logger.info(`Transaction tree successful`);
@@ -1,11 +1,12 @@
1
1
  import { Wallet } from 'ethers';
2
2
  import { JettonMinterData, NFTItemData } from '../../artifacts/tonTypes';
3
3
  import { FT, NFT } from '../assets';
4
- import { IConfiguration, ILogger, IOperationTracker, ITacExplorerClient, ITacSDK } from '../interfaces';
4
+ import { ContractOpener, IConfiguration, ILogger, IOperationTracker, ITacExplorerClient, ITacSDK } from '../interfaces';
5
5
  import type { SenderAbstraction } from '../sender';
6
6
  import { AssetFromFTArg, AssetFromNFTCollectionArg, AssetFromNFTItemArg, AssetLike, BatchCrossChainTxWithAssetLike, CrossChainPayloadResult, CrossChainTransactionOptions, CrossChainTransactionsOptions, CrosschainTx, EVMAddress, EvmProxyMsg, ExecutionFeeEstimationResult, NFTAddressType, SDKParams, SuggestedTVMExecutorFee, TacGasPrice, TACSimulationParams, TACSimulationResult, TransactionLinkerWithOperationId, TVMAddress, UserWalletBalanceExtended } from '../structs/Struct';
7
7
  export declare class TacSdk implements ITacSDK {
8
8
  readonly config: IConfiguration;
9
+ readonly contactOpener: ContractOpener;
9
10
  readonly operationTracker: IOperationTracker;
10
11
  readonly explorerClient: ITacExplorerClient;
11
12
  private readonly simulator;
@@ -45,4 +46,5 @@ export declare class TacSdk implements ITacSDK {
45
46
  getTacExplorerClient(): ITacExplorerClient;
46
47
  prepareCrossChainTransactionPayload(evmProxyMsg: EvmProxyMsg, senderAddress: string, assets?: AssetLike[], options?: CrossChainTransactionOptions): Promise<CrossChainPayloadResult[]>;
47
48
  getTACGasPrice(): Promise<TacGasPrice>;
49
+ getTonContractOpener(): ContractOpener;
48
50
  }
@@ -12,11 +12,11 @@ const Simulator_1 = require("./Simulator");
12
12
  const TacExplorerClient_1 = require("./TacExplorerClient");
13
13
  const TACTransactionManager_1 = require("./TACTransactionManager");
14
14
  const TONTransactionManager_1 = require("./TONTransactionManager");
15
- const TxFinalizer_1 = require("./TxFinalizer");
16
15
  const Utils_1 = require("./Utils");
17
16
  class TacSdk {
18
17
  constructor(config, simulator, tonTransactionManager, tacTransactionManager, operationTracker, explorerClient) {
19
18
  this.config = config;
19
+ this.contactOpener = config.TONParams.contractOpener;
20
20
  this.simulator = simulator;
21
21
  this.tonTransactionManager = tonTransactionManager;
22
22
  this.tacTransactionManager = tacTransactionManager;
@@ -44,8 +44,7 @@ class TacSdk {
44
44
  const operationTracker = new OperationTracker_1.OperationTracker(network, config.liteSequencerEndpoints);
45
45
  const explorerClient = new TacExplorerClient_1.TacExplorerClient(artifacts.TAC_EXPLORER_API_ENDPOINT);
46
46
  const simulator = new Simulator_1.Simulator(config, operationTracker, logger);
47
- const txFinalizer = sdkParams.TONParams?.txFinalizer ?? new TxFinalizer_1.TonTxFinalizer(config.TONParams.contractOpener, logger);
48
- const tonTransactionManager = new TONTransactionManager_1.TONTransactionManager(config, simulator, operationTracker, logger, txFinalizer);
47
+ const tonTransactionManager = new TONTransactionManager_1.TONTransactionManager(config, simulator, operationTracker, logger);
49
48
  const tacTransactionManager = new TACTransactionManager_1.TACTransactionManager(config, operationTracker, logger);
50
49
  return new TacSdk(config, simulator, tonTransactionManager, tacTransactionManager, operationTracker, explorerClient);
51
50
  }
@@ -197,5 +196,8 @@ class TacSdk {
197
196
  slow: response.gasPrices.slow,
198
197
  };
199
198
  }
199
+ getTonContractOpener() {
200
+ return this.contactOpener;
201
+ }
200
202
  }
201
203
  exports.TacSdk = TacSdk;
@@ -1,15 +1,8 @@
1
- import { ContractOpener, IHttpClient, ILogger } from '../interfaces';
1
+ import { IHttpClient, ILogger } from '../interfaces';
2
2
  import { ITxFinalizer } from '../interfaces/ITxFinalizer';
3
3
  import { TxFinalizerConfig } from '../structs/InternalStruct';
4
4
  import { TrackTransactionTreeParams } from '../structs/Struct';
5
5
  export declare class TonTxFinalizer implements ITxFinalizer {
6
- private logger;
7
- private contractOpener;
8
- constructor(contractOpener: ContractOpener, logger?: ILogger);
9
- private fetchAdjacentTransactions;
10
- trackTransactionTree(address: string, hash: string, params?: TrackTransactionTreeParams): Promise<void>;
11
- }
12
- export declare class TonIndexerTxFinalizer implements ITxFinalizer {
13
6
  private logger;
14
7
  private apiConfig;
15
8
  private readonly httpClient;
@@ -1,133 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TonIndexerTxFinalizer = exports.TonTxFinalizer = void 0;
4
- const ton_1 = require("@ton/ton");
3
+ exports.TonTxFinalizer = void 0;
5
4
  const errors_1 = require("../errors");
6
5
  const AxiosHttpClient_1 = require("./AxiosHttpClient");
7
6
  const Consts_1 = require("./Consts");
8
7
  const Logger_1 = require("./Logger");
9
8
  const Utils_1 = require("./Utils");
10
- const IGNORE_OPCODE = [
11
- 0xd53276db, // Excess
12
- ];
13
9
  class TonTxFinalizer {
14
- constructor(contractOpener, logger = new Logger_1.NoopLogger()) {
15
- this.contractOpener = contractOpener;
16
- this.logger = logger;
17
- }
18
- // Fetches adjacent transactions from toncenter
19
- async fetchAdjacentTransactions(address, hash, retries = 5, delay = 1000, opts) {
20
- for (let i = retries; i >= 0; i--) {
21
- try {
22
- const txs = await this.contractOpener.getAdjacentTransactions(address, hash, opts);
23
- return txs;
24
- }
25
- catch (error) {
26
- const errorMessage = error.message;
27
- // Rate limit error (429) - retry
28
- if (errorMessage.includes('429')) {
29
- if (i > 0) {
30
- await (0, Utils_1.sleep)(delay);
31
- }
32
- continue;
33
- }
34
- // Log all errors except 404 Not Found
35
- if (!errorMessage.includes('404')) {
36
- const logMessage = error instanceof Error ? error.message : error;
37
- this.logger.warn(`Failed to fetch adjacent transactions for ${hash}:`, logMessage);
38
- }
39
- if (i > 0) {
40
- await (0, Utils_1.sleep)(delay);
41
- }
42
- }
43
- }
44
- return [];
45
- }
46
- // Checks if all transactions in the tree are successful
47
- async trackTransactionTree(address, hash, params = { maxDepth: Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList: IGNORE_OPCODE }) {
48
- const { maxDepth = Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList = IGNORE_OPCODE } = params;
49
- const parsedAddress = ton_1.Address.parse(address);
50
- const visitedHashes = new Set();
51
- const queue = [{ address: parsedAddress, hash, depth: 0 }];
52
- while (queue.length > 0) {
53
- const { hash: currentHash, depth: currentDepth, address: currentAddress } = queue.shift();
54
- if (visitedHashes.has(currentHash)) {
55
- continue;
56
- }
57
- visitedHashes.add(currentHash);
58
- this.logger.debug(`Checking hash (depth ${currentDepth}): ${currentHash}`);
59
- const transactions = await this.fetchAdjacentTransactions(currentAddress, currentHash, 5, 1000, {
60
- limit: 10,
61
- archival: true,
62
- });
63
- this.logger.debug(`Found ${transactions.length} adjacent transactions for ${currentHash}`);
64
- if (transactions.length === 0)
65
- continue;
66
- for (const tx of transactions) {
67
- if (tx.description.type !== 'generic' || !tx.inMessage)
68
- continue;
69
- if (tx.inMessage.info.type === 'internal' && tx.inMessage.info.value.coins === Consts_1.IGNORE_MSG_VALUE_1_NANO)
70
- continue; // we ignore messages with 1 nanoton value as they are for notification purpose only
71
- const bodySlice = tx.inMessage.body.beginParse();
72
- if (bodySlice.remainingBits < 32)
73
- continue;
74
- const opcode = bodySlice.loadUint(32);
75
- if (!ignoreOpcodeList.includes(opcode)) {
76
- const { aborted, computePhase, actionPhase } = tx.description;
77
- const failureCase = (() => {
78
- if (aborted) {
79
- return 'Transaction was aborted';
80
- }
81
- if (!computePhase) {
82
- return 'computePhase not present';
83
- }
84
- if (computePhase.type === 'skipped') {
85
- return 'computePhase was skipped';
86
- }
87
- if (!computePhase.success) {
88
- return 'computePhase not successful';
89
- }
90
- if (computePhase.exitCode !== 0) {
91
- return `computePhase.exitCode was not zero (exitCode=${computePhase.exitCode})`;
92
- }
93
- if (actionPhase && !actionPhase.success) {
94
- return 'actionPhase not successful';
95
- }
96
- if (actionPhase && actionPhase.resultCode !== 0) {
97
- return `actionPhase.resultCode was not zero (resultCode=${actionPhase.resultCode})`;
98
- }
99
- return null;
100
- })();
101
- if (failureCase) {
102
- throw (0, errors_1.txFinalizationError)(`${tx.hash().toString('base64')}: ${failureCase}`);
103
- }
104
- if (currentDepth + 1 < maxDepth) {
105
- if (tx.outMessages.size > 0) {
106
- queue.push({
107
- hash: tx.hash().toString('base64'),
108
- address: tx.inMessage.info.dest,
109
- depth: currentDepth + 1,
110
- });
111
- }
112
- }
113
- }
114
- else {
115
- this.logger.debug(`Skipping hash (depth ${currentDepth}): ${tx.hash().toString('base64')}`);
116
- }
117
- }
118
- this.logger.debug(`Finished checking hash (depth ${currentDepth}): ${currentHash}`);
119
- }
120
- }
121
- }
122
- exports.TonTxFinalizer = TonTxFinalizer;
123
- class TonIndexerTxFinalizer {
124
10
  constructor(apiConfig, logger = new Logger_1.NoopLogger(), httpClient = new AxiosHttpClient_1.AxiosHttpClient()) {
125
11
  this.apiConfig = apiConfig;
126
12
  this.logger = logger;
127
13
  this.httpClient = httpClient;
128
14
  }
129
15
  // Fetches adjacent transactions from toncenter
130
- async fetchAdjacentTransactions(hash, retries = 5, delay = 1000) {
16
+ async fetchAdjacentTransactions(hash, retries = Consts_1.DEFAULT_RETRY_MAX_COUNT, delay = Consts_1.DEFAULT_RETRY_DELAY_MS) {
131
17
  for (let i = retries; i >= 0; i--) {
132
18
  try {
133
19
  const url = this.apiConfig.urlBuilder(hash);
@@ -161,8 +47,8 @@ class TonIndexerTxFinalizer {
161
47
  return [];
162
48
  }
163
49
  // Checks if all transactions in the tree are successful
164
- async trackTransactionTree(_, hash, params = { maxDepth: Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList: IGNORE_OPCODE }) {
165
- const { maxDepth = Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList = IGNORE_OPCODE } = params;
50
+ async trackTransactionTree(_, hash, params = { maxDepth: Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList: Consts_1.IGNORE_OPCODE }) {
51
+ const { maxDepth = Consts_1.DEFAULT_FIND_TX_MAX_DEPTH, ignoreOpcodeList = Consts_1.IGNORE_OPCODE } = params;
166
52
  const visitedHashes = new Set();
167
53
  const queue = [{ hash, depth: 0 }];
168
54
  while (queue.length > 0) {
@@ -191,18 +77,20 @@ class TonIndexerTxFinalizer {
191
77
  return 'computePh not successful';
192
78
  }
193
79
  if (computePh.exitCode !== 0) {
194
- return `computePh.exitCode was not zero (exitCode=${computePh.exitCode})`;
80
+ return `computePh.exitCode was not zero`;
195
81
  }
196
82
  if (action && !action.success) {
197
83
  return 'action not successful';
198
84
  }
199
85
  if (action && action.resultCode !== 0) {
200
- return `action.resultCode was not zero (resultCode=${action.resultCode})`;
86
+ return `action.resultCode was not zero`;
201
87
  }
202
88
  return null;
203
89
  })();
204
90
  if (failureCase) {
205
- throw (0, errors_1.txFinalizationError)(`${tx.hash}: ${failureCase}`);
91
+ const exitCode = computePh ? computePh.exitCode : 'N/A';
92
+ const resultCode = action ? action.resultCode : 'N/A';
93
+ throw (0, errors_1.txFinalizationError)(`${tx.hash}: ${failureCase} (exitCode=${exitCode}, resultCode=${resultCode})`);
206
94
  }
207
95
  if (currentDepth + 1 < maxDepth) {
208
96
  if (tx.outMsgs.length > 0) {
@@ -217,4 +105,4 @@ class TonIndexerTxFinalizer {
217
105
  }
218
106
  }
219
107
  }
220
- exports.TonIndexerTxFinalizer = TonIndexerTxFinalizer;
108
+ exports.TonTxFinalizer = TonTxFinalizer;
@@ -37,6 +37,11 @@ export declare function getString(cell?: Cell): string;
37
37
  * Calculates (a * b + c / 2) / c with proper rounding
38
38
  */
39
39
  export declare function muldivr(a: bigint, b: bigint, c: bigint): bigint;
40
+ /**
41
+ * Normalize hash string to base64 format
42
+ * Accepts: base64, hex, or raw string
43
+ */
44
+ export declare function normalizeHashToBase64(hash: string): string;
40
45
  export declare function getNormalizedExtMessageHash(message: Message): string;
41
46
  export declare function retry<T>(fn: () => Promise<T>, options: {
42
47
  retries: number;
@@ -20,6 +20,7 @@ exports.getAddressString = getAddressString;
20
20
  exports.getNumber = getNumber;
21
21
  exports.getString = getString;
22
22
  exports.muldivr = muldivr;
23
+ exports.normalizeHashToBase64 = normalizeHashToBase64;
23
24
  exports.getNormalizedExtMessageHash = getNormalizedExtMessageHash;
24
25
  exports.retry = retry;
25
26
  exports.recurisivelyCollectCellStats = recurisivelyCollectCellStats;
@@ -316,6 +317,29 @@ function muldivr(a, b, c) {
316
317
  }
317
318
  return (a * b + c / 2n) / c;
318
319
  }
320
+ /**
321
+ * Normalize hash string to base64 format
322
+ * Accepts: base64, hex, or raw string
323
+ */
324
+ function normalizeHashToBase64(hash) {
325
+ // If already base64 (contains +, /, = or matches base64 pattern)
326
+ if (/^[A-Za-z0-9+/]+={0,2}$/.test(hash)) {
327
+ try {
328
+ // Validate it's valid base64
329
+ Buffer.from(hash, 'base64');
330
+ return hash;
331
+ }
332
+ catch {
333
+ // Fall through to hex conversion
334
+ }
335
+ }
336
+ // Try as hex
337
+ if (/^[0-9a-fA-F]+$/.test(hash)) {
338
+ return Buffer.from(hash, 'hex').toString('base64');
339
+ }
340
+ // Assume it's already base64
341
+ return hash;
342
+ }
319
343
  function getNormalizedExtMessageHash(message) {
320
344
  if (message.info.type !== 'external-in') {
321
345
  throw new Error(`Message must be "external-in", got ${message.info.type}`);
@@ -99,6 +99,7 @@ export type TransactionDepth = {
99
99
  address?: Address;
100
100
  hash: string;
101
101
  depth: number;
102
+ hashType?: 'unknown' | 'in' | 'out';
102
103
  };
103
104
  export type AdjacentTransactionsResponse = {
104
105
  transactions: ToncenterTransaction[];
@@ -123,22 +124,6 @@ export type ConvertedCurrencyRawResult = {
123
124
  tacPrice: USDPriceInfoRaw;
124
125
  tonPrice: USDPriceInfoRaw;
125
126
  };
126
- export type GetTransactionsOptions = {
127
- limit: number;
128
- lt?: string;
129
- hash?: string;
130
- to_lt?: string;
131
- inclusive?: boolean;
132
- archival?: boolean;
133
- timeoutMs?: number;
134
- retryDelayMs?: number;
135
- };
136
- export type AddressInformation = {
137
- lastTransaction: {
138
- lt: string;
139
- hash: string;
140
- };
141
- };
142
127
  export type TONFeesParams = {
143
128
  accountBitPrice: number;
144
129
  accountCellPrice: number;
@@ -4,7 +4,6 @@ import { AbstractProvider } from 'ethers';
4
4
  import { JettonMinter, JettonMinterData } from '../../artifacts/tonTypes';
5
5
  import type { FT, NFT } from '../assets';
6
6
  import type { Asset, ContractOpener, ILogger } from '../interfaces';
7
- import { ITxFinalizer } from '../interfaces/ITxFinalizer';
8
7
  import { SendResult } from './InternalStruct';
9
8
  export type ContractState = {
10
9
  balance: bigint;
@@ -61,10 +60,6 @@ export type TONParams = {
61
60
  * Address of TON settings contract. Use only for tests.
62
61
  */
63
62
  settingsAddress?: string;
64
- /**
65
- * TxFinalizer for tracking transaction tree
66
- */
67
- txFinalizer?: ITxFinalizer;
68
63
  };
69
64
  export type SDKParams = {
70
65
  /**
@@ -451,7 +446,97 @@ export type TacGasPrice = {
451
446
  fast: number;
452
447
  slow: number;
453
448
  };
449
+ /**
450
+ * Parameters for tracking and validating transaction trees
451
+ */
454
452
  export type TrackTransactionTreeParams = {
453
+ /**
454
+ * Maximum number of transactions to fetch per pagination request
455
+ * @default 100
456
+ */
457
+ limit?: number;
458
+ /**
459
+ * Maximum depth to traverse in the transaction tree (prevents infinite loops)
460
+ * @default 10
461
+ */
455
462
  maxDepth?: number;
463
+ /**
464
+ * List of operation codes (opcodes) to skip during validation.
465
+ * Transactions with these opcodes in their incoming message will not be validated.
466
+ * @default [ 0xd53276db ] // Excess
467
+ */
456
468
  ignoreOpcodeList?: number[];
469
+ /**
470
+ * Direction to search the transaction tree:
471
+ * - 'forward': only search children (outgoing messages)
472
+ * - 'backward': only search parents (incoming messages)
473
+ * - 'both': search in both directions (default)
474
+ * @default 'both'
475
+ */
476
+ direction?: 'forward' | 'backward' | 'both';
477
+ };
478
+ /**
479
+ * Details about a transaction validation error
480
+ */
481
+ export type TransactionValidationError = {
482
+ /**
483
+ * Base64-encoded hash of the failed transaction
484
+ */
485
+ txHash: string;
486
+ /**
487
+ * Exit code from the compute phase, or 'N/A' if compute phase is missing
488
+ */
489
+ exitCode: number | 'N/A';
490
+ /**
491
+ * Result code from the action phase, or 'N/A' if action phase is missing
492
+ */
493
+ resultCode: number | 'N/A';
494
+ /**
495
+ * Reason for validation failure:
496
+ * - 'aborted': default: transaction was aborted
497
+ * - 'compute_phase_missing': compute phase is missing or skipped
498
+ * - 'compute_phase_failed': compute phase failed (exitCode !== 0)
499
+ * - 'action_phase_failed': action phase failed (resultCode !== 0)
500
+ */
501
+ reason: 'aborted' | 'compute_phase_missing' | 'compute_phase_failed' | 'action_phase_failed';
502
+ };
503
+ /**
504
+ * Result of transaction tree tracking and validation
505
+ */
506
+ export type TrackTransactionTreeResult = {
507
+ /**
508
+ * Whether all transactions in the tree passed validation
509
+ */
510
+ success: boolean;
511
+ /**
512
+ * Details about the first validation error encountered (if any)
513
+ */
514
+ error?: TransactionValidationError;
515
+ };
516
+ export type GetTransactionsOptions = {
517
+ /** Maximum number of transactions to retrieve */
518
+ limit?: number;
519
+ /** Logical time of the transaction to start from */
520
+ lt?: string;
521
+ /** Hash of the transaction to start from */
522
+ hash?: string;
523
+ /** Logical time of the transaction to end at */
524
+ to_lt?: string;
525
+ /** Whether to include the starting transaction in the results */
526
+ inclusive?: boolean;
527
+ /** Whether to search in archival nodes for historical data */
528
+ archival?: boolean;
529
+ /** Request timeout in milliseconds */
530
+ timeoutMs?: number;
531
+ /** Delay between retry attempts in milliseconds */
532
+ retryDelayMs?: number;
533
+ };
534
+ export type AddressInformation = {
535
+ /** Information about the last transaction of the address */
536
+ lastTransaction: {
537
+ /** Logical time of the last transaction */
538
+ lt: string;
539
+ /** Hash of the last transaction */
540
+ hash: string;
541
+ };
457
542
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonappchain/sdk",
3
- "version": "0.7.2-alpha-11",
3
+ "version": "0.7.2-alpha-13",
4
4
  "repository": "https://github.com/TacBuild/tac-sdk.git",
5
5
  "author": "TAC. <developers@tac>",
6
6
  "license": "MIT",
@@ -1,24 +0,0 @@
1
- import { Blockchain } from '@ton/sandbox';
2
- import { Address, TonClient, Transaction } from '@ton/ton';
3
- import { ContractOpener } from '../interfaces';
4
- import { GetTransactionsOptions } from '../structs/InternalStruct';
5
- import { Network } from '../structs/Struct';
6
- export declare function getAdjacentTransactionsHelper(addr: Address, hashB64: string, getTransactions: (addr: Address, opts: GetTransactionsOptions) => Promise<Transaction[]>, opts?: GetTransactionsOptions): Promise<Transaction[]>;
7
- type LiteServer = {
8
- ip: number;
9
- port: number;
10
- id: {
11
- '@type': string;
12
- key: string;
13
- };
14
- };
15
- export declare function liteClientOpener(options: {
16
- liteservers: LiteServer[];
17
- } | {
18
- network: Network;
19
- }): Promise<ContractOpener>;
20
- export declare function sandboxOpener(blockchain: Blockchain): ContractOpener;
21
- export declare function orbsOpener(network: Network): Promise<ContractOpener>;
22
- export declare function orbsOpener4(network: Network, timeout?: number): Promise<ContractOpener>;
23
- export declare function tonClientOpener(client: TonClient): ContractOpener;
24
- export {};