{"id":51540533,"url":"https://github.com/sandermuller/laravel-solana-sdk","last_synced_at":"2026-07-09T13:01:44.828Z","repository":{"id":357608458,"uuid":"1237661740","full_name":"SanderMuller/laravel-solana-sdk","owner":"SanderMuller","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-13T13:07:24.000Z","size":78,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T15:06:44.815Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SanderMuller.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-13T11:44:10.000Z","updated_at":"2026-05-13T13:13:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SanderMuller/laravel-solana-sdk","commit_stats":null,"previous_names":["sandermuller/laravel-solana-sdk"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/SanderMuller/laravel-solana-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SanderMuller%2Flaravel-solana-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SanderMuller%2Flaravel-solana-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SanderMuller%2Flaravel-solana-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SanderMuller%2Flaravel-solana-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SanderMuller","download_url":"https://codeload.github.com/SanderMuller/laravel-solana-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SanderMuller%2Flaravel-solana-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35299763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-09T13:01:41.642Z","updated_at":"2026-07-09T13:01:44.812Z","avatar_url":"https://github.com/SanderMuller.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Solana SDK\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/sandermuller/laravel-solana-sdk.svg?style=flat-square)](https://packagist.org/packages/sandermuller/laravel-solana-sdk)\n[![Tests](https://img.shields.io/github/actions/workflow/status/SanderMuller/laravel-solana-sdk/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/SanderMuller/laravel-solana-sdk/actions/workflows/run-tests.yml)\n[![PHPStan](https://img.shields.io/github/actions/workflow/status/SanderMuller/laravel-solana-sdk/phpstan.yml?branch=main\u0026label=phpstan\u0026style=flat-square)](https://github.com/SanderMuller/laravel-solana-sdk/actions/workflows/phpstan.yml)\n[![Total Downloads](https://img.shields.io/packagist/dt/sandermuller/laravel-solana-sdk.svg?style=flat-square)](https://packagist.org/packages/sandermuller/laravel-solana-sdk)\n[![License](https://img.shields.io/packagist/l/sandermuller/laravel-solana-sdk.svg?style=flat-square)](LICENSE)\n\nLaravel wrapper around [`sandermuller/solana-php-sdk`][core] — service\nprovider, facades, env-driven config, and artisan commands so you can\ncall Solana RPC from a Laravel app without wiring containers yourself.\n\n[core]: https://github.com/SanderMuller/solana-php-sdk\n\n```php\nuse SanderMuller\\LaravelSolanaSdk\\Facades\\Solana;\n\n$balance   = Solana::getBalance('SomeWalletAddressBase58'); // lamports as float\n$blockhash = Solana::latestBlockhash();                     // typed BlockhashInfo\n$status    = Solana::sendAndConfirmTransaction($tx, [$payer]);\n```\n\n## Contents\n\n- [Requirements](#requirements)\n- [Install](#install)\n- [Configuration](#configuration)\n- [Facades](#facades)\n- [Multi-endpoint transport](#multi-endpoint-transport)\n- [Confirming transactions on the queue](#confirming-transactions-on-the-queue)\n- [PubSub / WebSocket](#pubsub--websocket)\n- [Artisan commands](#artisan-commands)\n- [Testing](#testing)\n- [Upgrading](#upgrading)\n- [Changelog](#changelog)\n- [Contributing](#contributing)\n- [Security](#security)\n- [Credits](#credits)\n- [License](#license)\n\n## Requirements\n\n- PHP `^8.3`\n- Laravel `^11.0 || ^12.0 || ^13.0`\n- `ext-sodium` (transitively required by the core SDK)\n\n## Install\n\n```bash\ncomposer require sandermuller/laravel-solana-sdk\n```\n\nThe service provider auto-discovers. Publish the config if you want to\ncustomise defaults:\n\n```bash\nphp artisan vendor:publish --tag=solana-sdk-config\n```\n\n## Configuration\n\n`config/solana-sdk.php` exposes four knobs:\n\n```php\nreturn [\n    'network'          =\u003e env('SOLANA_NETWORK', 'mainnet'),\n    'token_program_id' =\u003e env('SOLANA_TOKEN_PROGRAM_ID', 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),\n    'transport' =\u003e [\n        'mode'    =\u003e env('SOLANA_TRANSPORT_MODE', 'fallback'),\n        'urls'    =\u003e array_values(array_filter([\n            env('SOLANA_RPC_URL'),\n            env('SOLANA_RPC_URL_FALLBACK'),\n        ])),\n        'headers' =\u003e [],\n        'timeout' =\u003e (float) env('SOLANA_RPC_TIMEOUT', 30.0),\n        'retry'   =\u003e [\n            'max_attempts'  =\u003e (int) env('SOLANA_RPC_RETRY_ATTEMPTS', 3),\n            'base_delay_ms' =\u003e (int) env('SOLANA_RPC_RETRY_BASE_MS', 100),\n            'max_delay_ms'  =\u003e (int) env('SOLANA_RPC_RETRY_MAX_MS', 2_000),\n        ],\n    ],\n    'commands' =\u003e [\n        'enabled' =\u003e env('SOLANA_COMMANDS_ENABLED', true),\n    ],\n];\n```\n\n`SOLANA_NETWORK` accepts `mainnet`, `mainnet-beta`, `testnet`, `devnet`\n(also `main`, `test`, `dev`). The RPC endpoint is derived from the\n`Network` enum in the core SDK.\n\n## Facades\n\n```php\nuse SanderMuller\\LaravelSolanaSdk\\Facades\\Solana;\nuse SanderMuller\\LaravelSolanaSdk\\Facades\\SolanaRpc;\n\n$balance   = Solana::getBalance('SomeWalletAddressBase58');\n$info      = Solana::accountInfo('SomeWalletAddressBase58'); // typed AccountInfo\n$blockhash = Solana::latestBlockhash();                      // typed BlockhashInfo\n\n// Send + poll until confirmed in a single call:\n$status = Solana::sendAndConfirmTransaction($tx, [$payer]);\n\n// Low-level JSON-RPC escape hatch\n$result = SolanaRpc::call('getSlot');\n```\n\n`Solana` proxies the typed `Connection` API (~60 RPC methods covering\n~80 % of the Solana JSON-RPC spec — accounts, blocks, slots, signatures,\ntokens, supply, stake, vote, inflation). `SolanaRpc` proxies the raw\n`SolanaRpcClient` for calls the typed facade does not yet cover.\n\nBoth bindings are also reachable via plain DI:\n\n```php\nuse SanderMuller\\SolanaPhpSdk\\Connection;\n\nclass WalletController\n{\n    public function show(Connection $solana, string $address): array\n    {\n        return ['balance' =\u003e $solana-\u003egetBalance($address)];\n    }\n}\n```\n\n### Programs, builders, signers\n\nThe core SDK ships first-class program builders (`SystemProgram`,\n`SplTokenProgram`, `Token2022Program`, `MemoProgram`, `StakeProgram`,\n`VoteProgram`, `AddressLookupTableProgram`, `ComputeBudgetProgram`,\n`MetaplexProgram`, `AnchorIdl`, …), a sanitize-safe\n`TransactionBuilder`, a `Util\\PriorityFee` helper, and a\n`Contracts\\MessageSigner` interface (with `Signing\\InMemoryMessageSigner`\nas the local adapter). Use them directly — no wrapping required:\n\n```php\nuse SanderMuller\\SolanaPhpSdk\\TransactionBuilder;\nuse SanderMuller\\SolanaPhpSdk\\Programs\\SystemProgram;\nuse SanderMuller\\LaravelSolanaSdk\\Facades\\Solana;\n\n$blockhash = Solana::latestBlockhash();\n\n$tx = TransactionBuilder::make()\n    -\u003efeePayer($payer-\u003epublicKey)\n    -\u003erecentBlockhash($blockhash)\n    -\u003eaddInstruction(SystemProgram::transfer($payer-\u003epublicKey, $to, $lamports))\n    -\u003eaddSigner($payer)\n    -\u003ebuild();\n\n$status = Solana::sendAndConfirmTransaction($tx, [$payer]);\n```\n\n## Multi-endpoint transport\n\nSet `SOLANA_RPC_URL` (and optionally `SOLANA_RPC_URL_FALLBACK`) to route\nthrough your own RPC provider with automatic retry + fallback. Leave\nboth unset to keep the public-endpoint default.\n\n```dotenv\nSOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=…\nSOLANA_RPC_URL_FALLBACK=https://api.mainnet-beta.solana.com\nSOLANA_TRANSPORT_MODE=fallback        # or round_robin\nSOLANA_RPC_TIMEOUT=30\nSOLANA_RPC_RETRY_ATTEMPTS=3\n```\n\nFor more elaborate setups (custom auth headers, multiple fallbacks)\npublish the config and edit `transport` directly — the wrapper hands\nthe array straight to `SanderMuller\\SolanaPhpSdk\\Rpc\\TransportFactory`.\n\n## Confirming transactions on the queue\n\nThis wrapper ships `SanderMuller\\LaravelSolanaSdk\\Queue\\ConfirmTransactionJob`\nout of the box. Dispatch it after `sendTransaction` so the long-tail\nconfirmation phase becomes a background job that fires\n`TransactionConfirmed` / `TransactionExpired` events (the event classes\nlive in the SDK):\n\n```php\nuse SanderMuller\\LaravelSolanaSdk\\Facades\\Solana;\nuse SanderMuller\\LaravelSolanaSdk\\Queue\\ConfirmTransactionJob;\n\n$blockhash = Solana::latestBlockhash();\n$signature = Solana::sendTransaction($tx, [$payer]);\n\nConfirmTransactionJob::dispatch(\n    signature: $signature,\n    lastValidBlockHeight: $blockhash-\u003elastValidBlockHeight,\n    context: ['order_id' =\u003e $order-\u003eid],\n);\n```\n\nListen for `SanderMuller\\SolanaPhpSdk\\Events\\TransactionConfirmed` and\n`SanderMuller\\SolanaPhpSdk\\Events\\TransactionExpired` in `EventServiceProvider`\n(events are SDK-side; only the Job moved to this wrapper).\n\n## PubSub / WebSocket\n\n`SolanaPubSubClient` is bound transient against the configured network,\nso you can typehint it directly:\n\n```php\nuse SanderMuller\\SolanaPhpSdk\\Services\\SolanaPubSubClient;\n\nclass WatchSignatures\n{\n    public function handle(SolanaPubSubClient $pubsub, string $signature): void\n    {\n        $pubsub-\u003eenableAutoReconnect();\n        $pubsub-\u003esignatureSubscribe($signature);\n\n        foreach ($pubsub-\u003elisten() as $event) {\n            // …\n        }\n    }\n}\n```\n\n## Artisan commands\n\n| Command                            | Purpose                                     |\n|------------------------------------|---------------------------------------------|\n| `solana:balance {address}`         | Print SOL balance + lamports                |\n| `solana:airdrop {address} {sol=1}` | Request devnet/testnet airdrop              |\n| `solana:account {address}`         | Dump raw account info JSON                  |\n| `solana:tx {signature}`            | Look up a transaction by signature          |\n| `solana:health`                    | RPC health + version                        |\n| `solana:tokens {owner}`            | List SPL token accounts owned by an address |\n| `solana:fees {addresses?*}`        | Recent prioritization fee samples           |\n\nDisable all bundled commands with `SOLANA_COMMANDS_ENABLED=false` (they\nhit live RPC; production may want them off).\n\n## Testing\n\n```bash\ncomposer test\n```\n\n### Stubbing RPC in tests\n\nCall `Solana::fake()` to swap the bound `SolanaRpcClient` for the core\nSDK's `InMemoryRpcStub` so the SDK never hits the network:\n\n```php\nuse SanderMuller\\LaravelSolanaSdk\\Facades\\Solana;\n\nit('reads the balance', function (): void {\n    Solana::fake()-\u003escript([\n        'getBalance' =\u003e ['value' =\u003e 5_000_000],\n    ]);\n\n    expect(Solana::getBalance($address))-\u003etoBe(5_000_000.0);\n    expect(Solana::fakedStub()?-\u003emethodCalls())-\u003etoContain('getBalance');\n});\n```\n\nWire the core Pest expectations (`toBeConfirmed`, `toHaveCustomCode`,\n`toBeInstructionError`) once from `tests/Pest.php`:\n\n```php\nuse SanderMuller\\SolanaPhpSdk\\Testing\\PestExpectations;\n\nPestExpectations::register();\n```\n\nThe wrapper's own test suite runs against Orchestra Testbench with the\npackage provider auto-registered. Network-dependent tests are not\nshipped — facade unit tests just verify resolution + container shape.\n\n## Upgrading\n\nSee [UPGRADING.md](UPGRADING.md).\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md). Updated automatically on release publish.\n\n## Contributing\n\nPRs welcome. Run the local gauntlet before opening one:\n\n```bash\nvendor/bin/pest          # tests\nvendor/bin/pint --test   # style\nvendor/bin/phpstan       # static analysis\nvendor/bin/rector --dry-run\n```\n\nThe package is intentionally a **thin** wrapper — net-new RPC methods,\nprogram builders, and DTOs belong in\n[`sandermuller/solana-php-sdk`][core]. The wrapper only adds Laravel\nglue (`@method` lines on the `Solana` facade, env-driven config keys,\ncontainer bindings, `solana:*` commands). See\n[`CLAUDE.md`](CLAUDE.md) for the full scope rules.\n\n## Security\n\nSee [SECURITY.md](SECURITY.md).\n\n## Credits\n\n- [Sander Muller](https://github.com/SanderMuller)\n- Wraps [`sandermuller/solana-php-sdk`](https://github.com/SanderMuller/solana-php-sdk)\n\n## License\n\nThe MIT License (MIT). See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandermuller%2Flaravel-solana-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandermuller%2Flaravel-solana-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandermuller%2Flaravel-solana-sdk/lists"}