Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
OKendigelyan committed Jan 24, 2025
1 parent cf4f285 commit 47e04cf
Show file tree
Hide file tree
Showing 18 changed files with 957 additions and 1,105 deletions.
1 change: 1 addition & 0 deletions apps/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { tamaguiConfig } from "../tamagui.config";

export default function RootLayout() {
const colorScheme = useColorScheme();

return (
<ToastProvider toast={{} as Toast}>
<TamaguiProvider config={tamaguiConfig} defaultTheme={colorScheme!}>
Expand Down
16 changes: 4 additions & 12 deletions apps/mobile/app/home.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { type SocialAccount } from "@umami/core";
import { useCurrentAccount, useGetAccountBalance } from "@umami/state";
import { router } from "expo-router";
import * as SecureStore from "expo-secure-store";
import { StyleSheet, Text, View } from "react-native";
import { Button } from "tamagui";

import { persistor } from "../store/store";
import { useSocialOnboarding } from "../services/auth/useSocialOnboarding";

export default function HomeScreen() {
const currentAccount = useCurrentAccount();
const getBalance = useGetAccountBalance();
const { logout } = useSocialOnboarding();
const balance = getBalance(currentAccount ? currentAccount.address.pkh : "");

return (
Expand All @@ -18,14 +17,7 @@ export default function HomeScreen() {
<Text>{currentAccount?.address.pkh}</Text>
<Text>{currentAccount?.label}</Text>
<Text>Balance: {balance}</Text>
<Button
onPress={async () => {
persistor.pause();
await AsyncStorage.clear();
await SecureStore.deleteItemAsync("authToken");
router.replace("/onboarding");
}}
>
<Button onPress={() => logout((currentAccount as SocialAccount).idp)}>
<Button.Text>Logout</Button.Text>
</Button>
</View>
Expand Down
1 change: 0 additions & 1 deletion apps/mobile/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Onboarding from "./onboarding";

export default function MainStack() {
const currentAccount = useCurrentAccount();
console.log("currentAccount", currentAccount);

if (!currentAccount) {
return <Onboarding />;
Expand Down
8 changes: 4 additions & 4 deletions apps/mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2450,14 +2450,14 @@ SPEC CHECKSUMS:
ExpoWebBrowser: 6890a769e6c9d83da938dceb9a03e764afc3ec9c
EXUpdatesInterface: 1dcebac98ac5dad4289e6ff2bd5616822e894397
FBLazyVector: be7314029d6ec6b90f0f75ce1195b8130ed9ac4f
fmt: 10c6e61f4be25dc963c36bd73fc7b1705fe975be
glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a
fmt: fad7775865bb4340e98e10997c965fd61b3c749e
glog: 94308668c25e8ccac76f853cda1931c7aa3f5fae
GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
hermes-engine: 0555a84ea495e8e3b4bde71b597cd87fbb382888
hermes-engine: 77f19b2923ed39b21649b7551471674e3ace7a0a
JWTDecode: 3eaab1e06b6f4dcbdd6716aff09ba4c2104ca8b7
RCT-Folly: bf5c0376ffe4dd2cf438dcf86db385df9fdce648
RCT-Folly: aac5a2e8a7b6b8108945e58a66d08f78b800a1ea
RCTDeprecation: 2c5e1000b04ab70b53956aa498bf7442c3c6e497
RCTRequired: 5f785a001cf68a551c5f5040fb4c415672dbb481
RCTTypeSafety: 6b98db8965005d32449605c0d005ecb4fee8a0f7
Expand Down
10 changes: 8 additions & 2 deletions apps/mobile/ios/mobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,10 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
Expand Down Expand Up @@ -529,7 +532,10 @@
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
Expand Down
6 changes: 3 additions & 3 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
"@react-native-google-signin/google-signin": "github:react-native-google-signin/google-signin",
"@react-navigation/bottom-tabs": "^7.0.0",
"@react-navigation/native": "^7.0.0",
"@tamagui/babel-plugin": "^1.121.5",
"@tamagui/config": "^1.116.15",
"@tamagui/babel-plugin": "1.123.0",
"@tamagui/config": "1.123.0",
"@taquito/utils": "^21.0.0",
"@umami/core": "workspace:^",
"@umami/crypto": "workspace:^",
Expand Down Expand Up @@ -82,7 +82,7 @@
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"styled-components": "^6.1.13",
"tamagui": "^1.120.1",
"tamagui": "^1.123.0",
"util": "^0.12.5",
"vm-browserify": "^1.1.2"
},
Expand Down
3 changes: 0 additions & 3 deletions apps/mobile/screens/Onboarding/Onboarding.screen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { TouchableOpacity, View } from "react-native";
import { Button } from "tamagui";

import {
AppleImage,
Expand Down Expand Up @@ -89,8 +88,6 @@ export const OnboardingScreen = () => {
<SecondaryButton>
<ButtonLabel>{strings.alreadyHaveWallet}</ButtonLabel>
</SecondaryButton>

<Button>Tamagui Button</Button>
</ButtonsWrapper>
</MainContainer>
<View style={{ alignItems: "center" }}>
Expand Down
32 changes: 3 additions & 29 deletions apps/mobile/screens/Onboarding/useOnboardingData.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { type IDP } from "@umami/social-auth";
import { useAsyncActionHandler, useRestoreSocial } from "@umami/state";
import { getPublicKeyPairFromSk } from "@umami/tezos";
import * as Linking from "expo-linking";
import { useRouter } from "expo-router";
import { useCallback, useEffect } from "react";

import { STRINGS } from "../../constants";
import { forIDP } from "../../services/forIDP";
import { useSocialOnboarding } from "../../services/auth";
import { openBrowser } from "../../utils/browserUtils";

export const useOnboardingData = () => {
const router = useRouter();
const { handleAsyncAction } = useAsyncActionHandler();
const restoreSocial = useRestoreSocial();
const socialLoginHandlers = useSocialOnboarding();

useEffect(() => {
const handleUrl = (event: any) => {
Expand All @@ -27,22 +21,6 @@ export const useOnboardingData = () => {
};
}, []);

const login = (idp: IDP) =>
handleAsyncAction(async () => {
const { secretKey, name, id, email } = await forIDP(idp).getCredentials();
const { pk, pkh } = await getPublicKeyPairFromSk(secretKey);
restoreSocial(pk, pkh, email || name || id, idp);
router.replace("/home");
});

const createLoginHandler = (provider: IDP) => () => login(provider);

const onGoogleLogin = createLoginHandler("google");
const onFacebookLogin = createLoginHandler("facebook");
const onXLogin = createLoginHandler("twitter");
const onRedditLogin = createLoginHandler("reddit");
const onAppleLogin = createLoginHandler("apple");

const openTerms = useCallback(() => openBrowser("https://umamiwallet.com/tos.html"), []);

const openPrivacy = useCallback(
Expand All @@ -54,10 +32,6 @@ export const useOnboardingData = () => {
strings: STRINGS,
openTerms,
openPrivacy,
onGoogleLogin,
onFacebookLogin,
onXLogin,
onRedditLogin,
onAppleLogin,
...socialLoginHandlers,
};
};
File renamed without changes.
70 changes: 36 additions & 34 deletions apps/mobile/services/Auth.ts → apps/mobile/services/auth/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,33 @@ import { makeRedirectUri } from "expo-auth-session";
import * as SecureStore from "expo-secure-store";
import * as WebBrowser from "expo-web-browser";

import { CHAIN_CONFIG_GHOSTNET, WEB3_AUTH_CLIENT_ID } from "../constants";
import { CHAIN_CONFIG_GHOSTNET, WEB3_AUTH_CLIENT_ID } from "../../constants";

const createWeb3AuthInstance = (): Web3Auth => {
const privateKeyProvider = new CommonPrivateKeyProvider({
config: { chainConfig: CHAIN_CONFIG_GHOSTNET },
});

const redirectUrl = makeRedirectUri({
scheme: "umami",
path: "auth",
});

return new Web3Auth(WebBrowser, SecureStore, {
clientId: WEB3_AUTH_CLIENT_ID!,
network: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
privateKeyProvider,
redirectUrl,
});
};

export const web3auth = createWeb3AuthInstance();

/**
* Abstract class that's responsible for the social auth process
* using Web3Auth SDK instead of Torus
*/
export abstract class Auth {
protected web3auth: Web3Auth;

constructor() {
this.web3auth = this.createWeb3AuthInstance();
}

protected createWeb3AuthInstance(): Web3Auth {
const privateKeyProvider = new CommonPrivateKeyProvider({
config: { chainConfig: CHAIN_CONFIG_GHOSTNET },
});

const redirectUrl = makeRedirectUri({
scheme: "umami",
path: "auth",
});

return new Web3Auth(WebBrowser, SecureStore, {
clientId: WEB3_AUTH_CLIENT_ID!,
network: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
privateKeyProvider,
redirectUrl,
});
}

protected abstract getLoginParams(): LoginParams;

async login(): Promise<{
Expand All @@ -47,26 +43,25 @@ export abstract class Auth {
verifierId?: string;
};
}> {
if (!this.web3auth.ready) {
await this.web3auth.init();
}

try {
if (!web3auth.connected) {
await web3auth.init();
}

const loginParams = this.getLoginParams();
console.log("loginParams", loginParams);
await this.web3auth.login(loginParams);
await web3auth.login(loginParams);
} catch (error) {
console.error("Error logging in with Web3Auth:", error);
throw error;
}

if (!this.web3auth.connected) {
if (!web3auth.connected) {
throw new Error("Web3Auth connection failed");
}

const userInfo = this.web3auth.userInfo();
const userInfo = web3auth.userInfo();

const privateKey = (await this.web3auth.provider?.request({
const privateKey = (await web3auth.provider?.request({
method: "private_key",
})) as string;

Expand All @@ -81,6 +76,13 @@ export abstract class Auth {
};
}

async logout() {
if (!web3auth.connected) {
await web3auth.init();
}
await web3auth.logout();
}

async getCredentials(): Promise<{
secretKey: string;
id: string;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const forIDP = (idp: IDP) => {
return new GoogleAuth();
case "email":
throw new Error("Email auth is not supported on mobile");

// TODO: Implement email auth for mobile
// return new EmailAuth();
case "reddit":
return new RedditAuth();
Expand All @@ -26,5 +28,7 @@ export const forIDP = (idp: IDP) => {
return new TwitterAuth();
case "apple":
return new AppleAuth();
default:
throw new Error(`Unsupported IDP: ${idp}`);
}
};
3 changes: 3 additions & 0 deletions apps/mobile/services/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./Auth";
export * from "./forIDP";
export * from "./useSocialOnboarding";
47 changes: 47 additions & 0 deletions apps/mobile/services/auth/useSocialOnboarding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { type IDP } from "@umami/social-auth";
import { useAsyncActionHandler, useRestoreSocial } from "@umami/state";
import { getPublicKeyPairFromSk } from "@umami/tezos";
import { useRouter } from "expo-router";

import { forIDP } from "./forIDP";
import { persistor } from "../../store/store";

export const useSocialOnboarding = () => {
const router = useRouter();
const restoreSocial = useRestoreSocial();
const { handleAsyncAction } = useAsyncActionHandler();

const login = (idp: IDP) =>
handleAsyncAction(async () => {
const { secretKey, name, id, email } = await forIDP(idp).getCredentials();
const { pk, pkh } = await getPublicKeyPairFromSk(secretKey);
restoreSocial(pk, pkh, email || name || id, idp);
router.replace("/home");
});

const logout = (idp: IDP) =>
handleAsyncAction(async () => {
await forIDP(idp).logout();
persistor.pause();
await AsyncStorage.clear();
router.replace("/onboarding");
});

const createLoginHandler = (provider: IDP) => () => login(provider);

const onGoogleLogin = createLoginHandler("google");
const onFacebookLogin = createLoginHandler("facebook");
const onXLogin = createLoginHandler("twitter");
const onRedditLogin = createLoginHandler("reddit");
const onAppleLogin = createLoginHandler("apple");

return {
onGoogleLogin,
onFacebookLogin,
onXLogin,
onRedditLogin,
onAppleLogin,
logout,
};
};
Loading

1 comment on commit 47e04cf

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Title Lines Statements Branches Functions
apps/desktop Coverage: 83%
83.74% (1788/2135) 79.43% (850/1070) 78.27% (454/580)
apps/web Coverage: 83%
83.74% (1788/2135) 79.43% (850/1070) 78.27% (454/580)
packages/components Coverage: 97%
97.51% (196/201) 95.91% (94/98) 88.13% (52/59)
packages/core Coverage: 81%
82.37% (215/261) 72.51% (95/131) 81.66% (49/60)
packages/crypto Coverage: 100%
100% (43/43) 90.9% (10/11) 100% (7/7)
packages/data-polling Coverage: 96%
94.63% (141/149) 87.5% (21/24) 92.85% (39/42)
packages/multisig Coverage: 98%
98.47% (129/131) 85.71% (18/21) 100% (36/36)
packages/social-auth Coverage: 95%
95.45% (21/22) 91.66% (11/12) 100% (3/3)
packages/state Coverage: 85%
84.3% (827/981) 80.5% (190/236) 77.83% (302/388)
packages/tezos Coverage: 89%
88.72% (118/133) 94.59% (35/37) 86.84% (33/38)
packages/tzkt Coverage: 89%
87.32% (62/71) 87.5% (14/16) 80.48% (33/41)

Please sign in to comment.