Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions dapps/deposit-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files

# dependencies
node_modules/

# Expo
.expo/
dist/
web-build/
expo-env.d.ts

# Native
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Metro
.metro-health-check*

# debug
npm-debug.*
yarn-debug.*
yarn-error.*

# macOS
.DS_Store
*.pem

# local env files
.env*.local
Comment thread
ganchoradkov marked this conversation as resolved.
Outdated

# typescript
*.tsbuildinfo

app-example
43 changes: 43 additions & 0 deletions dapps/deposit-app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"expo": {
"name": "deposit-app",
"slug": "deposit-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "depositapp",
"userInterfaceStyle": "automatic",
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
],
"expo-web-browser",
"expo-font",
"expo-image"
],
"experiments": {
"typedRoutes": true
}
}
}
58 changes: 58 additions & 0 deletions dapps/deposit-app/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
Inter_300Light,
Inter_400Regular,
Inter_500Medium,
Inter_600SemiBold,
Inter_700Bold,
} from '@expo-google-fonts/inter';
import { InstrumentSerif_400Regular } from '@expo-google-fonts/instrument-serif';
import {
JetBrainsMono_400Regular,
JetBrainsMono_500Medium,
} from '@expo-google-fonts/jetbrains-mono';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';

import { colors } from '@/constants/theme';
import { DepositProvider } from '@/stores/use-deposit-store';

SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
const [loaded] = useFonts({
Inter_300Light,
Inter_400Regular,
Inter_500Medium,
Inter_600SemiBold,
Inter_700Bold,
JetBrainsMono_400Regular,
JetBrainsMono_500Medium,
InstrumentSerif_400Regular,
});

useEffect(() => {
if (loaded) SplashScreen.hideAsync();
}, [loaded]);

if (!loaded) return null;

return (
<SafeAreaProvider>
{/*
The WalletConnect Pay rail (AppKit / wagmi providers + the real BX
checkout) gets wired here later — see .env for the credentials. For now
the deposit flow is simulated inside DepositProvider.
*/}
<DepositProvider>
<Stack screenOptions={{ headerShown: false, contentStyle: { backgroundColor: colors.surface } }}>
<Stack.Screen name="index" />
</Stack>
<StatusBar style="dark" />
</DepositProvider>
</SafeAreaProvider>
);
}
69 changes: 69 additions & 0 deletions dapps/deposit-app/app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

import { DepositOverlay } from '@/components/deposit/DepositOverlay';
import { BottomNav } from '@/components/home/BottomNav';
import { DesktopHome } from '@/components/home/DesktopHome';
import { MobileHome } from '@/components/home/MobileHome';
import { Sidebar } from '@/components/home/Sidebar';
import { SettingsModal } from '@/components/SettingsModal';
import { colors } from '@/constants/theme';
import { useDevice } from '@/hooks/use-device';
import { useDepositStore } from '@/stores/use-deposit-store';

/**
* Home screen. Renders the desktop layout (sidebar + scrollable main) on a wide
* web viewport, otherwise the mobile layout (content + bottom nav). The deposit
* flow opens as an overlay on top of either.
*/
export default function HomeScreen() {
const device = useDevice();
const { balance, activity, openDeposit, isLoadingBalance } = useDepositStore();
const [settingsOpen, setSettingsOpen] = useState(false);
const openSettings = () => setSettingsOpen(true);

if (device === 'desktop') {
return (
<View style={styles.desktop}>
<Sidebar onSettings={openSettings} />
<View style={styles.desktopMain}>
<View style={styles.desktopContent}>
<DesktopHome
balance={balance}
activity={activity}
onDeposit={openDeposit}
isLoadingBalance={isLoadingBalance}
/>
</View>
</View>
<DepositOverlay device={device} />
<SettingsModal visible={settingsOpen} device={device} onClose={() => setSettingsOpen(false)} />
</View>
);
}

return (
<SafeAreaView style={styles.mobile} edges={['top', 'bottom']}>
<View style={styles.mobileContent}>
<MobileHome
balance={balance}
activity={activity}
onDeposit={openDeposit}
isLoadingBalance={isLoadingBalance}
/>
</View>
<BottomNav onSettings={openSettings} />
<DepositOverlay device={device} />
<SettingsModal visible={settingsOpen} device={device} onClose={() => setSettingsOpen(false)} />
</SafeAreaView>
);
}

const styles = StyleSheet.create({
desktop: { flex: 1, flexDirection: 'row', backgroundColor: colors.surface },
desktopMain: { flex: 1, backgroundColor: colors.surface },
desktopContent: { flex: 1, paddingHorizontal: 40, paddingVertical: 40, maxWidth: 1100, width: '100%', alignSelf: 'center' },
mobile: { flex: 1, backgroundColor: colors.surface },
mobileContent: { flex: 1 },
});
Binary file added dapps/deposit-app/assets/fonts/KHTeka-Medium.otf
Binary file not shown.
Binary file added dapps/deposit-app/assets/fonts/KHTeka-Regular.otf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added dapps/deposit-app/assets/images/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dapps/deposit-app/assets/images/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dapps/deposit-app/assets/images/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dapps/deposit-app/assets/images/reown-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dapps/deposit-app/assets/images/splash-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions dapps/deposit-app/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = function (api) {
api.cache(true);
return {
presets: [["babel-preset-expo", { unstable_transformImportMeta: true }]],
};
};
148 changes: 148 additions & 0 deletions dapps/deposit-app/components/SettingsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { useState } from 'react';
import { Modal, Pressable, StyleSheet, Text, View } from 'react-native';
import Animated, { FadeIn, SlideInDown, ZoomIn } from 'react-native-reanimated';

import { Check, X } from '@/components/ui/icons';
import { colors, fonts, radius } from '@/constants/theme';
import { Device } from '@/hooks/use-device';
import { useDepositStore } from '@/stores/use-deposit-store';

/**
* Lightweight Settings modal, opened from the Settings nav item. Currently hosts
* a single demo affordance: clear the persisted deposits + cached balance.
*/
export function SettingsModal({
visible,
device,
onClose,
}: {
visible: boolean;
device: Device;
onClose: () => void;
}) {
const { clearDemoData } = useDepositStore();
const [cleared, setCleared] = useState(false);
const isMobile = device === 'mobile';

const onClear = () => {
clearDemoData();
setCleared(true);
setTimeout(() => setCleared(false), 1800);
};

const content = (
<>
<View style={styles.header}>
<Text style={styles.title}>Settings</Text>
<Pressable onPress={onClose} style={styles.closeBtn}>
<X size={16} color={colors.text} />
</Pressable>
</View>

<Text style={styles.sectionLabel}>Demo</Text>
<Pressable onPress={onClear} style={styles.row}>
<View style={styles.rowText}>
<Text style={styles.rowTitle}>Clear demo data</Text>
<Text style={styles.rowSub}>Removes saved deposits and cached balance.</Text>
</View>
{cleared ? (
<View style={styles.done}>
<Check size={14} color={colors.success} />
<Text style={styles.doneText}>Cleared</Text>
</View>
) : (
<Text style={styles.action}>Clear</Text>
)}
</Pressable>
</>
);

return (
<Modal visible={visible} transparent animationType="none" onRequestClose={onClose}>
{isMobile ? (
<Animated.View entering={FadeIn.duration(200)} style={styles.mobileBackdrop}>
<Pressable style={StyleSheet.absoluteFill} onPress={onClose} />
<Animated.View entering={SlideInDown.duration(350)} style={styles.sheet}>
<View style={styles.handleWrap}>
<View style={styles.handle} />
</View>
<View style={styles.body}>{content}</View>
</Animated.View>
</Animated.View>
) : (
<Animated.View entering={FadeIn.duration(200)} style={styles.desktopBackdrop}>
<Pressable style={StyleSheet.absoluteFill} onPress={onClose} />
<Animated.View entering={ZoomIn.duration(300)} style={styles.card}>
<View style={styles.body}>{content}</View>
</Animated.View>
</Animated.View>
)}
</Modal>
);
}

const styles = StyleSheet.create({
desktopBackdrop: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 24,
backgroundColor: 'rgba(15,15,15,0.5)',
},
card: {
width: 440,
borderRadius: radius['2xl'],
backgroundColor: colors.surface,
overflow: 'hidden',
},
mobileBackdrop: { flex: 1, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0.4)' },
sheet: {
borderTopLeftRadius: radius['4xl'],
borderTopRightRadius: radius['4xl'],
backgroundColor: colors.surface,
overflow: 'hidden',
},
handleWrap: { alignItems: 'center', paddingVertical: 8 },
handle: { width: 40, height: 4, borderRadius: radius.pill, backgroundColor: colors.border2 },
body: { paddingHorizontal: 24, paddingTop: 8, paddingBottom: 28 },
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
},
title: { fontFamily: fonts.semibold, fontSize: 15, color: colors.text },
closeBtn: {
width: 32,
height: 32,
borderRadius: radius.pill,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: colors.surface3,
},
sectionLabel: {
fontFamily: fonts.mono,
fontSize: 10,
letterSpacing: 1.5,
textTransform: 'uppercase',
color: colors.textDimmer,
marginBottom: 12,
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 14,
borderRadius: radius.xl,
backgroundColor: colors.surface2,
borderWidth: 1,
borderColor: colors.border,
},
rowText: { flex: 1, paddingRight: 12 },
rowTitle: { fontFamily: fonts.medium, fontSize: 13, color: colors.text },
rowSub: { fontFamily: fonts.regular, fontSize: 11, color: colors.textDimmer, marginTop: 2 },
action: { fontFamily: fonts.medium, fontSize: 13, color: colors.danger },
done: { flexDirection: 'row', alignItems: 'center', gap: 4 },
doneText: { fontFamily: fonts.mono, fontSize: 11, color: colors.success },
});
Loading
Loading