Skip to content

Latest commit

 

History

166 Commits

Folders and files

Repository files navigation

GenLayer Spinner

DGDreams — Web3 Space Terminal

Multi-chain daily task dashboard with 20 networks • GenLayer AI contracts • NFT soulbound streaks

🌐 Live Site · Features · Architecture · Networks

Next.js 16 TypeScript Wagmi RainbowKit GenLayer Bradbury Vercel


Overview

DGDreams is a unified dashboard where users connect their wallet once and execute daily on-chain tasks across 20 blockchain networks — Ethereum, Base, Arbitrum One, OP Mainnet, HyperEVM, Unichain, Tempo, Robinhood, Ink, Arc, BNB Chain and opBNB on mainnet, plus testnets including Arbitrum Sepolia, GenLayer Bradbury, LitVM, GIWA, ARC, and SimpleChain.

Feature Description
🔁 One wallet, many chains Connect with RainbowKit, switch networks seamlessly
✅ 3 daily tasks per network Check-in, GM, GN — a new day starts at 00:00 UTC
🚀 5-in-1 runner GM + GN plus three deploys in one click, ~69% less gas than the full-featured contracts
GenLayer AI contracts Python-based Intelligent Contract using genlayer-js SDK
🏆 Soulbound NFT streaks Mint tiered NFTs (Bronze → Legend) for 7+ day streaks
📊 Wallet-owned streaks Read from the chain, keyed to your address — never self-reported

Features

✨ Multi-Chain Task Execution

Users can run the same 3 daily tasks on any supported network:

  1. Daily Check-In — Start the day, build your streak
  2. GM — Morning greeting
  3. GN — Night sign-off

Each task writes to an on-chain contract that tracks streaks, action counts, and daily resets.

The day rolls over at 00:00 UTC — the same boundary for every user in every timezone, because the contract buckets days as block.timestamp / 1 days. The app mirrors that boundary exactly, so an open tab clears its "already done today" state at the same instant the contract does.

🚀 5-in-1 Runner

One button runs the two missions plus three deploys back to back:

  1. GM and GN on NikBase
  2. DGDemo — a greeter
  3. DGLiteToken — a minimal ERC-20
  4. DGLiteNft — a minimal ERC-721

These are size-optimised editions from contracts/OneClick.sol. Deployment gas is charged at 200 gas per byte of runtime code plus calldata, so every function nobody calls is still paid for on every deployment. Stripping the one-click contracts down to only what the flow exercises cuts the cost from ~2.78M to ~0.87M gas:

node scripts/measure-deploy-cost.mjs   # prints the per-contract bill

The card picks its own network, independent of the mission page, and reuses addresses it has already deployed on that network, so a second run costs almost nothing.

GenLayer Integration

GenLayer is a non-EVM chain using Python-based Intelligent Contracts with AI-validator consensus. This project integrates GenLayer as a first-class network:

  • Contract: NikBase — Python Intelligent Contract storing all user data as JSON in a single str state field
  • Client: genlayer-js SDK with MetaMask provider (window.ethereum)
  • Read/Write: Separate code paths via isGenLayer() check — wagmi for EVM chains, genlayer-js for GenLayer
  • Address: 0x1203ab4E8386220F792f129C605460fD0F52C412

🏆 Soulbound NFT Streaks

Networks with a soulbound NFT contract support minting and upgrading:

  • 7-day streak → Mint Bronze NFT
  • Streak milestones → Upgrade through Silver, Gold, Diamond, Legend tiers
  • NFTs are soulbound (non-transferable) and track your longest streak

Architecture

src/
├── app/
│   ├── dashboard/       # Network grid overview
│   ├── tasks/           # Daily task execution page
│   ├── 2048/            # Binary milestone game
│   ├── deploy/          # Deploy the app's own contracts
│   ├── faq/             # Help & documentation
│   └── api/             # Backend API routes
├── components/
│   ├── DailyTaskPanel   # Task execution modal (wagmi + genlayer-js)
│   ├── FiveInOne        # 5-in-1 runner (missions + three deploys)
│   ├── DailyMissionDeck # Mission cards with UTC-day state
│   ├── Sidebar          # Navigation sidebar
│   ├── DashboardLayout  # Shared layout wrapper
│   └── ...
├── config/
│   └── chains.ts        # All 20 chain definitions & NetworkConfig
├── lib/
│   ├── utcDay.ts        # 00:00 UTC boundary shared by the whole app
│   ├── sequence.ts      # Multi-step runner used by the 5-in-1 card
│   ├── genlayer/
│   │   ├── client.ts    # genlayer-js client factory
│   │   └── tasks.ts     # Write/read helpers for GenLayer
│   └── utils.ts         # Shared utilities
└── db/
    ├── schema.ts        # Drizzle ORM schema
    └── index.ts         # Database client

genlayer-contracts/
└── nikbase_genlayer.py  # Python Intelligent Contract for GenLayer

Data Flow

User connects wallet → RainbowKit → wagmi (EVM chains)
                                    └── genlayer-js (GenLayer)
                                           ↓
User selects network → switchChainAsync (wagmi)
                    └── manual wallet switch (GenLayer)
                           ↓
User clicks "Start" → DailyTaskPanel opens
                         ↓
              ┌──── isGenLayer(chainId)? ────┐
              ↓                               ↓
       genLayerWriteTask()           writeContractAsync()
       (genlayer-js SDK)            (wagmi viem)
              ↓                               ↓
       waitForTxReceipt              waitForTransactionReceipt
              ↓                               ↓
         Confirm task              Handle revert / success

Networks

Mainnet

Network Chain ID Currency
Ethereum 1 ETH
Base 8453 ETH
HyperEVM 999 HYPE
Unichain 130 ETH
Tempo 4217 USD
Robinhood 4663 ETH
Ink 57073 ETH
Arc 5042 USDC
BNB Chain 56 BNB
opBNB 204 BNB
Arbitrum One 42161 ETH
OP Mainnet 10 ETH

Testnet

Network Chain ID Currency
Sepolia 11155111 ETH
Base Sepolia 84532 ETH
GIWA Sepolia 91342 ETH
LitVM Liteforge 4441 zkLTC
GenLayer Bradbury 4221 GEN
ARC Testnet 5042002 ARC
SimpleChain 1913 SIM
Arbitrum Sepolia 421614 ETH

💡 Arbitrum and OP are the cheapest networks here — a full 5-in-1 run costs well under a cent, so they are the best place to start.


Deploying the Contracts

forge build

# preview: prints the per-contract gas bill, sends nothing
npm run deploy:l2:dry

# deploy NikBase + Game2048 + SoulboundStreak to Arbitrum One, OP Mainnet
# and Arbitrum Sepolia, then wire the addresses into the app config
npm run deploy:l2

Then verify on the explorers:

npm run verify:l2        # needs ARBITRUM_API_KEY / OPTIMISM_API_KEY

Both scripts read their target addresses back out of the app config, so a command can never be pointed at the wrong address. Add --only <chainId> to restrict to one network.


Getting Started

# Clone the repository
git clone https://github.com/Misagh95/dgdreams.git
cd dgdreams

# Install dependencies
npm install

# Set up environment variables
cp .env.example .env.local
# Add your WalletConnect Project ID to .env.local:
# NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id
# SESSION_SECRET=<openssl rand -hex 32>
# DEPLOYER_PRIVATE_KEY=0x...        (only needed to deploy contracts)

# Run development server
npm run dev

Prerequisites

  • Node.js >= 18
  • WalletConnect Project ID — get one at cloud.walletconnect.com
  • MetaMask browser extension (for EVM chains + GenLayer via genlayer-js)
  • SESSION_SECRET — signs the wallet-login tokens used to record streaks. Generate one with node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" and set it in .env.local and in your deployment platform's environment. Without it the site still builds, but signing in and streak recording are disabled.

GenLayer Contracts

Intelligent Contracts written in Python and deployed on GenLayer Bradbury testnet. All contracts use real UTC time fetched via gl.nondet.web.render("https://worldtimeapi.org/api/timezone/Etc/UTC") with gl.eq_principle.strict_eq consensus.

NikBase — Daily Check-In & Activity Tracker

genlayer-contracts/nikbase_genlayer.py

# { "Depends": "py-genlayer:1jb45aa8ynh2a9c9xn3b7qqh8sm5q93hwfp7jqmwsfhh8jpz09h6" }
from genlayer import *
import json

class NikBase(gl.Contract):
    store: str

    def _now(self) -> int:
        def fetch_time() -> str:
            raw = gl.nondet.web.render("https://worldtimeapi.org/api/timezone/Etc/UTC", mode="text")
            ...
        return int(gl.eq_principle.strict_eq(fetch_time))

    def _today(self) -> int:
        return self._now() // 86400

    @gl.public.write
    def dailyCheckIn(self) -> str: ...
    @gl.public.write
    def gm(self) -> None: ...
    @gl.public.write
    def gn(self) -> None: ...

Tracks daily on-chain actions (gm, gn, checkIn, dose, mood, sanitize, counter, spin) using real UTC time. Each action type can only be performed once per UTC day — enforced by comparing _today() against the stored lastActionDay per user.

AI Price Oracle

genlayer-contracts/price_oracle.py

Fetches live cryptocurrency prices from the Binance API using GenLayer's AI-validator consensus — 5 independent validators fetch the data and agree on the result via gl.eq_principle.prompt_comparative with 1% tolerance before it's written on-chain.

class PriceOracle(gl.Contract):
    store: str

    @gl.public.view
    def getPrice(self, symbol: str) -> str: ...

    @gl.public.view
    def isFresh(self, symbol: str, max_age_seconds: int) -> str:
        # Returns {"fresh": bool, "age": int, "max_age": int}

    @gl.public.write
    def fetchPrice(self, symbol: str) -> typing.Any:
        def fetch() -> str:
            raw = gl.nondet.web.render(
                f"https://api.binance.com/api/v3/ticker/24hr?symbol={symbol}USDT",
                mode="text"
            )
        result = gl.eq_principle.prompt_comparative(
            fetch,
            "Two prices are equivalent if they are for the same symbol and the price values differ by less than 1%."
        )
        parsed = json.loads(str(result))
        parsed["updated_at"] = self._now()           # freshness timestamp
        data[symbol] = parsed
        self.store = json.dumps(data, sort_keys=True)

Flow:

  1. User clicks "Fetch BTC/USDT" on the frontend
  2. Contract calls gl.nondet.web.render() — each validator independently fetches Binance
  3. gl.eq_principle.prompt_comparative() ensures validators agree within 1% tolerance
  4. Agreed price + updated_at timestamp is stored on-chain
  5. isFresh(symbol, max_age_seconds) view method checks whether stored data is still fresh

Page: /genlayer-oracle — switch to GenLayer, select a symbol, and fetch

Prediction Market

genlayer-contracts/prediction_market.py

A decentralized prediction market contract supporting conditional outcome resolution via direct web fetching or via the PriceOracle contract.

class PredictionMarket(gl.Contract):
    store: str

    @gl.public.write
    def createMarket(self, question: str, source_url: str, target_value: str, condition: str, resolves_at: int) -> int: ...

    @gl.public.write
    def predict(self, market_id: int, outcome: int, amount: int) -> str: ...

    @gl.public.write
    def resolveMarket(self, market_id: int, oracle_addr: str = "") -> str:
        # Direct resolution: validators fetch source_url and reach strict_eq consensus on outcome
        # Optionally accepts oracle_addr for audit trail

    @gl.public.write
    def resolveWithOracle(self, market_id: int, oracle_addr: str, symbol: str, max_age: int) -> str:
        # Oracle-mediated resolution:
        #   1. Checks oracle.isFresh(symbol, max_age) — rejects if stale
        #   2. Calls oracle.getPrice(symbol) for the current price
        #   3. Resolves market by comparing price against target_value/condition
        #   4. Stores oracle price + freshness info for audit trail

Two resolution modes:

  • resolveMarket — validators directly fetch the market's source_url and reach consensus via strict_eq. The optional oracle_addr parameter stores a reference for audit purposes.
  • resolveWithOracle — resolves via a PriceOracle contract. First checks freshness via isFresh(symbol, max_age), then fetches the price and resolves the market. Rejects stale data with an error message.

GenLayer uses Python (not Solidity) and a non-EVM runtime. Contract interactions go through genlayer-js, not wagmi/viem.

Tech Stack

Layer Technology
Framework Next.js 16 (App Router, Turbopack)
Language TypeScript
Wallet RainbowKit + Wagmi 2.x + Viem
GenLayer SDK genlayer-js
Database PostgreSQL + Drizzle ORM
Styling CSS Variables + Tailwind-like utility classes
Deployment Vercel
Contracts (EVM) Solidity (Hardhat)
Contracts (GenLayer) Python (GenLayer Studio)

License

This project is licensed under the MIT License.


About

Multi-chain Web3 task hub for daily on-chain actions across 20 EVM networks

Topics

Resources

Contributing

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages