amashukov/toncenter-client-php
Install the package:
composer require amashukov/toncenter-client-php
Set up PSR-18 HTTP client and PSR-17 factories:
use Amashukov\Toncenter\ToncenterClient;
use Nyholm\Psr7\Factory\Psr17Factory;
$psr17 = new Psr17Factory();
$httpClient = new YourPsr18Client(); // e.g., GuzzleHttp\Client or Amashukov\HttpClient\CurlClient
$toncenterClient = new ToncenterClient($httpClient, $psr17, $psr17);
First use case: Fetch masterchain info
$masterchainInfo = $toncenterClient->getMasterchainInfo();
echo $masterchainInfo->getLastBlock()->getSeqno();
Fetching Account Data
$accountInfo = $toncenterClient->getAddressInformation('EQ...');
if ($accountInfo->isActive()) {
$balance = $toncenterClient->getBalance($accountInfo->getAddress());
// Handle balance (string, e.g., "12345678901234567890")
}
Running Smart Contract Methods
$result = $toncenterClient->runMethod(
'EQ...',
'get_wallet_data',
['mode' => 33554432] // Optional stack parameters
);
if ($result->isOk()) {
$balance = $result->stack->readBigInt(); // Returns string (e.g., "1000000000")
}
Broadcasting Transactions
$signedBoc = base64_encode($signedTransactionBoc);
$result = $toncenterClient->sendBoc($signedBoc);
if ($result->isOk()) {
$transactionId = $result->getTransactionId();
}
Wallet RPC Integration
use Amashukov\Toncenter\ToncenterWalletRpc;
$walletRpc = new ToncenterWalletRpc($toncenterClient);
$seqno = $walletRpc->getSeqno('EQ...');
$walletRpc->sendBoc($signedBoc);
Middleware for Retries and Headers:
Use Amashukov\HttpClient\Middleware\RetryMiddleware and HeaderInjectionMiddleware to handle rate limits and transient errors (e.g., 542 or 429).
$http = new Pipeline(
new CurlClient($psr17, $psr17),
[
new HeaderInjectionMiddleware(['X-Api-Key' => env('TONCENTER_API_KEY')]),
new RetryMiddleware(maxAttempts: 3, retryStatusCodes: [429, 542]),
]
);
Transaction Monitoring: Fetch transactions with filters:
$transactions = $toncenterClient->getTypedTransactions(
'EQ...',
['limit' => 10, 'filter' => ['status' => 'success']]
);
Big Number Handling:
Always treat balances/gas as strings (e.g., "12345678901234567890") to avoid precision loss.
API Key Rate Limits:
Without X-Api-Key, the default rate limit is 1 RPS. Include the header to lift it to 10 RPS:
new HeaderInjectionMiddleware(['X-Api-Key' => 'your_api_key_here'])
Retry Logic:
542 (no workers) and 429 (rate-limited).maxAttempts (e.g., 3) to prevent cascading failures.[429, 500, 502, 503, 504, 542].Big Number Precision:
float: Balances/gas are returned as decimal strings (e.g., "1000000000" for 1 TON).runMethod stack results.Wallet RPC Edge Cases:
getSeqno() returns 0 for undeployed wallets. Handle this explicitly:
$seqno = $walletRpc->getSeqno('EQ...');
if ($seqno === 0) throw new \RuntimeException('Wallet not deployed');
Transaction Status Quirks:
TonTransaction statuses map to TVM phases:
Pending → Transaction submitted but not processed.ComputePhaseFailed → TVM execution failed during compute phase.ActionPhaseFailed → TVM execution failed during action phase.Aborted → Transaction was aborted (e.g., by sendBoc failure).Enable HTTP Logging:
Use middleware like Amashukov\HttpClient\Middleware\LogMiddleware to inspect requests/responses:
new LogMiddleware(\Monolog\Logger::create('toncenter'))
Validate API Responses:
The package throws TonRpcException for malformed {ok, result} envelopes. Catch it to debug:
try {
$result = $toncenterClient->runMethod('EQ...', 'invalid_method');
} catch (TonRpcException $e) {
echo $e->getMessage(); // e.g., "Method not found"
}
Stack Reader Pitfalls:
readBigInt() expects a TonTupleItemInt. If the stack item is a Slice, use readSliceBoc() instead.readSliceBoc() results with base64_decode() before processing.Custom PSR-18 Clients:
Replace the default client (e.g., CurlClient) with Guzzle, Symfony HttpClient, or others while maintaining PSR-18 compliance.
Extending Value Objects:
Subclass TonTransaction or TonAccountInfo to add domain-specific methods:
class MyTransaction extends TonTransaction {
public function isSuccessful(): bool {
return $this->getStatus() === 'success';
}
}
Custom Retry Logic: Override the retry middleware to implement exponential backoff or circuit breakers:
new RetryMiddleware(
maxAttempts: 5,
retryStatusCodes: [429, 542],
delayFactory: fn(int $attempt) => 1000 * (2 ** $attempt) // Exponential backoff
)
Symfony Integration:
Use blockchain-context-bundle to wire the client as a service with dependency injection:
# config/services.yaml
services:
Amashukov\Toncenter\ToncenterClient:
arguments:
$httpClient: '@amashukov.http_client'
$requestFactory: '@psr17_factory'
$streamFactory: '@psr17_factory'
How can I help you explore Laravel packages today?