Skip to content

Commit

Permalink
GE-2 Add Metamask support
Browse files Browse the repository at this point in the history
  • Loading branch information
aziolek committed Sep 27, 2022
1 parent 5add0de commit c2d9e3a
Show file tree
Hide file tree
Showing 16 changed files with 2,098 additions and 47 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
max_line_length = 100
trim_trailing_whitespace = true

[*.{css,html,js,jsx,ts,tsx}]
indent_size = 2

[*.py]
indent_size = 4
3 changes: 1 addition & 2 deletions client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/wildland.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Governance Game</title>
<title>Hexagon</title>
</head>
<body>
<div id="root"></div>
Expand Down
5 changes: 5 additions & 0 deletions client/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
13 changes: 10 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@
"prettier:js:pure": "prettier --config .prettierrc.yml --write",
"prettier:ts": "yarn prettier:ts:pure './**/*.{ts,tsx}'",
"prettier:ts:pure": "prettier --config .prettierrc.yml --parser typescript --write",
"type-check": "tsc --noEmit true"
"type-check": "tsc --noEmit true",
"test": "jest"
},
"dependencies": {
"classnames": "^2.3.1",
"ethers": "^5.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"regenerator-runtime": "^0.13.9"
"react-router-dom": "^6.4.1",
"regenerator-runtime": "^0.13.9",
"use-metamask": "^1.3.2"
},
"devDependencies": {
"@babel/core": "^7.18.13",
"@babel/eslint-parser": "^7.18.9",
"@babel/preset-react": "^7.18.6",
"@types/jest": "^29.0.3",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^5.36.2",
Expand All @@ -48,10 +53,12 @@
"eslint-plugin-sort-keys-fix": "^1.1.1",
"eslint-plugin-typescript-sort-keys": "^2.1.0",
"husky": "^8.0.1",
"jest": "^29.0.3",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"sass": "^1.54.5",
"typescript": "^4.8.2",
"ts-jest": "^29.0.2",
"typescript": "^4.8.3",
"vite": "^3.0.0"
},
"engines": {
Expand Down
22 changes: 11 additions & 11 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { HashRouter } from 'react-router-dom';
import { MetamaskStateProvider } from 'use-metamask';
import React, { ReactElement } from 'react';

import './styles/index.scss';
import RootRoutes from './routes/root-routes/root.routes';

const App = (): ReactElement => {
// @ts-ignore
const proposalsAddress = import.meta.env.VITE_PROPOSALS_ADDRESS;
import './styles/index.scss';

return (
<div>
<p>Client app.</p>
<p>{proposalsAddress}</p>
</div>
);
};
const App = (): ReactElement => (
<HashRouter>
<MetamaskStateProvider>
<RootRoutes />
</MetamaskStateProvider>
</HashRouter>
);

export default App;
16 changes: 16 additions & 0 deletions client/src/components/core/button/button.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { FC } from 'react';

import ButtonProps from './types';

const Button: FC<ButtonProps> = ({ children, label, onClick, type = 'button' }) => (
<button
onClick={onClick}
// eslint-disable-next-line react/button-has-type
type={type}
>
{children}
{label}
</button>
);

export default Button;
10 changes: 10 additions & 0 deletions client/src/components/core/button/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ButtonHTMLAttributes, ReactNode } from 'react';

export type ButtonType = ButtonHTMLAttributes<Element>['type'];

export default interface ButtonProps {
children?: ReactNode;
label?: string;
onClick: () => void;
type?: ButtonType;
}
31 changes: 31 additions & 0 deletions client/src/layouts/main-layout/main.layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ethers } from 'ethers';
import { useMetamask } from 'use-metamask';
import React, { FC } from 'react';

import Button from 'components/core/button/button.component';

import MainLayoutProps from './types';

const MainLayout: FC<MainLayoutProps> = ({ children }) => {
const {
connect,
metaState: { isConnected },
} = useMetamask();

const authUser = async () => {
if (!isConnected) {
await connect(ethers.providers.Web3Provider, 'any');
}
};

return (
<div>
<div>
<Button label="Connect MetaMask" onClick={authUser} />
</div>
{children}
</div>
);
};

export default MainLayout;
5 changes: 5 additions & 0 deletions client/src/layouts/main-layout/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ReactNode } from 'react';

export default interface MainLayoutProps {
children: ReactNode;
}
18 changes: 18 additions & 0 deletions client/src/routes/root-routes/root.routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Navigate, Route, Routes } from 'react-router-dom';
import React, { ReactElement } from 'react';

import MainLayout from 'layouts/main-layout/main.layout';
import ProposalsView from 'views/proposals-view/proposals.view';

import { ROOT_ROUTES } from './routes';

const RootRoutes = (): ReactElement => (
<MainLayout>
<Routes>
<Route element={<ProposalsView />} path={`${ROOT_ROUTES.proposals.relative}/*`} />
<Route element={<Navigate to={ROOT_ROUTES.proposals.absolute} />} path="*" />
</Routes>
</MainLayout>
);

export default RootRoutes;
7 changes: 7 additions & 0 deletions client/src/routes/root-routes/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { getPathObject } from 'utils/routing';

const ROOT = getPathObject('', '');

export const ROOT_ROUTES = {
proposals: getPathObject(ROOT, 'proposals'),
};
36 changes: 36 additions & 0 deletions client/src/utils/routing.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getPathObject } from './routing';

describe('getPathObject', () => {
it('properly creates base root path object', () => {
expect(getPathObject('', '')).toMatchObject({
absolute: '/',
relative: '',
});
});
it('properly creates path object for "/" given as root', () => {
expect(getPathObject('/', 'test')).toMatchObject({
absolute: '/test',
relative: 'test',
});
});
it('properly creates path object for given relative path', () => {
expect(getPathObject('some-path/some-subpath', 'relative-subpath')).toMatchObject({
absolute: 'some-path/some-subpath/relative-subpath',
relative: 'relative-subpath',
});
});
it('properly creates path object for Path object given as root path', () => {
expect(
getPathObject(
{
absolute: 'some-path/some-subpath',
relative: 'some-subpath',
},
'relative-subpath',
),
).toMatchObject({
absolute: 'some-path/some-subpath/relative-subpath',
relative: 'relative-subpath',
});
});
});
12 changes: 12 additions & 0 deletions client/src/utils/routing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Path {
absolute: string;
relative: string;
}

export const getPathObject = (root: string | Path, relativePath: string): Path => {
const rootPath = root && typeof root === 'object' ? root.absolute : root;
return {
absolute: rootPath !== '/' ? `${rootPath}/${relativePath}` : `/${relativePath}`,
relative: relativePath,
};
};
9 changes: 9 additions & 0 deletions client/src/views/proposals-view/proposals.view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { ReactElement } from 'react';

const ProposalsView = (): ReactElement => {
// @ts-ignore
const proposalsAddress = import.meta.env.VITE_PROPOSALS_ADDRESS;
return <div>ProposalsView {proposalsAddress}</div>;
};

export default ProposalsView;
1 change: 1 addition & 0 deletions client/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default defineConfig({
constants: path.resolve(__dirname, 'src/constants'),
context: path.resolve(__dirname, 'src/context'),
hooks: path.resolve(__dirname, 'src/hooks'),
layouts: path.resolve(__dirname, 'src/layouts'),
services: path.resolve(__dirname, 'src/services'),
styles: path.resolve(__dirname, 'src/styles'),
svg: path.resolve(__dirname, 'src/svg'),
Expand Down
Loading

0 comments on commit c2d9e3a

Please sign in to comment.