Skip to content

Commit

Permalink
Merge pull request #186 from valefar-on-discord/update-electron-version
Browse files Browse the repository at this point in the history
Update electron and electron-build version to 28.2.2 and 24.9.1 respectively
  • Loading branch information
remyroy committed Feb 12, 2024
2 parents 33e933f + 01345ea commit 1340328
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 66 deletions.
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -12,8 +12,8 @@
"@types/react-router-dom": "^5.1.8",
"@types/styled-components": "^5.1.11",
"@types/tmp": "^0.2.2",
"electron": "18.3.15",
"electron-builder": "^22.14.5",
"electron": "^28.2.2",
"electron-builder": "^24.9.1",
"ts-loader": "^9.2.3",
"typescript": "^4.3.5",
"webpack": "^5.88.2",
Expand Down
81 changes: 73 additions & 8 deletions src/electron/index.ts
Expand Up @@ -3,11 +3,31 @@
* This typescript file contains the Electron app which renders the React app.
*/

import { BrowserWindow, app, ipcMain, dialog, clipboard } from "electron";
import {
BrowserWindow,
app,
clipboard,
dialog,
ipcMain,
shell,
} from "electron";
import { OpenDialogOptions } from "electron/common";
import { accessSync, constants } from "fs";
import path from "path";
import { isAddress } from 'web3-utils';

import { accessSync, constants } from "fs";
import { OpenDialogOptions } from "electron/common";
import {
doesDirectoryExist,
findFirstFile,
isDirectoryWritable,
} from './BashUtils';
import {
createMnemonic,
generateBLSChange,
generateKeys,
validateBLSCredentials,
validateMnemonic,
} from './Eth2Deposit';

/**
* VERSION and COMMITHASH are set by the git-revision-webpack-plugin module.
Expand All @@ -27,7 +47,7 @@ const doesFileExist = (filename: string): boolean => {
app.on("ready", () => {
var iconPath = path.join("static", "icon.png");
const bundledIconPath = path.join(process.resourcesPath, "..", "static", "icon.png");

if (doesFileExist(bundledIconPath)) {
iconPath = bundledIconPath;
}
Expand Down Expand Up @@ -66,15 +86,60 @@ app.on("ready", () => {
* This logic closes the application when the window is closed, explicitly.
* On MacOS this is not a default feature.
*/
ipcMain.on('close', (evt, arg) => {
ipcMain.on('close', () => {
app.quit();
})
});

/**
* Will grab the provide text and copy to the cipboard
*/
ipcMain.on('clipboardWriteText', (evt, ext, type) => {
clipboard.writeText(ext, type);
});

/**
* Will open a file explorer to the path provided
*/
ipcMain.on('shellShowItemInFolder', (event, fullPath: string) => {
shell.showItemInFolder(fullPath);
});

/**
* Provides the renderer a way to call the dialog.showOpenDialog function using IPC.
*/
ipcMain.handle('showOpenDialog', async (event, options) => {
return await dialog.showOpenDialog(<OpenDialogOptions> options);
ipcMain.handle('showOpenDialog', async (event, options: OpenDialogOptions) => {
return await dialog.showOpenDialog(options);
});

/**
* Passthroughs for non-electron renderer calls
*/
ipcMain.handle('createMnemonic', async (event, ...args: Parameters<typeof createMnemonic>) => {
return await createMnemonic(...args);
});
ipcMain.handle('generateBLSChange', async (event, ...args: Parameters<typeof generateBLSChange>) => {
return await generateBLSChange(...args);
});
ipcMain.handle('generateKeys', async (event, ...args: Parameters<typeof generateKeys>) => {
return await generateKeys(...args);
});
ipcMain.handle('validateBLSCredentials', async (event, ...args: Parameters<typeof validateBLSCredentials>) => {
return await validateBLSCredentials(...args);
});
ipcMain.handle('validateMnemonic', async (event, ...args: Parameters<typeof validateMnemonic>) => {
return await validateMnemonic(...args);
});
ipcMain.handle('doesDirectoryExist', async (event, ...args: Parameters<typeof doesDirectoryExist>) => {
return await doesDirectoryExist(...args);
});
ipcMain.handle('isDirectoryWritable', async (event, ...args: Parameters<typeof isDirectoryWritable>) => {
return await isDirectoryWritable(...args);
});
ipcMain.handle('findFirstFile', async (event, ...args: Parameters<typeof findFirstFile>) => {
return await findFirstFile(...args);
});
ipcMain.handle('isAddress', async (event, ...args: Parameters<typeof isAddress>) => {
return await isAddress(...args);
});

/**
Expand Down
52 changes: 20 additions & 32 deletions src/electron/preload.ts
Expand Up @@ -5,49 +5,37 @@

import {
contextBridge,
shell,
clipboard,
ipcRenderer,
OpenDialogOptions,
OpenDialogReturnValue
} from "electron";

import Web3Utils from 'web3-utils';

import { createMnemonic, generateKeys, validateMnemonic, validateBLSCredentials, generateBLSChange } from './Eth2Deposit';

import { doesDirectoryExist, isDirectoryWritable, findFirstFile } from './BashUtils';

const ipcRendererSendClose = () => {
ipcRenderer.send('close');
};

const invokeShowOpenDialog = (options: OpenDialogOptions): Promise<OpenDialogReturnValue> => {
return ipcRenderer.invoke('showOpenDialog', options);
};
import {
IBashUtilsAPI,
IElectronAPI,
IEth2DepositAPI,
IWeb3UtilsAPI,
} from "./renderer";

contextBridge.exposeInMainWorld('electronAPI', {
'shellOpenExternal': shell.openExternal,
'shellShowItemInFolder': shell.showItemInFolder,
'clipboardWriteText': clipboard.writeText,
'ipcRendererSendClose': ipcRendererSendClose,
'invokeShowOpenDialog': invokeShowOpenDialog
'clipboardWriteText': (...args: Parameters<IElectronAPI['clipboardWriteText']>) => ipcRenderer.send('clipboardWriteText', ...args),
'invokeShowOpenDialog': (...args: Parameters<IElectronAPI['invokeShowOpenDialog']>) => ipcRenderer.invoke('showOpenDialog', ...args),
'ipcRendererSendClose': () => ipcRenderer.send('close'),
'shellShowItemInFolder': (...args: Parameters<IElectronAPI['shellShowItemInFolder']>) => ipcRenderer.send('shellShowItemInFolder', ...args),
});

contextBridge.exposeInMainWorld('eth2Deposit', {
'createMnemonic': createMnemonic,
'generateKeys': generateKeys,
'validateMnemonic': validateMnemonic,
'validateBLSCredentials': validateBLSCredentials,
'generateBLSChange': generateBLSChange
'createMnemonic': (...args: Parameters<IEth2DepositAPI['createMnemonic']>) => ipcRenderer.invoke('createMnemonic', ...args),
'generateBLSChange': (...args: Parameters<IEth2DepositAPI['generateBLSChange']>) => ipcRenderer.invoke('generateBLSChange', ...args),
'generateKeys': (...args: Parameters<IEth2DepositAPI['generateKeys']>) => ipcRenderer.invoke('generateKeys', ...args),
'validateBLSCredentials': (...args: Parameters<IEth2DepositAPI['validateBLSCredentials']>) => ipcRenderer.invoke('validateBLSCredentials', ...args),
'validateMnemonic': (...args: Parameters<IEth2DepositAPI['validateMnemonic']>) => ipcRenderer.invoke('validateMnemonic', ...args),
});

contextBridge.exposeInMainWorld('bashUtils', {
'doesDirectoryExist': doesDirectoryExist,
'isDirectoryWritable': isDirectoryWritable,
'findFirstFile': findFirstFile
'doesDirectoryExist': (...args: Parameters<IBashUtilsAPI['doesDirectoryExist']>) => ipcRenderer.invoke('doesDirectoryExist', ...args),
'findFirstFile': (...args: Parameters<IBashUtilsAPI['findFirstFile']>) => ipcRenderer.invoke('findFirstFile', ...args),
'isDirectoryWritable': (...args: Parameters<IBashUtilsAPI['isDirectoryWritable']>) => ipcRenderer.invoke('isDirectoryWritable', ...args),
});

contextBridge.exposeInMainWorld('web3Utils', {
'isAddress': Web3Utils.isAddress
});
'isAddress': (...args: Parameters<IWeb3UtilsAPI['isAddress']>) => ipcRenderer.invoke('isAddress', ...args),
});
13 changes: 6 additions & 7 deletions src/electron/renderer.d.ts
Expand Up @@ -24,30 +24,29 @@ import {
} from "child_process"

export interface IElectronAPI {
shellOpenExternal: (url: string, options?: Electron.OpenExternalOptions | undefined) => Promise<void>,
shellShowItemInFolder: (fullPath: string) => void,
clipboardWriteText: (ext: string, type?: "selection" | "clipboard" | undefined) => void,
ipcRendererSendClose: () => void,
invokeShowOpenDialog: (options: OpenDialogOptions) => Promise<OpenDialogReturnValue>
ipcRendererSendClose: () => void,
shellShowItemInFolder: (fullPath: string) => void,
}

export interface IEth2DepositAPI {
createMnemonic: (language: string) => Promise<string>,
generateBLSChange: (folder: string, chain: string, mnemonic: string, index: number, indices: string, withdrawal_credentials: string, execution_address: string) => Promise<void>,
generateKeys: (mnemonic: string, index: number, count: number, network: string,
password: string, eth1_withdrawal_address: string, folder: string) => Promise<void>,
validateMnemonic: (mnemonic: string) => Promise<void>,
validateBLSCredentials: (chain: string, mnemonic: string, index: number, withdrawal_credentials: string) => Promise<void>,
generateBLSChange: (folder: string, chain: string, mnemonic: string, index: number, indices: string, withdrawal_credentials: string, execution_address: string) => Promise<void>,
validateMnemonic: (mnemonic: string) => Promise<void>,
}

export interface IBashUtilsAPI {
doesDirectoryExist: (directory: string) => Promise<boolean>,
isDirectoryWritable: (directory: string) => Promise<boolean>,
findFirstFile: (directory: string, startsWith: string) => Promise<string>
isDirectoryWritable: (directory: string) => Promise<boolean>,
}

export interface IWeb3UtilsAPI {
isAddress: (address: string, chainId?: number | undefined) => boolean
isAddress: (address: string, chainId?: number | undefined) => Promise<boolean>
}

declare global {
Expand Down
9 changes: 5 additions & 4 deletions src/react/components/BTECConfigurationWizard.tsx
Expand Up @@ -29,7 +29,7 @@ type Props = {
/**
* This is the wizard the user will navigate to configure their BLS to execution change.
* It uses the notion of a 'step' to render specific pages within the flow.
*
*
* @param props.onStepBack function to execute when stepping back
* @param props.onStepForward function to execute when stepping forward
* @param props.network the network for which to generate this BTEC
Expand Down Expand Up @@ -112,9 +112,9 @@ const BTECConfigurationWizard: FC<Props> = (props): ReactElement => {
}
}

const validateInputs = () => {
const validateInputs = async () => {
let isError = false;

if (props.startIndex < 0) {
setStartingIndexError(true);
isError = true;
Expand Down Expand Up @@ -179,7 +179,8 @@ const BTECConfigurationWizard: FC<Props> = (props): ReactElement => {
}

if (props.withdrawalAddress != "") {
if (!window.web3Utils.isAddress(props.withdrawalAddress)) {
const isValidAddress = await window.web3Utils.isAddress(props.withdrawalAddress);
if (!isValidAddress) {
setWithdrawalAddressError(true);
setWithdrawalAddressErrorMsg(errors.ADDRESS_FORMAT_ERROR);
isError = true;
Expand Down
11 changes: 6 additions & 5 deletions src/react/components/KeyConfigurationWizard.tsx
Expand Up @@ -28,7 +28,7 @@ type Props = {
/**
* This is the wizard the user will navigate to configure their keys.
* It uses the notion of a 'step' to render specific pages within the flow.
*
*
* @param props.onStepBack function to execute when stepping back
* @param props.onStepForward function to execute when stepping forward
* @param props.keyGenerationStartIndex the index at which to start generating keys for the user
Expand Down Expand Up @@ -121,7 +121,7 @@ const KeyConfigurationWizard: FC<Props> = (props): ReactElement => {
}
}

const validateInputs = () => {
const validateInputs = async () => {
let isError = false;

if (props.numberOfKeys < 1 || props.numberOfKeys > 1000) {
Expand All @@ -130,14 +130,14 @@ const KeyConfigurationWizard: FC<Props> = (props): ReactElement => {
} else {
setNumberOfKeysError(false);
}

if (props.password.length < 8) {
setPasswordStrengthError(true);
isError = true;
} else {
setPasswordStrengthError(false);
}

if (props.keyGenerationStartIndex < 0) {
setStartingIndexError(true);
isError = true;
Expand All @@ -146,7 +146,8 @@ const KeyConfigurationWizard: FC<Props> = (props): ReactElement => {
}

if (props.withdrawalAddress != "") {
if (!window.web3Utils.isAddress(props.withdrawalAddress)) {
const isValidAddress = await window.web3Utils.isAddress(props.withdrawalAddress);
if (!isValidAddress) {
setWithdrawalAddressFormatError(true);
isError = true;
} else {
Expand Down
23 changes: 15 additions & 8 deletions src/react/components/OnlineDetector.tsx
Expand Up @@ -25,25 +25,32 @@ const FixedErrorButton = styled(Button)`

const PulseAnimation = keyframes`
0% {
box-shadow: 0 0 0 0px rgba(250, 30, 14, 0.7);
background-color: rgba(250, 30, 14, 0.7);
width: 0px;
height: 0px;
}
70% {
box-shadow: 0 0 0 22px rgba(250, 30, 14, 0);
background-color: rgba(250, 30, 14, 0);
width: 50px;
height: 50px;
margin: -25px;
}
100% {
box-shadow: 0 0 0 0px rgba(250, 30, 14, 0);
background-color: rgba(250, 30, 14, 0);
width: 60px;
height: 60px;
margin: -30px;
}
`

const PusleCircle = styled(Box)`
position: absolute;
width: 1px;
height: 1px;
left: 22px;
box-shadow: 0 0 0 0px rgba(250, 30, 14, 0.7);
opacity: 1;
width: 0px;
height: 0px;
left: 23px;
background-color: rgba(250, 30, 14, 0);
animation: ${PulseAnimation} 3s infinite;
border-radius: 1000px;
`
Expand Down

0 comments on commit 1340328

Please sign in to comment.