PHP code example of sandermuller / solana-php-sdk

1. Go to this page and download the library: Download sandermuller/solana-php-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

sandermuller / solana-php-sdk example snippets


use SanderMuller\SolanaPhpSdk\Keypair;

$payer = Keypair::generate();
echo $payer->getPublicKey()->toBase58(), "\n";
// → e.g.  4uTYf8w...EPnL  (this is your wallet address)

$secret = $payer->getSecretKey()->toArray(); // array<int, int> — 64 bytes
// Reload with:  Keypair::fromSecretKey($secret);

use SanderMuller\SolanaPhpSdk\Connection;
use SanderMuller\SolanaPhpSdk\Enum\Network;

$connection = app(Connection::class);          // Laravel
// $connection = Bootstrap::createContainer(__DIR__.'/config.php')->get(Connection::class); // standalone

$signature = $connection->requestAirdrop([
    $payer->getPublicKey()->toBase58(),
    1_000_000_000,                              // 1 SOL in lamports
]);
$connection->confirmTransaction($signature);    // blocks until landed

$lamports = $connection->getBalance($payer->getPublicKey()->toBase58());
echo $lamports / 1_000_000_000, " SOL\n";       // → 1.0

use SanderMuller\SolanaPhpSdk\Keypair;
use SanderMuller\SolanaPhpSdk\Programs\SystemProgram;
use SanderMuller\SolanaPhpSdk\Transaction;

$recipient = Keypair::generate()->getPublicKey();   // pretend this is a friend

$tx = new Transaction(feePayer: $payer->getPublicKey());
$tx->addInstructions(
    SystemProgram::transfer(
        fromPubkey:  $payer->getPublicKey(),
        toPublicKey: $recipient,
        lamports:    5_000_000,                       // 0.005 SOL
    ),
);

$signature = $connection->sendTransaction($tx, signers: [$payer]);
$connection->confirmTransaction($signature);

echo "https://explorer.solana.com/tx/{$signature}?cluster=devnet\n";

use SanderMuller\SolanaPhpSdk\Contracts\MessageSigner;
use SanderMuller\SolanaPhpSdk\PublicKey;

final class AwsKmsSigner implements MessageSigner
{
    public function __construct(
        private readonly string $kmsKeyId,
        private readonly PublicKey $publicKey,
        private readonly KmsClient $kms,
    ) {}

    public function getPublicKey(): PublicKey { return $this->publicKey; }

    public function signMessage(string $message): string
    {
        // Return 64-byte Ed25519 signature from your KMS / HSM.
        return $this->kms->signEd25519($this->kmsKeyId, $message);
    }
}

$tx = TransactionBuilder::new()
    ->feePayer($publicKey)
    ->recentBlockhash($connection->latestBlockhash())
    ->addInstruction($instruction)
    ->addMessageSigner(new AwsKmsSigner(/* … */))
    ->build();

final class VaultTransitSigner implements MessageSigner
{
    public function __construct(
        private readonly string $keyName,
        private readonly PublicKey $publicKey,
        private readonly VaultClient $vault,
    ) {}

    public function getPublicKey(): PublicKey { return $this->publicKey; }

    public function signMessage(string $message): string
    {
        $reply = $this->vault->write(
            "transit/sign/{$this->keyName}/ed25519",
            ['input' => base64_encode($message), 'hash_algorithm' => 'none'],
        );

        // Vault returns "vault:v1:<base64-signature>"; strip prefix + decode.
        return base64_decode(explode(':', $reply['data']['signature'])[2]);
    }
}

use SanderMuller\SolanaPhpSdk\TransactionBuilder;
use SanderMuller\SolanaPhpSdk\Programs\SystemProgram;

$tx = TransactionBuilder::new()
    ->feePayer($payer->getPublicKey())
    ->recentBlockhash($connection->latestBlockhash())   // BlockhashInfo or string
    ->addInstruction(SystemProgram::transfer($payer->getPublicKey(), $to, 1))
    ->addSigner($payer)
    ->build();

$status = $connection->sendAndConfirmTransaction(
    transaction: $tx,
    signers:     [$payer],
);
// $status->confirmationStatus === 'confirmed'

$info = $connection->accountInfo('11111111111111111111111111111111');

// Typed DTO — no array-shape memorisation needed.
$info->lamports;     // int
$info->owner;        // PublicKey
$info->executable;   // bool
$info->data;         // Buffer — base64 already decoded
$info->data?->toArray();

$infos = $connection->multipleAccounts(['Acc1...', 'Acc2...', 'Acc3...']);

foreach ($infos as $info) {
    if ($info === null) continue;   // missing slot
    echo $info->owner->toBase58(), ' ', $info->lamports, "\n";
}

$tokens = $connection->getTokenAccountsByOwner(
    $payer->getPublicKey(),
    ['programId' => 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
);

$rows = $connection->programAccountsPaged(
    programId: SplTokenProgram::TOKEN_PROGRAM_ID,
    dataSizes: [82, 165],   // mints + token accounts
);

foreach ($rows as $row) {
    echo $row->pubkey->toBase58(), "\n";
}

use SanderMuller\SolanaPhpSdk\DataObjects\GpaFilter;
use SanderMuller\SolanaPhpSdk\Programs\SplTokenProgram;

// All SPL Token accounts holding a specific mint (offset 0..32 = mint pubkey).
$rows = $connection->programAccounts(
    programId: SplTokenProgram::TOKEN_PROGRAM_ID,
    filters: [
        GpaFilter::dataSize(165),                 // SPL Token Account = 165 bytes
        GpaFilter::memcmp(0, $mintPublicKey),     // mint at offset 0
    ],
);

foreach ($rows as $row) {
    echo $row->pubkey->toBase58(), ' ', $row->account->lamports, "\n";
    // $row->account->data is a base64-decoded Buffer
}

$txs = $connection->getSignaturesForAddress($payer->getPublicKey(), ['limit' => 25]);
foreach ($txs as $tx) {
    echo $tx['signature'], ' ', $tx['blockTime'], "\n";
}

use SanderMuller\SolanaPhpSdk\Services\SolanaPubSubClient;
use SanderMuller\SolanaPhpSdk\Enum\Network;

$pubsub = new SolanaPubSubClient(network: Network::MAINNET);

$subId = $pubsub->signatureSubscribe(
    $signature,
    ['commitment' => 'finalized'],
);

foreach ($pubsub->listen(maxEvents: 1) as $event) {
    // $event['result']['value']['err'] === null when the tx succeeded
}

$pubsub->unsubscribe($subId);
$pubsub->close();

$pubsub->enableAutoReconnect(maxRetries: 0, baseDelayMs: 500);  // 0 = forever

use SanderMuller\SolanaPhpSdk\Programs\MemoProgram;

$tx->addInstructions(
    MemoProgram::build('order-id=42', signers: [$payer->getPublicKey()]),
);

use SanderMuller\SolanaPhpSdk\Util\PriorityFee;

[$limit, $price] = PriorityFee::buildInstructions(
    connection:        $connection,
    computeUnitLimit:  200_000,
    writableAccounts:  [$payer->getPublicKey()],   // tighter estimate
    percentile:        0.75,                       // beat 75% of recent traffic
);

$tx = new Transaction(feePayer: $payer->getPublicKey());
$tx->addInstructions($limit, $price, /* your real instructions */);

use SanderMuller\SolanaPhpSdk\Programs\Token2022Program;

$program = new Token2022Program();

// 1. Allocate the mint account (system program), then queue extensions
//    BEFORE InitializeMint — Token-2022 ordering rule.
$tx = TransactionBuilder::new()
    ->feePayer($payer->getPublicKey())
    ->recentBlockhash($connection->latestBlockhash())
    ->addInstructions(
        // Allocate + assign owner via SystemProgram::createAccount (omitted)
        $program->createInitializeNonTransferableMintInstruction($mint->getPublicKey()),
        $program->createInitializeMintCloseAuthorityInstruction($mint->getPublicKey(), $payer->getPublicKey()),
        $program->createInitializeTransferFeeConfigInstruction(
            mint: $mint->getPublicKey(),
            transferFeeConfigAuthority: $payer->getPublicKey(),
            withdrawWithheldAuthority: $payer->getPublicKey(),
            transferFeeBasisPoints: 250,            // 2.5%
            maximumFee: 1_000_000,
        ),
        // Finally initialize the mint
        $program->createInitializeMint2Instruction(
            mint: $mint->getPublicKey(),
            decimals: 6,
            mintAuthority: $payer->getPublicKey(),
            freezeAuthority: null,
        ),
    )
    ->addSigner($payer)
    ->addSigner($mint)
    ->build();

// Enable both initializes the extension and turns the ToggleInstruction($tokenAccount, $owner->getPublicKey(), enable: true),
);

// Later — turn it off:
$program->createMemoTransferToggleInstruction($tokenAccount, $owner->getPublicKey(), enable: false);

use SanderMuller\SolanaPhpSdk\Programs\Token2022Program;

$program = new Token2022Program();

$ix = $program->createTransferCheckedInstruction(
    source:      $sourceAta,
    mint:        $mint,
    destination: $destAta,
    owner:       $owner->getPublicKey(),
    amount:      1_000_000,
    decimals:    6,
);

use SanderMuller\SolanaPhpSdk\Programs\AddressLookupTableProgram;

// 1. Create the lookup table (one-time, returns a PDA address + bump)
$slot = $connection->getSlot();
$create = AddressLookupTableProgram::createLookupTable($authority, $payer, $slot);

// 2. Extend it with up to 256 addresses (across calls)
$extend = AddressLookupTableProgram::extendLookupTable(
    lookupTable: $create['lookupTableAddress'],
    authority:   $authority,
    payer:       $payer,
    addresses:   [$mint, $programId, /* ... */],
);

use SanderMuller\SolanaPhpSdk\PublicKey;

$ok = PublicKey::verify($pubkeyBytes, $messageBytes, $signatureBytes);

use SanderMuller\SolanaPhpSdk\Anchor\AnchorIdl;

$idl = AnchorIdl::fromFile(__DIR__ . '/my_program.json');

$ix = $idl->instruction('initialize')->build(
    accounts: [
        'state' => $statePubkey,
        'user'  => $payer->getPublicKey(),
        // `systemProgram` etc. are auto-filled from the IDL's fixed `address` field
    ],
    args: [
        'amount' => 1_000_000,
        'label'  => 'hello',
    ],
);

$tx = (new Transaction(feePayer: $payer->getPublicKey()))->addInstructions($ix);
$connection->sendTransaction($tx, signers: [$payer]);



use SanderMuller\SolanaPhpSdk\Bootstrap;
use SanderMuller\SolanaPhpSdk\Connection;

$container  = Bootstrap::createContainer(__DIR__ . '/config/solana-php-sdk.php');
$connection = $container->get(Connection::class);

echo $connection->getSlot();
bash
composer