Skip to content
Open
297 changes: 234 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,279 @@
<img src="./canopy-logo-white-bg.svg" alt="Canopy Logo" width="500"/>
# 🌿 Praxis — Prediction Market on Canopy

_Official golang implementation of the Canopy Network Protocol_
> A fully on-chain YES/NO prediction market built as a Canopy appchain plugin.
> Submitted for the **Canopy Vibe Coding Contest 2026**.

[![GoDoc](https://img.shields.io/badge/godoc-reference-white.svg)](https://godoc.org/github.com/canopy-network/canopy)
[![Getting Started](https://img.shields.io/badge/getting%20started-guide-white)](https://canopynetwork.org)
[![Go Version](https://img.shields.io/badge/golang-v1.21-white.svg)](https://golang.org)
[![Next.js Version](https://img.shields.io/badge/next%20js-v14.2.3-white.svg)](https://nextjs.org/)
![Chain](https://img.shields.io/badge/Chain-Canopy%20Betanet-4CAF50?style=flat-square)
![Language](https://img.shields.io/badge/Language-Go-00ADD8?style=flat-square&logo=go)
![License](https://img.shields.io/badge/License-MIT-blue?style=flat-square)
![Status](https://img.shields.io/badge/Status-Testnet-orange?style=flat-square)

---

# Overview
## What is Praxis?

[![License](https://img.shields.io/badge/License-MIT-white.svg)](https://opensource.org/licenses/MIT)
[![Testing](https://img.shields.io/badge/testing-docker%20compose-white)](https://docs.docker.com/compose/)
[![Platform](https://img.shields.io/badge/platform-linux%20%7C%20macos-white.svg)](https://github.com/canopy-network/canopy/releases)
[![Status](https://img.shields.io/badge/status-alphanet-white)](https://docs.docker.com/compose/)
Praxis is a sovereign prediction market appchain built on the Canopy Network. Anyone can create a YES/NO question, stake tokens on an outcome, and earn a proportional payout from the losing pool when the market resolves.

### ⫸ **Welcome to the Network that Powers the Peer-to-Peer Launchpad for New Chains**
Every action — creating a market, placing a bet, resolving an outcome, claiming winnings — is a real on-chain transaction processed by a custom Canopy plugin. No smart contracts. No shared blockspace. Full sovereignty.

Built on a recursive architecture, chains bootstrap each other into independence —
forming an `unstoppable` web of utility and security.
---

**Here you'll find:**
## How It Works

➪ A recursive framework to build blockchains.
### The Flow

➪ The seed chain that started the recursive cycle.
```
Creator opens a market → Forecasters place bets → Resolver declares winner → Winners claim payout
```

### Payout Formula

```
payout = your_stake + (your_stake × losing_pool / winning_pool)
```

**Example:** If you bet 100 PRX on YES and YES wins with a 60/40 split:

```
payout = 100 + (100 × 40/60) = ~167 PRX
```

---

## Transaction Types

| Transaction | Who Signs | What It Does |
|---|---|---|
| `create_market` | Creator | Opens a new YES/NO market with a question, resolver, and resolution block height |
| `submit_prediction` | Forecaster | Places a bet of X amount on YES (1) or NO (0) |
| `resolve_market` | Resolver | Declares the winning outcome after the resolution height |
| `claim_winnings` | Winner | Collects proportional payout from the losing pool |
| `send` | Sender | Standard token transfer (built-in) |

---

## State Schema

| Prefix | Type | Description |
|---|---|---|
| `0x01` | Account | Token balances |
| `0x02` | Pool | Fee pool |
| `0x07` | FeeParams | Governance fee parameters |
| `0x10` | Market | All market data (question, pools, status, winner) |
| `0x11` | Prediction | Individual forecaster bets (keyed by marketId + address) |
| `0x12` | MarketCounter | Auto-incrementing market ID counter |
| `0x13` | ForecasterRecord | Leaderboard stats per forecaster |

---

For more information on the Canopy Network Protocol visit [https://canopynetwork.org](https://canopynetwork.org)
## Files Changed

## Network Status
```
plugin/go/proto/tx.proto ← Added 4 transaction message types + 5 state objects
plugin/go/contract/contract.go ← Full prediction market plugin logic
plugin/go/frontend/index.html ← Complete web frontend
plugin/go/PRAXIS.md ← This file
cmd/rpc/web/explorer/dist/.gitkeep ← Required for Go build
cmd/rpc/web/wallet/out/.gitkeep ← Required for Go build
```

---

⪢ Canopy is in `Betanet` 🚀 ➝ learn more about the [road-to-mainnet](https://www.canopynetwork.org/learn-more/road-to-mainnet)
## Running Locally

## Protocol Documentation
### Prerequisites

➪ Check out the Canopy Network wiki: [https://canopy-network.gitbook.io/docs](https://canopy-network.gitbook.io/docs)
- Go 1.25+
- Git + Make
- `protoc` + `protoc-gen-go`

## Repository Documentation
### Step 1 — Clone and build Canopy

Welcome to the Canopy Network reference implementation. This repository can be well understood reading about the core modules:
```bash
git clone https://github.com/Makaveli912/canopy.git
cd canopy
git checkout feat/praxis-prediction-market

# Create required placeholder folders
mkdir -p cmd/rpc/web/explorer/dist
mkdir -p cmd/rpc/web/wallet/out
echo '<html></html>' > cmd/rpc/web/explorer/dist/index.html
echo '<html></html>' > cmd/rpc/web/wallet/out/index.html

# Build the canopy binary
go build -o ~/go/bin/canopy ./cmd/main
```

### Step 2 — Regenerate proto files

```bash
cd plugin/go/proto
chmod +x _generate.sh
./_generate.sh
```

### Step 3 — Build the plugin

```bash
cd plugin/go
GOTOOLCHAIN=local go mod tidy
GOTOOLCHAIN=local go build -o go-plugin .
```

### Step 4 — Configure

Start the node once to generate config files:

```bash
~/go/bin/canopy start
# Press Enter twice for no password and default nickname
# Then Ctrl+C after a few seconds
```

- [Controller](controller/README.md): Coordinates communication between all the major parts of the Canopy blockchain, like a central hub or "bus" that connects the system together.
- [Finite State Machine (FSM)](fsm/README.md): Defines the logic for how transactions change the blockchain's state — it decides what’s valid and how state transitions happen from one block to the next.
- [Byzantine Fault Tolerant (BFT) Consensus](bft/README.md): A consensus mechanism that allows the network to agree on new blocks even if some nodes are unreliable or malicious.
- [Peer-to-Peer Networking](p2p/README.md): A secure and encrypted communication system that lets nodes talk directly to each other without needing a central server.
- [Persistence](store/README.md): Manages the blockchain’s storage — it saves the current state (ledger), indexes past transactions, and ensures fast and reliable data verification.
Set the plugin in `~/.canopy/config.json`:

## How to Run It
```json
"plugin": "go"
```

➪ To run the Canopy binary, use the following commands:
### Step 5 — Start the chain

```bash
make build/canopy-full
canopy start
~/go/bin/canopy start
```

## How to Run It with 🐳 Docker
Watch for:

```
go-plugin started successfully
Plugin service listening on socket: /tmp/plugin/plugin.sock
```

Then watch for blocks:

```
Committed block xxxxx at H:1 🔒
```

### Step 6 — Open the frontend

In a separate terminal or background process:

➪ To run a Canopy `Localnet` in a *containerized* environment, use the following commands:
```bash
make docker/build
make docker/up-fast
make docker/logs
python3 -m http.server 8080 --directory plugin/go/frontend
```

Open your browser at:

```
http://localhost:8080
```

The green dot in the sidebar confirms the chain is connected.

or simply
---

## RPC Endpoints

| Port | Purpose |
|---|---|
| `50002` | Public RPC — submit transactions, query state, check height |
| `50003` | Admin RPC — keystore access, key management (localhost only) |

### Key endpoints used by the frontend

make docker/up && make docker/logs
```
POST /v1/query/height → current block height
POST /v1/query/account → account balance
POST /v1/tx → submit signed transaction
GET /v1/query/state?prefix= → scan state by prefix
POST /v1/admin/keystore-get → retrieve signing key (admin only)
```

---

## Running Tests
## Signing Transactions

Canopy uses **BLS12-381** signatures. Per the builder docs:

```
1. Build Transaction proto with signature = nil
2. signBytes = proto.Marshal(transaction)
3. sig = bls12381PrivKey.Sign(signBytes)
4. Attach signature: { publicKey: hexPubKey, signature: hexSig }
5. POST to /v1/tx — byte fields as base64 (protojson encoding)
```

➪ To run Canopy unit tests, use the Go testing tools:
Get your private key from the admin keystore:

```bash
make test
~/go/bin/canopy admin ks
~/go/bin/canopy admin keystore-get --address <your-address> --password ""
```

## How to Contribute
---

## Architecture

```
┌─────────────────────────────────────────┐
│ CANOPY NODE │
│ P2P │ NestBFT Consensus │ Persistence │
│ │ │
│ FSM Controller │
│ │ Unix socket │
└──────────────┼──────────────────────────┘
┌──────────▼──────────┐
│ PRAXIS PLUGIN │
│ │
│ CheckTx() │ ← stateless validation
│ DeliverTx() │ ← state transitions
│ BeginBlock() │ ← capture block height
│ EndBlock() │
└─────────────────────┘
│ HTTP (port 50002/50003)
┌──────────┴──────────┐
│ PRAXIS FRONTEND │
│ index.html │
│ │
│ - Create Markets │
│ - Place Bets │
│ - Resolve Markets │
│ - Claim Winnings │
│ - Leaderboard │
└─────────────────────┘
```

---

## Technical Notes

### Why a package-level height variable?

Canopy's `plugin.go` creates a **new Contract instance for every FSM message**. This means state set in `BeginBlock()` would be lost by the time `DeliverTx()` runs. We solve this with a package-level `globalHeight` variable protected by `sync.RWMutex`.

➪ Canopy is an open-source project, and we welcome contributions from the community. Here's how to get involved:
### Why `GOTOOLCHAIN=local`?

1. **Fork** the repository and clone it locally.
2. **Code** your improvements or fixes.
3. **Submit a Pull Request** (PR) for review.
The plugin's dependency `github.com/drand/kyber` requires Go 1.25. Setting `GOTOOLCHAIN=local` prevents Go from trying to auto-download a newer toolchain, which causes segfaults in constrained environments like Userland on Android.

➣ Please follow these [guidelines](CONTRIBUTING.md) to maintain high-quality contributions:
### State key design

### High Impact or Architectural Changes
All state keys use `JoinLenPrefix` with unique byte prefixes to avoid collisions with built-in keys (`0x01` accounts, `0x02` pools, `0x07` fee params). Our custom types start at `0x10`.

➪ Before making large changes, discuss them with the Canopy team on [Discord](https://discord.gg/pNcSJj7Wdh) to ensure alignment.
---

### Coding Style
## About

- Code must adhere to official Go formatting (use [`gofmt`](https://golang.org/cmd/gofmt)).
- (Optional) Use [EditorConfig](https://editorconfig.org) for consistent formatting.
- All code should follow Go documentation/commentary guidelines.
- PRs should be opened against the `development` branch.
Built by **Makaveli912** for the Canopy Vibe Coding Contest 2026.

[![Pre-Release](https://img.shields.io/github/release-pre/canopy-network/canopy.svg)](https://github.com/canopy-network/canopy/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/canopy-network/canopy)](https://goreportcard.com/report/github.com/canopy-network/canopy)
[![Contributors](https://img.shields.io/github/contributors/canopy-network/canopy.svg)](https://github.com/canopy-network/canopy/pulse)
[![Last Commit](https://img.shields.io/github/last-commit/canopy-network/canopy.svg)](https://github.com/canopy-network/canopy/pulse)
| | |
|---|---|
| **PR** | https://github.com/canopy-network/canopy/pull/375 |
| **Branch** | `feat/praxis-prediction-market` |
| **Chain** | Canopy Betanet |

## Contact
---

[![Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://x.com/CNPYNetwork)
[![Discord](https://img.shields.io/badge/discord-online-blue.svg)](https://discord.gg/pNcSJj7Wdh)
> *"Praxis — where prediction meets sovereignty."*
1 change: 1 addition & 0 deletions cmd/rpc/web/explorer/dist/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions cmd/rpc/web/wallet/out/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading