diff --git a/.env.example b/.env.example index d563968..e5066ca 100644 --- a/.env.example +++ b/.env.example @@ -4,5 +4,4 @@ REACT_APP_DEFAULT_GAS_PRICE=0.025 # Reference: https://github.com/cosmos/cosmos-sdk/issues/16020 REACT_APP_GAS_ADJUSTMENT=2 REACT_APP_LACONICD_RPC_URL=https://laconicd-sapo.laconic.com - REACT_APP_DEPLOY_APP_URL= diff --git a/src/App.tsx b/src/App.tsx index ac840a9..827b397 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -41,6 +41,7 @@ import { AutoSignIn } from "./screens/AutoSignIn"; import { checkSufficientFunds, getPathKey, sendMessage } from "./utils/misc"; import useAccountsData from "./hooks/useAccountsData"; import { useWebViewHandler } from "./hooks/useWebViewHandler"; +import SignMessageEmbed from "./screens/SignMessageEmbed"; const Stack = createStackNavigator(); @@ -390,6 +391,14 @@ const App = (): React.JSX.Element => { header: () => <>, }} /> +
, + }} + /> ; + +const SignMessageEmbed = ({ route }: SignRequestProps) => { + const [displayAccount, setDisplayAccount] = useState(); + const [message, setMessage] = useState(''); + const [chainId, setChainId] = useState(''); + const [signDoc, setSignDoc] = useState(null); + const [signerAddress, setSignerAddress] = useState(''); + const [origin, setOrigin] = useState(''); + const [sourceWindow, setSourceWindow] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [isApproving, setIsApproving] = useState(false); + + const navigation = + useNavigation>(); + + const signMessageHandler = async () => { + if (!signDoc || !signerAddress || !sourceWindow) return; + + setIsApproving(true); + try { + const requestAccount = await retrieveSingleAccount(COSMOS, chainId, signerAddress); + const path = (await getPathKey(`${COSMOS}:${chainId}`, requestAccount!.index)).path; + const mnemonic = await getMnemonic(); + const cosmosAccount = await getCosmosAccounts(mnemonic, path, 'zenith'); + + const cosmosAminoSignature = await cosmosAccount.cosmosWallet.signAmino( + signerAddress, + signDoc, + ); + + const signature = cosmosAminoSignature.signature.signature; + + sendMessage( + sourceWindow, + 'ZENITH_SIGNED_MESSAGE', + { signature }, + origin, + ); + + navigation.navigate('Home'); + } catch (err) { + console.error('Signing failed:', err); + sendMessage( + sourceWindow!, + 'ZENITH_SIGNED_MESSAGE', + { error: err }, + origin, + ); + } finally { + setIsApproving(false); + } + }; + + + const rejectRequestHandler = async () => { + if (sourceWindow && origin) { + sendMessage( + sourceWindow, + 'ZENITH_SIGNED_MESSAGE', + { error: 'User rejected the request' }, + origin, + ); + } + navigation.navigate('Home'); + }; + + useEffect(() => { + const handleCosmosSignMessage = async (event: MessageEvent) => { + if (event.data.type !== 'SIGN_ZENITH_MESSAGE') return; + + try { + const { signerAddress, signDoc } = event.data.params; + + setSignerAddress(signerAddress); + setSignDoc(signDoc); + setMessage(signDoc.memo || ''); + setOrigin(event.origin); + setSourceWindow(event.source as Window); + setChainId(event.data.chainId); + + const requestAccount = await retrieveSingleAccount( + COSMOS, + event.data.chainId, + signerAddress, + ); + + setDisplayAccount(requestAccount); + setIsLoading(false); + } catch (err) { + console.error('Error preparing sign request:', err); + setIsLoading(false); + } + }; + + window.addEventListener('message', handleCosmosSignMessage); + return () => window.removeEventListener('message', handleCosmosSignMessage); + }, []); + + useEffect(() => { + navigation.setOptions({ + // eslint-disable-next-line react/no-unstable-nested-components + header: ({ options, back }) => { + const title = getHeaderTitle(options, 'Sign Message'); + + return ( + + {back && ( + { + await rejectRequestHandler(); + navigation.navigate('Home'); + }} + /> + )} + + + ); + }, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [navigation, route.name]); + + return ( + <> + {isLoading ? ( + + + + ) : ( + <> + + + + {message} + + + + + + + + )} + + ); +}; + +export default SignMessageEmbed; diff --git a/src/types.ts b/src/types.ts index 3b7341e..84ce968 100644 --- a/src/types.ts +++ b/src/types.ts @@ -40,6 +40,7 @@ export type StackParamsList = { }; "wallet-embed": undefined; "auto-sign-in": undefined; + "sign-message-embed": undefined; }; export type Account = { diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 8d03e44..7113d0b 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -18,6 +18,18 @@ export const DEFAULT_NETWORKS: NetworksFormData[] = [ gasPrice: '0.001', isDefault: true, }, + { + chainId: 'zenith-testnet', + networkName: 'zenithd testnet', + namespace: COSMOS, + rpcUrl: 'http://127.0.0.1:26657', + blockExplorerUrl: '', + nativeDenom: 'znt', + addressPrefix: 'zenith', + coinType: '118', + gasPrice: '0.01', + isDefault: true, + }, { chainId: 'laconic_9000-1', networkName: 'laconicd',