Skip to content

Commit 5e25260

Browse files
Merge pull request #63 from OpenFuturePlatform/key-management
Key management
2 parents 28880f1 + 366d600 commit 5e25260

69 files changed

Lines changed: 1729 additions & 32 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.gradle

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ sourceCompatibility = 11
1717

1818
repositories {
1919
mavenCentral()
20-
maven {
21-
url "https://dl.bintray.com/ethereum/maven/"
22-
}
2320
}
2421

2522
ext {
@@ -45,9 +42,7 @@ dependencies {
4542
// Ethereum
4643
implementation("org.web3j:web3j-spring-boot-starter:1.6.0")
4744
implementation('org.web3j:core:4.5.0')
48-
implementation("org.ethereum:ethereumj-core:1.7.2-RELEASE")
49-
implementation("org.ethereum:solcJ-all:0.4.25")
50-
45+
compile group: 'org.web3j', name: 'web3j-sokt', version: '0.2.1'
5146
// AWS
5247
implementation("com.amazonaws:aws-java-sdk-s3:${s3Version}")
5348

@@ -63,6 +58,7 @@ dependencies {
6358

6459
// Utils
6560
implementation('commons-io:commons-io:2.8.0')
61+
implementation 'org.apache.commons:commons-lang3:3.6'
6662

6763
// Test
6864
testImplementation('org.springframework.boot:spring-boot-starter-test')

frontend/package.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"semantic-ui-react": "^2.0.3",
3333
"styled-components": "^5.2.1",
3434
"typescript": "^4.1.3",
35-
"web3": "^1.3.3",
35+
"web3": "^1.5.0",
3636
"websocket": "^1.0.33"
3737
},
3838
"scripts": {
@@ -43,5 +43,17 @@
4343
},
4444
"devDependencies": {
4545
"lodash": "^4.17.20"
46+
},
47+
"browserslist": {
48+
"production": [
49+
">0.2%",
50+
"not dead",
51+
"not op_mini all"
52+
],
53+
"development": [
54+
"last 1 chrome version",
55+
"last 1 firefox version",
56+
"last 1 safari version"
57+
]
4658
}
4759
}

frontend/src/App.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { connect } from 'react-redux';
66
import Scaffolds from './scenes/Scaffolds';
77
import Keys from './scenes/Keys';
88
import Header from './components/Header';
9+
import GatewayApplication from "./scenes/GatewayApplication";
910
import { Container } from 'semantic-ui-react';
1011
import './css/main.css';
1112
import { t } from './utils/messageTexts';
@@ -39,6 +40,7 @@ class App extends Component {
3940
<Switch>
4041
<Route path="/scaffolds" component={Scaffolds} />
4142
<Route path="/keys" component={Keys} />
43+
<Route path="/applications" component={GatewayApplication} />
4244
<Redirect from="*" to="/scaffolds" />
4345
</Switch>
4446
);

frontend/src/actions/gateways.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {apiDelete, apiGet, apiPost} from "./apiRequest";
2+
import {
3+
getGatewayApplicationsPath,
4+
getGatewayApplicationWalletsPath,
5+
} from "../utils/apiPathes";
6+
import {
7+
FETCH_GATEWAY_APPLICATION_WALLET,
8+
FETCH_GATEWAY_APPLICATIONS, SET_ETHEREUM_SCAFFOLD_SET, SET_GATEWAY_APPLICATION_SET,
9+
SHOW_MODAL
10+
} from "./types";
11+
import {parseApiError} from "../utils/parseApiError";
12+
13+
14+
export const fetchGatewayApplications = (offset = 0, limit = 10) => async dispatch => {
15+
const params = { offset, limit };
16+
17+
try {
18+
const data = await dispatch(apiGet(getGatewayApplicationsPath(), params));
19+
dispatch({ type: FETCH_GATEWAY_APPLICATIONS, payload: data });
20+
} catch (err) {
21+
const error = parseApiError(err);
22+
dispatch({
23+
type: SHOW_MODAL,
24+
payload: {showLoader: false, showModal: true, error: error.message}
25+
});
26+
throw error;
27+
}
28+
};
29+
30+
export const saveGatewayApplication = formValues => async (dispatch) => {
31+
await dispatch(apiPost(getGatewayApplicationsPath(), formValues));
32+
};
33+
34+
export const fetchGatewayApplicationDetails = (id) => async dispatch => {
35+
dispatch({ type: SET_GATEWAY_APPLICATION_SET, payload: { id, loading: true } });
36+
37+
try {
38+
const gateway = await dispatch(apiGet(getGatewayApplicationsPath(id)));
39+
const wallets = await dispatch(getGatewayApplicationWallet(id));
40+
const error = '';
41+
const payload = { id, gateway, wallets, error, loading: false };
42+
dispatch({ type: SET_GATEWAY_APPLICATION_SET, payload });
43+
44+
} catch (e) {
45+
const response = e.response || {};
46+
const error = `${response.status}: ${response.message || response.statusText}`;
47+
const payload = { id, error, loading: false };
48+
dispatch({ type: SET_GATEWAY_APPLICATION_SET, payload });
49+
throw e;
50+
}
51+
};
52+
53+
export const removeGatewayApplication = (id) => async dispatch => {
54+
try {
55+
await dispatch(apiDelete(getGatewayApplicationsPath()+"?id="+id, {}));
56+
await dispatch(fetchGatewayApplications())
57+
} catch (e) {
58+
throw parseApiError(e);
59+
}
60+
};
61+
62+
export const getGatewayApplicationWallet = (gatewayId) => async dispatch => {
63+
const wallets = await dispatch(apiGet(getGatewayApplicationWalletsPath(gatewayId), {}));
64+
const error = '';
65+
dispatch({ type: SET_GATEWAY_APPLICATION_SET, payload: {gatewayId, wallets, error, loading: false} });
66+
return wallets;
67+
};
68+
69+
export const generateGatewayApplicationWallet = (wallet, blockchain) => async (dispatch) => {
70+
await dispatch(apiPost(getGatewayApplicationWalletsPath(), {applicationId: wallet.applicationId, webHook: wallet.webHook, blockchainType: blockchain.blockchain}));
71+
dispatch(fetchGatewayApplicationDetails(wallet.applicationId))
72+
};
73+
74+
export const removeGatewayApplicationWallet = (gatewayId, address) => async dispatch => {
75+
try {
76+
await dispatch(apiDelete( getGatewayApplicationWalletsPath()+"?applicationId="+gatewayId+"&address="+address, {}));
77+
await dispatch(fetchGatewayApplicationDetails(gatewayId))
78+
} catch (e) {
79+
throw parseApiError(e);
80+
}
81+
};

frontend/src/actions/types.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ export const SET_DEV_SHARES = 'SET_DEV_SHARES';
2929

3030
export const SHOW_MODAL = 'SHOW_MODAL';
3131
export const SHOW_WITHDRAWAL_MODAL = 'SHOW_WITHDRAWAL_MODAL';
32+
33+
export const FETCH_GATEWAY_APPLICATIONS = 'FETCH_GATEWAY_APPLICATIONS';
34+
export const SET_GATEWAY_APPLICATION_SET = 'SET_GATEWAY_APPLICATION_SET';
35+
export const FETCH_GATEWAY_APPLICATION_WALLET = 'FETCH_GATEWAY_APPLICATION_WALLET';
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React, {Component} from 'react';
2+
import {connect} from 'react-redux';
3+
import {Button, Card, Divider, Grid, Icon} from 'semantic-ui-react';
4+
import {ProjectPagination} from '../components-ui/ProjectPagination';
5+
import {GATEWAY_LIMIT} from '../const';
6+
import {
7+
fetchGatewayApplications,
8+
getGatewayApplicationWallet,
9+
removeGatewayApplication
10+
} from "../actions/gateways";
11+
import {GatewayApplicationRemove} from "./GatewayApplicationRemove";
12+
import {WordWrap} from "../components-ui/WordWrap";
13+
import {Link} from "react-router-dom";
14+
15+
16+
class GatewayApplicationList extends Component {
17+
componentDidMount() {
18+
this.fetchGatewayApplications();
19+
}
20+
21+
fetchGatewayApplications = (offset = 0, limit = GATEWAY_LIMIT) => {
22+
this.props.fetchGatewayApplications(offset, limit);
23+
};
24+
25+
onRemoveGateway = gateway => {
26+
this.props.removeGatewayApplication(gateway.id);
27+
}
28+
29+
onFetchWallet = gateway => this.props.getGatewayApplicationWallet(gateway.id)
30+
31+
renderApplications() {
32+
const gateways = this.props.gateways;
33+
34+
return gateways.list.map((gateway, index) => {
35+
return (
36+
<Card fluid key={index}>
37+
<Card.Content>
38+
39+
<Grid.Row>
40+
<Grid.Column width={8}>
41+
<Link to={`/applications/${gateway.id}`}>
42+
<Card.Header>
43+
<WordWrap>{gateway.name}</WordWrap>
44+
</Card.Header>
45+
</Link>
46+
<div className="meta">
47+
Webhook: {gateway.webHook}
48+
</div>
49+
</Grid.Column>
50+
</Grid.Row>
51+
</Card.Content>
52+
<Card.Content extra>
53+
<div className='ui three buttons'>
54+
55+
<Button basic color='red'>
56+
<GatewayApplicationRemove gateway={gateway} onSubmit={() => this.onRemoveGateway(gateway)} />
57+
</Button>
58+
59+
</div>
60+
</Card.Content>
61+
</Card>
62+
);
63+
});
64+
}
65+
66+
render() {
67+
const gateways = this.props.gateways;
68+
return (
69+
<Grid.Row>
70+
<Grid.Column width={16}>
71+
{this.renderApplications()}
72+
<ProjectPagination limit={GATEWAY_LIMIT} totalCount={gateways.totalCount} onChange={this.fetchGatewayApplications} />
73+
</Grid.Column>
74+
</Grid.Row>
75+
);
76+
}
77+
}
78+
const mapStateToProps = ({ gateways }) => ({ gateways: gateways });
79+
80+
export default connect(
81+
mapStateToProps,
82+
{
83+
fetchGatewayApplications,
84+
removeGatewayApplication,
85+
getGatewayApplicationWallet
86+
}
87+
)(GatewayApplicationList);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {EntityRemove} from "./EntityRemove";
2+
import {t} from "../utils/messageTexts";
3+
import React from "react";
4+
5+
export const GatewayApplicationRemove = ({ onSubmit }) => (
6+
<EntityRemove onSubmit={onSubmit} header="Delete Gateway">
7+
<div>
8+
{t('sure to delete Gateway')}
9+
</div>
10+
</EntityRemove>
11+
);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React from "react";
2+
import {Button, Divider, Grid, Icon, Input, Modal, Segment} from "semantic-ui-react";
3+
import {EtherscanLink} from "../components-ui/EtherscanLink";
4+
import {connect} from "react-redux";
5+
6+
7+
import {Table} from "../components-ui/Table";
8+
import {WalletGenerate} from "./GatewayApplicationWalletGenerate";
9+
import {generateGatewayApplicationWallet, removeGatewayApplicationWallet} from "../actions/gateways";
10+
11+
import {getGatewayWalletSelector} from "../selectors/getGatewayWalletsSelector";
12+
13+
import {GatewayApplicationWalletRemove} from "./GatewayApplicationWalletRemove";
14+
15+
const getColumns = (wallets, onRemove) => [
16+
{
17+
Header: 'Wallet Address',
18+
accessor: 'address',
19+
Cell: ({ value }) => <EtherscanLink>{value}</EtherscanLink>,
20+
sortable: false
21+
},
22+
{
23+
Header: 'Blockchain',
24+
accessor: 'blockchain',
25+
width: 200,
26+
Cell: ({ value }) => <span>{value}</span>,
27+
sortable: false
28+
},
29+
{
30+
Header: '',
31+
accessor: 'address',
32+
width: 150,
33+
Cell: ({ value }) => (
34+
<span>
35+
<GatewayApplicationWalletRemove onSubmit={() => onRemove(value)} />
36+
</span>
37+
),
38+
sortable: false
39+
}
40+
];
41+
42+
class GatewayApplicationWalletComponent extends React.Component {
43+
44+
onRemoveWallet = address => {
45+
const { gateway } = this.props;
46+
return this.props.removeGatewayApplicationWallet(gateway.id, address);
47+
};
48+
49+
onGenerateWallet = blockchain => {
50+
const { gateway } = this.props;
51+
this.props.generateGatewayApplicationWallet({ applicationId: gateway.id, webHook: gateway.webHook}, blockchain);
52+
}
53+
54+
render() {
55+
const { wallets, gateway } = this.props;
56+
57+
const columns = getColumns(wallets, this.onRemoveWallet);
58+
const noDataText = 'No Wallet exist'
59+
return (
60+
<div className="table-with-add">
61+
<WalletGenerate gateway={gateway} onSubmit={this.onGenerateWallet} />
62+
<Segment attached styles={{ padding: 0 }}>
63+
<Table data={wallets} columns={columns} noDataText={noDataText} />
64+
</Segment>
65+
</div>
66+
);
67+
}
68+
}
69+
70+
const mapStateToProps = (state, { gateway }) => {
71+
const wallets = getGatewayWalletSelector(state, gateway.id);
72+
return { gateway, wallets };
73+
};
74+
75+
export const GatewayApplicationWallet = connect(
76+
mapStateToProps,
77+
{
78+
generateGatewayApplicationWallet,
79+
removeGatewayApplicationWallet
80+
}
81+
)(GatewayApplicationWalletComponent);

0 commit comments

Comments
 (0)