@pioneer-platform/ton-network 8.11.0

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.
@@ -0,0 +1,2 @@
1
+
2
+ $ tsc -p .
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare const NETWORK_ID = "ton:-239";
2
+ export declare const CHAIN_SYMBOL = "TON";
3
+ export declare const DECIMALS = 9;
package/lib/index.js ADDED
@@ -0,0 +1,488 @@
1
+ "use strict";
2
+ /*
3
+ TON (The Open Network) Network Module
4
+
5
+ Provides connectivity to the TON blockchain network.
6
+
7
+ Network ID: ton:-239
8
+ SLIP44: 607
9
+ Decimals: 9 (nanotons)
10
+
11
+ Public API Endpoints:
12
+ - https://toncenter.com/api/v2 (TonCenter)
13
+ - https://tonapi.io/v2 (TonAPI)
14
+
15
+ TON addresses use two formats:
16
+ - Raw: workchain:hex_hash (e.g., 0:abc123...)
17
+ - User-friendly: Base64 encoded with checksum (e.g., EQ...)
18
+
19
+ TODO: Implement full network functionality
20
+ - Transaction building (TL-B cells)
21
+ - Transaction signing coordination with KeepKey
22
+ - Balance fetching
23
+ - Jetton (TRC-20) token queries
24
+ - NFT support
25
+ */
26
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
27
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28
+ return new (P || (P = Promise))(function (resolve, reject) {
29
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
33
+ });
34
+ };
35
+ var __generator = (this && this.__generator) || function (thisArg, body) {
36
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
37
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
38
+ function verb(n) { return function (v) { return step([n, v]); }; }
39
+ function step(op) {
40
+ if (f) throw new TypeError("Generator is already executing.");
41
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
42
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
43
+ if (y = 0, t) op = [op[0] & 2, t.value];
44
+ switch (op[0]) {
45
+ case 0: case 1: t = op; break;
46
+ case 4: _.label++; return { value: op[1], done: false };
47
+ case 5: _.label++; y = op[1]; op = [0]; continue;
48
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
49
+ default:
50
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
51
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
52
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
53
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
54
+ if (t[2]) _.ops.pop();
55
+ _.trys.pop(); continue;
56
+ }
57
+ op = body.call(thisArg, _);
58
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
59
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
60
+ }
61
+ };
62
+ Object.defineProperty(exports, "__esModule", { value: true });
63
+ exports.DECIMALS = exports.CHAIN_SYMBOL = exports.NETWORK_ID = void 0;
64
+ var TAG = " | ton-network | ";
65
+ require("dotenv").config({ path: '../../../../.env' });
66
+ var axiosLib = require('axios');
67
+ var Axios = axiosLib.default || axiosLib;
68
+ var https = require('https');
69
+ var log = require('@pioneer-platform/loggerdog')();
70
+ // Default TON mainnet API (TonCenter)
71
+ var DEFAULT_API_URL = "https://toncenter.com/api/v2";
72
+ // Network constants
73
+ exports.NETWORK_ID = 'ton:-239';
74
+ exports.CHAIN_SYMBOL = 'TON';
75
+ exports.DECIMALS = 9;
76
+ // Create axios instance for API calls
77
+ var axios = Axios.create({
78
+ httpsAgent: new https.Agent({
79
+ rejectUnauthorized: false
80
+ }),
81
+ headers: {
82
+ 'Content-Type': 'application/json'
83
+ }
84
+ });
85
+ // Module state
86
+ var apiUrl = DEFAULT_API_URL;
87
+ var apiKey = null;
88
+ var isInitialized = false;
89
+ /**********************************
90
+ // Module Exports
91
+ //**********************************/
92
+ module.exports = {
93
+ /**
94
+ * Initialize the TON network module
95
+ * @param url - Optional custom API URL
96
+ * @param settings - Optional settings object (may contain apiKey)
97
+ */
98
+ init: function (url, settings) {
99
+ return __awaiter(this, void 0, void 0, function () {
100
+ var tag, headers, testResult, e_1;
101
+ return __generator(this, function (_a) {
102
+ switch (_a.label) {
103
+ case 0:
104
+ tag = TAG + " | init | ";
105
+ _a.label = 1;
106
+ case 1:
107
+ _a.trys.push([1, 3, , 4]);
108
+ apiUrl = url || process.env['TON_API_URL'] || DEFAULT_API_URL;
109
+ apiKey = (settings === null || settings === void 0 ? void 0 : settings.apiKey) || process.env['TONCENTER_API_KEY'] || null;
110
+ log.info(tag, "Initializing TON network...");
111
+ log.info(tag, "API Endpoint:", apiUrl);
112
+ log.info(tag, "API Key configured:", apiKey ? "Yes" : "No (rate limited)");
113
+ headers = { 'Content-Type': 'application/json' };
114
+ if (apiKey) {
115
+ headers['X-API-Key'] = apiKey;
116
+ }
117
+ return [4 /*yield*/, axios({
118
+ url: "".concat(apiUrl, "/getMasterchainInfo"),
119
+ method: 'GET',
120
+ headers: headers
121
+ })];
122
+ case 2:
123
+ testResult = _a.sent();
124
+ if (testResult.data && testResult.data.ok) {
125
+ log.info(tag, "Successfully connected to TON API");
126
+ log.info(tag, "Masterchain seqno:", testResult.data.result.last.seqno);
127
+ isInitialized = true;
128
+ return [2 /*return*/, true];
129
+ }
130
+ else {
131
+ throw new Error("Invalid response from TON API");
132
+ }
133
+ return [3 /*break*/, 4];
134
+ case 3:
135
+ e_1 = _a.sent();
136
+ log.error(tag, "Failed to initialize:", e_1.message);
137
+ throw e_1;
138
+ case 4: return [2 /*return*/];
139
+ }
140
+ });
141
+ });
142
+ },
143
+ /**
144
+ * Check if the module is online and initialized
145
+ */
146
+ isOnline: function () {
147
+ return isInitialized;
148
+ },
149
+ /**
150
+ * Get the balance of a TON address
151
+ * @param address - TON address (user-friendly or raw format)
152
+ * @returns Balance in TON
153
+ */
154
+ getBalance: function (address) {
155
+ return get_balance(address);
156
+ },
157
+ /**
158
+ * Get address info for a TON address
159
+ * @param address - TON address
160
+ */
161
+ getAddressInfo: function (address) {
162
+ return get_address_info(address);
163
+ },
164
+ /**
165
+ * Get wallet seqno (sequence number for transactions)
166
+ * @param address - TON address
167
+ */
168
+ getWalletSeqno: function (address) {
169
+ return get_wallet_seqno(address);
170
+ },
171
+ /**
172
+ * Broadcast a signed transaction (BOC)
173
+ * @param boc - Base64 encoded BOC (Bag of Cells)
174
+ */
175
+ broadcast: function (boc) {
176
+ return broadcast_transaction(boc);
177
+ },
178
+ /**
179
+ * Get transaction details
180
+ * @param address - Address involved in transaction
181
+ * @param lt - Logical time of transaction
182
+ * @param hash - Transaction hash
183
+ */
184
+ getTransaction: function (address, lt, hash) {
185
+ return get_transaction(address, lt, hash);
186
+ },
187
+ /**
188
+ * Get transactions for an address
189
+ * @param address - TON address
190
+ * @param limit - Number of transactions to fetch (default 10)
191
+ */
192
+ getTransactions: function (address, limit) {
193
+ if (limit === void 0) { limit = 10; }
194
+ return get_transactions(address, limit);
195
+ },
196
+ /**
197
+ * Get masterchain info
198
+ */
199
+ getMasterchainInfo: function () {
200
+ return get_masterchain_info();
201
+ },
202
+ // Network constants
203
+ NETWORK_ID: exports.NETWORK_ID,
204
+ CHAIN_SYMBOL: exports.CHAIN_SYMBOL,
205
+ DECIMALS: exports.DECIMALS
206
+ };
207
+ /**********************************
208
+ // Implementation Functions
209
+ //**********************************/
210
+ function getHeaders() {
211
+ var headers = { 'Content-Type': 'application/json' };
212
+ if (apiKey) {
213
+ headers['X-API-Key'] = apiKey;
214
+ }
215
+ return headers;
216
+ }
217
+ function get_balance(address) {
218
+ return __awaiter(this, void 0, void 0, function () {
219
+ var tag, response, balanceInNanotons, balanceInTON, e_2;
220
+ return __generator(this, function (_a) {
221
+ switch (_a.label) {
222
+ case 0:
223
+ tag = TAG + " | get_balance | ";
224
+ _a.label = 1;
225
+ case 1:
226
+ _a.trys.push([1, 3, , 4]);
227
+ log.debug(tag, "Getting balance for:", address);
228
+ return [4 /*yield*/, axios({
229
+ url: "".concat(apiUrl, "/getAddressBalance"),
230
+ method: 'GET',
231
+ headers: getHeaders(),
232
+ params: { address: address }
233
+ })];
234
+ case 2:
235
+ response = _a.sent();
236
+ if (response.data && response.data.ok) {
237
+ balanceInNanotons = BigInt(response.data.result);
238
+ balanceInTON = Number(balanceInNanotons) / Math.pow(10, exports.DECIMALS);
239
+ log.debug(tag, "Balance retrieved:", balanceInTON, "TON");
240
+ return [2 /*return*/, balanceInTON];
241
+ }
242
+ if (response.data && !response.data.ok) {
243
+ log.warn(tag, "API error:", response.data.error);
244
+ return [2 /*return*/, 0];
245
+ }
246
+ return [2 /*return*/, 0];
247
+ case 3:
248
+ e_2 = _a.sent();
249
+ log.error(tag, "Error getting balance:", e_2.message);
250
+ return [2 /*return*/, 0];
251
+ case 4: return [2 /*return*/];
252
+ }
253
+ });
254
+ });
255
+ }
256
+ function get_address_info(address) {
257
+ return __awaiter(this, void 0, void 0, function () {
258
+ var tag, response, result, e_3;
259
+ var _a, _b;
260
+ return __generator(this, function (_c) {
261
+ switch (_c.label) {
262
+ case 0:
263
+ tag = TAG + " | get_address_info | ";
264
+ _c.label = 1;
265
+ case 1:
266
+ _c.trys.push([1, 3, , 4]);
267
+ log.debug(tag, "Getting address info for:", address);
268
+ return [4 /*yield*/, axios({
269
+ url: "".concat(apiUrl, "/getAddressInformation"),
270
+ method: 'GET',
271
+ headers: getHeaders(),
272
+ params: { address: address }
273
+ })];
274
+ case 2:
275
+ response = _c.sent();
276
+ if (response.data && response.data.ok) {
277
+ result = response.data.result;
278
+ return [2 /*return*/, {
279
+ balance: Number(BigInt(result.balance)) / Math.pow(10, exports.DECIMALS),
280
+ state: result.state,
281
+ lastTransactionLt: (_a = result.last_transaction_id) === null || _a === void 0 ? void 0 : _a.lt,
282
+ lastTransactionHash: (_b = result.last_transaction_id) === null || _b === void 0 ? void 0 : _b.hash
283
+ }];
284
+ }
285
+ return [2 /*return*/, null];
286
+ case 3:
287
+ e_3 = _c.sent();
288
+ log.error(tag, "Error getting address info:", e_3.message);
289
+ throw e_3;
290
+ case 4: return [2 /*return*/];
291
+ }
292
+ });
293
+ });
294
+ }
295
+ function get_wallet_seqno(address) {
296
+ return __awaiter(this, void 0, void 0, function () {
297
+ var tag, response, stack, e_4;
298
+ return __generator(this, function (_a) {
299
+ switch (_a.label) {
300
+ case 0:
301
+ tag = TAG + " | get_wallet_seqno | ";
302
+ _a.label = 1;
303
+ case 1:
304
+ _a.trys.push([1, 3, , 4]);
305
+ log.debug(tag, "Getting wallet seqno for:", address);
306
+ return [4 /*yield*/, axios({
307
+ url: "".concat(apiUrl, "/runGetMethod"),
308
+ method: 'POST',
309
+ headers: getHeaders(),
310
+ data: {
311
+ address: address,
312
+ method: "seqno",
313
+ stack: []
314
+ }
315
+ })];
316
+ case 2:
317
+ response = _a.sent();
318
+ if (response.data && response.data.ok) {
319
+ stack = response.data.result.stack;
320
+ if (stack && stack.length > 0) {
321
+ // seqno is returned as a number on the stack
322
+ return [2 /*return*/, parseInt(stack[0][1], 16)];
323
+ }
324
+ }
325
+ return [2 /*return*/, null];
326
+ case 3:
327
+ e_4 = _a.sent();
328
+ // If seqno fails, it might be an uninitialized wallet
329
+ log.warn(tag, "Error getting seqno (wallet may be uninitialized):", e_4.message);
330
+ return [2 /*return*/, 0];
331
+ case 4: return [2 /*return*/];
332
+ }
333
+ });
334
+ });
335
+ }
336
+ function broadcast_transaction(boc) {
337
+ return __awaiter(this, void 0, void 0, function () {
338
+ var tag, output, response, e_5;
339
+ var _a;
340
+ return __generator(this, function (_b) {
341
+ switch (_b.label) {
342
+ case 0:
343
+ tag = TAG + " | broadcast_transaction | ";
344
+ output = { success: false };
345
+ _b.label = 1;
346
+ case 1:
347
+ _b.trys.push([1, 3, , 4]);
348
+ log.debug(tag, "Broadcasting transaction...");
349
+ return [4 /*yield*/, axios({
350
+ url: "".concat(apiUrl, "/sendBoc"),
351
+ method: 'POST',
352
+ headers: getHeaders(),
353
+ data: { boc: boc }
354
+ })];
355
+ case 2:
356
+ response = _b.sent();
357
+ if (response.data) {
358
+ if (response.data.ok) {
359
+ output.success = true;
360
+ output.hash = (_a = response.data.result) === null || _a === void 0 ? void 0 : _a.hash;
361
+ log.info(tag, "Transaction broadcast successful");
362
+ }
363
+ else {
364
+ output.success = false;
365
+ output.error = response.data.error || 'Unknown error';
366
+ log.error(tag, "Broadcast error:", output.error);
367
+ }
368
+ }
369
+ return [2 /*return*/, output];
370
+ case 3:
371
+ e_5 = _b.sent();
372
+ log.error(tag, "Broadcast error:", e_5.message);
373
+ output.error = e_5.message;
374
+ return [2 /*return*/, output];
375
+ case 4: return [2 /*return*/];
376
+ }
377
+ });
378
+ });
379
+ }
380
+ function get_transaction(address, lt, hash) {
381
+ return __awaiter(this, void 0, void 0, function () {
382
+ var tag, response, e_6;
383
+ return __generator(this, function (_a) {
384
+ switch (_a.label) {
385
+ case 0:
386
+ tag = TAG + " | get_transaction | ";
387
+ _a.label = 1;
388
+ case 1:
389
+ _a.trys.push([1, 3, , 4]);
390
+ log.debug(tag, "Getting transaction:", { address: address, lt: lt, hash: hash });
391
+ return [4 /*yield*/, axios({
392
+ url: "".concat(apiUrl, "/getTransactions"),
393
+ method: 'GET',
394
+ headers: getHeaders(),
395
+ params: {
396
+ address: address,
397
+ lt: lt,
398
+ hash: hash,
399
+ limit: 1
400
+ }
401
+ })];
402
+ case 2:
403
+ response = _a.sent();
404
+ if (response.data && response.data.ok && response.data.result.length > 0) {
405
+ return [2 /*return*/, response.data.result[0]];
406
+ }
407
+ return [2 /*return*/, null];
408
+ case 3:
409
+ e_6 = _a.sent();
410
+ log.error(tag, "Error getting transaction:", e_6.message);
411
+ throw e_6;
412
+ case 4: return [2 /*return*/];
413
+ }
414
+ });
415
+ });
416
+ }
417
+ function get_transactions(address_1) {
418
+ return __awaiter(this, arguments, void 0, function (address, limit) {
419
+ var tag, response, e_7;
420
+ if (limit === void 0) { limit = 10; }
421
+ return __generator(this, function (_a) {
422
+ switch (_a.label) {
423
+ case 0:
424
+ tag = TAG + " | get_transactions | ";
425
+ _a.label = 1;
426
+ case 1:
427
+ _a.trys.push([1, 3, , 4]);
428
+ log.debug(tag, "Getting transactions for:", address);
429
+ return [4 /*yield*/, axios({
430
+ url: "".concat(apiUrl, "/getTransactions"),
431
+ method: 'GET',
432
+ headers: getHeaders(),
433
+ params: {
434
+ address: address,
435
+ limit: limit
436
+ }
437
+ })];
438
+ case 2:
439
+ response = _a.sent();
440
+ if (response.data && response.data.ok) {
441
+ return [2 /*return*/, response.data.result];
442
+ }
443
+ return [2 /*return*/, []];
444
+ case 3:
445
+ e_7 = _a.sent();
446
+ log.error(tag, "Error getting transactions:", e_7.message);
447
+ throw e_7;
448
+ case 4: return [2 /*return*/];
449
+ }
450
+ });
451
+ });
452
+ }
453
+ function get_masterchain_info() {
454
+ return __awaiter(this, void 0, void 0, function () {
455
+ var tag, response, e_8;
456
+ return __generator(this, function (_a) {
457
+ switch (_a.label) {
458
+ case 0:
459
+ tag = TAG + " | get_masterchain_info | ";
460
+ _a.label = 1;
461
+ case 1:
462
+ _a.trys.push([1, 3, , 4]);
463
+ return [4 /*yield*/, axios({
464
+ url: "".concat(apiUrl, "/getMasterchainInfo"),
465
+ method: 'GET',
466
+ headers: getHeaders()
467
+ })];
468
+ case 2:
469
+ response = _a.sent();
470
+ if (response.data && response.data.ok) {
471
+ return [2 /*return*/, {
472
+ workchain: response.data.result.last.workchain,
473
+ shard: response.data.result.last.shard,
474
+ seqno: response.data.result.last.seqno,
475
+ rootHash: response.data.result.last.root_hash,
476
+ fileHash: response.data.result.last.file_hash
477
+ }];
478
+ }
479
+ return [2 /*return*/, null];
480
+ case 3:
481
+ e_8 = _a.sent();
482
+ log.error(tag, "Error getting masterchain info:", e_8.message);
483
+ throw e_8;
484
+ case 4: return [2 /*return*/];
485
+ }
486
+ });
487
+ });
488
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@pioneer-platform/ton-network",
3
+ "version": "8.11.0",
4
+ "main": "./lib/index.js",
5
+ "types": "./lib/index.d.ts",
6
+ "description": "Pioneer Platform TON Network module",
7
+ "keywords": [
8
+ "ton",
9
+ "toncoin",
10
+ "blockchain",
11
+ "pioneer"
12
+ ],
13
+ "scripts": {
14
+ "create": "pnpm run build && pnpm run test",
15
+ "build": "tsc -p .",
16
+ "test": "pnpm run build && node __tests__/test-module.js",
17
+ "prepublish": "rm -R lib && pnpm run build",
18
+ "refresh": "rm -rf ./node_modules ./package-lock.json && pnpm install"
19
+ },
20
+ "dependencies": {
21
+ "@pioneer-platform/loggerdog": "^8.11.0",
22
+ "axios": "^1.6.0",
23
+ "dotenv": "^16.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^18.16.0",
27
+ "typescript": "^5.0.4"
28
+ },
29
+ "gitHead": "aeae28273014ab69b42f22abec159c6693a56c40"
30
+ }