DChain single-node blockchain + React Native messenger client. Core: - PBFT consensus with multi-sig validator admission + equivocation slashing - BadgerDB + schema migration scaffold (CurrentSchemaVersion=0) - libp2p gossipsub (tx/v1, blocks/v1, relay/v1, version/v1) - Native Go contracts (username_registry) alongside WASM (wazero) - WebSocket gateway with topic-based fanout + Ed25519-nonce auth - Relay mailbox with NaCl envelope encryption (X25519 + Ed25519) - Prometheus /metrics, per-IP rate limit, body-size cap Deployment: - Single-node compose (deploy/single/) with Caddy TLS + optional Prometheus - 3-node dev compose (docker-compose.yml) with mocked internet topology - 3-validator prod compose (deploy/prod/) for federation - Auto-update from Gitea via /api/update-check + systemd timer - Build-time version injection (ldflags → node --version) - UI / Swagger toggle flags (DCHAIN_DISABLE_UI, DCHAIN_DISABLE_SWAGGER) Client (client-app/): - Expo / React Native / NativeWind - E2E NaCl encryption, typing indicator, contact requests - Auto-discovery of canonical contracts, chain_id aware, WS reconnect on node switch Documentation: - README.md, CHANGELOG.md, CONTEXT.md - deploy/single/README.md with 6 operator scenarios - deploy/UPDATE_STRATEGY.md with 4-layer forward-compat design - docs/contracts/*.md per contract
83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
/**
|
|
* Create Account screen.
|
|
* Generates a new Ed25519 + X25519 keypair and saves it securely.
|
|
*/
|
|
|
|
import React, { useState } from 'react';
|
|
import { View, Text, ScrollView, Alert } from 'react-native';
|
|
import { router } from 'expo-router';
|
|
import { generateKeyFile } from '@/lib/crypto';
|
|
import { saveKeyFile } from '@/lib/storage';
|
|
import { useStore } from '@/lib/store';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { Input } from '@/components/ui/Input';
|
|
import { Card } from '@/components/ui/Card';
|
|
|
|
export default function CreateAccountScreen() {
|
|
const setKeyFile = useStore(s => s.setKeyFile);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
async function handleCreate() {
|
|
setLoading(true);
|
|
try {
|
|
const kf = generateKeyFile();
|
|
await saveKeyFile(kf);
|
|
setKeyFile(kf);
|
|
router.replace('/(auth)/created');
|
|
} catch (e: any) {
|
|
Alert.alert('Error', e.message);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<ScrollView
|
|
className="flex-1 bg-background"
|
|
contentContainerClassName="px-6 pt-16 pb-10"
|
|
>
|
|
{/* Header */}
|
|
<Button variant="ghost" size="sm" onPress={() => router.back()} className="self-start mb-6 -ml-2">
|
|
← Back
|
|
</Button>
|
|
|
|
<Text className="text-white text-3xl font-bold mb-2">Create Account</Text>
|
|
<Text className="text-muted text-base mb-8 leading-6">
|
|
A new identity will be generated on your device.
|
|
Your private key never leaves this app.
|
|
</Text>
|
|
|
|
{/* Info cards */}
|
|
<Card className="mb-4 gap-3">
|
|
<InfoRow icon="🔑" label="Ed25519 signing key" desc="Your blockchain address and tx signing key" />
|
|
<InfoRow icon="🔒" label="X25519 encryption key" desc="End-to-end encryption for messages" />
|
|
<InfoRow icon="📱" label="Stored on device" desc="Keys are encrypted in the device secure store" />
|
|
</Card>
|
|
|
|
<Card className="mb-8 border-primary/30 bg-primary/10">
|
|
<Text className="text-accent text-sm font-semibold mb-1">⚠ Important</Text>
|
|
<Text className="text-muted text-sm leading-5">
|
|
After creation, export and backup your key file.
|
|
If you lose it there is no recovery — the blockchain has no password reset.
|
|
</Text>
|
|
</Card>
|
|
|
|
<Button onPress={handleCreate} loading={loading} size="lg">
|
|
Generate Keys & Create Account
|
|
</Button>
|
|
</ScrollView>
|
|
);
|
|
}
|
|
|
|
function InfoRow({ icon, label, desc }: { icon: string; label: string; desc: string }) {
|
|
return (
|
|
<View className="flex-row items-start gap-3">
|
|
<Text className="text-xl">{icon}</Text>
|
|
<View className="flex-1">
|
|
<Text className="text-white text-sm font-semibold">{label}</Text>
|
|
<Text className="text-muted text-xs mt-0.5">{desc}</Text>
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|