Sol.College

Full lesson

sca

Solana Commerce Application

What it does

From the project README:

A Solana blockchain tool designed as Proof-Of-Concept, to illustrate how blockchain can be used to tackle real world problems. The particular problem we are addressing here is the lack of safety when selling items over the internet.
Original
Sergio-Flores-Torres/sca
SuperStack fork
Blockchains/sca @ 699122f
Stars
0
Last push (original)
2026-09-06
Languages
TypeScript, Rust, Shell
Detected stack
Native Rustweb3.js
Categories
Other
Licence
MIT

Architecture

31 source files. By extension: .ts ×25, .rs ×6.

Top-level directorySource files
clients18
test7
program6

❌ Does not build as-is, checked 2026-11-02 Tested on 2026-11-02: full log results.json

Build it yourself: step-by-step guide

Every command below was run on 2026-11-02 by tests/run_fork.py against the pinned commit, and the results come from that run. The full output is in the committed log.

1. Prerequisites (versions we tested with)

2. Clone at the tested commit

git clone https://github.com/Blockchains/sca.git && cd sca
git checkout 699122f3f3d117d763ed286227ed026b9031d3c2

3. Configure

No environment file is needed.

7. Deploy to a local validator

8. Run and exercise it

DirectoryCommandResultTime
.bash /workspace/sol-college/repo/tests/flows/sca.sh✅ pass37s

Proof: program IDs and transactions

Deploy to devnet (free)

solana config set --url devnet
solana airdrop 2   # or https://faucet.solana.com
anchor deploy --provider.cluster devnet   # native: solana program deploy target/deploy/<name>.so
# point the frontend RPC env var at https://api.devnet.solana.com

Notes: Native (non-Anchor) program. The repo's hardcoded program ID is swapped for a fresh local keypair, and the Pinata upload is stubbed because it needs a Pinata JWT.

How it works

Every instruction handler in the program, with the accounts struct it validates. Each link points to the line at the pinned commit.

InstructionAccountsWhere
InitializeOperationnative instruction variantprogram/sca/src/instruction/mod.rs:21
RegisterBuyernative instruction variantprogram/sca/src/instruction/mod.rs:23
RegisterArbiternative instruction variantprogram/sca/src/instruction/mod.rs:25
ParticipantApprovesArbitersnative instruction variantprogram/sca/src/instruction/mod.rs:27
BuyerDepositnative instruction variantprogram/sca/src/instruction/mod.rs:29
BuyerReleasenative instruction variantprogram/sca/src/instruction/mod.rs:31
SellerRefundnative instruction variantprogram/sca/src/instruction/mod.rs:33
StartDisputenative instruction variantprogram/sca/src/instruction/mod.rs:35
SellerAddInfonative instruction variantprogram/sca/src/instruction/mod.rs:37
BuyerAddInfonative instruction variantprogram/sca/src/instruction/mod.rs:39
ArbiterVotenative instruction variantprogram/sca/src/instruction/mod.rs:41
ParticipantClaimnative instruction variantprogram/sca/src/instruction/mod.rs:43

Extend it

  1. Add an integration test that runs the main flow end to end and asserts every account state change.
  2. Add a negative test: call each instruction with the wrong signer or account and check that it fails.
  3. Add an event (emit!) to each state-changing instruction and subscribe to it from the client.
  4. Replace any unchecked AccountInfo with typed accounts plus has_one/seeds constraints.
  5. Make the frontend read the cluster from an env var, deploy it to GitHub Pages and point it at your devnet program.
  6. Wire the build into CI by copying this site's verify-forks workflow.

Dapp: deploying

This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/sca/, 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.

Sergio-Flores-Torres/sca · program/sca/src/operation/mod.rs L61–84 @ 699122f · MIT · original
	// Check SELLER account validity	is_signed_by_writable_account(seller_account_info, "SELLER account is not a valid account.")?;		// Get the OPERATIONACCOUNT account 	let operation_account_info = next_account_info(accounts_iter)?; 	// Check OPERATIONACCOUNT account validity	is_owned_and_writable(program_id, operation_account_info, "OPERATIONACCOUNT account is not a valid account.")?;  	// ================ Enforce configuration rules section  	// Get the estimated creation time for tracking operation validity, etc	// This is in unixepoch seconds; in tests the time is days off, so it needs to be validated further 	let unix_timestamp = match Clock::get() {		Err(_e) => {			msg!("WARN: Could not get a valid Clock. Using zero time.");			0		},		Ok(clock) => clock.unix_timestamp,	}; 	// Load the account so that we can read it and/or modify it.
  1. Line 76 let unix_timestamp = match Clock::get() {: Reads on-chain time from the Clock sysvar.
  2. Line 78 msg!("WARN: Could not get a valid Clock. Using zero time.");: Logs to the program log, which is visible in explorers and the test output.

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
testnpm run startnode dist/index.js
testnpm run buildtsc
testnpm run testecho "Error: no test specified" && exit 1
clients/sellernpm run startOPERATION=x URL=http://localhost:8899 PROGRAMID=7f3bKvFg9WrUr3RGig5gGj8GnEFYMML86ffgxaH19ft1 JWT=x GATEWAY=x node dist/i
clients/sellernpm run buildtsc
clients/sellernpm run testecho "Error: no test specified" && exit 1
clients/buyernpm run startOPERATION=x URL=http://localhost:8899 PROGRAMID=7f3bKvFg9WrUr3RGig5gGj8GnEFYMML86ffgxaH19ft1 JWT=x GATEWAY=x node dist/i
clients/buyernpm run buildtsc
clients/buyernpm run testecho "Error: no test specified" && exit 1
clients/arbiternpm run startOPERATION=x URL=http://localhost:8899 PROGRAMID=7f3bKvFg9WrUr3RGig5gGj8GnEFYMML86ffgxaH19ft1 GATEWAY=x node dist/index.j
clients/arbiternpm run buildtsc
clients/arbiternpm run testecho "Error: no test specified" && exit 1

What you could build from it