Sol.College

Full lesson

vijay

A trustless freelancing platform on Solana

What it does

From the project README:

Vijay is a decentralized freelancing platform built on the Solana blockchain. It introduces a new trustless protocol where clients and freelancers can collaborate on projects securely, without intermediaries. The platform leverages smart contracts to manage registration, project assignment, escrowed payments, and task validation. It enables Clients and Freelancers to collaborate trustlessly using a milestone-based escrow system. Funds are securely held in program-controlled accounts and released on task approval, ensuring a transparent and secure freelancing experience.
Original
Harry-027/vijay
SuperStack fork
Blockchains/vijay @ bf21c0c
Stars
0
Last push (original)
2025-05-14
Languages
TypeScript, Rust, CSS, JavaScript
Detected stack
AnchorNext.jsweb3.js
Categories
Infrastructure & Tooling
Licence
MIT
Homepage
https://vijay-woad.vercel.app

Architecture

57 source files. By extension: .tsx ×36, .rs ×12, .ts ×9.

Top-level directorySource files
src39
anchor17
(root)1

On-chain programs: anchor/programs/vijay

Dapp: deploying

This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/vijay/, once it is deployed and checked on devnet. Until then, 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.

Harry-027/vijay · anchor/programs/vijay/src/instructions/project_init.rs L49–72 @ bf21c0c · MIT · original
pub struct ProjectInfo<'info> {    #[account(mut)]    pub signer: Signer<'info>,     #[account(        mut,        seeds = [b"client", signer.key().as_ref()],        bump,    )]    pub client: Account<'info, Client>,     #[account(        mut,        seeds = [b"client_report", signer.key().as_ref()],        bump,    )]    pub client_report_card: Account<'info, ClientReportCard>,     #[account(        init,        space = 8 + Project::INIT_SPACE,        payer = signer,        seeds = [b"client_project", client.project_counter.checked_add(1).unwrap().to_le_bytes().as_ref(), signer.key().as_ref()],        bump
  1. Line 51 pub signer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 55 seeds = [b"client", signer.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  3. Line 56 bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  4. Line 68 init,: Creates and pays for a new account. Space and payer must be specified.
  5. Line 71 seeds = [b"client_project", client.project_counter.checked_add(1).unwrap().to_le_bytes().a: Uses checked arithmetic so overflow fails instead of wrapping.
Harry-027/vijay · anchor/programs/vijay/src/instructions/project_transfer.rs L73–96 @ bf21c0c · MIT · original
          let mut actual_total_projects = client_report.total_projects.checked_sub(client_report.projects_in_progress).ok_or(ErrorCode::NumericalOverflow)?;     if actual_total_projects == 0 {        actual_total_projects = 1;     }      client_report.success_rate = ((client_report.completed * 10000) / actual_total_projects) as u16;      let total_risk_points = client_report.transferred + client_report.withdrawn;     let total_finished_projects = total_risk_points + client_report.completed;     client_report.risk_score = ((total_risk_points * 10000) / total_finished_projects) as u16;      Ok(())} #[derive(Accounts)]#[instruction(project_id: u64, new_freelancer_key: Pubkey)]pub struct TransferInfo<'info> {    #[account(mut)]    pub signer: Signer<'info>,     #[account(        mut,        seeds = [b"client_project", project_id.to_le_bytes().as_ref(), signer.key().as_ref()],        bump
  1. Line 74 let mut actual_total_projects = client_report.total_projects.checked_sub(client_report.pro: Uses checked arithmetic so overflow fails instead of wrapping.
  2. Line 91 pub signer: Signer<'info>,: Requires this account to have signed the transaction.
  3. Line 95 seeds = [b"client_project", project_id.to_le_bytes().as_ref(), signer.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 96 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
Harry-027/vijay · anchor/programs/vijay/src/instructions/project_withdraw.rs L49–72 @ bf21c0c · MIT · original
    let mut actual_total_projects = client_report_card.total_projects.checked_sub(client_report_card.projects_in_progress).ok_or(ErrorCode::NumericalOverflow)?;    if actual_total_projects == 0 {        actual_total_projects = 1;    }     client_report_card.success_rate = ((client_report_card.completed * 10000) / actual_total_projects) as u16;        let total_risk_points = client_report_card.withdrawn + client_report_card.transferred;    let total_finished_projects = total_risk_points + client_report_card.completed;    client_report_card.risk_score = ((total_risk_points * 10000) / total_finished_projects) as u16;    Ok(())}  #[derive(Accounts)]#[instruction(project_id: u64)]pub struct WithdrawInfo<'info> {     #[account(mut)]    pub signer: Signer<'info>,     #[account(        mut,        seeds = [b"client_project", project_id.to_le_bytes().as_ref(), signer.key().as_ref()],        bump
  1. Line 49 let mut actual_total_projects = client_report_card.total_projects.checked_sub(client_repor: Uses checked arithmetic so overflow fails instead of wrapping.
  2. Line 67 pub signer: Signer<'info>,: Requires this account to have signed the transaction.
  3. Line 71 seeds = [b"client_project", project_id.to_le_bytes().as_ref(), signer.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 72 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
Harry-027/vijay · anchor/programs/vijay/src/instructions/freelancer_init.rs L25–48 @ bf21c0c · MIT · original
    freelancer_report.risk_score = 0;    freelancer_report.success_rate = 0;    Ok(())} #[derive(Accounts)]pub struct FreelancerInfo<'info> {    #[account(mut)]    pub signer: Signer<'info>,     #[account(        init,        space = 8 + Freelancer::INIT_SPACE,        payer = signer,        seeds = [b"freelancer", signer.key().as_ref()],        bump    )]    pub freelancer: Account<'info, Freelancer>,     #[account(        init,        space = 8 + FreelancerReportCard::INIT_SPACE,        seeds = [b"freelancer_report", signer.key().as_ref()],        bump,
  1. Line 33 pub signer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 36 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 39 seeds = [b"freelancer", signer.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 40 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.

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
.npm run devnext dev
.npm run startnext start
.npm run buildnext build
.npm run lintnext lint
anchoranchor buildcompile programs and generate IDLs
anchoranchor testlocal validator + test suite
anchoranchor run test../node_modules/.bin/jest --preset ts-jest

What you could build from it