Skip to content

Commit

Permalink
Air drop (#420)
Browse files Browse the repository at this point in the history
* initial commit

* updated

* u
  • Loading branch information
ehsan6sha authored Oct 24, 2024
1 parent ff99562 commit b74f670
Show file tree
Hide file tree
Showing 18 changed files with 5,288 additions and 3,429 deletions.
8 changes: 7 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<queries>
<package android:name="io.metamask"/>
<package android:name="com.wallet.crypto.trustapp"/>
</queries>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
Expand All @@ -14,6 +19,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SHORT_SERVICE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" tools:node="remove" />

<application
android:name=".MainApplication"
Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 26
minSdkVersion = 30
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "26.2.11394342"
kotlin_version = "1.9.22" // Update this to your version
kotlin_version = "2.0.0" // Update this to your version
enableHermes = true
}
repositories {
Expand Down
86 changes: 20 additions & 66 deletions app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,12 @@ import {
useNavigationPersistence,
} from './navigators'
import AsyncStorage from '@react-native-async-storage/async-storage'
import {
MetaMaskProvider,
SDKConfigProvider,
useSDKConfig,
} from '@metamask/sdk-react'
import { COMM_SERVER_URL, INFURA_API_KEY } from './utils/walletConnectConifg'
import { ErrorBoundary } from './screens/error/error-boundary'
import { ThemeProvider, RneLightTheme, RneDarkTheme } from './theme'
import BackgroundTimer from 'react-native-background-timer'
import { MetaMaskSDKProvider } from './contexts/MetaMaskContext';
import { WalletConnectModal } from '@walletconnect/modal-react-native';

// TODO how to properly make sure we only try to open link when the app is active?
// current problem is that sdk declaration is outside of the react scope so I cannot directly verify the state
Expand All @@ -49,60 +46,6 @@ const canOpenLink = true

export const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE'

const WithSDKConfig = ({ children }: { children: React.ReactNode }) => {
const {
socketServer,
infuraAPIKey,
useDeeplink,
debug,
checkInstallationImmediately,
} = useSDKConfig()

return (
<MetaMaskProvider
// debug={debug}
sdkOptions={{
// communicationServerUrl: socketServer,
// TODO: change to enableAnalytics when updating the SDK version
// enableDebug: true,
infuraAPIKey,
readonlyRPCMap: {
'0x539': process.env.NEXT_PUBLIC_PROVIDER_RPCURL ?? '',
},
logging: {
developerMode: true,
plaintext: true,
},
openDeeplink: (link: string, _target?: string) => {
console.debug(`App::openDeepLink() ${link}`)
if (canOpenLink) {
Linking.openURL(link)
} else {
console.debug(
'useBlockchainProiver::openDeepLink app is not active - skip link',
link,
)
}
},
timer: BackgroundTimer,
useDeeplink,
checkInstallationImmediately,
storage: {
enabled: true,
},
dappMetadata: {
name: 'fxfotos',
},
i18nOptions: {
enabled: true,
},
}}
>
{children}
</MetaMaskProvider>
)
}

/**
* This is the root component of our app.
*/
Expand Down Expand Up @@ -142,15 +85,23 @@ function App() {
// In Android: https://stackoverflow.com/a/45838109/204044
// You can replace with your own loading component if you wish.
if (!isNavigationStateRestored) return null
const projectId = '56755e4e110a783c85b3e6f74beedb2e';

const providerMetadata = {
name: 'FxFotos',
description: 'A Decentralized Galley app',
url: 'https://fx.land/',
icons: ['https://your-project-logo.com/'],
redirect: {
native: 'fotos://',
universal: 'fx.land'
}
};

// otherwise, we're ready to render the app
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SDKConfigProvider
initialSocketServer={COMM_SERVER_URL}
initialInfuraKey={INFURA_API_KEY}
>
<WithSDKConfig>
<MetaMaskSDKProvider>
<RneThemeProvider
theme={scheme === 'dark' ? RneDarkTheme : RneLightTheme}
>
Expand All @@ -164,8 +115,11 @@ function App() {
</SafeAreaProvider>
</ThemeProvider>
</RneThemeProvider>
</WithSDKConfig>
</SDKConfigProvider>
</MetaMaskSDKProvider>
<WalletConnectModal
projectId={projectId}
providerMetadata={providerMetadata}
></WalletConnectModal>
</GestureHandlerRootView>
)
}
Expand Down
8 changes: 0 additions & 8 deletions app/components/header/header-avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@ type Props = {
iconSize?: number
size?: ('small' | 'medium' | 'large' | 'xlarge') | number
connected?: boolean
provider?: any
onPress?: () => void
}
export function HeaderAvatar({
size,
iconSize,
connected,
provider,
onPress,
}: Props) {
return (
<>
{provider || connected ? (
<Avatar
containerStyle={styles.disconnectedAvatar}
source={
Expand All @@ -38,10 +34,6 @@ export function HeaderAvatar({
rounded
onPress={onPress}
/>
) : (
<ActivityIndicator />
)}
</>
)
}

Expand Down
117 changes: 117 additions & 0 deletions app/contexts/MetaMaskContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { createContext, useContext, useCallback, useState, useEffect, useMemo, useRef } from 'react';
import { useSDK } from '@metamask/sdk-react';
import notifee, { AndroidImportance } from '@notifee/react-native';
import Toast from 'react-native-toast-message'
import { useWalletConnectModal } from '@walletconnect/modal-react-native';

interface MetaMaskContextType {
personalSign: (message: string) => Promise<string | null>;
isLinking: boolean;
cancelSign: () => void;
}

const MetaMaskContext = createContext<MetaMaskContextType>({
personalSign: async () => null,
isLinking: false,
cancelSign: () => {},
});

export const MetaMaskSDKProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { open, isConnected, provider } = useWalletConnectModal();
const [isLinking, setIsLinking] = useState(false);

const cancelSign = useCallback(() => {
setIsLinking(false);
try {
console.log("cancelSign notifee closed");
notifee.stopForegroundService();
} catch (e) {
console.log('Error stopping foreground service:', e);
}
provider?.cleanupPendingPairings()

if (isConnected) {
provider?.disconnect();
}
}, [provider, isConnected]);

const personalSign = useCallback(async (chainCode: string) => {
try {
console.log("personal sign started");
setIsLinking(true);

// Create notification channel
const channelId = await notifee.createChannel({
id: 'sticky',
name: 'Sticky Notifications',
importance: AndroidImportance.HIGH,
});

await notifee.displayNotification({
id: 'wallet',
title: 'Connecting wallet...',
body: 'Wallet connection in progress, click to move back to the app',
android: {
channelId,
progress: { indeterminate: true },
pressAction: { id: 'default' },
ongoing: true,
asForegroundService: true
}
});

// First connect if not connected
if (!isConnected) {
console.log('wallet opening')
await open();
return
} else if (isConnected) {
console.log('getting accounts')
// Get accounts
const accounts = await provider?.request({
method: 'eth_requestAccounts'
}) as string[]; // Add type assertion

if (!accounts || !Array.isArray(accounts) || accounts.length === 0) {
throw new Error('No accounts connected');
}
console.log("Connected accounts:", accounts);

// Sign message
console.log("calling sing with chainCode="+chainCode)
const signature = await provider?.request({
method: 'personal_sign',
params: [chainCode, accounts[0]]
});

console.log("Signature received:", signature);
return signature;
}

} catch (error) {
console.log("Error in personalSign:", error);
return null;
} finally {
setIsLinking(false);
try {
await notifee.stopForegroundService();
} catch (e) {
console.log('Error stopping foreground service:', e);
}
}
}, [provider, isConnected, open]); // Add dependencies

const contextValue = useMemo(() => ({
personalSign,
isLinking,
cancelSign
}), [personalSign, isLinking, cancelSign]);

return (
<MetaMaskContext.Provider value={contextValue}>
{children}
</MetaMaskContext.Provider>
);
};

export const useMetaMask = () => useContext(MetaMaskContext);
1 change: 1 addition & 0 deletions app/navigators/app-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ export function AppNavigator(props: NavigationProps) {
'http://fotos.fx.land',
'fotos://fotos.fx.land',
'fotos://',
'fxfotos://',
],
config: {
initialRouteName: AppNavigationNames.HomeScreen,
Expand Down
20 changes: 19 additions & 1 deletion app/navigators/home-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5'

import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { HomeScreen, LibraryScreen, SearchScreen } from '../screens'
import { HomeScreen, LibraryScreen, SearchScreen, RewardsScreen } from '../screens'
import { TabHeader } from '../components/header/tab-header'
import { UnderConstruction } from '../components'

Expand All @@ -20,6 +20,7 @@ export enum HomeNavigationTypes {
HomeScreen = 'HomeTab',
LibraryScreen = 'LibraryTab',
SearchScreen = 'SearchTab',
RewardsScreen = 'RewardsTab',
}
function UnderConstructionScreen() {
return (
Expand Down Expand Up @@ -124,6 +125,23 @@ export function HomeNavigator() {
}}
component={LibraryScreen}
/>
<HomeTabs.Screen
name={HomeNavigationTypes.RewardsScreen}
options={{
tabBarLabel: 'Rewards',
tabBarIcon: function tabIcon(props) {
return (
<FontAwesome5
name="gift"
color={props?.focused ? colors.text : 'gray'}
size={25}
style={{}}
/>
)
},
}}
component={RewardsScreen}
/>
</HomeTabs.Navigator>
)
}
Loading

0 comments on commit b74f670

Please sign in to comment.