Handoff
This page is the punch list a fresh contributor (human or agent) should read before starting work. The mobile repo also has mobile/HANDOFF.md checked in; this doc is the canonical web-readable version.
Priority 1 — finish the mobile MVP
-
Real passkey wallet creation on device. Today's Simulator fallback creates a plain
G…Stellar account, which can't call our Router contract. To get the production path working:- Apple Developer Program enrolment for the team.
- Host
apple-app-site-associationonpesalo.fun/.well-known/. - Host the Android
assetlinks.jsonequivalent. - Real-device testing via
eas build -p ios --profile developmentthen install via Orbit. - Once passkey lands, drop the dev-keypair fallback for production builds.
-
Boost / Unboost on dev keypair. Either:
- Build a "Stellar Account Boost" Router variant that accepts plain Ed25519 auth, or
- Decide that boost is passkey-only and explicitly disable the CTA for dev accounts (currently it lights up but the call will fail).
-
Bring the indexer back online. The Railway-hosted backend is offline. Options laid out in Backend / Deployment. Until it's back, the mobile app's Rates / Prices / Positions endpoints return empty.
-
Real USD prices. The
/v1/pricesendpoint depends on whatever oracle the backend wires up. Confirm it pulls from a real source (CoinGecko, Reflector). The mobile UI silently zeros balances when prices are missing. -
Activity surfacing for Boost / Auto-Earn events. Currently
lib/stellar/horizonActivity.tsonly parsespayment,create_account,path_payment_*. Soroban contract events (which are how boost/redeem land on chain) flow throughinvoke_host_functionrecords that the current parser ignores. Add a case for them. -
Maturity flow polish.
app/savings/maturity/[id].tsxexists but needs to be wired to the Router'sredeem_boostmethod. The "Unboost early" CTA from the position detail screen needs to callunboost. -
Error UX polish. Raw error strings currently render in red inline text. Replace with a friendly toast / snackbar + retry button. Specific common errors (insufficient funds, no trustline, expired session) deserve dedicated copy.
Priority 2 — production hardening
-
Move
EXPO_PUBLIC_CHANNELS_API_KEYoff the client. It currently ships in every dev build. For production, proxy through the backend so the key never lands on user devices. -
Sentry / observability.
lib/observability/sentry.tsalready initialises Sentry; the DSN is empty (EXPO_PUBLIC_SENTRY_DSN=). Provision a project + wire it. -
OTA updates.
eas.jsonreferences channels butexpo-updatesisn't installed. Runnpx expo install expo-updates && eas update:configureso JS-only patches don't need a full rebuild. -
Mainnet readiness. Switch:
- OZ Channels endpoint → mainnet.
Networks.TESTNET→Networks.PUBLIC.- Horizon + Soroban RPC URLs → mainnet.
- Re-deploy all five contracts on mainnet, repoint env vars.
Assets to source
- App icon (1024×1024 PNG at
mobile/assets/icon.png). - Adaptive icon foreground (1024×1024 PNG at
mobile/assets/adaptive-icon.png). - Splash screen (1284×2778 on dark
#080B11). - Brand Sprout PNG export (for share cards + store listings).
- High-fidelity token icons if we want to swap the in-app SVGs for Circle / Stellar's official PNGs.
- Empty-state illustrations for Discover and Activity (optional).
Things to remember about this codebase
See Mobile / Quirks for the full list. The big ones:
bufferpolyfill returns plainUint8Arrays, soTransaction.toXDR()doesn't return a base64 string in RN. Use the explicitbytesToBase64()helper.- Five copies of
@stellar/stellar-basein node_modules. Don't round-trip Transactions through XDR strings across module boundaries. @openzeppelin/relayer-plugin-channelsis shimmed to only expose its client subpath. The plugin half crashes at module-load on RN.- Stellar SDK v14 has a packaging bug that Metro intercepts.
- Polyfill ordering matters.
index.jsis the entry, notexpo-router/entry. - exFAT AppleDouble sidecars are blocked at Metro + tsconfig level.