Opinionated React Native crypto x AI chat app boilerplate with embedded wallet support, conversational AI, and dynamic UI component injection.
mallory/
├── apps/
│ ├── client/ # React Native app (iOS, Android, Web)
│ └── server/ # Backend API (Node.js + Express)
├── packages/
│ └── shared/ # Shared types and utilities
└── package.json # Workspace configuration
git clone https://github.com/darkresearch/mallory.git
cd mallory
bun install
.env in apps/client/)# Copy from template
cp apps/client/.env.example apps/client/.env
# Required variables:
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
EXPO_PUBLIC_BACKEND_API_URL=http://localhost:3001
EXPO_PUBLIC_GRID_API_KEY=your-grid-api-key
EXPO_PUBLIC_GRID_ENV=sandbox
.env in apps/server/)# Copy from template
cp apps/server/.env.example apps/server/.env
# Required variables:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
ANTHROPIC_API_KEY=sk-ant-your-key
BIRDEYE_API_KEY=your-birdeye-key
GRID_API_KEY=your-grid-api-key
# Optional (for AI tools):
EXA_API_KEY=your-exa-key
# Infinite Memory (OpenMemory for infinite context):
OPENMEMORY_URL=http://localhost:8080
OPENMEMORY_API_KEY=your-openmemory-key
bun run dev
# Terminal 1 - Backend
bun run server
# Terminal 2 - Client (Web)
bun run client
The client will be available at: - Web: http://localhost:8081 - API: http://localhost:3001
See apps/client/README.md for detailed client documentation.
Key Commands:
cd apps/client
# Web
bun run web
# iOS (requires Mac + Xcode)
bun run ios
# Android (requires Android Studio)
bun run android
See apps/server/README.md for detailed server documentation.
API Endpoints:
- POST /api/chat - AI chat streaming with tool calling
- GET /api/wallet/holdings - Wallet holdings with price data
- GET /health - Health check
AI Tools:
- searchWeb - Web search via Exa (always available)
- addMemory - User memory via Supermemory (optional)
- nansen* - 20+ Nansen API endpoints for blockchain analytics (requires x402 payments)
Mallory uses Grid for embedded wallets:
Grid's architecture means neither the client nor server ever has access to user private keys, making it truly non-custodial while still providing seamless transaction signing.
The packages/shared directory contains TypeScript types and utilities shared between client and server:
import type { ChatRequest, HoldingsResponse } from '@darkresearch/mallory-shared';
import { X402PaymentService } from '@darkresearch/mallory-shared';
Mallory has comprehensive test coverage: unit tests, integration tests, and E2E tests.
Run tests:
cd apps/client
# Fast tests (unit + integration)
bun test
# E2E tests (requires backend running)
bun run test:e2e
# AI-powered tests (optional - expensive)
# These use Claude to verify response completeness and test 200k+ token conversations
bun test __tests__/e2e/chat-message-flow.test.ts # ~5-10 min, ~$1-2
bun test __tests__/e2e/long-context.test.ts # ~10-20 min, ~$2-3
CI/CD:
- Regular tests run on every PR
- AI tests only run when [run-ai-tests] is in commit message:
bash
git commit -m "fix: improve streaming [run-ai-tests]"
See apps/client/tests/CHAT_STATE_TESTS.md for full testing documentation.
See apps/client/README.md for details.
See apps/server/README.md for details.
The 400 response means Supabase doesn’t know about the Google provider yet. Here’s the full fix, covering both the browser login flow and the native Expo app.
https://<project-ref>.supabase.co/auth/v1/callback). You’ll paste that into Google Cloud Console in a moment.https://<project-ref>.supabase.co/auth/v1/callbackhttp://localhost:8081) if you’re running the web client.What about
exp://…?
That kind of URI applies when you’re using Expo’s WebView-based AuthSession. Mallory’s native flow uses@react-native-google-signin/google-signin, which talks directly to Google Play Services and does not need (or accept) anexp://URI. So you can skip adding exp:// schemes here.
Still on the Google provider page in Supabase: - Paste the Client ID and Client secret you just copied. - Click Save. Supabase now accepts Google logins.
Whether you’re running the browser app or the Expo-native build, you need the same Google client ID available at runtime.
- Edit apps/client/.env (or wherever you manage env vars) and set:
ini
EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID=<the web client ID from Google>
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=<optional iOS client ID if you generated one>
Mallory’s native layer uses the “Web application” client for Android; for iOS you can optionally create an iOS-specific client and set it here.
- If you’re running the web client, also ensure the same ID is present; the config.ts module pulls from these EXPO_PUBLIC_* variables.
- Restart Expo / Metro (and rebuild Android/iOS if needed) so the new env values take effect.
bun run android or bun run ios), trigger Continue with Google. The native Google Sign-In dialog should appear. After you grant access, Supabase will issue the session tokens and Mallory should log you in.http://localhost:8081). Add it under “Authorized JavaScript origins” if you need to load Google scripts directly (not strictly required for Supabase-based OAuth, but harmless).exp:// redirect URI is required for the Google Sign-In library Mallory uses. Just ensure the web client ID is configured and Supabase has the provider enabled.
Once those steps are done, the “Unsupported provider: provider is not enabled” error disappears for both web and native runs.Mallory uses synchronized semantic versioning across all packages.
Include [release: v*.*.*] in your PR title:
feat: add new wallet feature [release: v0.2.0]
When merged to main, the version automatically bumps and a GitHub release is created! 🚀
bun scripts/sync-version.js 0.2.0
git add . && git commit -m "chore: bump version to 0.2.0"
git tag v0.2.0 && git push && git push --tags
See VERSION.md for details.
Contributions welcome! Please read CONTRIBUTING.md first.
Apache License 2.0 - see LICENSE for details.
Built with: - Expo - React Native framework - Grid (Squads) - Embedded wallets - Anthropic - Claude AI with extended thinking - Exa - AI-powered web search - Supermemory - User memory & RAG - Supabase - Auth & database - Birdeye - Solana market data - Nansen - Blockchain analytics (via x402) - Faremeter - x402 payment protocol - streamdown-rn - React Native markdown streaming
Made with ❤️ by Dark
$ claude mcp add mallory \
-- python -m otcore.mcp_server <graph>