Extraton is a simple and powerful php-library to binding with the TON SDK. It allows to interact with FreeTON blockchain. It has the rich abilities:
- All methods of the TON SDK v1.0.0 are implemented
- Interaction with the TON SDK through an asynchronous calls
- The every method contains inline-doc
- The full autocomplete is available in a such IDE like the PHPStorm
- Simple installation by the Composer package manager
- The automatic download of the TON SDK library for the current environment
- The client auto configuration (out-of-the-box)
- Covered by the unit-tests
- Fully covered by the integration tests
- Tools to maintain code quality (static analyser and codestyle checker)
- Tools to the quick start to develop (see Dockerfile + Makefile)
- The error handling by the general exception interface (see src/Exception)
- Using generators to iterate the asynchronous events
- You can add your own client implementation based on FFIAdapter and Binding
- A simple interface to the graphql requests
- Temporary logs creation for the detailed analysis on integration tests running
- php7.4+ or php8.0+
- ffi extension
- json extension
- zlib extension
- TON SDK Library 1.22.0 (download script included)
To install it via Composer simply run:
composer require extraton/php-ton-client
To automatically download the TON SDK library add the following lines to your project composer.json
file:
...
"scripts": {
"download-ton-sdk-library": "Extraton\\TonClient\\Composer\\Scripts::downloadLibrary",
"post-update-cmd": [
"@download-ton-sdk-library"
],
"post-install-cmd": [
"@download-ton-sdk-library"
]
}
...
The library will be downloaded after the commands composer install
or composer update
are called in your project root. To forced download the TON SDK library for your operating system, run the following command:
composer run download-ton-sdk-library
The TON SDK library will be installed to the directory YOUR_PROJECT_ROOT/vendor/extranton/php-ton-client/bin/
.
Simple TonClient instantiation:
$tonClient = TonClient::createDefault();
It uses the default configuration:
$config = [
"network" => [
'server_address' => 'net.ton.dev',
'network_retries_count' => 5,
'message_retries_count' => 5,
'message_processing_timeout' => 60000,
'wait_for_timeout' => 60000,
'out_of_sync_threshold' => 30000,
'access_key' => ''
],
'abi' => [
'workchain' => 0,
'message_expiration_timeout' => 60000,
'message_expiration_timeout_grow_factor' => 1.35
],
'crypto' => [
'mnemonic_dictionary' => 1,
'mnemonic_word_count' => 12,
'hdkey_derivation_path' => "m/44'/396'/0'/0/0",
'hdkey_compliant' => true
],
];
You can start using a simple configuration for TonClient:
$config = [
'network' => [
'server_address' => 'net.ton.dev'
]
];
All configuration options are available here. After instantiate the TonClient will automatically detect operating system and path to the TON SDK library:
// Create new instance with custom configuration and default path to TON SDK library
$tonClient = new TonClient($config);
Default path: YOUR_PROJECT_ROOT/vendor/extraton/bin/tonclient.*
. Also you can specify path by the following lines of code:
// Create new instance TonClient with custom path to TON SDK library
$binding = new Binding('PATH_TO_TON_SDK_LIBRARY');
$tonClient = new TonClient($config, $binding);
// Get TON SDK version
$result = $tonClient->version();
echo "TON SDK version: " , $result->getVersion() . PHP_EOL;
// Get instance of Crypto module
$crypto = $tonClient->getCrypto();
// Generate random key pair
$result = $crypto->generateRandomSignKeys();
$keyPair = $result->getKeyPair();
echo 'Public key: ' . $keyPair->getPublic() . PHP_EOL;
echo 'Private key: ' . $keyPair->getSecret() . PHP_EOL;
// Get instance of Utils module
$utils = $tonClient->getUtils();
// Convert address to hex format
$result = $utils->convertAddressToHex('ee65d170830136253ad8bd2116a28fcbd4ac462c6f222f49a1505d2fa7f7f528');
echo 'Hex: ' . $result->getAddress() . PHP_EOL;
Use special classes to easily build queries:
$query = (new ParamsOfWaitForCollection('accounts'))
->addResultField('id', 'last_paid')
->addFilter('last_paid', Filters::IN, [1601332024, 1601331924])
->setTimeout(60_000);
$net->waitForCollection($query);
$query = (new ParamsOfSubscribeCollection('transactions'))
->addResultField('id', 'block_id', 'balance_delta')
->addFilter('balance_delta', Filters::GT, '0x5f5e100');
$net->subscribeCollection($query);
$query = new ParamsOfQueryCollection('accounts');
$query->addResultField(
'acc_type',
'acc_type_name',
'balance',
'boc',
'id',
'last_paid',
'workchain_id',
);
$query->addFilter(
'last_paid',
Filters::IN,
[
1601332024,
1601331924,
1601332491,
1601332679
]
);
$query->addOrderBy('last_paid', OrderBy::DESC)->setLimit(2);
$net->queryCollection($query);
You can add your own query class that implements the interface \Extraton\TonClient\Entity\Net\QueryInterface
or extends the class \Extraton\TonClient\Entity\Net\AbstractQuery
.
The following constants are available for filters and directions:
class Filters implements Params
{
public const EQ = 'eq';
public const GE = 'ge';
public const GT = 'gt';
public const IN = 'in';
public const LE = 'le';
public const LT = 'lt';
public const NE = 'ne';
public const NOT_IN = 'notIn';
...
class OrderBy implements Params
{
public const ASC = 'ASC';
public const DESC = 'DESC';
...
Use the following example to build an application for monitoring events coming from the blockchain network:
// Build query
$query = (new ParamsOfSubscribeCollection('transactions'))
->addResultField('id', 'block_id', 'balance_delta')
->addFilter('balance_delta', Filters::GT, '0x5f5e100');
// Get result with handle and start watching
$result = $net->subscribeCollection($query);
echo "Handle: {$result->getHandle()}." . PHP_EOL;
$counter = 0;
// Iterate generator
foreach ($result->getIterator() as $event) {
$counter++;
echo "Event counter: {$counter}, event data:" . PHP_EOL;
var_dump($event->getResult());
if ($counter > 25) {
echo 'Manual stop watching.' . PHP_EOL;
$result->stop(); // or call: $net->unsubscribe($result->getHandle());
}
}
echo 'Finished.' . PHP_EOL;
Please see Examples and Integration tests for more information on detailed usage.
We use experemental PHP extension FFI. This extension allows the loading of shared libraries, calling of C functions and accessing of C data structures in pure PHP. This is the only one possible way to async integrate with the TON SDK library.
Please read the official warnings from the developers of php:
Warning This extension is EXPERIMENTAL. The behaviour of this extension including the names of its functions and any other documentation surrounding this extension may change without notice in a future release of PHP. This extension should be used at your own risk.
Although this works, this functionality is not supported on all libffi platforms, is not efficient and leaks resources by the end of request.
We have not detected memory leaks. But sometimes we caught segmentation faults during testing. 🙏 Hopefully the FFI extension will be stabilized in future versions of php.
Please see CHANGELOG for more information on what has changed recently.
Run the following command to run unit tests:
make test-unit
... and integration tests:
make test-integration
Some tests use TON SDK methods that listen for asynchronous events. Data from these events is saved to the directory /tests/Integration/artifacts/
. This way you can analyze them in detail. For example, the test \Extraton\Tests\Integration\TonClient\ProcessingTest::testProcessMessageWithEvents
uses the call of method \Extraton\TonClient\Processing::processMessage
. Events received during generator iteration are saved in a file.
We use PHPStan and PHP Coding Standards Fixer to control code quality. Run the following commands to analyze the code and fix code style errors:
make analyze
make codestyle
make codestyle-fix
Please see CONTRIBUTING for details.
If you have any issues, just feel free and open it in this repository, thx!
The Apache License Version 2.0. Please see License File for more information.