feat(mobile): Nostr identity — Amber NIP-55 deep link + nsec fallback
Some checks failed
CI / Typecheck & Lint (pull_request) Failing after 0s
Some checks failed
CI / Typecheck & Lint (pull_request) Failing after 0s
Implements mobile Nostr identity management per issue #29. Android — NIP-55 Amber integration: - Opens com.greenart7c3.nostrsigner via `nostrsigner:` URI scheme to retrieve the user's public key without exposing it to the app. - Listens for the `mobile://nostr-callback` deep link response and stores the resulting npub in Expo SecureStore. - Falls back to Play Store install prompt when Amber is not installed. iOS / manual fallback: - NostrConnectModal accepts an nsec1 paste-in, validates bech32, derives the pubkey via nostr-tools getPublicKey, and stores the key only in Expo SecureStore — never in AsyncStorage, Redux, or logs. Both platforms: - Truncated npub and signer type (Amber / nsec) shown in Settings. - "Disconnect Nostr" wipes all keys from SecureStore and resets state. - Identity persists across restarts via SecureStore. Supporting changes: - NostrContext: new React context for identity lifecycle. - NostrConnectModal: platform-aware bottom-sheet modal for connect flow. - TimmyContext: added apiBaseUrl/setApiBaseUrl/isConnected; URL persisted in AsyncStorage and restored on mount; circular dep broken via refs. - constants/colors: added field, textInverted, destructive, link colours. - constants/storage-keys: added SERVER_URL_KEY. - app.json: added Android intent filter for mobile://nostr-callback. - package.json: added nostr-tools and expo-secure-store dependencies. Fixes #29 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||
|
||||
import { ErrorBoundary } from "@/components/ErrorBoundary";
|
||||
import { TimmyProvider } from "@/context/TimmyContext";
|
||||
import { NostrProvider } from "@/context/NostrContext";
|
||||
import { ONBOARDING_COMPLETED_KEY } from "@/constants/storage-keys";
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
@@ -77,9 +78,11 @@ export default function RootLayout() {
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||
<KeyboardProvider>
|
||||
<TimmyProvider>
|
||||
<RootLayoutNav />
|
||||
</TimmyProvider>
|
||||
<NostrProvider>
|
||||
<TimmyProvider>
|
||||
<RootLayoutNav />
|
||||
</TimmyProvider>
|
||||
</NostrProvider>
|
||||
</KeyboardProvider>
|
||||
</GestureHandlerRootView>
|
||||
</QueryClientProvider>
|
||||
|
||||
Reference in New Issue
Block a user