Learn Solana by building small, readable DApps.
Wallet connections, SOL transfers, Anchor counters, on-chain data stores, and Pyth-priced payments.
This repository began as my first Solana DApp and live-coding learning project. It now uses Solana Kit and Wallet Standard for the browser examples, with buildable Anchor sources alongside them. Each lesson exposes the underlying instructions instead of hiding the transaction flow behind a large framework.
This is an educational project. The wallet actions target Devnet. Jupiter quotes use Mainnet market data and do not execute trades.
Requirements: Node.js 24, npm, and a Wallet Standard wallet set to Devnet.
git clone https://github.com/SebastianBoehler/solana-dapp-learning.git
cd solana-dapp-learning
npm ci
cp .env.example .env.local
npm run devOpen localhost:3000. Connect your wallet and obtain Devnet SOL through the Solana faucet. The SOL transfer lesson works without deploying a custom program.
Counter, oracle, and USD payments require your own matching programs deployed
on Devnet. Enter their public addresses in .env.local, then restart Next.js.
See program setup.
| Variable | Required for |
|---|---|
NEXT_PUBLIC_COUNTER_PROGRAM_ID |
Counter actions |
NEXT_PUBLIC_ORACLE_PROGRAM_ID |
Exchange data store actions |
NEXT_PUBLIC_PAY_USD_PROGRAM_ID |
Pyth-priced SOL payments |
NEXT_PUBLIC_SOL_USD_PRICE_ACCOUNT |
A fresh Pyth SOL/USD price update account on Devnet |
PYTH_API_KEY |
Server-side Hermes price preview |
JUPITER_API_KEY |
Server-side Jupiter V2 quotes |
API keys stay on the server. Do not prefix them with NEXT_PUBLIC_.
Missing configuration and upstream failures are shown as errors.
| Lesson | Where to start | What happens |
|---|---|---|
| Wallet connection | wallet-button.tsx |
Discovers Wallet Standard wallets and connects a Devnet signer |
| SOL transfer | sendLamports.tsx |
Builds a System Program transfer to a recipient you enter |
| Counter | counter.tsx, counter/src/lib.rs |
Derives a wallet PDA, initializes, changes by four, reads, and closes it |
| Exchange data store | oracle.tsx, oracle/src/lib.rs |
Reads BTC/USDT from Binance and lets your wallet write one scaled value |
| Pyth-priced payment | pyth_send_usd.tsx, pyth-pay-usd/src/lib.rs |
Sends SOL for a USD amount in cents, using a verified Pyth pull-oracle price |
| SPL token minting | spl_token.tsx |
Callable helper creates a fresh mint and associated token account, then mints 200 tokens |
| Round-trip quotes | /arbitrage, jupiter.ts |
Compares SOL → USDC → SOL quotes from Jupiter V2 |
The main page contains SOL transfers, payments, the counter, and the exchange
data store. Dedicated pages are available at /oracle, /sendUsd, and
/arbitrage. The token helper is a source example without a dedicated UI:
call mintToken(client, connected.signer) from a connected-wallet component.
The exchange data store is user-controlled data, not a verified oracle. The Binance stream closes when the component unmounts. Every write needs wallet approval; the example does not use a shared signing key or an automated writer.
The payment program uses pyth-solana-receiver-sdk, validates the SOL/USD feed
and full verification through get_price_no_older_than, and rejects prices more
than 60 seconds old or dated in the future. It uses checked integer arithmetic
and rounds up to the next lamport. Only system-owned recipient accounts are accepted.
Configure a current Pyth Devnet pull-oracle account. Publishing and refreshing that account is a separate prerequisite; the UI does not publish price updates. The Hermes button previews an off-chain price through the current Hermes SDK and a server-only key. That preview is not the payment program's price source.
See Pyth's Solana integration guide and Hermes authentication.
Get an API key from the Jupiter developer portal.
The example calls /swap/v2/order without a taker, so it receives quotes without
transactions. Sequential quotes are not atomic. Their difference excludes
execution costs and does not demonstrate profitable arbitrage.
See Jupiter V2.
The Cargo workspace contains three separate Anchor programs under contract/.
It pins Anchor 1.2.1 and Pyth's receiver SDK 2.0.0.
Host compilation and arithmetic tests require stable Rust:
cargo test --workspace --lockedFor deployable Solana binaries, install Anchor CLI 1.2.1 and its supported Solana/Agave SBF toolchain. Follow the current Anchor installation instructions. The original public program addresses remain in the sources to preserve project history; this repository does not contain their deployment keys.
For your own deployments:
- Generate local program keypairs with your Solana CLI in
target/deploy/, namedmy_counter-keypair.json,my_oracle-keypair.json, andpyth_program-keypair.json. - Run
anchor keys syncto updatedeclare_id!andAnchor.tomlto those addresses. - Run
anchor buildwith the matching current toolchain. - Deploy to Devnet with
anchor deploy --provider.cluster devnetusing your funded local wallet. - Put the deployed addresses into
.env.local. Configure the Pyth Devnet account separately.
Keep your local wallet and deployment keypairs out of Git. Keys previously published with the historical demos have been removed from the current tree; they remain in Git history and must not be reused.
npm run typecheck
npm test
npm run build
cargo test --workspace --lockedThe JavaScript tests cover exact amount parsing and instruction encoding,
including the counter's u8 step and the oracle's name/data signatures.
Rust tests cover counter overflow/underflow and USD-to-lamport conversion.
GitHub Actions runs these checks for pushes and pull requests.
These checks validate local compilation and selected behavior. They do not validate deployed programs, SBF binaries, wallet approvals, live Pyth publishing, or authenticated Jupiter requests. See manual checks for the remaining integration steps.
src/components/ Lesson UI and shared wallet/status components
src/hooks/ Instruction builders and token example
src/lib/ Solana client, amount parsing, and Jupiter requests
src/pages/ Next.js pages and server-only API routes
contract/ Anchor program sources and Cargo manifests
tests/ JavaScript regression tests
The original learning sessions are on my YouTube channel. Questions, corrections, and focused example improvements are welcome through GitHub issues and pull requests. See CONTRIBUTING.md.
MIT.