Full lesson
trustlesswork-solana
What it does
From the project README:
Trustless Work is a non-custodial escrow protocol built on Solana that enables milestone-based payments with institutional-grade compliance (KYC/KYT/AML/Travel Rule). It allows any application to embed programmable escrow logic via a simple REST API, while all fund custody and release logic lives on-chain.
- Original
- Trustless-Work/trustlesswork-solana
- SuperStack fork
- Blockchains/trustlesswork-solana @
6bf738f - Stars
- 0
- Last push (original)
- 2026-05-09
- Languages
- TypeScript, Rust, CSS, Shell, JavaScript, Dockerfile
- Detected stack
- AnchorNext.jsweb3.js
- Categories
- Other
- Licence
- MIT
Architecture
443 source files. By extension: .ts ×256, .tsx ×164, .rs ×20, .js ×3.
| Top-level directory | Source files |
|---|---|
apps | 394 |
packages | 46 |
programs | 2 |
(root) | 1 |
On-chain programs: apps/smart-contract/programs/escrow
Dapp: deploying
This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/trustlesswork-solana/, 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.
apps/smart-contract/programs/escrow/src/context.rs L409–432 @ 6bf738f · MIT · original #[account( mut, seeds = [b"compliance_registry"], bump, constraint = registry.authority == authority.key() @ EscrowError::OnlyComplianceAuthority, close = authority )] pub registry: Account<'info, ComplianceRegistry>,} #[derive(Accounts)]pub struct VerifyAddress<'info> { #[account(mut)] pub authority: Signer<'info>, #[account( seeds = [b"compliance_registry"], bump, constraint = registry.authority == authority.key() @ EscrowError::OnlyComplianceAuthority )] pub registry: Account<'info, ComplianceRegistry>, #[account( init,- Line 411
seeds = [b"compliance_registry"],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match. - Line 412
bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve. - Line 414
close = authority: Closes the account at the end of the instruction and refunds its lamports. - Line 422
pub authority: Signer<'info>,: Requires this account to have signed the transaction. - Line 432
init,: Creates and pays for a new account. Space and payer must be specified.
apps/smart-contract/programs/escrow/src/instructions/compliance.rs L37–60 @ 6bf738f · MIT · original) -> Result<()> { // Account is closed by the `close = authority` constraint Ok(())} pub fn verify_address_handler( ctx: Context<VerifyAddress>, kyc_provider: String, jurisdiction: String, risk_score: u8,) -> Result<()> { validate_jurisdiction(&jurisdiction)?; let verification = &mut ctx.accounts.verification; verification.address = ctx.accounts.address.key(); verification.kyc_verified = true; verification.kyc_provider = kyc_provider.clone(); verification.kyc_timestamp = Clock::get()?.unix_timestamp; verification.risk_score = risk_score; verification.jurisdiction = jurisdiction.clone(); emit!(AddressKycVerified { address: verification.address, kyc_provider,- Line 38
// Account is closed by the `close = authority` constraint: Closes the account at the end of the instruction and refunds its lamports. - Line 54
verification.kyc_timestamp = Clock::get()?.unix_timestamp;: Reads on-chain time from the Clock sysvar. - Line 58
emit!(AddressKycVerified {: Emits an Anchor event that clients can parse from the logs.
apps/smart-contract/programs/escrow/src/instructions/multi_release.rs L385–408 @ 6bf738f · MIT · original } } let remaining = ctx.accounts.escrow_token_account.amount; if remaining == 0 { return Err(EscrowError::NoRemainingFunds.into()); } let bump = ctx.bumps.escrow_account; let engagement_id = escrow.engagement_id.clone(); let binding = [bump]; let authority_seeds: &[&[u8]] = &[b"multi_escrow", engagement_id.as_bytes(), &binding]; transfer_from_escrow( remaining, ctx.accounts.escrow_token_account.to_account_info(), ctx.accounts.approver_token_account.to_account_info(), escrow_account_info, ctx.accounts.token_program.to_account_info(), authority_seeds, )?; emit!(RemainingFundsWithdrawn { escrow_id: engagement_id,- Line 393
let bump = ctx.bumps.escrow_account;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve. - Line 407
emit!(RemainingFundsWithdrawn {: Emits an Anchor event that clients can parse from the logs.
apps/smart-contract/programs/escrow/src/instructions/escrow.rs L157–180 @ 6bf738f · MIT · original // Validate escrow has no balance if escrow.balance > 0 { return Err(EscrowError::CannotCancelFundedEscrow.into()); } // Validate escrow has not been released if escrow.flags.release { return Err(EscrowError::CannotCancelReleasedEscrow.into()); } // Validate no milestones have been approved for milestone in &escrow.milestones { if milestone.approved_flag { return Err(EscrowError::CannotCancelWithApprovedMilestones.into()); } } emit!(EscrowCancelled { escrow_id: escrow.engagement_id.clone(), cancelled_by: ctx.accounts.platform_signer.key(), }); // Account will be closed automatically due to `close = platform_signer` constraint- Line 175
emit!(EscrowCancelled {: Emits an Anchor event that clients can parse from the logs. - Line 180
// Account will be closed automatically due to `close = platform_signer` constraint: Closes the account at the end of the instruction and refunds its lamports.
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.
| Directory | Command | Runs |
|---|---|---|
packages/allbridge | npm run build | tsc |
packages/sdk | npm run build | tsup |
apps/smart-contract | npm run build | ./build.sh |
apps/smart-contract | npm run test | bun test tests/ |
apps/dashboard | npm run dev | next dev |
apps/dashboard | npm run start | next start |
apps/dashboard | npm run build | next build |
apps/dashboard | npm run lint | next lint |
apps/server | npm run start | node -r dotenv/config dist/main |
apps/server | npm run build | nest build |
apps/server | npm run test | jest |
apps/server | npm run lint | eslint "{src,apps,libs,test}/**/*.ts" --fix |
apps/smart-contract | anchor build | compile programs and generate IDLs |
apps/smart-contract | anchor test | local validator + test suite |
apps/smart-contract | anchor run test | yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts |
What you could build from it
- Fork the SuperStack copy and extend it within the Other gaps listed on the idea page.
- Learn the pattern first: Program Derived Addresses (PDAs)
- Learn the pattern first: Cross-Program Invocations (CPIs)