Skip to content

Repository files navigation

SkillStake

SkillStake is a Solana commitment staking dApp built with Anchor and React. A user escrows SOL into a stake PDA together with a goal, deadline, and validator wallet. The validator can resolve the commitment on or before the deadline:

  • complete_stake: returns the locked SOL to the creator
  • fail_stake: sends the locked SOL to the configured treasury wallet

The repo includes:

See CONTRIBUTING.md for local setup and INTERVIEW.md for talking points to discuss in interviews.

Architecture

Each stake is a PDA derived from:

["stake", creator_pubkey, stake_id_le_bytes]

The stake_id is generated in the frontend, which lets the same wallet create multiple commitments without collisions.

StakeAccount stores:

  • goal
  • deadline
  • validator
  • treasury
  • amount
  • creator
  • created_at
  • status

When a stake is created, the program initializes the PDA and transfers the staked SOL from the creator into that PDA. When the validator resolves the stake, the locked amount is moved to the creator or treasury, and the PDA closes back to the creator.

Project structure

.
├── Anchor.toml
├── Cargo.toml
├── programs/commitment-stake
├── tests
├── app
└── .github/workflows

Prerequisites

  • Rust stable
  • Solana CLI
  • Anchor CLI
  • Node.js 20+
  • A wallet at ~/.config/solana/id.json for local Anchor commands

Helpful installs:

cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
avm install latest
avm use latest
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"

Local setup

  1. Install JavaScript dependencies:
npm install
  1. Build the program:
npm run anchor:build
  1. If you are deploying with a new program key, sync the generated program ID:
anchor keys list
anchor keys sync
  1. Start a local validator in a separate terminal:
solana-test-validator
  1. Run the test suite:
npm run anchor:test

Frontend setup

Copy the example env file and fill in your network values:

cp app/.env.example app/.env

Recommended app/.env for devnet:

VITE_SOLANA_RPC_URL=https://api.devnet.solana.com
VITE_PROGRAM_ID=YOUR_DEPLOYED_PROGRAM_ID
VITE_TREASURY_WALLET=YOUR_DEVNET_TREASURY_PUBKEY
VITE_NETWORK=devnet
VITE_BASE_PATH=/

Run the frontend locally:

npm run app:dev

Build the frontend:

npm run app:build

Docker

Build and serve the frontend in a container:

docker build --tag skillstake-frontend ./app

Run the container on port 8080:

docker run --rm -p 8080:80 skillstake-frontend

Open http://localhost:8080 in your browser.

If you want to build with custom env values, pass build args:

docker build \
  --build-arg VITE_PROGRAM_ID=YOUR_PROGRAM_ID \
  --build-arg VITE_SOLANA_RPC_URL=https://api.devnet.solana.com \
  --build-arg VITE_TREASURY_WALLET=YOUR_TREASURY_PUBKEY \
  --build-arg VITE_NETWORK=devnet \
  --build-arg VITE_BASE_PATH=/ \
  --tag skillstake-frontend ./app

Use Docker Compose to build and run the app with a single command:

docker compose up --build

Then open http://localhost:8080.

Deploying the Solana program

Localnet

anchor deploy

Devnet

  1. Switch Solana CLI:
solana config set --url devnet
  1. Fund your deployer:
solana airdrop 2
  1. Update Anchor.toml provider cluster if needed, then deploy:
anchor deploy --provider.cluster devnet
  1. Put the deployed program ID into app/.env.

GitHub-ready deployment

This repo is set up for GitHub Pages deployment of the React app.

1. Push the repo to GitHub

git init
git add .
git commit -m "Initial SkillStake dApp"
git branch -M main
git remote add origin <your-repo-url>
git push -u origin main

2. Enable Pages

  • In GitHub, open Settings -> Pages
  • Set the source to GitHub Actions

3. Add repository variables

In Settings -> Secrets and variables -> Actions -> Variables, add:

  • VITE_PROGRAM_ID
  • VITE_SOLANA_RPC_URL
  • VITE_TREASURY_WALLET
  • VITE_NETWORK

The workflow automatically sets:

  • VITE_BASE_PATH=/<repo-name>/

4. Push to main

The workflow in .github/workflows/deploy-pages.yml builds app/dist and deploys it to GitHub Pages.

Core flows

Create stake

  • creator enters goal, validator pubkey, deadline, and SOL amount
  • frontend generates a stake_id and derives the stake PDA
  • Anchor creates the stake account and transfers SOL into it

Complete stake

  • validator signs complete_stake
  • program checks that the signer matches the stake validator
  • locked SOL is returned to creator

Fail stake

  • validator signs fail_stake
  • program checks the validator and treasury
  • locked SOL is moved to treasury

Important behavior

  • validators can only resolve a stake while it is still pending
  • resolution must happen on or before the stored deadline
  • a failed stake can only send funds to the treasury originally stored on creation
  • rent is returned to the creator when the stake PDA closes

Suggested next upgrades

  • add an admin-owned global config PDA for treasury management
  • add index filtering by creator and validator on-chain
  • emit events for easier analytics and notification services
  • add support for automatic failure after deadline through an external crank service

Notes

  • The placeholder program ID in this repo is the standard Anchor default until you deploy your own program.
  • The frontend uses the checked-in IDL at app/src/idl/commitment_stake.json. After changing program interfaces, rebuild and update the frontend copy.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages