town is an ios app that lets you post comments to the ethereum comments protocol. join the testflight https://t.me/+xs2OaEu_928yZTI0
A SwiftUI iOS app and Bun + Hono backend for the Ethereum Comments Protocol (ECP).
- The iOS app lets you browse posts, compose replies, and receive push notifications for replies and reactions.
- The backend provides SIWE auth, device registration, notification fanout via APNs, an on-chain listener, and background workers.
ecp-client/— iOS app (SwiftUI)ecp-client.xcodeproj— Xcode projectecp-client/— app source- Key files:
ecp_clientApp.swift— app entry; bootstraps auth, notifications, deep linksContentView.swift— main feed, compose FAB, settings & notifications sheetsComposeCommentView.swift— compose/reply UI, identity/approval checks, balance guardNotificationsView.swift— in-app notification center with grouping and deep linksAuthService.swift— SIWE auth using app key; JWT stored in KeychainNotificationService.swift— permission flow, APNs registration, event history, unread badgeDeepLinkService.swift— app routes and handling notification payloads & custom URLsCommentsService.swift— fetch main feed, pagination, pull-to-refreshCommentManager.swift— ECP contract structures and helpers (posting, approvals, gas est.)WalletConfigurationService.swift— CoinbaseWalletSDK host/callback configurationAppConfiguration.swift— readsAPI_BASE_URLfromInfo.plistor env
api/— Bun + Hono backend- Hono HTTP server, Prisma/Postgres, BullMQ (Redis), APNs, on-chain listener
- See
api/README.mdfor detailed setup and API reference
- Feed and details
- Infinite scroll, pull-to-refresh, skeleton loading
- Comment rows with reactions and reply counts
- Detail sheets via deep link routing
- Compose & reply
- Identity/approval checks with clear guidance when not configured
- Reply context preview; character count and validation
- Balance warning + quick link to settings
- Notifications
- Foreground alert handling and unread badge
- In-app notification center: server-side history with pagination
- Reaction aggregation (e.g., “Alice and 3 others liked your post”), avatar rows
- Taps deep link to the relevant post or parent thread
- Authentication
- SIWE: request nonce, sign message locally, verify, and store JWT in Keychain
- Auto re-auth on 401; token validation on launch
- Push registration
- Permission prompts, Settings fallback, register/unregister current device
- Server status check (
/api/notifications/status) and test send
- Deep linking
- Custom scheme:
ecp-client://comment/<id> - Notification payload keys supported:
type(reply|reaction|mention|...),commentId,parentId
- Custom scheme:
- Wallet config
- Configures
CoinbaseWalletSDKhost and callback URL; app restart if wallet host changes
- Configures
- Auth (SIWE)
- Issue nonce, verify signature, set JWT cookie (
auth),/api/auth/me - JWT also accepted via
Authorization: Bearer <token>
- Issue nonce, verify signature, set JWT cookie (
- Notifications service
- Register/remove device tokens; list and status endpoints
- Send test notification; persist notification events for in-app feed
- APNs via token-based auth; invalid token cleanup
- Background processing
commentsworker: reacts to on-chain comments, notifies parent on reply/reaction, mentionsnotificationsworker: fans out to approved app accounts with registered devices- On-chain listener watches
CommentManageron Base and enqueues jobs
- Data model (Prisma)
User(id = app address),NotificationDetails(device tokens),Approval(author→app approvals)
- Open
ecp-client.xcodeprojin Xcode (iOS 16+ recommended). - Set API base URL:
- Add
API_BASE_URLtoInfo.plist(e.g.,http://localhost:3000).
- Add
- Build and run on a real device for push notifications.
- First launch:
- The app attempts SIWE auth using your stored app private key (see Settings/Keychain utilities in the app code).
- You may be prompted to enable notifications; device token is registered with the backend.
Notes:
- Push notifications require the backend running with valid APNs credentials.
- For local device testing, ensure your phone can reach your machine (use LAN IP or a tunnel for
API_BASE_URL).
See api/README.md for full details. Minimal steps:
cd api
bun install
# Optionally start Postgres and Redis
docker compose up -d
# Apply DB migrations
bunx prisma migrate deploy
# Run the server
bun run dev
# (opt) workers & listener in separate terminals
bun run workers
BASE_RPC_URL="https://base-mainnet.g.alchemy.com/v2/KEY" bun run listenerEnvironment variables (selection; see api/README.md):
DATABASE_URL,REDIS_URL,REDIS_QUEUE_URL,JWT_SECRETAPNS_KEYorAPNS_KEY_PATH,APNS_KEY_ID,APNS_TEAM_ID,APNS_BUNDLE_IDNODE_ENV,BASE_RPC_URL
AppConfiguration.swiftreadsAPI_BASE_URLfromInfo.plistor process env and normalizes it.ecp_clientApp.swiftwiresAuthService,NotificationService,DeepLinkService, and promotes deep links from notifications.- Foreground notifications are shown as banner/list/sound via
UNUserNotificationCenterDelegate.
- iOS: SwiftUI,
@StateObjectservice pattern, modular views, skeletons, and haptics. - API: Hono routes under
api/src/routes, Prisma client atapi/src/generated/prisma, workers underapi/src/workers.
MIT