Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,33 @@ npx blueprint run --custom https://toncenter.com/api/v2/jsonRPC --custom-version

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
npx blueprint verify --custom https://toncenter.com/api/v2/jsonRPC --custom-version v2 --custom-type mainnet --custom-key YOUR_API_KEY
Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -49,6 +49,7 @@
"dotenv": "^16.1.4",
"inquirer": "^8.2.5",
"qrcode-terminal": "^0.12.0",
"ton-lite-client": "^3.1.0",
"ts-node": "^10.9.1"
},
"packageManager": "yarn@4.3.1"
Expand Down
2 changes: 1 addition & 1 deletion src/config/CustomNetwork.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type CustomNetwork = {
endpoint: string;
version?: 'v2' | 'v4' | 'tonapi';
version?: 'v2' | 'v4' | 'tonapi' | 'liteclient';
key?: string;
type?: 'mainnet' | 'testnet' | 'custom';
};
3 changes: 2 additions & 1 deletion src/network/NetworkProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;


/**
Expand Down
40 changes: 39 additions & 1 deletion src/network/createNetworkProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, LiteRoundRobinEngine, LiteSingleEngine } from 'ton-lite-client';

const INITIAL_DELAY = 400;
const MAX_ATTEMPTS = 4;
Expand Down Expand Up @@ -284,6 +285,41 @@ 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 { 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 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}`);
}
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 });
}

class NetworkProviderBuilder {
constructor(
private args: Args,
Expand Down Expand Up @@ -407,7 +443,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
}
Expand Down Expand Up @@ -440,6 +476,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);
}
Expand Down
Loading