Refactor iframe request and response types
This commit is contained in:
parent
2611950c10
commit
d94980efe1
@ -44,7 +44,7 @@ import { useWebViewHandler } from "./hooks/useWebViewHandler";
|
||||
import SignRequestEmbed from "./screens/SignRequestEmbed";
|
||||
import useAddAccountEmbed from "./hooks/useAddAccountEmbed";
|
||||
import useExportPKEmbed from "./hooks/useExportPrivateKeyEmbed";
|
||||
import { SendTxEmbed } from "./screens/SendTxEmbed";
|
||||
import { SignTxEmbed } from "./screens/SignTxEmbed";
|
||||
|
||||
const Stack = createStackNavigator<StackParamsList>();
|
||||
|
||||
@ -390,8 +390,8 @@ const App = (): React.JSX.Element => {
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="send-tx-embed"
|
||||
component={SendTxEmbed}
|
||||
name="sign-tx-embed"
|
||||
component={SignTxEmbed}
|
||||
options={{
|
||||
header: () => <></>,
|
||||
}}
|
||||
|
||||
@ -5,6 +5,7 @@ import { sendMessage } from "../utils/misc";
|
||||
import useAccountsData from "./useAccountsData";
|
||||
import { useNetworks } from "../context/NetworksContext";
|
||||
import { useAccounts } from "../context/AccountsContext";
|
||||
import { WALLET_ACCOUNTS_DATA } from "../utils/constants";
|
||||
|
||||
const REACT_APP_ALLOWED_URLS = process.env.REACT_APP_ALLOWED_URLS;
|
||||
|
||||
@ -48,7 +49,7 @@ const useGetOrCreateAccounts = () => {
|
||||
const accountsData = await getOrCreateAccountsForChain(event.data.chainId);
|
||||
|
||||
sendMessage(
|
||||
event.source as Window, 'WALLET_ACCOUNTS_DATA',
|
||||
event.source as Window, WALLET_ACCOUNTS_DATA,
|
||||
accountsData.map(account => account.address),
|
||||
event.origin
|
||||
);
|
||||
|
||||
@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
|
||||
|
||||
import { useNetworks } from '../context/NetworksContext';
|
||||
import { signMessage } from '../utils/sign-message';
|
||||
import { EIP155 } from '../utils/constants';
|
||||
import { AUTO_SIGN_IN, EIP155, SIGN_IN_RESPONSE } from '../utils/constants';
|
||||
import { sendMessage } from '../utils/misc';
|
||||
import useAccountsData from '../hooks/useAccountsData';
|
||||
import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts';
|
||||
@ -16,7 +16,7 @@ export const AutoSignIn = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const handleSignIn = async (event: MessageEvent) => {
|
||||
if (event.data.type !== 'AUTO_SIGN_IN') return;
|
||||
if (event.data.type !== AUTO_SIGN_IN) return;
|
||||
|
||||
if (!REACT_APP_ALLOWED_URLS) {
|
||||
console.log('Allowed URLs are not set');
|
||||
@ -38,7 +38,7 @@ export const AutoSignIn = () => {
|
||||
|
||||
const signature = await signMessage({ message: event.data.message, accountId: accountsData[0].index, chainId: event.data.chainId, namespace: EIP155 })
|
||||
|
||||
sendMessage(event.source as Window, 'SIGN_IN_RESPONSE', { message: event.data.message, signature }, event.origin);
|
||||
sendMessage(event.source as Window, SIGN_IN_RESPONSE, { message: event.data.message, signature }, event.origin);
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleSignIn);
|
||||
|
||||
@ -14,7 +14,8 @@ import AccountDetails from '../components/AccountDetails';
|
||||
import styles from '../styles/stylesheet';
|
||||
import { getCosmosAccounts, retrieveSingleAccount } from '../utils/accounts';
|
||||
import { getMnemonic, getPathKey, sendMessage } from '../utils/misc';
|
||||
import { COSMOS } from '../utils/constants';
|
||||
import { COSMOS, SIGN_MESSAGE, SIGNED_MESSAGE } from '../utils/constants';
|
||||
import { useNetworks } from '../context/NetworksContext';
|
||||
|
||||
const REACT_APP_ALLOWED_URLS = process.env.REACT_APP_ALLOWED_URLS;
|
||||
|
||||
@ -31,6 +32,7 @@ const SignRequestEmbed = ({ route }: SignRequestProps) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isApproving, setIsApproving] = useState(false);
|
||||
|
||||
const { networksData } = useNetworks();
|
||||
const navigation =
|
||||
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
||||
|
||||
@ -42,7 +44,13 @@ const SignRequestEmbed = ({ route }: SignRequestProps) => {
|
||||
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 requestedNetworkData = networksData.find(networkData => networkData.chainId === chainId)
|
||||
if (!requestedNetworkData) {
|
||||
throw new Error("Requested network not found")
|
||||
}
|
||||
|
||||
const cosmosAccount = await getCosmosAccounts(mnemonic, path, requestedNetworkData?.addressPrefix);
|
||||
|
||||
const cosmosAminoSignature = await cosmosAccount.cosmosWallet.signAmino(
|
||||
signerAddress,
|
||||
@ -53,7 +61,7 @@ const SignRequestEmbed = ({ route }: SignRequestProps) => {
|
||||
|
||||
sendMessage(
|
||||
sourceWindow,
|
||||
'ZENITH_SIGNED_MESSAGE',
|
||||
SIGNED_MESSAGE,
|
||||
{ signature },
|
||||
origin,
|
||||
);
|
||||
@ -63,7 +71,7 @@ const SignRequestEmbed = ({ route }: SignRequestProps) => {
|
||||
console.error('Signing failed:', err);
|
||||
sendMessage(
|
||||
sourceWindow!,
|
||||
'ZENITH_SIGNED_MESSAGE',
|
||||
SIGNED_MESSAGE,
|
||||
{ error: err },
|
||||
origin,
|
||||
);
|
||||
@ -76,7 +84,7 @@ const SignRequestEmbed = ({ route }: SignRequestProps) => {
|
||||
if (sourceWindow && origin) {
|
||||
sendMessage(
|
||||
sourceWindow,
|
||||
'ZENITH_SIGNED_MESSAGE',
|
||||
SIGNED_MESSAGE,
|
||||
{ error: 'User rejected the request' },
|
||||
origin,
|
||||
);
|
||||
@ -85,7 +93,7 @@ const SignRequestEmbed = ({ route }: SignRequestProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
const handleCosmosSignMessage = async (event: MessageEvent) => {
|
||||
if (event.data.type !== 'SIGN_ZENITH_MESSAGE') return;
|
||||
if (event.data.type !== SIGN_MESSAGE) return;
|
||||
|
||||
|
||||
if (!REACT_APP_ALLOWED_URLS) {
|
||||
|
||||
@ -19,9 +19,7 @@ import { getPathKey, sendMessage } from '../utils/misc';
|
||||
import { useNetworks } from '../context/NetworksContext';
|
||||
import TxErrorDialog from '../components/TxErrorDialog';
|
||||
import { Account, NetworksDataState } from '../types';
|
||||
|
||||
const GET_ACCOUNTS_RESPONSE = "GET_ACCOUNTS_RESPONSE";
|
||||
const SIGN_ONBOARD_TX_RESPONSE = "SIGN_ONBOARD_TX_RESPONSE";
|
||||
import { REQUEST_SIGN_TX, REQUEST_COSMOS_ACCOUNTS_DATA, COSMOS_ACCOUNTS_RESPONSE, SIGN_TX_RESPONSE } from '../utils/constants';
|
||||
|
||||
// Type Definitions
|
||||
|
||||
@ -39,7 +37,7 @@ type IncomingMessageData = SignOnboardTxRequestData | GetAccountsRequestData;
|
||||
|
||||
interface IncomingMessageEventData {
|
||||
id: string;
|
||||
type: 'SIGN_ONBOARD_TX_REQUEST' | 'GET_ACCOUNTS_REQUEST';
|
||||
type: typeof REQUEST_SIGN_TX | typeof REQUEST_COSMOS_ACCOUNTS_DATA;
|
||||
data: IncomingMessageData;
|
||||
}
|
||||
|
||||
@ -64,7 +62,7 @@ interface GetAccountsResponse {
|
||||
}>;
|
||||
}
|
||||
|
||||
export const SendTxEmbed = () => {
|
||||
export const SignTxEmbed = () => {
|
||||
const [isTxApprovalVisible, setIsTxApprovalVisible] = useState<boolean>(false);
|
||||
const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null);
|
||||
const [isTxLoading, setIsTxLoading] = useState(false);
|
||||
@ -74,26 +72,27 @@ export const SendTxEmbed = () => {
|
||||
|
||||
// Message Handlers
|
||||
|
||||
const handleGetAccountsRequest = useCallback(async (event: MessageEvent<IncomingMessageEventData>) => {
|
||||
const handleGetCosmosAccountsRequest = useCallback(async (event: MessageEvent<IncomingMessageEventData>) => {
|
||||
const { id, data } = event.data;
|
||||
const source = event.source as Window;
|
||||
const origin = event.origin;
|
||||
const requestData = data as GetAccountsRequestData;
|
||||
|
||||
console.log("Received GET_ACCOUNTS_REQUEST", id);
|
||||
console.log(`Received ${REQUEST_COSMOS_ACCOUNTS_DATA}`, id);
|
||||
try {
|
||||
const requestedNetworkData = networksData.find(networkData => networkData.chainId === requestData.chainId)
|
||||
|
||||
if(!requestedNetworkData) {
|
||||
throw new Error("Zenith network data not found")
|
||||
throw new Error("Network data not found")
|
||||
}
|
||||
// Ensure retrieveAccounts exists and returns Account[]
|
||||
const allAccounts = await retrieveAccounts(requestedNetworkData); // Use retrieveAccounts
|
||||
|
||||
const allAccounts = await retrieveAccounts(requestedNetworkData);
|
||||
|
||||
if (!allAccounts || allAccounts.length === 0) {
|
||||
throw new Error("Accounts not found for zenithNetwork")
|
||||
throw new Error("Accounts not found for network")
|
||||
}
|
||||
|
||||
// TODO: Refactor getCosmosAccounts functions to return all accounts
|
||||
const responseAccounts = await Promise.all(
|
||||
allAccounts.map(async (acc) => {
|
||||
const cosmosAccount = await getCosmosAccount(acc.hdPath, requestedNetworkData.addressPrefix!);
|
||||
@ -105,13 +104,13 @@ export const SendTxEmbed = () => {
|
||||
);
|
||||
|
||||
const response: GetAccountsResponse = { accounts: responseAccounts };
|
||||
sendMessage(source, GET_ACCOUNTS_RESPONSE, {id, data: response}, origin);
|
||||
sendMessage(source, COSMOS_ACCOUNTS_RESPONSE, {id, data: response}, origin);
|
||||
} catch (error: unknown) {
|
||||
console.error("Error handling GET_ACCOUNTS_REQUEST:", error);
|
||||
console.error(`Error handling ${REQUEST_COSMOS_ACCOUNTS_DATA}:`, error);
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
// Check if source is a Window before sending message
|
||||
if (source instanceof Window) {
|
||||
sendMessage(source, GET_ACCOUNTS_RESPONSE, { id, error: `Failed to get accounts: ${errorMsg}` }, origin);
|
||||
sendMessage(source, COSMOS_ACCOUNTS_RESPONSE, { id, error: `Failed to get accounts: ${errorMsg}` }, origin);
|
||||
} else {
|
||||
console.error("Cannot send error message: source is not a Window");
|
||||
}
|
||||
@ -124,7 +123,7 @@ export const SendTxEmbed = () => {
|
||||
const origin = event.origin;
|
||||
const requestData = data as SignOnboardTxRequestData;
|
||||
|
||||
console.log("Received SIGN_ONBOARD_TX_REQUEST", id);
|
||||
console.log(`Received ${REQUEST_SIGN_TX}`, id);
|
||||
setIsTxApprovalVisible(false);
|
||||
setTransactionDetails(null);
|
||||
setTxError(null);
|
||||
@ -171,7 +170,7 @@ export const SendTxEmbed = () => {
|
||||
setIsTxApprovalVisible(true);
|
||||
|
||||
} catch (error: unknown) {
|
||||
console.error("Error handling SIGN_ONBOARD_TX_REQUEST:", error);
|
||||
console.error(`Error handling ${REQUEST_SIGN_TX}:`, error);
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
|
||||
sendMessage(source, id, { error: `Failed to prepare transaction: ${errorMsg}` }, origin);
|
||||
@ -187,16 +186,16 @@ export const SendTxEmbed = () => {
|
||||
const messageData = event.data as IncomingMessageEventData;
|
||||
|
||||
switch (messageData.type) {
|
||||
case 'GET_ACCOUNTS_REQUEST':
|
||||
handleGetAccountsRequest(event as MessageEvent<IncomingMessageEventData>);
|
||||
case REQUEST_COSMOS_ACCOUNTS_DATA:
|
||||
handleGetCosmosAccountsRequest(event as MessageEvent<IncomingMessageEventData>);
|
||||
break;
|
||||
case 'SIGN_ONBOARD_TX_REQUEST':
|
||||
case REQUEST_SIGN_TX:
|
||||
handleSignOnboardTxRequest(event as MessageEvent<IncomingMessageEventData>);
|
||||
break;
|
||||
default:
|
||||
console.warn(`Received unknown message type: ${messageData.type}`);
|
||||
}
|
||||
}, [handleGetAccountsRequest, handleSignOnboardTxRequest]);
|
||||
}, [handleGetCosmosAccountsRequest, handleSignOnboardTxRequest]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('message', handleIncomingMessage);
|
||||
@ -228,7 +227,7 @@ export const SendTxEmbed = () => {
|
||||
// Perform the actual signing
|
||||
const signResponse = await wallet.signDirect(signerAddress, signDoc);
|
||||
|
||||
sendMessage(source as Window, SIGN_ONBOARD_TX_RESPONSE, {id: requestId, data: signResponse}, origin);
|
||||
sendMessage(source as Window, SIGN_TX_RESPONSE, {id: requestId, data: signResponse}, origin);
|
||||
console.log("Sent signDirect response:", requestId);
|
||||
|
||||
setIsTxApprovalVisible(false);
|
||||
@ -239,7 +238,7 @@ export const SendTxEmbed = () => {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
|
||||
setTxError(errorMsg);
|
||||
sendMessage(source as Window, SIGN_ONBOARD_TX_RESPONSE, {id: requestId, error: `Failed to sign transaction: ${errorMsg}` }, origin);
|
||||
sendMessage(source as Window, SIGN_TX_RESPONSE, {id: requestId, error: `Failed to sign transaction: ${errorMsg}` }, origin);
|
||||
} finally {
|
||||
setIsTxLoading(false);
|
||||
}
|
||||
@ -250,7 +249,7 @@ export const SendTxEmbed = () => {
|
||||
const { requestId, source, origin } = transactionDetails;
|
||||
console.log("Rejecting request:", requestId);
|
||||
|
||||
sendMessage(source as Window, SIGN_ONBOARD_TX_RESPONSE, {id: requestId, error: "User rejected the signature request." }, origin);
|
||||
sendMessage(source as Window, SIGN_TX_RESPONSE, {id: requestId, error: "User rejected the signature request." }, origin);
|
||||
setIsTxApprovalVisible(false);
|
||||
setTransactionDetails(null);
|
||||
setTxError(null);
|
||||
|
||||
@ -26,6 +26,7 @@ import { MEMO } from '../screens/ApproveTransfer';
|
||||
import { Account, NetworksDataState } from '../types';
|
||||
import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts';
|
||||
import useAccountsData from '../hooks/useAccountsData';
|
||||
import { REQUEST_TX, REQUEST_WALLET_ACCOUNTS, TRANSACTION_RESPONSE, WALLET_ACCOUNTS_DATA } from '../utils/constants';
|
||||
|
||||
type TransactionDetails = {
|
||||
chainId: string;
|
||||
@ -51,8 +52,7 @@ export const WalletEmbed = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const handleGetAccounts = async (event: MessageEvent) => {
|
||||
// TODO: Keep event data types in constant file
|
||||
if (event.data.type !== 'REQUEST_WALLET_ACCOUNTS') return;
|
||||
if (event.data.type !== REQUEST_WALLET_ACCOUNTS) return;
|
||||
|
||||
const accountsData = await getAccountsData(event.data.chainId);
|
||||
|
||||
@ -63,7 +63,7 @@ export const WalletEmbed = () => {
|
||||
|
||||
sendMessage(
|
||||
event.source as Window,
|
||||
'WALLET_ACCOUNTS_DATA',
|
||||
WALLET_ACCOUNTS_DATA,
|
||||
accountsData.map(account => account.address),
|
||||
event.origin
|
||||
);
|
||||
@ -82,7 +82,7 @@ export const WalletEmbed = () => {
|
||||
const handleTxRequested = useCallback(
|
||||
async (event: MessageEvent) => {
|
||||
try {
|
||||
if (event.data.type !== 'REQUEST_TX') return;
|
||||
if (event.data.type !== REQUEST_TX) return;
|
||||
|
||||
txEventRef.current = event;
|
||||
|
||||
@ -208,7 +208,7 @@ export const WalletEmbed = () => {
|
||||
|
||||
const event = txEventRef.current;
|
||||
if (event?.source) {
|
||||
sendMessage(event.source as Window, 'TRANSACTION_RESPONSE', txResult.transactionHash, event.origin);
|
||||
sendMessage(event.source as Window, TRANSACTION_RESPONSE, txResult.transactionHash, event.origin);
|
||||
} else {
|
||||
console.error('No event source available to send message');
|
||||
}
|
||||
@ -228,7 +228,7 @@ export const WalletEmbed = () => {
|
||||
setIsTxRequested(false);
|
||||
setTransactionDetails(null);
|
||||
if (event?.source) {
|
||||
sendMessage(event.source as Window, 'TRANSACTION_RESPONSE', null, event.origin);
|
||||
sendMessage(event.source as Window, TRANSACTION_RESPONSE, null, event.origin);
|
||||
} else {
|
||||
console.error('No event source available to send message');
|
||||
}
|
||||
@ -308,7 +308,7 @@ export const WalletEmbed = () => {
|
||||
hideDialog={() => {
|
||||
setTxError(null)
|
||||
if (window.parent) {
|
||||
sendMessage(window.parent, 'TRANSACTION_RESPONSE', null, '*');
|
||||
sendMessage(window.parent, TRANSACTION_RESPONSE, null, '*');
|
||||
sendMessage(window.parent, 'closeIframe', null, '*');
|
||||
}
|
||||
}}
|
||||
|
||||
@ -41,7 +41,7 @@ export type StackParamsList = {
|
||||
"wallet-embed": undefined;
|
||||
"auto-sign-in": undefined;
|
||||
"sign-request-embed": undefined;
|
||||
"send-tx-embed": undefined;
|
||||
"sign-tx-embed": undefined;
|
||||
};
|
||||
|
||||
export type Account = {
|
||||
|
||||
@ -74,3 +74,19 @@ export const INVALID_URL_ERROR = 'Invalid URL';
|
||||
export const IS_NUMBER_REGEX = /^\d+$/;
|
||||
|
||||
export const IS_IMPORT_WALLET_ENABLED = false;
|
||||
|
||||
// iframe request types
|
||||
export const REQUEST_COSMOS_ACCOUNTS_DATA = 'REQUEST_COSMOS_ACCOUNTS_DATA';
|
||||
export const REQUEST_SIGN_TX = 'REQUEST_SIGN_TX';
|
||||
export const SIGN_MESSAGE = 'SIGN_MESSAGE';
|
||||
export const REQUEST_WALLET_ACCOUNTS = 'REQUEST_WALLET_ACCOUNTS';
|
||||
export const REQUEST_TX = 'REQUEST_TX';
|
||||
export const AUTO_SIGN_IN = 'AUTO_SIGN_IN';
|
||||
|
||||
// iframe response types
|
||||
export const COSMOS_ACCOUNTS_RESPONSE = 'COSMOS_ACCOUNTS_RESPONSE';
|
||||
export const SIGN_TX_RESPONSE = 'SIGN_TX_RESPONSE';
|
||||
export const SIGNED_MESSAGE = 'SIGNED_MESSAGE';
|
||||
export const WALLET_ACCOUNTS_DATA = 'WALLET_ACCOUNTS_DATA';
|
||||
export const TRANSACTION_RESPONSE = 'TRANSACTION_RESPONSE';
|
||||
export const SIGN_IN_RESPONSE = 'SIGN_IN_RESPONSE';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user