diff --git a/electron/main.js b/electron/main.js
index 5f22cfe3e..439c78d3d 100644
--- a/electron/main.js
+++ b/electron/main.js
@@ -5,18 +5,16 @@ const {
BrowserWindow,
Tray,
Menu,
- shell,
Notification,
ipcMain,
} = require('electron');
-const { spawn, exec } = require('child_process');
+const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const os = require('os');
const next = require('next');
const http = require('http');
-const { isDockerRunning } = require('./docker');
const {
setupDarwin,
setupUbuntu,
diff --git a/frontend/components/Setup.tsx b/frontend/components/Setup.tsx
index 501cbec22..478df1c9c 100644
--- a/frontend/components/Setup.tsx
+++ b/frontend/components/Setup.tsx
@@ -1,6 +1,5 @@
import { CopyOutlined } from '@ant-design/icons';
import { Button, Input, message, Spin, Typography } from 'antd';
-import crypto from 'crypto';
import { useContext, useEffect, useMemo, useState } from 'react';
import { copyToClipboard } from '@/common-util';
@@ -26,14 +25,10 @@ export const Setup = () => {
switch (setupObject.state) {
case SetupScreen.Welcome:
return ;
- case SetupScreen.Backup:
- return ;
- case SetupScreen.Import:
- return ;
case SetupScreen.Password:
return ;
- case SetupScreen.Recovery:
- return ;
+ case SetupScreen.Backup:
+ return ;
case SetupScreen.Finalizing:
return ;
default:
@@ -49,60 +44,20 @@ const SetupWelcome = () => {
return (
Welcome
-
-
-
- );
-};
-
-const SetupBackup = () => {
- const { goto } = useSetup();
- const [mnemonic] = useState(
- 'test test test test test test test test test test test test',
- );
- return (
-
- Backup
-
- Please write down the following mnemonic phrase and keep it safe.
-
-
-
-
-
- );
-};
-
-const SetupImport = () => {
- const { goto } = useSetup();
- return (
-
- Import
-
- Enter your mnemonic phrase to import your account
-
-
-
+
+
);
};
const SetupPassword = () => {
- const { goto, setPasswordHash } = useSetup();
+ const { goto } = useSetup();
const [password, setPassword] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
- const passwordHash = useMemo(
- () => crypto.createHash('sha256').update(password).digest('hex'),
- [password],
- );
+ const handleClick = () => {
+ goto(SetupScreen.Backup);
+ };
return (
@@ -113,28 +68,35 @@ const SetupPassword = () => {
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
-
);
};
-const SetupRecovery = () => {
+const SetupBackup = () => {
const { goto } = useSetup();
+ const [mnemonic] = useState(
+ 'test test test test test test test test test test test test',
+ );
return (
- Recovery
+ Backup
- Please enter a public key that you can use to recover your wallet.
+ Please write down the following mnemonic phrase and keep it safe.
-
- goto(SetupScreen.Finalizing)}>Recover
+
+
+ copyToClipboard(mnemonic).then(() =>
+ message.success('Copied successfully!'),
+ )
+ }
+ >
+ Copy to clipboard
+
+ goto(SetupScreen.Finalizing)}>Next
);
};
diff --git a/frontend/context/UserBalanceProvider.tsx b/frontend/context/UserBalanceProvider.tsx
new file mode 100644
index 000000000..fd9537861
--- /dev/null
+++ b/frontend/context/UserBalanceProvider.tsx
@@ -0,0 +1,33 @@
+import { createContext, PropsWithChildren, useState } from 'react';
+import { useInterval } from 'usehooks-ts';
+
+import { useAppInfo } from '@/hooks';
+import { EthersService } from '@/service';
+
+export const UserBalanceContext = createContext<{
+ balance: number;
+}>({
+ balance: 0,
+});
+
+export const UserBalanceProvider = ({ children }: PropsWithChildren) => {
+ const { userPublicKey } = useAppInfo();
+ const [balance, setBalance] = useState(0);
+
+ const updateBalance = () => {
+ if (userPublicKey)
+ EthersService.getEthBalance(userPublicKey, 'http://localhost:8545').then(
+ (res) => setBalance(res),
+ );
+ };
+
+ useInterval(() => {
+ updateBalance();
+ }, 5000);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/frontend/hooks/useAppInfo.tsx b/frontend/hooks/useAppInfo.tsx
index e6025e386..298dfd7a9 100644
--- a/frontend/hooks/useAppInfo.tsx
+++ b/frontend/hooks/useAppInfo.tsx
@@ -6,7 +6,7 @@ import { Address } from '@/types';
export const useAppInfo = () => {
const { appInfo } = useContext(AppInfoContext);
- const userPublicKey: Address | undefined = appInfo?.account.key;
+ const userPublicKey: Address | undefined = appInfo?.account?.key;
return {
userPublicKey,
diff --git a/frontend/hooks/useUserBalance.tsx b/frontend/hooks/useUserBalance.tsx
new file mode 100644
index 000000000..5784ee536
--- /dev/null
+++ b/frontend/hooks/useUserBalance.tsx
@@ -0,0 +1,7 @@
+import { useContext } from 'react';
+
+import { UserBalanceContext } from '@/context/UserBalanceProvider';
+
+export const useUserBalance = () => {
+ return useContext(UserBalanceContext);
+};
diff --git a/frontend/pages/_app.tsx b/frontend/pages/_app.tsx
index 7a31f0f84..608165cd0 100644
--- a/frontend/pages/_app.tsx
+++ b/frontend/pages/_app.tsx
@@ -9,20 +9,23 @@ import {
ServicesProvider,
SetupProvider,
} from '@/context';
+import { UserBalanceProvider } from '@/context/UserBalanceProvider';
import { mainTheme } from '@/theme';
export default function App({ Component, pageProps }: AppProps) {
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx
index 52a32e243..2ae86644a 100644
--- a/frontend/pages/index.tsx
+++ b/frontend/pages/index.tsx
@@ -18,6 +18,7 @@ import { Receive, Send } from '@/components/Wallet';
import { serviceTemplates } from '@/constants';
import { PageState } from '@/enums';
import { usePageState, useServices } from '@/hooks';
+import { useUserBalance } from '@/hooks/useUserBalance';
import { ServicesService } from '@/service';
const { useToken } = theme;
@@ -50,8 +51,10 @@ const Main = () => {
const { token } = useToken();
const { setPageState } = usePageState();
const { services } = useServices();
+ const { balance } = useUserBalance();
const [serviceButtonState, setServiceButtonState] = useState({
+ isFunded: false,
isLoading: false,
isRunning: false,
});
@@ -80,15 +83,16 @@ const Main = () => {
const handleStart = useCallback(() => {
setServiceButtonState({ ...serviceButtonState, isLoading: true });
if (services.length > 0) {
- ServicesService.startDeployment(services[0].hash).then(() => {
+ return ServicesService.startDeployment(services[0].hash).then(() => {
setServiceButtonState({ ...serviceButtonState, isRunning: true });
});
}
- ServicesService.createService({ serviceTemplate, deploy: true }).then(
- () => {
- setServiceButtonState({ ...serviceButtonState, isLoading: false });
- },
- );
+ return ServicesService.createService({
+ serviceTemplate,
+ deploy: true,
+ }).then(() => {
+ setServiceButtonState({ ...serviceButtonState, isLoading: false });
+ });
}, [serviceButtonState, serviceTemplate, services]);
const handleStop = useCallback(() => {
@@ -100,6 +104,12 @@ const Main = () => {
}, [serviceButtonState, services]);
const serviceToggleButton = useMemo(() => {
+ if (!serviceButtonState.isFunded)
+ return (
+
+ Not funded
+
+ );
if (serviceButtonState.isLoading)
return (
@@ -123,14 +133,21 @@ const Main = () => {
);
}, [handleStart, handleStop, serviceButtonState]);
+ // Service button interval
useInterval(() => {
+ setServiceButtonState((prev) => ({ ...prev, isFunded: balance > 1 }));
+
if (services.length <= 0) {
- setServiceButtonState({ isLoading: false, isRunning: false });
+ setServiceButtonState((prev) => ({
+ ...prev,
+ isLoading: false,
+ isRunning: false,
+ }));
return;
}
if (services[0]) {
- ServicesService.getServiceStatus(services[0].hash).then((res) => {
+ ServicesService.getDeployment(services[0].hash).then((res) => {
res.status === DeploymentStatus.DEPLOYED
? setServiceButtonState((prev) => ({ ...prev, isRunning: true }))
: setServiceButtonState((prev) => ({ ...prev, isRunning: false }));
@@ -157,7 +174,9 @@ const Main = () => {
$
- 2,101
+
+ {balance.toFixed(2)}
+
+ fetch(`${BACKEND_URL}/account`).then((res) => res.json());
+
+/**
+ * Creates a local user account
+ */
+const createAccount = (password: string) =>
+ fetch(`${BACKEND_URL}/account`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ password }),
+ }).then((res) => res.json());
+
+/**
+ * Updates user's password
+ */
+const updateAccount = (oldPassword: string, newPassword: string) =>
+ fetch(`${BACKEND_URL}/account`, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ old_password: oldPassword,
+ new_password: newPassword,
+ }),
+ }).then((res) => res.json());
+
+/**
+ * Logs in a user
+ */
+const loginAccount = (password: string) =>
+ fetch(`${BACKEND_URL}/account/login`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ password,
+ }),
+ }).then((res) => res.json());
+
+export const AccountService = {
+ getAccount,
+ createAccount,
+ updateAccount,
+ loginAccount,
+};
diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts
index 62b8d8bd0..9dab2b105 100644
--- a/frontend/service/Services.ts
+++ b/frontend/service/Services.ts
@@ -2,22 +2,6 @@ import { Deployment, Service, ServiceHash, ServiceTemplate } from '@/client';
import { isDev } from '@/common-util';
import { BACKEND_URL } from '@/constants';
-/**
- * Get the status of a service
- * @param serviceHash
- * @returns
- */
-const getServiceStatus = async (
- serviceHash: ServiceHash,
-): Promise => {
- return fetch(`${BACKEND_URL}/services/${serviceHash}/status`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- }).then((response) => response.json());
-};
-
/**
* Get a single service from the backend
* @param serviceHash
@@ -99,10 +83,15 @@ const deleteDeployment = async (
method: 'POST',
}).then((response) => response.json());
+const getDeployment = async (serviceHash: ServiceHash): Promise =>
+ fetch(`${BACKEND_URL}/services/${serviceHash}/deployment`).then((response) =>
+ response.json(),
+ );
+
export const ServicesService = {
getService,
getServices,
- getServiceStatus,
+ getDeployment,
createService,
deployOnChain,
stopOnChain,
diff --git a/frontend/service/Wallet.ts b/frontend/service/Wallet.ts
new file mode 100644
index 000000000..04b1c6eaa
--- /dev/null
+++ b/frontend/service/Wallet.ts
@@ -0,0 +1,7 @@
+// import { BACKEND_URL } from '@/constants';
+
+// /**
+// * Returns a list of available wallets
+// */
+// const getWallets = async () =>
+// fetch(`${BACKEND_URL}/wallet`).then((res) => res.json());