Programa on-chain em Rust/Anchor com 4 instruções (initialize, increment, decrement, reset) e um frontend em Next.js para interagir com o contrato via carteira Phantom.
counter-program/
├── programs/counter-program/src/lib.rs # Contrato Rust/Anchor
├── tests/counter-program.ts # Testes Mocha/TypeScript
├── Anchor.toml # Configuração do Anchor
└── app/ # Frontend Next.js
├── app/page.tsx # Página principal
├── components/CounterApp.tsx # UI do contador
├── components/SolanaProviders.tsx # Wallet Adapter providers
└── lib/useProgram.ts # Hook Anchor
| Ferramenta | Versão |
|---|---|
| Solana CLI | 1.18.x |
| Anchor CLI | 0.29.x / 0.32.x |
| Rust | stable (via rustup) |
| Node.js | 18+ |
| Phantom Wallet | (extensão do browser) |
Verifique:
solana --version && anchor --versionO anchor test não precisa de validator rodando — ele sobe e derruba um automaticamente.
cd counter-program
anchor testSaída esperada:
counter-program
✔ Can initialize
✔ Can increment
✔ Can decrement
✔ Cannot go below zero (saturating_sub)
✔ Can reset
5 passing (3s)
Se quiser fazer deploy e interagir via frontend:
Aba 1 — Validator local:
solana config set --url localhost --keypair ~/.config/solana/id.json
solana-test-validatorAba 2 — Deploy:
cd counter-program
anchor build
anchor deploycd counter-program/app
# Copie o env e ajuste se necessário
cp .env.local.example .env.local
# Instale as dependências (se ainda não fez)
npm install
# Inicie o servidor de desenvolvimento
npm run devAcesse: http://localhost:3000
- Abra http://localhost:3000
- Clique em Select Wallet → Phantom
- Configure a Phantom para apontar para Localhost 8899
- Clique em ⚡ Inicializar Contador
- Use os botões Increment, Decrement e Reset
A carteira Phantom precisa estar na rede Localnet (Settings → Developer Settings → Change Network → Localhost)
| Conceito | Descrição |
|---|---|
| Account (PDA) | Onde o estado vive on-chain (count, owner) |
| Instruction | Função stateless que lê/modifica a Account |
#[account]
pub struct Counter {
pub count: u64, // valor atual
pub owner: Pubkey, // dono do contador
}space = 8 + 8 + 32 → 8 bytes discriminador Anchor + 8 bytes u64 + 32 bytes Pubkey
// ❌ Perigoso — underflow em programs custam $$$
counter.count -= 1;
// ✅ Seguro — para em 0
counter.count = counter.count.saturating_sub(1);