From 0907255377aeaa6bb349cd0cd02f8ee542bd0bb2 Mon Sep 17 00:00:00 2001
From: Iuri Pereira <689440+iuricmp@users.noreply.github.com>
Date: Wed, 30 Oct 2024 10:55:26 +0000
Subject: [PATCH 1/5] feat: universal login
Signed-off-by: Iuri Pereira <689440+iuricmp@users.noreply.github.com>
---
mobile/app/(app)/home/home.tsx | 3 +--
mobile/app/(app)/tologin/index.tsx | 9 +++++++--
mobile/app/index.tsx | 9 ++++-----
mobile/redux/features/linkingSlice.ts | 19 ++++++++++++++++---
4 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/mobile/app/(app)/home/home.tsx b/mobile/app/(app)/home/home.tsx
index d01ca58..3a53b66 100644
--- a/mobile/app/(app)/home/home.tsx
+++ b/mobile/app/(app)/home/home.tsx
@@ -3,7 +3,7 @@ import { FlatList, TouchableOpacity, View } from "react-native";
import { useNavigation, useRouter } from "expo-router";
import { Layout } from "@/components/index";
import Text from "@/components/text";
-import { selectMasterPassword, selectTxInput, useAppDispatch, useAppSelector } from "@/redux";
+import { isToLoginSelector, selectMasterPassword, useAppDispatch, useAppSelector } from "@/redux";
import { KeyInfo, useGnoNativeContext } from "@gnolang/gnonative";
import Octicons from '@expo/vector-icons/Octicons';
import TextInput from "@/components/textinput";
@@ -22,7 +22,6 @@ export default function Page() {
const { gnonative } = useGnoNativeContext();
const navigation = useNavigation();
const dispatch = useAppDispatch();
- const txInput = useAppSelector(selectTxInput);
const masterPassword = useAppSelector(selectMasterPassword)
useEffect(() => {
diff --git a/mobile/app/(app)/tologin/index.tsx b/mobile/app/(app)/tologin/index.tsx
index e162d00..76bbdfd 100644
--- a/mobile/app/(app)/tologin/index.tsx
+++ b/mobile/app/(app)/tologin/index.tsx
@@ -3,7 +3,7 @@ import Button from "@/components/button";
import VaultListItem from "@/components/list/vault-list/VaultListItem";
import Spacer from "@/components/spacer";
import Text from "@/components/text";
-import { selectCallback, sendAddressToSoliciting, useAppDispatch, useAppSelector } from "@/redux";
+import { clearLinking, selectCallback, sendAddressToSoliciting, useAppDispatch, useAppSelector } from "@/redux";
import { KeyInfo, useGnoNativeContext } from "@gnolang/gnonative";
import { router, useNavigation } from "expo-router";
import { useCallback, useEffect, useMemo, useState } from "react";
@@ -41,6 +41,11 @@ export default function Page() {
router.push("/home")
}, [callback]);
+ const onCancel = () => {
+ dispatch(clearLinking())
+ router.push("/home")
+ }
+
return (
<>
@@ -58,7 +63,7 @@ export default function Page() {
ListEmptyComponent={There are no items to list.}
/>
)}
- router.push("/home")}>
+
>
diff --git a/mobile/app/index.tsx b/mobile/app/index.tsx
index 7be6264..365fb98 100644
--- a/mobile/app/index.tsx
+++ b/mobile/app/index.tsx
@@ -3,7 +3,7 @@ import { ScrollView, View } from "react-native";
import { useRouter } from "expo-router";
import { Layout } from "@/components/index";
import Text from "@/components/text";
-import { getInitialState, selectInitialized, selectMasterPassword, selectPath, signIn, signUp, useAppDispatch, useAppSelector } from "@/redux";
+import { getInitialState, isToLoginSelector, selectInitialized, selectMasterPassword, selectPath, signIn, signUp, useAppDispatch, useAppSelector } from "@/redux";
import * as Application from "expo-application";
import SignInView from "@/views/signin";
import SignUpView from "@/views/signup";
@@ -19,7 +19,7 @@ export default function Root() {
const appInitialized = useAppSelector(selectInitialized)
const hasMasterPassword = useAppSelector(selectMasterPassword)
- const path = useAppSelector(selectPath);
+ const isToLogin = useAppSelector(isToLoginSelector);
useEffect(() => {
dispatch(getInitialState())
@@ -50,9 +50,8 @@ export default function Root() {
};
const naviateTo = () => {
- console.log("path", path);
- if (path) {
- route.replace(path as string);
+ if (isToLogin) {
+ route.replace('/tologin');
} else {
route.replace("/home");
}
diff --git a/mobile/redux/features/linkingSlice.ts b/mobile/redux/features/linkingSlice.ts
index 4e3c9ea..603deb2 100644
--- a/mobile/redux/features/linkingSlice.ts
+++ b/mobile/redux/features/linkingSlice.ts
@@ -14,6 +14,7 @@ interface CounterState {
callback?: string;
/* The path of the requested screen */
path?: string | 'tologin';
+ hostname?: string;
}
const initialState: CounterState = {
@@ -23,6 +24,7 @@ const initialState: CounterState = {
txInput: undefined,
callback: undefined,
path: undefined,
+ hostname: undefined,
};
/**
@@ -76,6 +78,7 @@ interface SetLinkResponse {
callback?: string;
path: string;
keyinfo?: KeyInfo;
+ hostname?: string;
}
export const setLinkingData = createAsyncThunk("linking/setLinkingData", async (parsedURL, thunkAPI) => {
@@ -98,12 +101,13 @@ export const setLinkingData = createAsyncThunk {
+ console.log("clearing linking data");
+ state = { ...initialState };
+ },
+ },
extraReducers: (builder) => {
builder.addCase(setLinkingData.fulfilled, (state, action) => {
state.reason = action.payload.reason;
@@ -121,6 +130,7 @@ export const linkingSlice = createSlice({
state.callback = action.payload.callback;
state.path = action.payload.path;
state.keyinfo = action.payload.keyinfo;
+ state.hostname = action.payload.hostname;
})
},
selectors: {
@@ -131,7 +141,10 @@ export const linkingSlice = createSlice({
selectClientName: (state) => state.clientName,
selectKeyInfo: (state) => state.keyinfo,
reasonSelector: (state) => state.reason,
+ isToLoginSelector: (state) => state.hostname === 'tologin',
},
});
-export const { selectTxInput, selectCallback, selectPath, selectBech32Address, selectClientName, reasonSelector, selectKeyInfo } = linkingSlice.selectors;
+export const { clearLinking } = linkingSlice.actions;
+
+export const { selectTxInput, selectCallback, selectPath, selectBech32Address, selectClientName, reasonSelector, selectKeyInfo, isToLoginSelector } = linkingSlice.selectors;
From 360451629c756f64ad194f82a498a544e2edeb4b Mon Sep 17 00:00:00 2001
From: Iuri Pereira <689440+iuricmp@users.noreply.github.com>
Date: Wed, 30 Oct 2024 13:45:29 +0000
Subject: [PATCH 2/5] fix loop
---
mobile/README.md | 31 +++++++++++++++++++++++++++
mobile/app/(app)/home/home.tsx | 2 +-
mobile/app/(app)/tologin/index.tsx | 2 +-
mobile/app/index.tsx | 8 +++----
mobile/redux/features/linkingSlice.ts | 3 ++-
5 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/mobile/README.md b/mobile/README.md
index 9114550..9709f23 100644
--- a/mobile/README.md
+++ b/mobile/README.md
@@ -125,3 +125,34 @@ make android
# to start Metro Bundler:
make start
```
+
+## Inter App communication
+
+dSocial and Gnokey mobile app are using `expo-linking` to exchange data.
+So that way you can signin or sign a transaction using Gnokey mobile app.
+
+### Sign in
+
+Example of dSocial asking for sign in
+```
+land.gno.gnokey://tologin?callback=tech.berty.dsocial%3A%2F%2Flogin-callback
+```
+- Base url: `land.gno.gnokey://tologin`
+- Parameters:
+ - callback: the url that Gnokey mobile will call after the user selecting the account.
+
+
+### Sign a transaction
+Example of dSocial asking Gnokey Mobile to sign a transaction:
+```
+land.gno.gnokey://tosign?tx=%257B%2522msg%2522%253A%255B%257B%2522%2540type%2522%253A%2522%252Fvm.m_call%2522%252C%2522caller%2522%253A%2522g1gl0hrpuegawx6pv24xjq8jjmufzp5r5mnn896w%2522%252C%2522send%2522%253A%2522%2522%252C%2522pkg_path%2522%253A%2522gno.land%252Fr%252Fberty%252Fsocial%2522%252C%2522func%2522%253A%2522PostMessage%2522%252C%2522args%2522%253A%255B%2522Test%25203%2522%255D%257D%255D%252C%2522fee%2522%253A%257B%2522gas_wanted%2522%253A%252210000000%2522%252C%2522gas_fee%2522%253A%25221000000ugnot%2522%257D%252C%2522signatures%2522%253Anull%252C%2522memo%2522%253A%2522%2522%257D&address=g1gl0hrpuegawx6pv24xjq8jjmufzp5r5mnn896w&client_name=dSocial&reason=Post%20a%20message&callback=tech.berty.dsocial%253A%252F%252Fpost
+```
+
+- Base url: `land.gno.gnokey://tosign`
+- Parameters:
+ - tx: the json result of `gnonative.makeCallTx(...)`
+ - address: bech32 address of whoever you want to sign the transaction.
+ - client_name: the name of the application that is calling the Gnokey mobile application. It will be displayed to the user.
+ - reason: the reason behind this action. It will be displayed to the user.
+ - callback: the callback URL that will be called from Gnokey mobile after signing the tx.
+
diff --git a/mobile/app/(app)/home/home.tsx b/mobile/app/(app)/home/home.tsx
index 3a53b66..31118dd 100644
--- a/mobile/app/(app)/home/home.tsx
+++ b/mobile/app/(app)/home/home.tsx
@@ -3,7 +3,7 @@ import { FlatList, TouchableOpacity, View } from "react-native";
import { useNavigation, useRouter } from "expo-router";
import { Layout } from "@/components/index";
import Text from "@/components/text";
-import { isToLoginSelector, selectMasterPassword, useAppDispatch, useAppSelector } from "@/redux";
+import { selectMasterPassword, useAppDispatch, useAppSelector } from "@/redux";
import { KeyInfo, useGnoNativeContext } from "@gnolang/gnonative";
import Octicons from '@expo/vector-icons/Octicons';
import TextInput from "@/components/textinput";
diff --git a/mobile/app/(app)/tologin/index.tsx b/mobile/app/(app)/tologin/index.tsx
index 76bbdfd..5f083cb 100644
--- a/mobile/app/(app)/tologin/index.tsx
+++ b/mobile/app/(app)/tologin/index.tsx
@@ -6,7 +6,7 @@ import Text from "@/components/text";
import { clearLinking, selectCallback, sendAddressToSoliciting, useAppDispatch, useAppSelector } from "@/redux";
import { KeyInfo, useGnoNativeContext } from "@gnolang/gnonative";
import { router, useNavigation } from "expo-router";
-import { useCallback, useEffect, useMemo, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { FlatList } from "react-native";
export default function Page() {
diff --git a/mobile/app/index.tsx b/mobile/app/index.tsx
index 365fb98..19d7887 100644
--- a/mobile/app/index.tsx
+++ b/mobile/app/index.tsx
@@ -3,7 +3,7 @@ import { ScrollView, View } from "react-native";
import { useRouter } from "expo-router";
import { Layout } from "@/components/index";
import Text from "@/components/text";
-import { getInitialState, isToLoginSelector, selectInitialized, selectMasterPassword, selectPath, signIn, signUp, useAppDispatch, useAppSelector } from "@/redux";
+import { getInitialState, selectAction, selectInitialized, selectMasterPassword, signIn, signUp, useAppDispatch, useAppSelector } from "@/redux";
import * as Application from "expo-application";
import SignInView from "@/views/signin";
import SignUpView from "@/views/signup";
@@ -19,7 +19,7 @@ export default function Root() {
const appInitialized = useAppSelector(selectInitialized)
const hasMasterPassword = useAppSelector(selectMasterPassword)
- const isToLogin = useAppSelector(isToLoginSelector);
+ const action = useAppSelector(selectAction);
useEffect(() => {
dispatch(getInitialState())
@@ -50,8 +50,8 @@ export default function Root() {
};
const naviateTo = () => {
- if (isToLogin) {
- route.replace('/tologin');
+ if (action) {
+ route.replace(action);
} else {
route.replace("/home");
}
diff --git a/mobile/redux/features/linkingSlice.ts b/mobile/redux/features/linkingSlice.ts
index 603deb2..a62eb65 100644
--- a/mobile/redux/features/linkingSlice.ts
+++ b/mobile/redux/features/linkingSlice.ts
@@ -142,9 +142,10 @@ export const linkingSlice = createSlice({
selectKeyInfo: (state) => state.keyinfo,
reasonSelector: (state) => state.reason,
isToLoginSelector: (state) => state.hostname === 'tologin',
+ selectAction: (state) => state.hostname,
},
});
export const { clearLinking } = linkingSlice.actions;
-export const { selectTxInput, selectCallback, selectPath, selectBech32Address, selectClientName, reasonSelector, selectKeyInfo, isToLoginSelector } = linkingSlice.selectors;
+export const { selectTxInput, selectCallback, selectPath, selectBech32Address, selectClientName, reasonSelector, selectKeyInfo, isToLoginSelector, selectAction } = linkingSlice.selectors;
From 9d2727dd01e92ae6d4fdf31ab4917a440a33041d Mon Sep 17 00:00:00 2001
From: Iuri Pereira <689440+iuricmp@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:01:25 +0000
Subject: [PATCH 3/5] cleaning for safety
---
mobile/app/(app)/tosign/index.tsx | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/mobile/app/(app)/tosign/index.tsx b/mobile/app/(app)/tosign/index.tsx
index 3dbad3b..3dbd978 100644
--- a/mobile/app/(app)/tosign/index.tsx
+++ b/mobile/app/(app)/tosign/index.tsx
@@ -2,7 +2,7 @@ import { Layout } from "@/components";
import Button from "@/components/button";
import Spacer from "@/components/spacer";
import Text from "@/components/text";
-import { selectClientName, selectBech32Address, selectTxInput, signTx, useAppDispatch, useAppSelector, reasonSelector, selectCallback, selectKeyInfo } from "@/redux";
+import { selectClientName, selectBech32Address, selectTxInput, signTx, useAppDispatch, useAppSelector, reasonSelector, selectCallback, selectKeyInfo, clearLinking } from "@/redux";
import { useGnoNativeContext } from "@gnolang/gnonative";
import { router } from "expo-router";
import { useEffect, useState } from "react";
@@ -48,6 +48,11 @@ export default function Page() {
router.push("/home")
}
+ const onCancel = () => {
+ dispatch(clearLinking());
+ router.push("/home")
+ }
+
return (
<>
@@ -66,7 +71,7 @@ export default function Page() {
- router.push("/home")}>
+
>
From 677d1aa3db42998a4492d18022c0eff3397bfd74 Mon Sep 17 00:00:00 2001
From: Iuri Pereira <689440+iuricmp@users.noreply.github.com>
Date: Tue, 5 Nov 2024 11:12:21 +0000
Subject: [PATCH 4/5] fix: avoiding default url
---
mobile/redux/features/linkingSlice.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mobile/redux/features/linkingSlice.ts b/mobile/redux/features/linkingSlice.ts
index a62eb65..9ddfd6a 100644
--- a/mobile/redux/features/linkingSlice.ts
+++ b/mobile/redux/features/linkingSlice.ts
@@ -142,10 +142,13 @@ export const linkingSlice = createSlice({
selectKeyInfo: (state) => state.keyinfo,
reasonSelector: (state) => state.reason,
isToLoginSelector: (state) => state.hostname === 'tologin',
- selectAction: (state) => state.hostname,
+ selectAction: (state) => state.hostname !== expo_default ? state.hostname : undefined,
},
});
+// Expo default hostname
+const expo_default = 'expo-development-client';
+
export const { clearLinking } = linkingSlice.actions;
export const { selectTxInput, selectCallback, selectPath, selectBech32Address, selectClientName, reasonSelector, selectKeyInfo, isToLoginSelector, selectAction } = linkingSlice.selectors;
From 87679f4f10872507ea71085500514a6c83960b1c Mon Sep 17 00:00:00 2001
From: Iuri Pereira <689440+iuricmp@users.noreply.github.com>
Date: Tue, 5 Nov 2024 11:12:35 +0000
Subject: [PATCH 5/5] chore: change defauilt entrypoint
---
mobile/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mobile/package.json b/mobile/package.json
index 52963ba..813aa4f 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -1,7 +1,7 @@
{
"name": "gnokey",
"version": "0.0.1",
- "main": "expo-router/entry",
+ "main": "index.ts",
"scripts": {
"start": "expo start -d",
"android": "expo run:android",