From 79456e392756680fbe101914f63b31cb0dbb0d73 Mon Sep 17 00:00:00 2001 From: thesn10 <38666407+thesn10@users.noreply.github.com> Date: Thu, 21 May 2026 22:21:48 +0200 Subject: [PATCH] readme --- README.md | 158 ++++++++++++++++++++++++++++++++++++++++++++++ docs/local-dev.md | 133 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 README.md create mode 100644 docs/local-dev.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..34f89a2 --- /dev/null +++ b/README.md @@ -0,0 +1,158 @@ +# descro + +A decentralized escrow protocol on Solana for physical goods trading. Fully permissionless and resolver-agnostic — any wallet or program that implements the resolver interface can adjudicate disputes. + +## Overview + +``` +APPLICATION LAYER + Central Platform (own resolver, KYC, normal UX) + Decentralized Clients (raw protocol access, free resolver choice) + │ +PROTOCOL LAYER + ┌─────────────────┐ ┌──────────────────────┐ + │ Escrow Program │────▶│ Resolver Registry │ + │ (descro) │ CPI │ (descro_ext_res.) │ + └─────────────────┘ └──────────────────────┘ +``` + +The protocol only defines the interface. Any resolver that implements it is compatible — from a single authority wallet to a jury DAO voting contract. + +## Programs + +| Program | ID | +|---|---| +| `descro` | `DjVR4EuYV6USMJFfsGZwhZ3y8rtWsmG8EvDY96GTqqi3` | +| `descro_ext_resolvers` | `GwUPAKs3HHzCpj8uhet4NAnxk9GWNwfrYbpihu5DyFp` | + +### Escrow Program (`descro`) + +Holds trade state and SOL. Two PDAs per escrow: + +- **EscrowAccount** `["escrow", seller_pubkey, escrow_id_le_bytes]` — trade state +- **Vault** `["vault", escrow_account_pubkey]` — system-owned, holds SOL only + +**Instruction flow:** + +``` +create_escrow (seller) + └─▶ deposit (buyer) + ├─▶ complete (buyer) → SOL released to seller + └─▶ dispute (buyer | seller) + └─▶ resolve (resolver) → SOL released to winner +cancel (seller, only from AwaitingDeposit) +``` + +The `dispute_resolver` field in the escrow can be any pubkey — a wallet signing directly or a program calling `resolve()` via CPI. The check is identical either way. + +**Emergency resolve:** After 14 days in `Disputed` state with no resolution, either party can call `emergency_resolve` to unlock funds. + +### Resolver Registry (`descro_ext_resolvers`) + +An on-chain directory for resolvers. Resolvers register with metadata (name, type, fee, URI); resolution stats are auto-incremented by the escrow program via CPI and cannot be manipulated externally. + +`update_stats` is callable only by the escrow program — enforced via an `["escrow_authority"]` PDA that only the escrow program can sign for. + +Resolver types: `CentralAuthority`, `JuryDAO`, `MAD`, `Algorithmic`, `Multisig` + +## Repository Structure + +``` +programs/ +├── descro/ — Escrow Program (Rust/Anchor) +└── descro_ext_resolvers/ — Resolver Registry (Rust/Anchor) +sdk/ — @descro/sdk TypeScript client +├── src/ +│ ├── idl/ — Anchor-generated IDL JSON +│ ├── escrow.ts — EscrowClient (instruction builders + fetchers) +│ ├── registry.ts — RegistryClient +│ ├── listener.ts — WebSocket subscriptions +│ ├── pda.ts — PDA derivation helpers +│ ├── types.ts — TypeScript types matching on-chain state +│ └── index.ts — Re-exports + DescroSdk convenience class +app/ — Next.js + Tamagui playground +├── src/app/ — App Router pages + providers +├── src/components/ — EscrowDetail, ResolverPanel, … +└── src/hooks/ — useEscrows, useEscrowDetail +``` + +## Getting Started + +### Prerequisites + +- Rust + `cargo-build-sbf` +- Solana CLI +- Node.js + Yarn + +### Build + +Programs must be built in order — the escrow program depends on the registry: + +```bash +cargo build-sbf --manifest-path programs/descro_ext_resolvers/Cargo.toml +cargo build-sbf --manifest-path programs/descro/Cargo.toml +``` + +Install JS dependencies from the repo root: + +```bash +yarn install +``` + +### Test + +Tests load the compiled `.so` files via `include_bytes!`, so programs must be built first: + +```bash +cargo test --manifest-path programs/descro/Cargo.toml +cargo test --manifest-path programs/descro_ext_resolvers/Cargo.toml +``` + +Run a single test: + +```bash +cargo test --manifest-path programs/descro/Cargo.toml -- test_create_escrow +cargo test --manifest-path programs/descro/Cargo.toml --test test_resolve +``` + +### App (dev server) + +```bash +yarn workspace descro-app run dev +``` + +## SDK Usage + +The SDK is consumed as raw TypeScript via `transpilePackages` in the Next.js config — no build step needed. + +```ts +import { DescroSdk } from "@descro/sdk"; + +const sdk = new DescroSdk(provider); + +// Create escrow +await sdk.escrow.createEscrow({ amount, disputeResolver, escrowId }); + +// Fetch all escrows for a seller +const escrows = await sdk.escrow.fetchEscrowsBySeller(sellerPubkey); + +// Subscribe to state changes +sdk.listener.onEscrowUpdate(escrowPubkey, (account) => { ... }); +``` + +## Security Properties + +| Property | Mechanism | +|---|---| +| Nobody can take SOL without consent | Network enforces signature requirement at protocol level | +| Vault can only be drained by the escrow program | Vault owner = system_program, only accessible via `invoke_signed` with correct seeds | +| Wrong resolver cannot call `resolve()` | `require!(signer.key() == escrow.dispute_resolver)` | +| PDAs cannot be spoofed | Program verifies seeds on-chain for every instruction | +| Registry stats cannot be manipulated | `update_stats` only callable via CPI from the escrow program | + +## Architecture Notes + +- **Anchor 1.0.x:** `UncheckedAccount<'info>` with `/// CHECK:` doc comments; `#[derive(InitSpace)]` + `#[max_len(N)]` for strings. +- **`@coral-xyz/anchor@0.32.x`:** Use `new Program(idl, provider)` — the IDL's `address` field provides the program ID. The 3-argument form is broken in 0.32.x. +- **Yarn workspaces:** `nodeLinker: node-modules` (not PnP) — required for Next.js Turbopack compatibility. +- **LiteSVM tests:** each `tests/common/mod.rs` provides `setup()`, PDA helpers, `send()`/`try_send()`, `ix_*` builders, and `read_*` deserializers. `test_resolve_with_registry.rs` loads both `.so` files to test the full CPI flow. diff --git a/docs/local-dev.md b/docs/local-dev.md new file mode 100644 index 0000000..cfdefb9 --- /dev/null +++ b/docs/local-dev.md @@ -0,0 +1,133 @@ +# Descro — Local Development & Testing + +## Prerequisites + +- [Rust](https://rustup.rs/) with the `solana` toolchain (`rust-toolchain.toml` pins the version) +- [Solana CLI](https://docs.solana.com/cli/install-solana-cli-tools) ≥ 1.18 +- [Anchor CLI](https://www.anchor-lang.com/docs/installation) (used for `build-sbf`) +- Node.js + [Yarn](https://yarnpkg.com/) +- A browser wallet extension (Phantom, Backpack, etc.) + +--- + +## 1 — Start a local validator + +```bash +solana-test-validator --reset +``` + +Leave this running in a dedicated terminal. The validator listens on: + +| Endpoint | Address | +|---|---| +| RPC | `http://localhost:8899` | +| WebSocket | `ws://localhost:8900` | + +--- + +## 2 — Configure the Solana CLI to use localhost + +```bash +solana config set --url localhost +``` + +Verify: + +```bash +solana config get +# RPC URL: http://localhost:8899 +``` + +If you do not yet have a local keypair: + +```bash +solana-keygen new --outfile ~/.config/solana/id.json +solana airdrop 10 +``` + +--- + +## 3 — Build and deploy the programs + +Build order matters — `descro` depends on `descro_ext_resolvers`. + +```bash +# Build the resolver registry first +cargo build-sbf --manifest-path programs/descro_ext_resolvers/Cargo.toml + +# Then build the escrow program +cargo build-sbf --manifest-path programs/descro/Cargo.toml +``` + +Deploy both to the local validator: + +```bash +solana program deploy \ + --program-id programs/descro_ext_resolvers/keypair.json \ + target/deploy/descro_ext_resolvers.so + +solana program deploy \ + --program-id programs/descro/keypair.json \ + target/deploy/descro.so +``` + +> **Note:** if you don't have per-program keypair files, omit `--program-id` and note +> the deployed address; then update the IDs in `sdk/src/pda.ts` and the IDL `address` +> fields accordingly. + +Expected program IDs (as declared in `Anchor.toml`): + +| Program | ID | +|---|---| +| `descro` | `DjVR4EuYV6USMJFfsGZwhZ3y8rtWsmG8EvDY96GTqqi3` | +| `descro_ext_resolvers` | `GwUPAKs3HHzCpj8uhet4NAnxk9GWNwfrYbpihu5DyFp` | + +--- + +## 4 — Configure your browser wallet for localhost + +**Phantom:** +1. Settings → Developer Settings → Testnet Mode (or add a custom RPC) +2. Network → Custom → `http://localhost:8899` + +**Backpack:** +1. Settings → Solana → RPC Connection → Custom → `http://localhost:8899` + +Airdrop yourself some SOL from the CLI or from the Solana faucet panel inside the wallet. + +--- + +## 5 — Start the app + +```bash +yarn install # from repo root, only needed once +yarn workspace descro-app run dev +``` + +Open [http://localhost:3000](http://localhost:3000). + +In the top-right **Network** dropdown, select **Localnet**. The app will connect to +`http://localhost:8899`. Connect your wallet and you can create escrows, deposit funds, +and test the full instruction flow against the locally-deployed programs. + +--- + +## Running tests + +Tests load the compiled `.so` files via `include_bytes!`, so always build before testing. + +```bash +# All tests for the escrow program (includes CPI flow test) +cargo test --manifest-path programs/descro/Cargo.toml + +# All tests for the resolver registry +cargo test --manifest-path programs/descro_ext_resolvers/Cargo.toml + +# Single test by name +cargo test --manifest-path programs/descro/Cargo.toml -- test_create_escrow + +# Specific test file +cargo test --manifest-path programs/descro/Cargo.toml --test test_resolve +``` + +Tests use **LiteSVM** (in-process) and do not require a running validator.