From 8d1a9cdc51c3a90655c80ba008ed3d993c279de0 Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Tue, 8 Oct 2024 16:50:52 +0200 Subject: [PATCH 1/5] chore: gnoboard: Add GnoboardProvider. See the PR Signed-off-by: Jeff Thompson --- examples/js/expo/gnoboard/App.tsx | 5 ++- .../src/provider/gnoboard-provider.tsx | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 examples/js/expo/gnoboard/src/provider/gnoboard-provider.tsx diff --git a/examples/js/expo/gnoboard/App.tsx b/examples/js/expo/gnoboard/App.tsx index da1fda81..5693a0cf 100644 --- a/examples/js/expo/gnoboard/App.tsx +++ b/examples/js/expo/gnoboard/App.tsx @@ -2,6 +2,7 @@ import 'react-native-polyfill-globals/auto'; import { GnoNativeProvider } from '@gnolang/gnonative'; +import { GnoboardProvider } from '@gno/provider/gnoboard-provider'; import CustomRouter from '@gno/router/custom-router'; // Polyfill async.Iterator. For some reason, the Babel presets and plugins are not doing the trick. @@ -16,7 +17,9 @@ function App() { return ( - + + + ); } diff --git a/examples/js/expo/gnoboard/src/provider/gnoboard-provider.tsx b/examples/js/expo/gnoboard/src/provider/gnoboard-provider.tsx new file mode 100644 index 00000000..9db95a33 --- /dev/null +++ b/examples/js/expo/gnoboard/src/provider/gnoboard-provider.tsx @@ -0,0 +1,35 @@ +import { createContext, useContext, useState, useCallback } from 'react'; + +import { KeyInfo } from '@gnolang/gnonative'; + +interface GnoboardProviderProps { + children: React.ReactNode; +} +interface GnoboardContextType { + account: KeyInfo | undefined; + setAccount: (keyInfo : KeyInfo | undefined) => void; +} + +const GnoboardContext = createContext(null); + +const GnoboardProvider: React.FC = ({ children }) => { + const [account, setAccount] = useState(undefined) + + const value = { + account, + setAccount + }; + + return {children}; +}; + +function useGnoboardContext() { + const context = useContext(GnoboardContext) as GnoboardContextType; + + if (context === undefined) { + throw new Error('useGnoboardContext must be used within a GnoboardProvider'); + } + return context; +} + +export { GnoboardProvider, useGnoboardContext }; From 50c517b6ed68c132fcb460f5d4f6bfb48c0bc695 Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Tue, 8 Oct 2024 17:36:50 +0200 Subject: [PATCH 2/5] chore: gnoboard switch-accounts: Change selectAccount to GnoboardProvider setAccount. Signed-off-by: Jeff Thompson --- .../src/screens/certify/create-password/index.tsx | 8 +++++--- .../gnoboard/src/screens/certify/enter-seed/index.tsx | 7 +++++-- .../expo/gnoboard/src/screens/switch-accounts/index.tsx | 5 ++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/examples/js/expo/gnoboard/src/screens/certify/create-password/index.tsx b/examples/js/expo/gnoboard/src/screens/certify/create-password/index.tsx index 654f447b..4db64214 100644 --- a/examples/js/expo/gnoboard/src/screens/certify/create-password/index.tsx +++ b/examples/js/expo/gnoboard/src/screens/certify/create-password/index.tsx @@ -12,6 +12,7 @@ import SeedBox from '@gno/components/seedbox'; import Alert from '@gno/components/alert'; import { Spacer } from '@gno/components/row'; import { ModalConfirm } from '@gno/components/modal'; +import { useGnoboardContext } from '@gno/provider/gnoboard-provider'; const text = { title: 'Create\na Password', @@ -27,7 +28,7 @@ const CreatePassword: React.FC = ({ route }) => { const [confirmPassword, setConfirmPassword] = useState(''); const [error, setError] = useState(undefined); const [showModal, setShowModal] = useState(false); - + const { setAccount } = useGnoboardContext(); const { gnonative } = useGnoNativeContext(); const navigation = useNavigation(); @@ -51,8 +52,9 @@ const CreatePassword: React.FC = ({ route }) => { const response = await gnonative.createAccount(name, phrase, password); console.log('createAccount response: ' + response); - await gnonative.selectAccount(name); - await gnonative.setPassword(password); + await gnonative.activateAccount(name); + setAccount(response); + await gnonative.setPassword(password, response!.address); navigation.navigate(RoutePath.Home); } catch (error) { setError(JSON.stringify(error)); diff --git a/examples/js/expo/gnoboard/src/screens/certify/enter-seed/index.tsx b/examples/js/expo/gnoboard/src/screens/certify/enter-seed/index.tsx index a49ec283..3b78e3a8 100644 --- a/examples/js/expo/gnoboard/src/screens/certify/enter-seed/index.tsx +++ b/examples/js/expo/gnoboard/src/screens/certify/enter-seed/index.tsx @@ -11,6 +11,7 @@ import TextInput from '@gno/components/textinput'; import Alert from '@gno/components/alert'; import { Spacer } from '@gno/components/row'; import { ModalConfirm } from '@gno/components/modal'; +import { useGnoboardContext } from '@gno/provider/gnoboard-provider'; const walletContent = { title: 'Import with Seed Phrase', @@ -27,6 +28,7 @@ const EnterSeedPhrase = () => { const [showModal, setShowModal] = useState(false); const { gnonative } = useGnoNativeContext(); const navigation = useNavigation(); + const { setAccount } = useGnoboardContext(); const recoverAccount = async (override: boolean = false) => { if (!recoveryPhrase || !name || !password || !confirmPassword) return; @@ -47,8 +49,9 @@ const EnterSeedPhrase = () => { } const response = await gnonative.createAccount(name, recoveryPhrase, password); - await gnonative.selectAccount(name); - await gnonative.setPassword(password); + await gnonative.activateAccount(name); + await gnonative.setPassword(password, response!.address); + setAccount(response); console.log('createAccount response: ' + response); navigation.navigate(RoutePath.Home); } catch (error) { diff --git a/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx b/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx index 9b830461..0c7d4ea5 100644 --- a/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx +++ b/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx @@ -4,6 +4,7 @@ import { KeyInfo, useGnoNativeContext } from '@gnolang/gnonative'; import { RouterWelcomeStackProp } from '@gno/router/custom-router'; import { useNavigation } from '@react-navigation/native'; import { useEffect, useState } from 'react'; +import { useGnoboardContext } from '@gno/provider/gnoboard-provider'; import Loading from '../loading'; import SideMenuAccountList from '@gno/components/common/side-menu-account-list/side-menu-account-list'; import { RoutePath } from '@gno/router/path'; @@ -15,6 +16,7 @@ const SwitchAccounts = () => { const [loading, setLoading] = useState(undefined); const [accounts, setAccounts] = useState([]); const [reenterPassword, setReenterPassword] = useState(undefined); + const { setAccount } = useGnoboardContext(); useEffect(() => { const unsubscribe = navigation.addListener('focus', async () => { @@ -35,7 +37,8 @@ const SwitchAccounts = () => { const onChangeAccountHandler = async (value: KeyInfo) => { try { setLoading('Changing account...'); - const response = await gnonative.selectAccount(value.name); + const response = await gnonative.activateAccount(value.name); + setAccount(value); setLoading(undefined); if (!response.hasPassword) { setReenterPassword(value.name); From f6fdc3256b66056b2b706500bb450ba504f780b8 Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Tue, 8 Oct 2024 17:38:08 +0200 Subject: [PATCH 3/5] chore: gnoboard ReenterPassword: Add param accountAddress and use it in setPassword Signed-off-by: Jeff Thompson --- .../expo/gnoboard/src/screens/devmode/index.tsx | 15 +++++++++++---- .../screens/switch-accounts/ReenterPassword.tsx | 5 +++-- .../src/screens/switch-accounts/index.tsx | 4 +++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/examples/js/expo/gnoboard/src/screens/devmode/index.tsx b/examples/js/expo/gnoboard/src/screens/devmode/index.tsx index 01e69401..2e3ab72e 100644 --- a/examples/js/expo/gnoboard/src/screens/devmode/index.tsx +++ b/examples/js/expo/gnoboard/src/screens/devmode/index.tsx @@ -14,24 +14,31 @@ import { ConnectError } from '@connectrpc/connect'; import { useNavigation } from '@react-navigation/native'; import { RouterWelcomeStackProp } from '@gno/router/custom-router'; import { RoutePath } from '@gno/router/path'; +import { useGnoboardContext } from '@gno/provider/gnoboard-provider'; function DevMode() { const [postContent, setPostContent] = useState(''); const [appConsole, setAppConsole] = useState(''); const [loading, setLoading] = useState(undefined); const [reenterPassword, setReenterPassword] = useState(undefined); + const [reenterPasswordAddress, setReenterPasswordAddress] = useState(undefined); const navigate = useNavigation(); const { gnonative } = useGnoNativeContext(); + const { account } = useGnoboardContext(); const onPostPress = async () => { + if (!account) + // shouldn't happen, but just in case + throw new Error("No active account"); + setLoading('Replying to a post...'); setAppConsole('replying to a post...'); const gasFee = '1000000ugnot'; const gasWanted = BigInt(2000000); const args: Array = ['1', '1', '1', postContent]; try { - for await (const response of await gnonative.call('gno.land/r/demo/boards', 'CreateReply', args, gasFee, gasWanted)) { + for await (const response of await gnonative.call('gno.land/r/demo/boards', 'CreateReply', args, gasFee, gasWanted, account.address)) { console.log('response: ', response); setAppConsole(Buffer.from(response.result).toString()); } @@ -39,8 +46,8 @@ function DevMode() { if (error instanceof ConnectError) { const err = new GRPCError(error); if (err.errCode() === ErrCode.ErrDecryptionFailed) { - const account = await gnonative.getActiveAccount(); - setReenterPassword(account.key?.name); + setReenterPassword(account.name); + setReenterPasswordAddress(account.address); return; } } @@ -86,7 +93,7 @@ function DevMode() { {reenterPassword ? ( - + ) : null} ); diff --git a/examples/js/expo/gnoboard/src/screens/switch-accounts/ReenterPassword.tsx b/examples/js/expo/gnoboard/src/screens/switch-accounts/ReenterPassword.tsx index c82fa132..8651911c 100644 --- a/examples/js/expo/gnoboard/src/screens/switch-accounts/ReenterPassword.tsx +++ b/examples/js/expo/gnoboard/src/screens/switch-accounts/ReenterPassword.tsx @@ -12,10 +12,11 @@ import { ConnectError } from '@connectrpc/connect'; export type Props = { visible: boolean; accountName: string; + accountAddress: Uint8Array; onClose: (sucess: boolean) => void; }; -const ReenterPassword = ({ visible, accountName, onClose }: Props) => { +const ReenterPassword = ({ visible, accountName, accountAddress, onClose }: Props) => { const { gnonative } = useGnoNativeContext(); const [password, setPassword] = useState(''); const [error, setError] = useState(undefined); @@ -25,7 +26,7 @@ const ReenterPassword = ({ visible, accountName, onClose }: Props) => { try { setError(undefined); - await gnonative.setPassword(password); + await gnonative.setPassword(password, accountAddress); onClose(true); } catch (error) { if (error instanceof ConnectError) { diff --git a/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx b/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx index 0c7d4ea5..a572ed2e 100644 --- a/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx +++ b/examples/js/expo/gnoboard/src/screens/switch-accounts/index.tsx @@ -16,6 +16,7 @@ const SwitchAccounts = () => { const [loading, setLoading] = useState(undefined); const [accounts, setAccounts] = useState([]); const [reenterPassword, setReenterPassword] = useState(undefined); + const [reenterPasswordAddress, setReenterPasswordAddress] = useState(undefined); const { setAccount } = useGnoboardContext(); useEffect(() => { @@ -42,6 +43,7 @@ const SwitchAccounts = () => { setLoading(undefined); if (!response.hasPassword) { setReenterPassword(value.name); + setReenterPasswordAddress(value.address); return; } navigation.navigate(RoutePath.Home); @@ -71,7 +73,7 @@ const SwitchAccounts = () => { {reenterPassword ? ( - + ) : null} ); From 533329d8fdc2e3a9c72a839a54b1c3caf52ff4cb Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Tue, 8 Oct 2024 17:48:18 +0200 Subject: [PATCH 4/5] chore: gnoboard: wallet/home: Pass in account instead of getActiveAccount Signed-off-by: Jeff Thompson --- .../expo/gnoboard/src/screens/wallet/home/index.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/js/expo/gnoboard/src/screens/wallet/home/index.tsx b/examples/js/expo/gnoboard/src/screens/wallet/home/index.tsx index 68dfd056..acd6d06d 100644 --- a/examples/js/expo/gnoboard/src/screens/wallet/home/index.tsx +++ b/examples/js/expo/gnoboard/src/screens/wallet/home/index.tsx @@ -12,27 +12,25 @@ import { AccountBalance } from '@gno/components/account'; import { Spacer } from '@gno/components/row'; import { ConnectError } from '@connectrpc/connect'; import { ErrCode, GRPCError, useGnoNativeContext, KeyInfo, QueryAccountResponse } from '@gnolang/gnonative'; +import { useGnoboardContext } from '@gno/provider/gnoboard-provider'; export const Home: React.FC = () => { const navigation = useNavigation(); const { gnonative } = useGnoNativeContext(); + const { account } = useGnoboardContext(); const [loading, setLoading] = React.useState(undefined); - const [account, setAccount] = React.useState(undefined); const [balance, setBalance] = React.useState(undefined); const [unknownAddress, setUnknownAddress] = React.useState(false); useEffect(() => { const unsubscribe = navigation.addListener('focus', async () => { setUnknownAddress(false); - setAccount(undefined); setBalance(undefined); try { - const response = await gnonative.getActiveAccount(); - setAccount(response.key); - if (response.key) { - const balance = await gnonative.queryAccount(response.key.address); + if (account) { + const balance = await gnonative.queryAccount(account.address); setBalance(balance); } } catch (error) { @@ -47,7 +45,7 @@ export const Home: React.FC = () => { } }); return unsubscribe; - }, [navigation]); + }, [navigation, account]); if (loading) { return ; From 312fd4706990f2e78f8ff5f28f400aa02ace43e8 Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Tue, 8 Oct 2024 17:50:05 +0200 Subject: [PATCH 5/5] chore: gnoboard: In Makefile, call ts_check after node_modules for each target This is the same fix as PR https://github.com/gnolang/dsocial/pull/134 Signed-off-by: Jeff Thompson --- examples/js/expo/gnoboard/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/js/expo/gnoboard/Makefile b/examples/js/expo/gnoboard/Makefile index 12c96070..390b8173 100644 --- a/examples/js/expo/gnoboard/Makefile +++ b/examples/js/expo/gnoboard/Makefile @@ -29,14 +29,14 @@ ts_check: # - Node: Handle node_modules -node_modules: ts_check package.json package-lock.json +node_modules: package.json package-lock.json $(call check-program, npm) (npm install && touch $@) || true .PHONY: node_modules ######### ANDROID ######### -android: node_modules $(ANDROID_FRAMEWORK_SRC) +android: node_modules ts_check $(ANDROID_FRAMEWORK_SRC) $(call check-program, npx) npx expo run:android .PHONY: build.android @@ -46,7 +46,7 @@ $(ANDROID_FRAMEWORK_SRC): $(go_deps) ######### IOS ######### -ios: node_modules $(IOS_FRAMEWORK_SRC) +ios: node_modules ts_check $(IOS_FRAMEWORK_SRC) $(call check-program, npx) npx expo run:ios .PHONY: build.ios