Install the Bundle
composer require aminin/blockchain-bundle
For Symfony 4+, the bundle auto-registers via Flex.
Configure API Credentials
Add to config/packages/ami_blockchain.yaml (Symfony 4+) or config.yml (Symfony 2/3):
ami_blockchain:
api_key: '%env(BLOCKCHAIN_API_KEY)%' # Use .env for security
service_url: 'https://blockchain.info/api/v2' # Default Blockchain.info API URL
First Use Case: Fetch Bitcoin Price Inject the service in a controller or command:
use Ami\BlockchainBundle\Service\BlockchainService;
class CryptoController extends AbstractController
{
public function showPrice(BlockchainService $blockchain)
{
$price = $blockchain->getTicker();
return $this->json($price);
}
}
API Service Integration
Use the BlockchainService to interact with Blockchain.info endpoints:
// Fetch raw transaction data
$tx = $blockchain->getRawTransaction('tx_hash_here');
// Get wallet balance
$balance = $blockchain->getBalance('wallet_address');
Event-Driven Notifications Poll for new transactions periodically (e.g., via a Symfony command):
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CheckTransactionsCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$transactions = $this->blockchain->getTransactions('wallet_address');
foreach ($transactions as $tx) {
if ($tx['confirmations'] > 0) {
$this->notifyUser($tx);
}
}
}
}
Dependency Injection Prefer constructor injection for testability:
class PaymentService
{
public function __construct(private BlockchainService $blockchain) {}
public function verifyPayment(string $txId): bool
{
return $this->blockchain->getTransaction($txId)['confirmations'] >= 6;
}
}
Caching Responses Cache API responses to reduce rate limits (e.g., using Symfony Cache component):
$cache = $this->container->get('cache.app');
$key = 'blockchain_ticker';
$ticker = $cache->get($key, function() use ($blockchain) {
return $blockchain->getTicker();
});
API Rate Limits
$cache->set('ticker', $ticker, 300); // 5 minutes
Deprecated API Endpoints
blockchain/blockchain PHP client may lag behind Blockchain.info’s API updates. Check the client’s GitHub for deprecations.$client = new \GuzzleHttp\Client();
$response = $client->get('https://blockchain.info/rawtx/...');
Environment Variables
config.yml. Use .env:
ami_blockchain:
api_key: '%env(BLOCKCHAIN_API_KEY)%'
config/packages/ami_blockchain.yaml:
imports:
- { resource: '.env' }
Error Handling
try {
$blockchain->getTransaction($txId);
} catch (\Ami\BlockchainBundle\Exception\BlockchainException $e) {
$this->addFlash('error', 'Blockchain API error: ' . $e->getMessage());
}
Custom API Endpoints Extend the service to add unsupported endpoints:
// src/Service/ExtendedBlockchainService.php
class ExtendedBlockchainService extends BlockchainService
{
public function getUnspentOutputs(string $address): array
{
$url = $this->serviceUrl . '/unspent?active=' . $address;
return $this->httpClient->get($url)->json();
}
}
Register as a service in config/services.yaml:
services:
App\Service\ExtendedBlockchainService:
decorates: ami_blockchain.blockchain
arguments: ['@ami_blockchain.blockchain']
Webhook Integration Use the bundle to verify incoming webhook signatures (e.g., for payment notifications):
public function verifyWebhook(Request $request): bool
{
$payload = json_decode($request->getContent(), true);
$signature = $request->headers->get('X-Blockchain-Signature');
return $this->blockchain->verifyWebhook($payload, $signature);
}
Testing
Mock the BlockchainService in tests:
$mock = $this->createMock(BlockchainService::class);
$mock->method('getBalance')->willReturn(['balance' => 1.0]);
$this->container->set('ami_blockchain.blockchain', $mock);
Enable API Logging
Add to config/packages/monolog.yaml:
handlers:
blockchain:
type: stream
path: '%kernel.logs_dir%/blockchain.log'
level: debug
channels: ['blockchain']
Then log requests in a custom service decorator.
Check HTTP Headers
Use stderr to log raw API responses during development:
$response = $this->httpClient->get($url);
error_log($response->getBody()->getContents());
How can I help you explore Laravel packages today?