Files
dchain/client-app
vsecoder 3e9ddc1a43 chore(client): remove dev-seed for chats + feed
Two dev-only seed modules removed now that the app talks to a real
backend:

- lib/devSeed.ts — fake 15+ contacts with mock chat histories,
  mounted via useDevSeed() in (app)/_layout.tsx on empty store.
  Was useful during client-first development; now it fights real
  contact sync and confuses operators bringing up fresh nodes
  ("why do I see NBA scores and a dchain_updates channel in my
  chat list?").

- lib/devSeedFeed.ts — 12 synthetic feed posts surfaced when the
  real API returned empty. Same reasoning: operator imports genesis
  key on a fresh node, opens Feed, sees 12 mock posts that aren't on
  their chain. "Test data" that looks real is worse than an honest
  empty state.

Feed screen now shows its proper empty state ("Пока нет
рекомендаций", etc.) when the API returns zero items OR on network
error. Chat screen starts empty until real contacts + messages
arrive via WS / storage cache.

Also cleaned a stale comment in chats/[id].tsx that referenced
devSeed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 23:07:42 +03:00
..

DChain Messenger — React Native Client

E2E-encrypted mobile/desktop messenger built on the DChain blockchain stack.

Stack: React Native · Expo · NativeWind (Tailwind) · TweetNaCl · Zustand

Quick Start

cd client-app
npm install
npx expo start          # opens Expo Dev Tools
# Press 'i' for iOS simulator, 'a' for Android, 'w' for web

Requirements

  • Node.js 18+
  • Expo Go on your phone (for Expo tunnel), or iOS/Android emulator
  • A running DChain node (see root README for docker compose up --build -d)

Project Structure

client-app/
├── app/
│   ├── _layout.tsx           # Root layout — loads keys, sets up nav
│   ├── index.tsx             # Welcome / onboarding
│   ├── (auth)/
│   │   ├── create.tsx        # Generate new Ed25519 + X25519 keys
│   │   ├── created.tsx       # Key created — export reminder
│   │   └── import.tsx        # Import existing key.json
│   └── (app)/
│       ├── _layout.tsx       # Tab bar — Chats · Wallet · Settings
│       ├── chats/
│       │   ├── index.tsx     # Chat list with contacts
│       │   └── [id].tsx      # Individual chat with E2E encryption
│       ├── requests.tsx      # Incoming contact requests
│       ├── new-contact.tsx   # Add contact by @username or address
│       ├── wallet.tsx        # Balance + TX history + send
│       └── settings.tsx      # Node URL, key export, profile
├── components/ui/            # shadcn-style components (Button, Card, Input…)
├── hooks/
│   ├── useMessages.ts        # Poll relay inbox, decrypt messages
│   ├── useBalance.ts         # Poll token balance
│   └── useContacts.ts        # Load contacts + poll contact requests
└── lib/
    ├── api.ts                # REST client for all DChain endpoints
    ├── crypto.ts             # NaCl box encrypt/decrypt, Ed25519 sign
    ├── storage.ts            # SecureStore (keys) + AsyncStorage (data)
    ├── store.ts              # Zustand global state
    ├── types.ts              # TypeScript interfaces
    └── utils.ts              # cn(), formatAmount(), relativeTime()

Cryptography

Operation Algorithm Library
Transaction signing Ed25519 TweetNaCl sign
Key exchange X25519 (Curve25519) TweetNaCl box
Message encryption NaCl box (XSalsa20-Poly1305) TweetNaCl box
Key storage Device secure enclave expo-secure-store

Messages are encrypted as:

Envelope {
  sender_pub:    <X25519 hex>   // sender's public key
  recipient_pub: <X25519 hex>   // recipient's public key
  nonce:         <24-byte hex>  // random per message
  ciphertext:    <hex>          // NaCl box(plaintext, nonce, sender_priv, recipient_pub)
}

Connect to your node

  1. Start the DChain node: docker compose up --build -d
  2. Open the app → Settings → Node URL → http://YOUR_IP:8081
  3. If using Expo Go on physical device: your PC and phone must be on the same network, or use npx expo start --tunnel

Key File Format

The key.json exported/imported by the app:

{
  "pub_key":     "26018d40...",   // Ed25519 public key (64 hex chars)
  "priv_key":    "...",           // Ed25519 private key (128 hex chars)
  "x25519_pub":  "...",           // X25519 public key (64 hex chars)
  "x25519_priv": "..."            // X25519 private key (64 hex chars)
}

This is the same format as the Go node's --key flag.