Decentralized freelance escrow on Solana. AI oracle verifies deliverables via dual-model consensus (Gemini + Claude) and settles payments autonomously on-chain. No platform fees. No middlemen. MIT licensed.
README
Mappers Protocol
On-chain freelance settlement infrastructure for Solana, combining programmable escrow with an off-chain dual-model verification oracle.
Mappers is an open-source decentralized escrow protocol for freelance and milestone-based work. Client funds are locked in deterministic Solana vault accounts and released or refunded through explicit on-chain state transitions. The Oracle middleware observes jobs, evaluates submitted artifacts through independent Gemini and Claude verdicts, and signs a settlement transaction only when the configured consensus policy is satisfied.
Current release: v0.1.0
Program ID (Devnet): 52yt1gCbPeiKP4JYjUVKmMJSgBMMcUx8xRGqozMKX2Mu
How It Works
Client / Dashboard
| API requests and signed transactions
v
API Server (Express 5 + PostgreSQL)
| job metadata and deliverable submission
v
Oracle Middleware (Node.js)
| Helius Yellowstone gRPC event stream
| Gemini + Claude verification
v
Anchor Escrow Program (Rust)
|-- GigEscrow PDA: job state and metadata
|-- Vault PDA: locked SOL
|
+--> release_payment or cancel_job
A client initializes a job and funds its vault. The Oracle listens for the on-chain job, receives the freelancer’s deliverable through the application flow, and requests independent structured verdicts from Gemini and Claude. Agreement above the configured thresholds allows the Oracle to submit the corresponding settlement instruction. A disagreement or sub-threshold result remains eligible for human arbitration rather than moving funds automatically.
Repository Structure
Mappers is a pnpm 11 workspace monorepo. The Oracle is a first-class workspace package and shares the root pnpm-lock.yaml; npm and yarn installation are intentionally rejected.
mappers_contract/
|
|-- programs/project_mappers/ Anchor smart contract (Rust)
|-- oracle/ Off-chain verification service (workspace)
|
|-- apps/
| |-- api-server/ Express 5 REST API
| |-- dashboard/ Vite + React 19 frontend
|
|-- lib/
| |-- sdk/ @mappers-protocol/sdk
| |-- db/ Drizzle schema and migrations
| |-- api-zod/ Shared Zod validation schemas
| |-- api-spec/ OpenAPI specification and code generation
| |-- api-client-react/ Generated TanStack Query hooks
|
|-- tests/ Anchor integration tests
|-- scripts/ Devnet and integration scripts
|-- docs/wiki/ Version-controlled wiki source
|-- mappers_whitepaper.md Protocol design and economic model
|-- CHANGELOG.md Human-readable release history
Technology Stack
| Layer | Technology |
|---|---|
| Smart contract | Rust, Anchor program crate 0.30.1 |
| Solana tooling | Solana 1.18-compatible toolchain; Anchor CLI in CI |
| TypeScript client/tests | @coral-xyz/anchor 0.32.1, TypeScript, ts-mocha |
| API server | Express 5, Drizzle ORM, PostgreSQL, Pino |
| Frontend | Vite, React 19, TanStack Query, Tailwind CSS, shadcn/ui |
| Oracle runtime | Node.js, Helius Yellowstone gRPC, Vitest |
| Verification models | Google Gemini API and Anthropic Claude API |
| Package manager | pnpm 11 workspaces |
| Security tooling | cargo audit, pnpm audit, CodeQL, Dependabot |
| License | MIT |
Getting Started
Prerequisites
Install the following tools before starting local development:
- Node.js 22 or newer.
- pnpm 11 or newer.
- Rust, Solana CLI, and an Anchor CLI compatible with the program crate.
- PostgreSQL 14 or newer for the API server and database package.
Install and Validate
Run these commands from the repository root:
pnpm install
pnpm run typecheck:libs
pnpm run typecheck
pnpm run build
pnpm run typecheck:oracle
pnpm run test:oracle
pnpm run test:anchor
pnpm install is the only supported root installation command. The repository contains one authoritative workspace lockfile. Do not create or restore oracle/package-lock.json.
Run the API Server
The API server expects a PostgreSQL connection string and a valid Oracle URL.
export DATABASE_URL="postgresql://localhost:5432/mappers_dev"
export ORACLE_URL="http://localhost:3001"
cd apps/api-server
pnpm run dev
To push the current Drizzle schema to a development database:
cd lib/db
pnpm run push
Run the Dashboard
cd apps/dashboard
pnpm run dev
The Vite development server uses port 5173 by default. Configure the API base URL using the dashboard’s environment configuration when the API is not running on its default local address.
Run the Oracle
The Oracle is installed and run through the root pnpm workspace:
cp oracle/.env.example oracle/.env
cd oracle
pnpm run dev
The service requires environment-specific credentials and endpoints. Typical values include SOLANA_RPC_URL, PROGRAM_ID, ORACLE_PRIVATE_KEY, HELIUS_GRPC_ENDPOINT, GEMINI_API_KEY, and ANTHROPIC_API_KEY. Keep private keys and API credentials outside version control.
Run the Anchor Program
anchor build
pnpm run test:anchor
The default Anchor test script uses tsconfig.anchor.json and the repository’s pinned TypeScript test tooling. CI also installs the compatibility Rust toolchain required by the Anchor IDL build.
Smart Contract
The programs/project_mappers program manages a job through three instructions:
| Instruction | Caller | Effect |
|---|---|---|
initialize_job(job_id, amount, duration) |
Client | Creates the escrow and vault PDAs, validates the job, and deposits SOL. |
release_payment() |
Client or Oracle | Pays the stored freelancer and closes the escrow. |
cancel_job() |
Oracle | Refunds the stored client and closes the escrow. |
The program uses separate state and vault PDAs, stores canonical bumps, enforces a 32-byte job-ID seed boundary, protects terminal states from double spending, and returns account rent to the client when an escrow closes. The Devnet deployment is recorded in Anchor.toml and the deployment table below.
Oracle Consensus
The Oracle exposes a Node.js service for job tracking, artifact submission, and verification. It listens to the configured Helius Yellowstone gRPC endpoint and uses the program IDL to interpret escrow activity. The verification implementation remains a dual-model policy: Gemini and Claude produce independent structured verdicts, and divergent or sub-threshold outcomes are not automatically settled.
The protected consensus implementation is oracle/src/verification.ts. Model credentials are supplied only through environment variables; no credentials belong in the repository.
API and Dashboard
The API server in apps/api-server/ provides job registration, status, submission, statistics, health, and Oracle-proxy routes. Request and response validation is generated from the OpenAPI specification in lib/api-spec/, with shared Zod schemas and typed React Query hooks consumed by the dashboard.
The dashboard in apps/dashboard/ provides job overviews, job details, settlement metadata, aggregate statistics, and Oracle health visibility. It is a Vite-built React 19 application styled with Tailwind CSS and shadcn/ui.
CI/CD and Dependency Automation
The repository has five required validation workflows: CI, Anchor Program, Security Audit, CodeQL, and Semantic PR Title. The repository also runs DCO validation, wiki synchronization, and Dependabot updates.
Dependabot updates the single root npm/pnpm workspace, the Cargo program, and GitHub Actions. The root workspace includes Oracle so its manifest and dependencies are updated through the same supported pnpm workspace model. A small set of dependencies with opaque upstream updater failures is explicitly ignored in .github/dependabot.yml and must be reviewed manually when newer versions are needed.
The release candidate for v0.1.0 was validated on main with clean local typecheck/build/Oracle tests and passin
… README truncated here; the full file ships with the clone.
230 files
every file readable free; the clone is the same bytes, packaged and agent-payable
.github/14
- .github/CODEOWNERS52 B
- .github/FUNDING.yml41 B
- .github/ISSUE_TEMPLATE/bug_report.yml1 KB
- .github/ISSUE_TEMPLATE/config.yml187 B
- .github/ISSUE_TEMPLATE/feature_request.yml481 B
- .github/dependabot.yml637 B
- .github/strip-ai-attribution.yml2 KB
- .github/workflows/anchor.yml2 KB
- .github/workflows/ci.yml3 KB
- .github/workflows/codeql.yml1 KB
- .github/workflows/dco.yml248 B
- .github/workflows/security.yml1 KB
- .github/workflows/semantic-pr.yml2 KB
- .github/workflows/wiki-sync.yml878 B
apps/93
- apps/api-server/build.mjs3 KB
- apps/api-server/package.json965 B
- apps/api-server/src/app.ts963 B
- apps/api-server/src/index.ts535 B
- apps/api-server/src/lib/.gitkeep0 B
- apps/api-server/src/lib/logger.ts421 B
- apps/api-server/src/middlewares/.gitkeep0 B
- apps/api-server/src/routes/health.ts288 B
- apps/api-server/src/routes/index.ts228 B
- apps/api-server/src/routes/jobs.ts8 KB
- apps/api-server/tsconfig.json335 B
- apps/dashboard/components.json434 B
- apps/dashboard/index.html1 KB
- apps/dashboard/package.json3 KB
- apps/dashboard/public/.well-known/security.txt316 B
- apps/dashboard/public/favicon.svg163 B
- apps/dashboard/public/opengraph.jpg117 KB
- apps/dashboard/public/robots.txt23 B
- apps/dashboard/src/App.tsx9 KB
- apps/dashboard/src/components/job-card.tsx3 KB
- apps/dashboard/src/components/status-badge.tsx982 B
- apps/dashboard/src/components/ui/accordion.tsx2 KB
- apps/dashboard/src/components/ui/alert-dialog.tsx4 KB
- apps/dashboard/src/components/ui/alert.tsx2 KB
- apps/dashboard/src/components/ui/aspect-ratio.tsx140 B
- apps/dashboard/src/components/ui/avatar.tsx1 KB
- apps/dashboard/src/components/ui/badge.tsx1 KB
- apps/dashboard/src/components/ui/breadcrumb.tsx3 KB
- apps/dashboard/src/components/ui/button-group.tsx2 KB
- apps/dashboard/src/components/ui/button.tsx2 KB
- apps/dashboard/src/components/ui/calendar.tsx7 KB
- apps/dashboard/src/components/ui/card.tsx2 KB
- apps/dashboard/src/components/ui/carousel.tsx6 KB
- apps/dashboard/src/components/ui/chart.tsx11 KB
- apps/dashboard/src/components/ui/checkbox.tsx1 KB
- apps/dashboard/src/components/ui/collapsible.tsx329 B
- apps/dashboard/src/components/ui/command.tsx5 KB
- apps/dashboard/src/components/ui/context-menu.tsx7 KB
- apps/dashboard/src/components/ui/dialog.tsx4 KB
- apps/dashboard/src/components/ui/drawer.tsx3 KB
- apps/dashboard/src/components/ui/dropdown-menu.tsx7 KB
- apps/dashboard/src/components/ui/empty.tsx2 KB
- apps/dashboard/src/components/ui/field.tsx6 KB
- apps/dashboard/src/components/ui/form.tsx4 KB
- apps/dashboard/src/components/ui/hover-card.tsx1 KB
- apps/dashboard/src/components/ui/input-group.tsx5 KB
- apps/dashboard/src/components/ui/input-otp.tsx2 KB
- apps/dashboard/src/components/ui/input.tsx768 B
- apps/dashboard/src/components/ui/item.tsx4 KB
- apps/dashboard/src/components/ui/kbd.tsx862 B
- apps/dashboard/src/components/ui/label.tsx724 B
- apps/dashboard/src/components/ui/menubar.tsx8 KB
- apps/dashboard/src/components/ui/navigation-menu.tsx5 KB
- apps/dashboard/src/components/ui/pagination.tsx3 KB
- apps/dashboard/src/components/ui/popover.tsx1 KB
- apps/dashboard/src/components/ui/progress.tsx792 B
- apps/dashboard/src/components/ui/radio-group.tsx1 KB
- apps/dashboard/src/components/ui/resizable.tsx3 KB
- apps/dashboard/src/components/ui/scroll-area.tsx2 KB
- apps/dashboard/src/components/ui/select.tsx6 KB
- apps/dashboard/src/components/ui/separator.tsx756 B
- apps/dashboard/src/components/ui/sheet.tsx4 KB
- apps/dashboard/src/components/ui/sidebar.tsx21 KB
- apps/dashboard/src/components/ui/skeleton.tsx266 B
- apps/dashboard/src/components/ui/slider.tsx1 KB
- apps/dashboard/src/components/ui/sonner.tsx894 B
- apps/dashboard/src/components/ui/spinner.tsx331 B
- apps/dashboard/src/components/ui/switch.tsx1 KB
- apps/dashboard/src/components/ui/table.tsx3 KB
- apps/dashboard/src/components/ui/tabs.tsx2 KB
- apps/dashboard/src/components/ui/textarea.tsx649 B
- apps/dashboard/src/components/ui/toast.tsx5 KB
- apps/dashboard/src/components/ui/toaster.tsx772 B
- apps/dashboard/src/components/ui/toggle-group.tsx2 KB
- apps/dashboard/src/components/ui/toggle.tsx1 KB
- apps/dashboard/src/components/ui/tooltip.tsx1 KB
- apps/dashboard/src/components/wallet-button.tsx4 KB
- apps/dashboard/src/components/wallet-provider.tsx637 B
- apps/dashboard/src/hooks/use-mappers-client.ts962 B
- apps/dashboard/src/hooks/use-mobile.tsx565 B
- apps/dashboard/src/hooks/use-toast.ts4 KB
- apps/dashboard/src/index.css8 KB
- apps/dashboard/src/lib/format.ts839 B
- apps/dashboard/src/lib/utils.ts166 B
- apps/dashboard/src/main.tsx157 B
- apps/dashboard/src/pages/create-job.tsx16 KB
- apps/dashboard/src/pages/dashboard.tsx11 KB
- apps/dashboard/src/pages/job-detail.tsx18 KB
- apps/dashboard/src/pages/jobs.tsx9 KB
- apps/dashboard/src/pages/not-found.tsx711 B
- apps/dashboard/src/pages/oracle.tsx9 KB
- apps/dashboard/tsconfig.json670 B
- apps/dashboard/vite.config.ts2 KB
docs/14
- docs/adr/0001-dual-pda-architecture.md2 KB
- docs/adr/0002-dual-model-ai-consensus.md2 KB
- docs/wiki/API-Reference.md9 KB
- docs/wiki/Architecture.md10 KB
- docs/wiki/Dashboard.md5 KB
- docs/wiki/Development-Guide.md8 KB
- docs/wiki/Getting-Started.md7 KB
- docs/wiki/Glossary.md9 KB
- docs/wiki/Home.md6 KB
- docs/wiki/README.md3 KB
- docs/wiki/Release-Notes.md2 KB
- docs/wiki/SDK-Reference.md9 KB
- docs/wiki/_Footer.md166 B
- docs/wiki/_Sidebar.md524 B
lib/43
- lib/api-client-react/package.json265 B
- lib/api-client-react/src/custom-fetch.ts11 KB
- lib/api-client-react/src/generated/api.schemas.ts3 KB
- lib/api-client-react/src/generated/api.ts17 KB
- lib/api-client-react/src/index.ts194 B
- lib/api-client-react/tsconfig.json251 B
- lib/api-spec/openapi.yaml8 KB
- lib/api-spec/orval.config.ts2 KB
- lib/api-spec/package.json228 B
- lib/api-zod/package.json189 B
- lib/api-zod/src/generated/api.ts5 KB
- lib/api-zod/src/generated/types/dashboardStats.ts326 B
- lib/api-zod/src/generated/types/deliverableInput.ts388 B
- lib/api-zod/src/generated/types/deliverableInputDeliverableType.ts387 B
- lib/api-zod/src/generated/types/healthStatus.ts182 B
- lib/api-zod/src/generated/types/index.ts598 B
- lib/api-zod/src/generated/types/job.ts701 B
- lib/api-zod/src/generated/types/jobInput.ts359 B
- lib/api-zod/src/generated/types/jobStatus.ts311 B
- lib/api-zod/src/generated/types/jobUpdate.ts289 B
- lib/api-zod/src/generated/types/jobUpdateStatus.ts335 B
- lib/api-zod/src/generated/types/listJobsParams.ts268 B
- lib/api-zod/src/generated/types/listJobsStatus.ts331 B
- lib/api-zod/src/generated/types/oracleHealth.ts226 B
- lib/api-zod/src/generated/types/submitResult.ts404 B
- lib/api-zod/src/generated/types/submitResultOutcome.ts371 B
- lib/api-zod/src/index.ts68 B
- lib/api-zod/tsconfig.json221 B
- lib/db/drizzle.config.ts352 B
- lib/db/package.json578 B
- lib/db/src/index.ts416 B
- lib/db/src/schema/index.ts757 B
- lib/db/src/schema/jobs.ts1 KB
- lib/db/tsconfig.json244 B
- lib/sdk/package.json346 B
- lib/sdk/src/client.ts5 KB
- lib/sdk/src/constants.ts317 B
- lib/sdk/src/idl.ts3 KB
- lib/sdk/src/index.ts188 B
- lib/sdk/src/oracle.ts2 KB
- lib/sdk/src/pda.ts669 B
- lib/sdk/src/types.ts2 KB
- lib/sdk/tsconfig.json275 B
oracle/18
- oracle/.env.example3 KB
- oracle/idl.json2 KB
- oracle/package.json1 KB
- oracle/src/__tests__/config.test.ts8 KB
- oracle/src/__tests__/index.test.ts14 KB
- oracle/src/__tests__/listener.test.ts7 KB
- oracle/src/__tests__/store.test.ts8 KB
- oracle/src/__tests__/verification.test.ts16 KB
- oracle/src/chain.ts5 KB
- oracle/src/config.ts2 KB
- oracle/src/index.ts11 KB
- oracle/src/listener.ts6 KB
- oracle/src/store.ts969 B
- oracle/src/types.ts3 KB
- oracle/src/utils.ts1 KB
- oracle/src/verification.ts8 KB
- oracle/tsconfig.json388 B
- oracle/vitest.config.ts315 B
programs/2
scripts/4
shared/1
- shared/pda.ts1 KB
tests/2
wiki/12
- .gitattributes434 B
- .gitignore452 B
- .mailmap76 B
- .npmrc56 B
- .prettierignore213 B
- Anchor.toml411 B
- CHANGELOG.md2 KB
- CODE_OF_CONDUCT.md2 KB
- CONTRIBUTING.md2 KB
- Cargo.lock47 KB
- Cargo.toml200 B
- DEVIN_KNOWLEDGE.md19 KB
- GOVERNANCE.md2 KB
- LICENSE1 KB
- Makefile2 KB
- README.md12 KB
- SECURITY.md281 B
- idl.json7 KB
- mappers_whitepaper.md23 KB
- package.json1 KB
- pnpm-lock.yaml356 KB
- pnpm-workspace.yaml7 KB
- pull_request_template.md781 B
- security.json292 B
- tsconfig.anchor.json257 B
- tsconfig.base.json692 B
- tsconfig.json235 B