Sol.College

Full lesson

OuroC

A Fully on-chain, compliance aligned subscription tool for Solana

What it does

From the project README:

๐Ÿš€ **Proof-of-Concept Subscription Infrastructure** - ICP Timer + Solana Smart Contract
Original
Legatia/OuroC
SuperStack fork
Blockchains/OuroC @ 7f4b495
Stars
2
Last push (original)
2025-11-10
Languages
Motoko, TypeScript, Rust, Python, HTML, JavaScript
Detected stack
AnchorNext.jsweb3.js
Categories
Infrastructure & Tooling
Licence
MIT

Architecture

299 source files. By extension: .tsx ร—107, .ts ร—105, .rs ร—57, .js ร—22, .py ร—8.

Top-level directorySource files
Archive168
OuroC-Mesos104
solana-contract27

On-chain programs: Archive/solana-contract-mesos/ouroc_prima/programs/ouroc_prima, solana-contract/ouroc_prima/programs/ouroc_prima

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/ouroc/. 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.

Legatia/OuroC ยท Archive/solana-contract-mesos/ouroc_prima/programs/ouroc_prima/src/lib.rs L73โ€“95 @ 7f4b495 ยท MIT ยท original
    #[account(        mut,        has_one = authority @ ErrorCode::UnauthorizedAccess    )]    pub config: Account<'info, Config>,     pub authority: Signer<'info>,} #[derive(Accounts)]#[instruction(subscription_id: String)]pub struct CreateSubscription<'info> {    #[account(        init,        payer = subscriber,        space = 8 + Subscription::LEN,        seeds = [b"subscription", subscription_id.as_bytes()],        bump    )]    pub subscription: Account<'info, Subscription>,     #[account(seeds = [b"config"], bump)]    pub config: Account<'info, Config>,
  1. Line 75 has_one = authority @ ErrorCode::UnauthorizedAccess: Checks that a stored pubkey field matches the passed account.
  2. Line 79 pub authority: Signer<'info>,: Requires this account to have signed the transaction.
  3. Line 86 init,: Creates and pays for a new account. Space and payer must be specified.
  4. Line 89 seeds = [b"subscription", subscription_id.as_bytes()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  5. Line 90 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
Legatia/OuroC ยท solana-contract/ouroc_prima/programs/ouroc_prima/src/lib.rs L73โ€“96 @ 7f4b495 ยท MIT ยท original
    #[account(        mut,        has_one = authority @ ErrorCode::UnauthorizedAccess    )]    pub config: Account<'info, Config>,     pub authority: Signer<'info>,} #[derive(Accounts)]#[instruction(subscription_id: String)]pub struct CreateSubscription<'info> {    #[account(        init,        payer = subscriber,        space = 8 + Subscription::LEN,        seeds = [b"subscription", subscription_id.as_bytes()],        bump    )]    pub subscription: Account<'info, Subscription>,     /// Subscription PDA (same as subscription account key, for delegation)    /// CHECK: PDA derived from subscription_id    #[account(
  1. Line 75 has_one = authority @ ErrorCode::UnauthorizedAccess: Checks that a stored pubkey field matches the passed account.
  2. Line 79 pub authority: Signer<'info>,: Requires this account to have signed the transaction.
  3. Line 86 init,: Creates and pays for a new account. Space and payer must be specified.
  4. Line 89 seeds = [b"subscription", subscription_id.as_bytes()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  5. Line 90 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
Legatia/OuroC ยท Archive/solana-contract-mesos/ouroc_prima/programs/ouroc_prima/src/payment_helpers.rs L121โ€“144 @ 7f4b495 ยท MIT ยท original
    let fee_config = &config.fee_config;    let platform_fee = subscription.amount        .checked_mul(fee_config.fee_percentage_basis_points as u64)        .ok_or(ErrorCode::MathOverflow)?        .checked_div(BASIS_POINTS_DIVISOR)        .ok_or(ErrorCode::MathOverflow)?;     let merchant_amount = subscription.amount        .checked_sub(platform_fee)        .ok_or(ErrorCode::InsufficientAmount)?;     // Use subscription PDA as authority (subscriber must delegate to this PDA)    // Derive PDA signer seeds for CPI - Clone ID to avoid borrow issues    let subscription_id = subscription.id.clone();    let subscription_key = subscription.key();     // Find the bump seed for this subscription PDA    let (subscription_pda, bump) = Pubkey::find_program_address(        &[b"subscription", subscription_id.as_bytes()],        program_id    );     // Verify the subscription account matches the derived PDA    require!(
  1. Line 123 .checked_mul(fee_config.fee_percentage_basis_points as u64): Uses checked arithmetic so overflow fails instead of wrapping.
  2. Line 137 // Find the bump seed for this subscription PDA: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 138 let (subscription_pda, bump) = Pubkey::find_program_address(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
  4. Line 144 require!(: An explicit validation that aborts the instruction with an error.
Legatia/OuroC ยท Archive/solana-contract-mesos/ouroc_prima/programs/ouroc_prima/src/instruction_handlers.rs L337โ€“360 @ 7f4b495 ยท MIT ยท original
 /// Pause a subscriptionpub fn pause_subscription(ctx: Context<UpdateSubscription>) -> Result<()> {    let subscription = &mut ctx.accounts.subscription;    require!(subscription.status == SubscriptionStatus::Active, ErrorCode::SubscriptionNotActive);     let clock = Clock::get()?;    let subscription_id = subscription.id.clone();     subscription.status = SubscriptionStatus::Paused;     msg!("Subscription {} paused", subscription_id);     emit!(SubscriptionPaused {        subscription_id,        paused_at: clock.unix_timestamp,    });     Ok(())} /// Resume a subscriptionpub fn resume_subscription(ctx: Context<UpdateSubscription>) -> Result<()> {    let subscription = &mut ctx.accounts.subscription;
  1. Line 341 require!(subscription.status == SubscriptionStatus::Active, ErrorCode::SubscriptionNotActi: An explicit validation that aborts the instruction with an error.
  2. Line 343 let clock = Clock::get()?;: Reads on-chain time from the Clock sysvar.
  3. Line 348 msg!("Subscription {} paused", subscription_id);: Logs to the program log, which is visible in explorers and the test output.
  4. Line 350 emit!(SubscriptionPaused {: Emits an Anchor event that clients can parse from the logs.

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
Archive/demo-dappnpm run devnext dev -p 3002
Archive/demo-dappnpm run startnext start
Archive/demo-dappnpm run buildnext build
Archive/demo-dappnpm run lintnext lint
OuroC-Mesos/frontendnpm run devvite
OuroC-Mesos/frontendnpm run buildvite build
OuroC-Mesos/frontendnpm run linteslint .
solana-contract/ouroc_primanpm run testanchor test
solana-contract/ouroc_primanpm run lintprettier */*.js "*/**/*{.js,.ts}" --check
Archive/solana-contract-mesos/ouroc_primaanchor buildcompile programs and generate IDLs
Archive/solana-contract-mesos/ouroc_primaanchor testlocal validator + test suite
Archive/solana-contract-mesos/ouroc_primaanchor run testyarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts
solana-contract/ouroc_primaanchor buildcompile programs and generate IDLs
solana-contract/ouroc_primaanchor testlocal validator + test suite
solana-contract/ouroc_primaanchor run testyarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts
.cargo buildRust workspace build

What you could build from it

Used in lessons