From d5478b1018ee1014bfc0b99b402d53df70931108 Mon Sep 17 00:00:00 2001 From: Alejandbel Date: Tue, 20 May 2025 16:55:05 +0300 Subject: [PATCH 1/7] chore: update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6b3fc59..dc832855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added ton lite client network provider + ## [0.34.0] - 2025-05-20 ### Added From 6fb04a8fdfc386ce2f81167ec0d49521584d0e0e Mon Sep 17 00:00:00 2001 From: Alejandbel Date: Mon, 26 May 2025 15:42:04 +0300 Subject: [PATCH 2/7] feat: start implementing network provider --- package.json | 9 +- src/network/NetworkProvider.ts | 3 +- yarn.lock | 193 +++++++++++++++++++++++++++++---- 3 files changed, 178 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index a69746ab..c54d1d93 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,10 @@ "devDependencies": { "@tact-lang/compiler": "^1.6.5", "@ton-community/func-js": "^0.9.0", - "@ton/core": "^0.59.0", + "@ton/core": "^0.60.1", "@ton/crypto": "^3.3.0", "@ton/tolk-js": "^0.12.0", - "@ton/ton": "^15.0.0", + "@ton/ton": "^15.2.1", "@types/inquirer": "^8.2.6", "@types/node": "^20.2.5", "@types/qrcode-terminal": "^0.12.0", @@ -34,10 +34,10 @@ "peerDependencies": { "@tact-lang/compiler": ">=1.6.5", "@ton-community/func-js": ">=0.9.0", - "@ton/core": ">=0.59.0", + "@ton/core": ">=0.60.1", "@ton/crypto": ">=3.3.0", "@ton/tolk-js": ">=0.12.0", - "@ton/ton": ">=15.0.0" + "@ton/ton": ">=15.2.1" }, "dependencies": { "@ton-api/client": "^0.2.0", @@ -49,6 +49,7 @@ "dotenv": "^16.1.4", "inquirer": "^8.2.5", "qrcode-terminal": "^0.12.0", + "ton-lite-client": "^3.0.0", "ts-node": "^10.9.1" }, "packageManager": "yarn@4.3.1" diff --git a/src/network/NetworkProvider.ts b/src/network/NetworkProvider.ts index a3b491dd..3203f998 100644 --- a/src/network/NetworkProvider.ts +++ b/src/network/NetworkProvider.ts @@ -2,8 +2,9 @@ import { TonClient, TonClient4 } from '@ton/ton'; import { Address, Cell, Contract, ContractProvider, OpenedContract, Sender, StateInit } from '@ton/core'; import { ContractAdapter } from '@ton-api/ton-adapter'; import { UIProvider } from '../ui/UIProvider'; +import { LiteClient } from "ton-lite-client"; -export type BlueprintTonClient = TonClient4 | TonClient | ContractAdapter; +export type BlueprintTonClient = TonClient4 | TonClient | ContractAdapter | LiteClient; /** diff --git a/yarn.lock b/yarn.lock index 71b022fa..362df89d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,6 +64,20 @@ __metadata: languageName: node linkType: hard +"@noble/ed25519@npm:^1.6.1": + version: 1.7.5 + resolution: "@noble/ed25519@npm:1.7.5" + checksum: 10/d763f97ae721eab307f0c873ec4d2e22b0a50c06bf64ff7bcf0423b8139e826705c18609c1c163a2ca3c7c9ea166be18f21020b934ab47960676b49355d7b69d + languageName: node + linkType: hard + +"@noble/hashes@npm:^1.2.0": + version: 1.8.0 + resolution: "@noble/hashes@npm:1.8.0" + checksum: 10/474b7f56bc6fb2d5b3a42132561e221b0ea4f91e590f4655312ca13667840896b34195e2b53b7f097ec080a1fdd3b58d902c2a8d0fbdf51d2e238b53808a177e + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -216,10 +230,10 @@ __metadata: "@ton-api/client": "npm:^0.2.0" "@ton-api/ton-adapter": "npm:^0.2.0" "@ton-community/func-js": "npm:^0.9.0" - "@ton/core": "npm:^0.59.0" + "@ton/core": "npm:^0.60.1" "@ton/crypto": "npm:^3.3.0" "@ton/tolk-js": "npm:^0.12.0" - "@ton/ton": "npm:^15.0.0" + "@ton/ton": "npm:^15.2.1" "@tonconnect/sdk": "npm:^2.2.0" "@types/inquirer": "npm:^8.2.6" "@types/node": "npm:^20.2.5" @@ -231,21 +245,22 @@ __metadata: inquirer: "npm:^8.2.5" prettier: "npm:^3.0.3" qrcode-terminal: "npm:^0.12.0" + ton-lite-client: "npm:^3.0.0" ts-node: "npm:^10.9.1" typescript: "npm:^5.8.3" peerDependencies: "@tact-lang/compiler": ">=1.6.5" "@ton-community/func-js": ">=0.9.0" - "@ton/core": ">=0.59.0" + "@ton/core": ">=0.60.1" "@ton/crypto": ">=3.3.0" "@ton/tolk-js": ">=0.12.0" - "@ton/ton": ">=15.0.0" + "@ton/ton": ">=15.2.1" bin: blueprint: ./dist/cli/cli.js languageName: unknown linkType: soft -"@ton/core@npm:0.60.1, @ton/core@npm:^0.60.0": +"@ton/core@npm:0.60.1, @ton/core@npm:^0.60.0, @ton/core@npm:^0.60.1": version: 0.60.1 resolution: "@ton/core@npm:0.60.1" dependencies: @@ -256,17 +271,6 @@ __metadata: languageName: node linkType: hard -"@ton/core@npm:^0.59.0": - version: 0.59.0 - resolution: "@ton/core@npm:0.59.0" - dependencies: - symbol.inspect: "npm:1.0.1" - peerDependencies: - "@ton/crypto": ">=3.2.0" - checksum: 10/cab72b14cf03f564612980424a0515ad6a373ad6361c2b33f56f9849c342b7ded5a9b4e4696a6be47b3833d6c78dd0fe50a89cb939394b047eaebc81731d37de - languageName: node - linkType: hard - "@ton/crypto-primitives@npm:2.0.0": version: 2.0.0 resolution: "@ton/crypto-primitives@npm:2.0.0" @@ -318,9 +322,9 @@ __metadata: languageName: node linkType: hard -"@ton/ton@npm:^15.0.0": - version: 15.0.0 - resolution: "@ton/ton@npm:15.0.0" +"@ton/ton@npm:^15.2.1": + version: 15.2.1 + resolution: "@ton/ton@npm:15.2.1" dependencies: axios: "npm:^1.6.7" dataloader: "npm:^2.0.0" @@ -328,9 +332,9 @@ __metadata: teslabot: "npm:^1.3.0" zod: "npm:^3.21.4" peerDependencies: - "@ton/core": ">=0.56.0" + "@ton/core": ">=0.60.0" "@ton/crypto": ">=3.2.0" - checksum: 10/135df6331ef76be621bffe4d92f8a932333e46a40476bdd6d1d71bb29d354e5fb640eb2ffccfe260b762be3220a02291e4db0e0afc0d33ba78efd25bab6793ee + checksum: 10/25edc421250c7e754dcf79ed3bf05d72c29fc06ba61302380d95e58f04325585ef42bf56e493c142ac20445caef04ed6150e6e1e99c0dd15314ca16c854c7155 languageName: node linkType: hard @@ -408,6 +412,15 @@ __metadata: languageName: node linkType: hard +"@types/bn.js@npm:^5.1.0": + version: 5.1.6 + resolution: "@types/bn.js@npm:5.1.6" + dependencies: + "@types/node": "npm:*" + checksum: 10/db565b5a2af59b09459d74441153bf23a0e80f1fb2d070330786054e7ce1a7285dc40afcd8f289426c61a83166bdd70814f70e2d439744686aac5d3ea75daf13 + languageName: node + linkType: hard + "@types/inquirer@npm:^8.2.6": version: 8.2.6 resolution: "@types/inquirer@npm:8.2.6" @@ -432,6 +445,13 @@ __metadata: languageName: node linkType: hard +"@types/pegjs@npm:^0.10.3": + version: 0.10.6 + resolution: "@types/pegjs@npm:0.10.6" + checksum: 10/be219504714e219b37daee7ef3214b6876d98405cc56b2d084763134032fd46394c5d0e387216ee3e52bd519fe7341e25bdec855f2a911c49a593b21fd8ea4a6 + languageName: node + linkType: hard + "@types/qrcode-terminal@npm:^0.12.0": version: 0.12.0 resolution: "@types/qrcode-terminal@npm:0.12.0" @@ -464,6 +484,28 @@ __metadata: languageName: node linkType: hard +"adnl@npm:^1.0.3": + version: 1.0.3 + resolution: "adnl@npm:1.0.3" + dependencies: + "@noble/ed25519": "npm:^1.6.1" + "@noble/hashes": "npm:^1.2.0" + aes-js: "npm:^3.1.2" + buffer: "npm:^6.0.3" + events: "npm:^3.3.0" + isomorphic-ws: "npm:^5.0.0" + ws: "npm:^8.8.1" + checksum: 10/bfb678580713b8786e8851b319f67d43a507e3d883b473b42410c7ebfbc17318cb789d13fadab74bb6c829d99a6300627187cd0623c97923d21d758c8a9d4335 + languageName: node + linkType: hard + +"aes-js@npm:^3.1.2": + version: 3.1.2 + resolution: "aes-js@npm:3.1.2" + checksum: 10/b65916767034a51375a3ac5aad62af452d89a386c1ae7b607bb9145d0bb8b8823bf2f3eba85bdfa52d61c65d5aed90ba90f677b8c826bfa1a8b7ae2fa3b54d91 + languageName: node + linkType: hard + "ansi-escapes@npm:^4.2.1": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" @@ -573,6 +615,13 @@ __metadata: languageName: node linkType: hard +"bn.js@npm:^5.2.0": + version: 5.2.2 + resolution: "bn.js@npm:5.2.2" + checksum: 10/51ebb2df83b33e5d8581165206e260d5e9c873752954616e5bf3758952b84d7399a9c6d00852815a0aeefb1150a7f34451b62d4287342d457fa432eee869e83e + languageName: node + linkType: hard + "buffer@npm:^5.5.0": version: 5.7.1 resolution: "buffer@npm:5.7.1" @@ -614,6 +663,13 @@ __metadata: languageName: node linkType: hard +"case-shift@npm:^2.5.3": + version: 2.5.3 + resolution: "case-shift@npm:2.5.3" + checksum: 10/dedc9859d9a19141052f0681a6d69d467bcf0624601f54aa0aaff2a3edcc9f647c6d58657e9bc540573ad7fdf87fe00b59a2df86ed3f50374d634a317e0d978a + languageName: node + linkType: hard + "chalk@npm:^4.1.0, chalk@npm:^4.1.1": version: 4.1.2 resolution: "chalk@npm:4.1.2" @@ -724,6 +780,15 @@ __metadata: languageName: node linkType: hard +"crc-32@npm:^1.2.2": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: 10/824f696a5baaf617809aa9cd033313c8f94f12d15ebffa69f10202480396be44aef9831d900ab291638a8022ed91c360696dd5b1ba691eb3f34e60be8835b7c3 + languageName: node + linkType: hard + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -738,6 +803,13 @@ __metadata: languageName: node linkType: hard +"dataloader@npm:^2.1.0": + version: 2.2.3 + resolution: "dataloader@npm:2.2.3" + checksum: 10/83fe6259abe00ae64c5f48252ef59d8e5fcabda9fd4d26685f14a76eeca596bf6f9500d9f22a0094c50c3ea782a0977728f9367e232dfa0fdb5c9d646de279b2 + languageName: node + linkType: hard + "debug@npm:^4.3.1": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -811,6 +883,13 @@ __metadata: languageName: node linkType: hard +"events@npm:^3.3.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: 10/a3d47e285e28d324d7180f1e493961a2bbb4cad6412090e4dec114f4db1f5b560c7696ee8e758f55e23913ede856e3689cd3aa9ae13c56b5d8314cd3b3ddd1be + languageName: node + linkType: hard + "eventsource@npm:^2.0.2": version: 2.0.2 resolution: "eventsource@npm:2.0.2" @@ -1010,6 +1089,15 @@ __metadata: languageName: node linkType: hard +"isomorphic-ws@npm:^5.0.0": + version: 5.0.0 + resolution: "isomorphic-ws@npm:5.0.0" + peerDependencies: + ws: "*" + checksum: 10/e20eb2aee09ba96247465fda40c6d22c1153394c0144fa34fe6609f341af4c8c564f60ea3ba762335a7a9c306809349f9b863c8beedf2beea09b299834ad5398 + languageName: node + linkType: hard + "it-all@npm:^1.0.4, it-all@npm:^1.0.5": version: 1.0.6 resolution: "it-all@npm:1.0.6" @@ -1110,6 +1198,13 @@ __metadata: languageName: node linkType: hard +"lru_map@npm:^0.4.1": + version: 0.4.1 + resolution: "lru_map@npm:0.4.1" + checksum: 10/c399afdb959c1820ace33b253c307c00e39a8a63705037f9dd58bf489950265de347b1614642fcfde26e0ff613fba633ddfd7eb5814ffb0a360a7037cc8a4008 + languageName: node + linkType: hard + "make-error@npm:^1.1.1": version: 1.3.6 resolution: "make-error@npm:1.3.6" @@ -1278,6 +1373,15 @@ __metadata: languageName: node linkType: hard +"pegjs@npm:^0.10.0": + version: 0.10.0 + resolution: "pegjs@npm:0.10.0" + bin: + pegjs: bin/pegjs + checksum: 10/edc12c9da9afa68ea1274350c3843026355ef3678de0e24213ba0598ee660d40f6752548ba5ddfbcdefee1904545c8a23bb59f331a5e8b3543bee29c21051f67 + languageName: node + linkType: hard + "prettier@npm:^3.0.3": version: 3.0.3 resolution: "prettier@npm:3.0.3" @@ -1474,7 +1578,7 @@ __metadata: languageName: node linkType: hard -"teslabot@npm:^1.3.0": +"teslabot@npm:^1.3.0, teslabot@npm:^1.5.0": version: 1.5.0 resolution: "teslabot@npm:1.5.0" checksum: 10/714ab9a3eadf17efdbcc78c140246c6cf02b0fceff2fd3b9e37de7c86ad05af816037145a258b4b115327bc88219d782f64047812483169037d6956f46bb1450 @@ -1497,6 +1601,36 @@ __metadata: languageName: node linkType: hard +"ton-lite-client@npm:^3.0.0": + version: 3.0.0 + resolution: "ton-lite-client@npm:3.0.0" + dependencies: + adnl: "npm:^1.0.3" + dataloader: "npm:^2.1.0" + lru_map: "npm:^0.4.1" + teslabot: "npm:^1.5.0" + ton-tl: "npm:^1.0.1" + tweetnacl: "npm:^1.0.3" + peerDependencies: + "@ton/core": "*" + checksum: 10/11d1f4e93ca4a7dc239e6a34f6c40ed1741a8d445352266b2471bbcc7f846bdfc014821e6ccbb88e90f938a6e48978e556885cd56017d0ec6ba7847073f492a0 + languageName: node + linkType: hard + +"ton-tl@npm:^1.0.1": + version: 1.0.1 + resolution: "ton-tl@npm:1.0.1" + dependencies: + "@types/bn.js": "npm:^5.1.0" + "@types/pegjs": "npm:^0.10.3" + bn.js: "npm:^5.2.0" + case-shift: "npm:^2.5.3" + crc-32: "npm:^1.2.2" + pegjs: "npm:^0.10.0" + checksum: 10/e3dd1ff0dd1e10c6d56186945918d14153f08cc6896541ead3b72e7af55b85dd84d32692dee6e831fee83ff4389d88ca65ef33e5a8a969d48378e04a71e6bf65 + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -1668,6 +1802,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.8.1": + version: 8.18.2 + resolution: "ws@npm:8.18.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/018e04ec95561d88248d53a2eaf094b4ae131e9b062f2679e6e8a62f04649bc543448f1e038125225ac6bbb25f54c1e65d7a2cc9dbc1e28b43e5e6b7162ad88e + languageName: node + linkType: hard + "yn@npm:3.1.1": version: 3.1.1 resolution: "yn@npm:3.1.1" From 338a4310da07c6de129b3084d23ac52388b75605 Mon Sep 17 00:00:00 2001 From: Alejandbel Date: Tue, 27 May 2025 11:44:25 +0300 Subject: [PATCH 3/7] feat: implement liteclient provider --- package.json | 2 +- src/config/CustomNetwork.ts | 4 +-- src/network/createNetworkProvider.ts | 44 ++++++++++++++++++++++++++-- yarn.lock | 12 ++++---- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index c54d1d93..806f6b1c 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "dotenv": "^16.1.4", "inquirer": "^8.2.5", "qrcode-terminal": "^0.12.0", - "ton-lite-client": "^3.0.0", + "ton-lite-client": "^3.1.s0", "ts-node": "^10.9.1" }, "packageManager": "yarn@4.3.1" diff --git a/src/config/CustomNetwork.ts b/src/config/CustomNetwork.ts index d8a75c13..194790dd 100644 --- a/src/config/CustomNetwork.ts +++ b/src/config/CustomNetwork.ts @@ -1,6 +1,6 @@ export type CustomNetwork = { - endpoint: string; - version?: 'v2' | 'v4' | 'tonapi'; + endpoint: string; // . + version?: 'v2' | 'v4' | 'tonapi' | 'liteclient'; key?: string; type?: 'mainnet' | 'testnet' | 'custom'; }; diff --git a/src/network/createNetworkProvider.ts b/src/network/createNetworkProvider.ts index 249badd0..c9002cb0 100644 --- a/src/network/createNetworkProvider.ts +++ b/src/network/createNetworkProvider.ts @@ -33,6 +33,7 @@ import { Config } from '../config/Config'; import { CustomNetwork } from '../config/CustomNetwork'; import axios, { AxiosAdapter, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; import { Network } from './Network'; +import {LiteClient, LiteEngine, LiteRoundRobinEngine, LiteSingleEngine} from "ton-lite-client"; const INITIAL_DELAY = 400; const MAX_ATTEMPTS = 4; @@ -284,6 +285,43 @@ async function createMnemonicProvider(client: BlueprintTonClient, network: Netwo }); } +function intToIP(int: number): string { + const part1 = int & 255; + const part2 = (int >> 8) & 255; + const part3 = (int >> 16) & 255; + const part4 = (int >> 24) & 255; + return `${(part4 + 256) % 256}.${(part3 + 256) % 256}.${(part2 + 256) % 256}.${ + (part1 + 256) % 256 + }`; +} + +async function buildLiteClient(configEndpoint: string) { + const response = await fetch(configEndpoint); + if (!response.ok) { + throw new Error(`Error fetching configuration from ${configEndpoint}. Use https://ton.org/testnet-global.config.json for testnet or https://ton.org/global.config.json for mainnet.`); + } + const config = await response.json(); + const engines: LiteEngine[] = []; + if (!Array.isArray(config.liteservers)) { + throw new Error(`Invalid liteclient configuration on ${configEndpoint}. Use`); + } + for (const server of config.liteservers) { + if (typeof server?.ip !== 'number' || typeof server?.port !== 'number' || typeof server?.id !== 'object' || typeof server?.id?.key !== 'string') { + throw new Error(`Invalid liteclient configuration on ${configEndpoint}`); + } + const ip = intToIP(server.ip); + const port = server.port; + const publicKey = Buffer.from(server.id.key, 'base64'); + const engine = new LiteSingleEngine({ + host: `tcp://${ip}:${port}`, + publicKey, + }); + engines.push(engine); + } + const engine: LiteEngine = new LiteRoundRobinEngine(engines); + return new LiteClient({ engine }); +} + class NetworkProviderBuilder { constructor( private args: Args, @@ -311,7 +349,7 @@ class NetworkProviderBuilder { if (network === 'custom') { const defaultCustomEndpoint = 'http://localhost:8081/'; this.args['--custom'] = ( - await this.ui.input(`Provide a custom API v2 endpoint (default is ${defaultCustomEndpoint})`) + await this.ui.input(`Provide a custom network endpoint (default is ${defaultCustomEndpoint})`) ).trim(); if (this.args['--custom'] === '') this.args['--custom'] = defaultCustomEndpoint; } @@ -407,7 +445,7 @@ class NetworkProviderBuilder { version = inputVer.toLowerCase() as any; // checks come later } const inputType = this.args['--custom-type']; - let type: 'mainnet' | 'testnet' | 'custom' | undefined = undefined; + let type: CustomNetwork['type'] = undefined; if (inputType !== undefined) { type = inputType as any; // checks come later } @@ -440,6 +478,8 @@ class NetworkProviderBuilder { apiKey: configNetwork.key, }), ); + } else if (configNetwork.version === 'liteclient') { + tc = await buildLiteClient(configNetwork.endpoint); } else { throw new Error('Unknown API version: ' + configNetwork.version); } diff --git a/yarn.lock b/yarn.lock index 362df89d..73cd575a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -245,7 +245,7 @@ __metadata: inquirer: "npm:^8.2.5" prettier: "npm:^3.0.3" qrcode-terminal: "npm:^0.12.0" - ton-lite-client: "npm:^3.0.0" + ton-lite-client: "npm:^3.1.0" ts-node: "npm:^10.9.1" typescript: "npm:^5.8.3" peerDependencies: @@ -1601,9 +1601,9 @@ __metadata: languageName: node linkType: hard -"ton-lite-client@npm:^3.0.0": - version: 3.0.0 - resolution: "ton-lite-client@npm:3.0.0" +"ton-lite-client@npm:^3.1.0": + version: 3.1.0 + resolution: "ton-lite-client@npm:3.1.0" dependencies: adnl: "npm:^1.0.3" dataloader: "npm:^2.1.0" @@ -1612,8 +1612,8 @@ __metadata: ton-tl: "npm:^1.0.1" tweetnacl: "npm:^1.0.3" peerDependencies: - "@ton/core": "*" - checksum: 10/11d1f4e93ca4a7dc239e6a34f6c40ed1741a8d445352266b2471bbcc7f846bdfc014821e6ccbb88e90f938a6e48978e556885cd56017d0ec6ba7847073f492a0 + "@ton/core": ^0.56.0 + checksum: 10/1ffa282e22b42c7adbef9e889f206c6dbb85ad15f9b9659cd131c5e44e41e03abb7962aee699b55e53036cc7ec98f2df5a6d1c025a77446f820eb2a921c8a3d9 languageName: node linkType: hard From 43a8ef6dc32b032d4a7f23c4a3ea15ef0441b5a0 Mon Sep 17 00:00:00 2001 From: Alejandbel Date: Tue, 27 May 2025 12:57:51 +0300 Subject: [PATCH 4/7] feat: add liteclient support --- README.md | 27 +++++++++++++++++++++++++- package.json | 2 +- src/network/createNetworkProvider.ts | 29 +++++++++++----------------- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f536cc19..c0e87126 100644 --- a/README.md +++ b/README.md @@ -290,7 +290,32 @@ The above config parameters are equivalent to the arguments in the following com npx blueprint run --custom https://toncenter.com/api/v2/jsonRPC --custom-version v2 --custom-type mainnet --custom-key YOUR_API_KEY ``` -Properties of the `network` object have the same semantics as the `--custom` flags with respective names (see `blueprint help run`). +### Liteclient Support + +Lite client is supported through the following configuration: + +```ts +import { Config } from '@ton/blueprint'; + +export const config: Config = { + network: { + endpoint: 'https://ton.org/testnet-global.config.json', // Use https://ton.org/global.config.json for mainnet or any custom configuration + version: 'liteclient', + type: 'testnet', + } +}; +``` + +You can also provide these parameters via CLI: + +```bash +npx blueprint run \ + --custom https://ton.org/testnet-global.config.json \ + --custom-version liteclient \ + --custom-type testnet +``` + +#### Contract Verification Using Custom Network You can also use custom network to verify contracts, like so: ```bash diff --git a/package.json b/package.json index 806f6b1c..40b82a98 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "dotenv": "^16.1.4", "inquirer": "^8.2.5", "qrcode-terminal": "^0.12.0", - "ton-lite-client": "^3.1.s0", + "ton-lite-client": "^3.1.0", "ts-node": "^10.9.1" }, "packageManager": "yarn@4.3.1" diff --git a/src/network/createNetworkProvider.ts b/src/network/createNetworkProvider.ts index c9002cb0..3e594af6 100644 --- a/src/network/createNetworkProvider.ts +++ b/src/network/createNetworkProvider.ts @@ -296,29 +296,22 @@ function intToIP(int: number): string { } async function buildLiteClient(configEndpoint: string) { - const response = await fetch(configEndpoint); - if (!response.ok) { - throw new Error(`Error fetching configuration from ${configEndpoint}. Use https://ton.org/testnet-global.config.json for testnet or https://ton.org/global.config.json for mainnet.`); + const { data } = await axios.get(configEndpoint); + if (!Array.isArray(data.liteservers)) { + throw new Error(`Invalid liteclient configuration on ${configEndpoint}. Use https://ton.org/testnet-global.config.json for testnet or https://ton.org/global.config.json for mainnet.`); } - const config = await response.json(); - const engines: LiteEngine[] = []; - if (!Array.isArray(config.liteservers)) { - throw new Error(`Invalid liteclient configuration on ${configEndpoint}. Use`); - } - for (const server of config.liteservers) { + + const engines = data.liteservers.map((server: any) => { if (typeof server?.ip !== 'number' || typeof server?.port !== 'number' || typeof server?.id !== 'object' || typeof server?.id?.key !== 'string') { throw new Error(`Invalid liteclient configuration on ${configEndpoint}`); } - const ip = intToIP(server.ip); - const port = server.port; - const publicKey = Buffer.from(server.id.key, 'base64'); - const engine = new LiteSingleEngine({ - host: `tcp://${ip}:${port}`, - publicKey, + return new LiteSingleEngine({ + host: `tcp://${intToIP(server.ip)}:${server.port}`, + publicKey: Buffer.from(server.id.key, 'base64'), }); - engines.push(engine); - } - const engine: LiteEngine = new LiteRoundRobinEngine(engines); + }) + + const engine = new LiteRoundRobinEngine(engines); return new LiteClient({ engine }); } From 14e8b2af8876f6c9f81c85411ad1241ac310642b Mon Sep 17 00:00:00 2001 From: Alejandbel Date: Tue, 27 May 2025 12:59:28 +0300 Subject: [PATCH 5/7] chore: update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c0e87126..96662eb2 100644 --- a/README.md +++ b/README.md @@ -290,6 +290,8 @@ The above config parameters are equivalent to the arguments in the following com npx blueprint run --custom https://toncenter.com/api/v2/jsonRPC --custom-version v2 --custom-type mainnet --custom-key YOUR_API_KEY ``` +Properties of the `network` object have the same semantics as the `--custom` flags with respective names (see `blueprint help run`). + ### Liteclient Support Lite client is supported through the following configuration: From 5cc3b283e077b97441c958b9131c6ce751c1a280 Mon Sep 17 00:00:00 2001 From: Alejandbel Date: Tue, 27 May 2025 13:01:15 +0300 Subject: [PATCH 6/7] refactor: small refactor --- src/config/CustomNetwork.ts | 2 +- src/network/createNetworkProvider.ts | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/config/CustomNetwork.ts b/src/config/CustomNetwork.ts index 194790dd..5bd84166 100644 --- a/src/config/CustomNetwork.ts +++ b/src/config/CustomNetwork.ts @@ -1,5 +1,5 @@ export type CustomNetwork = { - endpoint: string; // . + endpoint: string; version?: 'v2' | 'v4' | 'tonapi' | 'liteclient'; key?: string; type?: 'mainnet' | 'testnet' | 'custom'; diff --git a/src/network/createNetworkProvider.ts b/src/network/createNetworkProvider.ts index 3e594af6..2ee6d08f 100644 --- a/src/network/createNetworkProvider.ts +++ b/src/network/createNetworkProvider.ts @@ -33,7 +33,7 @@ import { Config } from '../config/Config'; import { CustomNetwork } from '../config/CustomNetwork'; import axios, { AxiosAdapter, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; import { Network } from './Network'; -import {LiteClient, LiteEngine, LiteRoundRobinEngine, LiteSingleEngine} from "ton-lite-client"; +import { LiteClient, LiteRoundRobinEngine, LiteSingleEngine } from 'ton-lite-client'; const INITIAL_DELAY = 400; const MAX_ATTEMPTS = 4; @@ -290,26 +290,31 @@ function intToIP(int: number): string { const part2 = (int >> 8) & 255; const part3 = (int >> 16) & 255; const part4 = (int >> 24) & 255; - return `${(part4 + 256) % 256}.${(part3 + 256) % 256}.${(part2 + 256) % 256}.${ - (part1 + 256) % 256 - }`; + return `${(part4 + 256) % 256}.${(part3 + 256) % 256}.${(part2 + 256) % 256}.${(part1 + 256) % 256}`; } async function buildLiteClient(configEndpoint: string) { const { data } = await axios.get(configEndpoint); if (!Array.isArray(data.liteservers)) { - throw new Error(`Invalid liteclient configuration on ${configEndpoint}. Use https://ton.org/testnet-global.config.json for testnet or https://ton.org/global.config.json for mainnet.`); + throw new Error( + `Invalid liteclient configuration on ${configEndpoint}. Use https://ton.org/testnet-global.config.json for testnet or https://ton.org/global.config.json for mainnet.`, + ); } const engines = data.liteservers.map((server: any) => { - if (typeof server?.ip !== 'number' || typeof server?.port !== 'number' || typeof server?.id !== 'object' || typeof server?.id?.key !== 'string') { + if ( + typeof server?.ip !== 'number' || + typeof server?.port !== 'number' || + typeof server?.id !== 'object' || + typeof server?.id?.key !== 'string' + ) { throw new Error(`Invalid liteclient configuration on ${configEndpoint}`); } return new LiteSingleEngine({ host: `tcp://${intToIP(server.ip)}:${server.port}`, publicKey: Buffer.from(server.id.key, 'base64'), }); - }) + }); const engine = new LiteRoundRobinEngine(engines); return new LiteClient({ engine }); From a9841cd542ed700221ccc389c2219025e0aaf5dd Mon Sep 17 00:00:00 2001 From: krigga Date: Thu, 29 May 2025 11:25:40 +0300 Subject: [PATCH 7/7] chore: revert message --- src/network/createNetworkProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/createNetworkProvider.ts b/src/network/createNetworkProvider.ts index 2ee6d08f..4eb8dc45 100644 --- a/src/network/createNetworkProvider.ts +++ b/src/network/createNetworkProvider.ts @@ -347,7 +347,7 @@ class NetworkProviderBuilder { if (network === 'custom') { const defaultCustomEndpoint = 'http://localhost:8081/'; this.args['--custom'] = ( - await this.ui.input(`Provide a custom network endpoint (default is ${defaultCustomEndpoint})`) + await this.ui.input(`Provide a custom API v2 endpoint (default is ${defaultCustomEndpoint})`) ).trim(); if (this.args['--custom'] === '') this.args['--custom'] = defaultCustomEndpoint; }