Le niveau gratuit couvre les projets personnels. Le paiement à l'usage évolue sans carte bancaire.
PHP
web3.php is the primary PHP library for OP Mainnet JSON-RPC interaction, letting a Laravel or vanilla PHP backend read balances, send ETH transfers, and call contracts on chain ID 10. Install it with composer require web3p/web3.php. The library uses a callback-based API — every eth method takes a closure that receives ($err, $result) — so wrap those calls inside a dedicated service class to keep your controllers clean and your error handling in one place.
web3.php exposes a callback-based API rather than promises, so each OP Mainnet call hands its result to a closure. In a Laravel project, wrapping these calls in a service class keeps controllers thin and lets you inject the same configured client wherever you need it.
Web3.php
Build the client by nesting the providers: new Web3(new HttpProvider(new HttpRequestManager("https://optimism.therpc.io/YOUR_API_KEY"))). Every eth method then takes a callback shaped as function ($err, $result). Always check $err before touching $result — on an RPC error $result is unset, so reading it blindly would mask the real failure on OP Mainnet behind a confusing null.
<?php
use Web3\Web3;
use Web3\Providers\HttpProvider;
use Web3\RequestManagers\HttpRequestManager;
class EthereumService
{
private $web3;
public function __construct()
{
$this->web3= new Web3(new HttpProvider(new HttpRequestManager('https://optimism.therpc.io/YOUR_API_KEY')));
}
public function getBalance(string $address): string
{
$balance = null;
$this->web3->eth->getBalance($address, 'latest', function ($err, $result) use (&$balance) {
Key features: full OP Mainnet JSON-RPC support, contract interactions, transaction handling, ETH unit conversion (wei to ether), and ABI encoding/decoding
Laravel Integration
In Laravel, keep the OP Mainnet endpoint out of your source by reading it from config('services.ethereum.node_url'), which in turn pulls the API-keyed URL from your .env. Balance queries are a prime candidate for caching: wrap them in Cache::remember with a short TTL so a busy page does not fire a fresh RPC call for every visitor — given OP Mainnet's roughly 2-second blocks, even a 30-second cache stays close to live while cutting request volume sharply.
<?php
namespace App\Services;
use Web3\Web3;
use Illuminate\Support\Facades\Cache;
class EthereumService
{
private $web3;
public function __construct()
{
$this->web3= new Web3(config('services.ethereum.node_url'));
}
public function getCachedBalance(string $address): string
{
return Cache::remember("eth_balance_{$address}", 300, function () use ($address) {
return $this->getBalance($address);
});
}
public function getTransactionCount(string $address): int
{
$count = null;
$this->web3->eth->getTransactionCount($address, 'latest', function ($err, $result) use (&$count) {
if ($err !== null) {
throw new Exception($err->getMessage());
}
$count = hexdec($result);
});
return $count;
}
}
Smart Contract Integration
For contract access, use the Contract class from web3.php: construct it with the provider and the ABI, then bind it to a deployed OP Mainnet address with ->at($contractAddress). Read-only methods run through ->call(), and as everywhere in this library you pass a callback to receive the decoded result — check the error argument first, then read the response.
<?php
use Web3\Contract;
class SmartContractService
{
private $contract;
public function __construct(string $abi, string $contractAddress)
{
$web3= new Web3(new HttpProvider(new HttpRequestManager('https://optimism.therpc.io/YOUR_API_KEY')));
$this->contract = new Contract($web3->provider, $abi);
$this->contract->at($contractAddress);
}
public function callMethod(string $method, array $params = [])
{
$result = null;
$this->contract->call($method, $params, function ($err, $response) use (&$result) {
if ($err !== null) {
throw new Exception($err->getMessage());
}
$result = $response;
});
return $result;
}
}
Error Handling
Define a domain EthereumException that wraps the original error returned from an OP Mainnet call. This gives you one typed exception to catch across your service layer, carries the underlying RPC error for logging, and keeps the messy provider details from leaking into controllers and views.
<?php
class EthereumException extends Exception
{
private $ethError;
public function __construct(string $message, $ethError = null)
{
parent::__construct($message);
$this->ethError = $ethError;
}
public function getEthError()
{
return $this->ethError;
}
}
class SafeEthereumService
{
public function safeGetBalance(string $address): string