Sol.College

Full lesson

dobro-stake-pool

The Dobro Solana Liquid Staking Pool

Original
grassets-tech/dobro-stake-pool
SuperStack fork
Blockchains/dobro-stake-pool @ cf35d15
Stars
0
Last push (original)
2025-05-13
Languages
Rust, Python, TypeScript, JavaScript, Shell
Detected stack
Native Rustsolana-pyweb3.js
Categories
DeFi
Licence
Apache-2.0

Architecture

89 source files. By extension: .rs ×39, .py ×32, .ts ×16, .js ×2.

Top-level directorySource files
clients53
program36

Dapp: devnet deploy pending

⏳ Devnet deploy pending — goes live when the devnet wallet is topped up. This fork's own dapp is not deployed yet, so there is no program address or transaction to show. It is queued in dapp-queue.txt; once devnet SOL is available it is deployed, exercised with real devnet transactions, and this section switches to the live dapp at /dapps/dobro-stake-pool/. Until then, the lesson and step-by-step guide below are complete, and you can run it locally with the commands below.

Key code, explained

Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.

grassets-tech/dobro-stake-pool · program/src/state.rs L49–72 @ cf35d15 · Apache-2.0 · original
    /// Manager authority, allows for updating the staker, manager, and fee    /// account    pub manager: Pubkey,     /// Staker authority, allows for adding and removing validators, and    /// managing stake distribution    pub staker: Pubkey,     /// Stake deposit authority    ///    /// If a depositor pubkey is specified on initialization, then deposits must    /// be signed by this authority. If no deposit authority is specified,    /// then the stake pool will default to the result of:    /// `Pubkey::find_program_address(    ///     &[&stake_pool_address.as_ref(), b"deposit"],    ///     program_id,    /// )`    pub stake_deposit_authority: Pubkey,     /// Stake withdrawal authority bump seed    /// for `create_program_address(&[state::StakePool account, "withdrawal"])`    pub stake_withdraw_bump_seed: u8,     /// Validator stake list storage account
  1. Line 54 /// managing stake distribution: Touches staking state: the amount locked and when it was locked.
  2. Line 62 /// `Pubkey::find_program_address(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
  3. Line 68 /// Stake withdrawal authority bump seed: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
grassets-tech/dobro-stake-pool · program/src/lib.rs L73–95 @ cf35d15 · Apache-2.0 · original
#[inline]pub fn minimum_delegation(stake_program_minimum_delegation: u64) -> u64 {    std::cmp::max(stake_program_minimum_delegation, MINIMUM_ACTIVE_STAKE)} /// Get the stake amount under consideration when calculating pool token/// conversions#[inline]pub fn minimum_reserve_lamports(meta: &Meta) -> u64 {    meta.rent_exempt_reserve        .saturating_add(MINIMUM_RESERVE_LAMPORTS)} /// Generates the deposit authority program address for the stake poolpub fn find_deposit_authority_program_address(    program_id: &Pubkey,    stake_pool_address: &Pubkey,) -> (Pubkey, u8) {    Pubkey::find_program_address(        &[stake_pool_address.as_ref(), AUTHORITY_DEPOSIT],        program_id,    )}
  1. Line 78 /// Get the stake amount under consideration when calculating pool token: Touches staking state: the amount locked and when it was locked.
  2. Line 91 Pubkey::find_program_address(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
grassets-tech/dobro-stake-pool · clients/py/stake_pool/constants.py L13–36 @ cf35d15 · Apache-2.0 · original
 MINIMUM_RESERVE_LAMPORTS: int = 0"""Minimum balance required in the stake pool reserve""" MINIMUM_ACTIVE_STAKE: int = MINIMUM_DELEGATION"""Minimum active delegated staked required in a stake account""" METADATA_PROGRAM_ID = Pubkey.from_string("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")"""Public key that identifies the Metaplex Token Metadata program."""  def find_deposit_authority_program_address(    program_id: Pubkey,    stake_pool_address: Pubkey,) -> Tuple[Pubkey, int]:    """Generates the deposit authority program address for the stake pool"""    return Pubkey.find_program_address(        [bytes(stake_pool_address), AUTHORITY_DEPOSIT],        program_id,    )  def find_withdraw_authority_program_address(    program_id: Pubkey,
  1. Line 15 """Minimum balance required in the stake pool reserve""": Touches staking state: the amount locked and when it was locked.
  2. Line 29 return Pubkey.find_program_address(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
grassets-tech/dobro-stake-pool · clients/py/stake_pool/actions.py L529–552 @ cf35d15 · Apache-2.0 · original
    data = resp.value.data if resp.value else bytes()    stake_pool = StakePool.decode(data)     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)    data = resp.value.data if resp.value else bytes()    validator_list = ValidatorList.decode(data)    (withdraw_authority, seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)     validator_info = next(x for x in validator_list.validators if x.vote_account_address == validator_vote)     if ephemeral_stake_seed is None:        transient_stake_seed = validator_info.transient_seed_suffix + 1  # bump up by one to avoid reuse    else:        # we are updating an existing transient stake account, so we must use the same seed        transient_stake_seed = validator_info.transient_seed_suffix     validator_stake_seed = validator_info.validator_seed_suffix or None    (transient_stake, _) = find_transient_stake_program_address(        STAKE_POOL_PROGRAM_ID,        validator_info.vote_account_address,        stake_pool_address,        transient_stake_seed,    )    (validator_stake, _) = find_stake_program_address(
  1. Line 540 transient_stake_seed = validator_info.transient_seed_suffix + 1 # bump up by one to avoid: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  2. Line 542 # we are updating an existing transient stake account, so we must use the same seed: Touches staking state: the amount locked and when it was locked.

How to run, build and test

These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.

DirectoryCommandRuns
clients/js-legacynpm run buildtsc && cross-env NODE_ENV=production rollup -c
clients/js-legacynpm run testjest
clients/js-legacynpm run linteslint --max-warnings 0 .
.cargo buildRust workspace build
.cargo testRust tests

What you could build from it

Used in lessons