Skip to content

Commit 4b82ffa

Browse files
author
Elaman Nazarkulov
authored
Merge pull request #88 from OpenFuturePlatform/key-master-fix
Stable Coin Transactions
2 parents 0ba5d0d + 88cbd04 commit 4b82ffa

File tree

65 files changed

+5246
-286
lines changed

Some content is hidden

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

65 files changed

+5246
-286
lines changed

frontend/src/App.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Container } from 'semantic-ui-react';
1010
import './css/main.css';
1111
import { t } from './utils/messageTexts';
1212
import styled from 'styled-components';
13+
import UserToken from "./scenes/UserToken";
1314

1415
const UnAuthorizeMessage = styled.div`
1516
font-size: 18px;
@@ -39,6 +40,7 @@ class App extends Component {
3940
<Switch>
4041
<Route path="/scaffolds" component={Scaffolds} />
4142
<Route path="/applications" component={GatewayApplication} />
43+
<Route path="/tokens" component={UserToken} />
4244
<Redirect from="*" to="/scaffolds" />
4345
</Switch>
4446
);

frontend/src/actions/eth-account.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { SET_CURRENT_ETH_ACCOUNT } from './types';
1+
import {SET_CURRENT_ETH_ACCOUNT} from './types';
22
import web3 from '../utils/web3';
33
import eth from '../utils/eth';
44
import ethUnit from 'ethjs-unit';
5-
import { openTokenSelectorEth } from '../selectors/open-token';
5+
import {openTokenSelectorEth} from '../selectors/open-token';
6+
import {ERC20_ABI} from "../const";
67

78
const setNetworkId = () => async dispatch => {
89
const activeNetworkId = await web3.eth.net.getId();
@@ -52,6 +53,19 @@ export const subscribeEthAccount = () => async dispatch => {
5253
return dispatch(setNetworkId());
5354
};
5455

56+
export const getErc20Token = address => async dispatch => {
57+
if (!web3 || address === undefined) {
58+
return;
59+
}
60+
61+
const tokenContract = new web3.eth.Contract(ERC20_ABI, address);
62+
const symbol = await tokenContract.methods.symbol().call();
63+
const decimals = await tokenContract.methods.decimals().call();
64+
const name = await tokenContract.methods.name().call();
65+
66+
return {address: address, name: name, symbol: symbol, decimal: decimals};
67+
};
68+
5569
export const unsubscribeEthAccount = () => () => {
5670
clearInterval(ethAccountTimer);
5771
ethAccountTimer = null;
+25-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,44 @@
11
import {apiDelete, apiGet, apiPost} from "./apiRequest";
2-
import {getGatewayApplicationWalletsPath} from "../utils/apiPathes";
2+
import {getGatewayApplicationWalletExport, getGatewayApplicationWalletsPath} from "../utils/apiPathes";
33
import {FETCH_GATEWAY_APPLICATION_WALLET} from "./types";
44
import {parseApiError} from "../utils/parseApiError";
55

66
export const getGatewayApplicationWallet = (gatewayId) => async dispatch => {
77
const wallets = await dispatch(apiGet(getGatewayApplicationWalletsPath(gatewayId), {}));
8-
dispatch({ type: FETCH_GATEWAY_APPLICATION_WALLET, payload: {gatewayId, wallets} });
8+
dispatch({type: FETCH_GATEWAY_APPLICATION_WALLET, payload: {gatewayId, wallets}});
99
};
1010

1111
export const generateGatewayApplicationWallet = (wallet, blockchain) => async (dispatch) => {
12-
await dispatch(apiPost(getGatewayApplicationWalletsPath(), {applicationId: wallet.applicationId, webHook: wallet.webHook, blockchainType: blockchain.blockchain}));
12+
await dispatch(apiPost(getGatewayApplicationWalletsPath(), {
13+
applicationId: wallet.applicationId,
14+
webHook: wallet.webHook,
15+
blockchainType: blockchain.blockchain
16+
}));
1317
dispatch(getGatewayApplicationWallet(wallet.applicationId));
1418
};
1519

1620
export const removeGatewayApplicationWallet = (gatewayId, address) => async dispatch => {
1721
try {
18-
await dispatch(apiDelete( getGatewayApplicationWalletsPath()+"?applicationId="+gatewayId+"&address="+address, {}));
22+
await dispatch(apiDelete(getGatewayApplicationWalletsPath() + "?applicationId=" + gatewayId + "&address=" + address, {}));
1923
await dispatch(getGatewayApplicationWallet(gatewayId));
2024
} catch (e) {
2125
throw parseApiError(e);
2226
}
2327
};
28+
29+
export const exportApplicationWalletPrivateKey = (address, blockchain) => async (dispatch) => {
30+
return await dispatch(apiPost(getGatewayApplicationWalletExport(), {
31+
address: address,
32+
blockchain: blockchain
33+
}));
34+
};
35+
36+
export const importGatewayApplicationWallet = (gateway, wallet) => async (dispatch) => {
37+
await dispatch(apiPost(getGatewayApplicationWalletsPath()+"import", {
38+
applicationId: gateway.applicationId,
39+
webHook: gateway.webHook,
40+
address: wallet.address,
41+
blockchainType: wallet.blockchain
42+
}));
43+
dispatch(getGatewayApplicationWallet(wallet.applicationId));
44+
};

frontend/src/actions/types.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,7 @@ export const SHOW_WITHDRAWAL_MODAL = 'SHOW_WITHDRAWAL_MODAL';
3232

3333
export const FETCH_GATEWAY_APPLICATIONS = 'FETCH_GATEWAY_APPLICATIONS';
3434
export const SET_GATEWAY_APPLICATION_SET = 'SET_GATEWAY_APPLICATION_SET';
35-
export const FETCH_GATEWAY_APPLICATION_WALLET = 'FETCH_GATEWAY_APPLICATION_WALLET';
35+
export const FETCH_GATEWAY_APPLICATION_WALLET = 'FETCH_GATEWAY_APPLICATION_WALLET';
36+
37+
export const FETCH_USER_TOKENS = 'FETCH_USER_TOKENS';
38+
export const SET_USER_TOKEN = 'SET_USER_TOKEN';

frontend/src/actions/user-token.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {apiGet, apiPost} from "./apiRequest";
2+
import {getUserTokenPath} from "../utils/apiPathes";
3+
import {FETCH_USER_TOKENS, SHOW_MODAL} from "./types";
4+
import {parseApiError} from "../utils/parseApiError";
5+
6+
export const fetchUserTokens = (offset = 0, limit = 10) => async dispatch => {
7+
const params = { offset, limit };
8+
9+
try {
10+
const data = await dispatch(apiGet(getUserTokenPath(), params));
11+
dispatch({ type: FETCH_USER_TOKENS, payload: data });
12+
} catch (err) {
13+
const error = parseApiError(err);
14+
dispatch({
15+
type: SHOW_MODAL,
16+
payload: {showLoader: false, showModal: true, error: error.message}
17+
});
18+
throw error;
19+
}
20+
};
21+
22+
export const saveUserToken = formValues => async (dispatch) => {
23+
await dispatch(apiPost(getUserTokenPath(), formValues));
24+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react";
2+
3+
export const OpenScanLink = ({children}) => (
4+
<a href={`http://localhost:8080/widget/trx/address/${children}`} target="_blank" rel="noopener noreferrer">
5+
{children}
6+
</a>
7+
);
8+

frontend/src/components/GatewayApplicationWallet.js

+32-6
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,23 @@ import {connect} from "react-redux";
77
import {Table} from "../components-ui/Table";
88
import {WalletGenerate} from "./GatewayApplicationWalletGenerate";
99
import {
10-
generateGatewayApplicationWallet,
10+
exportApplicationWalletPrivateKey,
11+
generateGatewayApplicationWallet, importGatewayApplicationWallet,
1112
removeGatewayApplicationWallet
1213
} from "../actions/gateway-wallet";
1314

1415
import {getGatewayWalletSelector} from "../selectors/getGatewayWalletsSelector";
1516

1617
import {GatewayApplicationWalletRemove} from "./GatewayApplicationWalletRemove";
18+
import {GatewayApplicationWalletPrivateKey} from "./GatewayApplicationWalletPrivateKey";
19+
import {WalletImport} from "./GatewayApplicationWalletImport";
20+
import {OpenScanLink} from "../components-ui/OpenScanLink";
1721

18-
const getColumns = (wallets, onRemove) => [
22+
const getColumns = (wallets, onRemove, onExport) => [
1923
{
2024
Header: 'Wallet Address',
2125
accessor: 'address',
22-
Cell: ({ value }) => <EtherscanLink>{value}</EtherscanLink>,
26+
Cell: ({ value }) => <OpenScanLink>{value}</OpenScanLink>,
2327
sortable: false
2428
},
2529
{
@@ -39,6 +43,17 @@ const getColumns = (wallets, onRemove) => [
3943
</span>
4044
),
4145
sortable: false
46+
},
47+
{
48+
Header: '',
49+
accessor: 'address',
50+
width: 150,
51+
Cell: (props) => (
52+
<span>
53+
<GatewayApplicationWalletPrivateKey onSubmit={() => onExport(props.row._original.address,props.row._original.blockchain)}/>
54+
</span>
55+
),
56+
sortable: false
4257
}
4358
];
4459

@@ -49,19 +64,28 @@ class GatewayApplicationWalletComponent extends React.Component {
4964
return this.props.removeGatewayApplicationWallet(gateway.id, address);
5065
};
5166

67+
onExportPrivateKey = (address, blockchain) => {
68+
return this.props.exportApplicationWalletPrivateKey(address, blockchain);
69+
}
70+
5271
onGenerateWallet = blockchain => {
5372
const { gateway } = this.props;
5473
this.props.generateGatewayApplicationWallet({ applicationId: gateway.id, webHook: gateway.webHook}, blockchain);
5574
}
5675

76+
onImportWallet = walletImport => {
77+
this.props.importGatewayApplicationWallet(walletImport.walletRequest, {address: walletImport.address, blockchain: walletImport.blockchain});
78+
}
79+
5780
render() {
5881
const { wallets, gateway } = this.props;
5982

60-
const columns = getColumns(wallets.list, this.onRemoveWallet);
83+
const columns = getColumns(wallets.list, this.onRemoveWallet, this.onExportPrivateKey);
6184
const noDataText = 'No Wallet exist'
6285
return (
6386
<div className="table-with-add">
6487
<WalletGenerate gateway={gateway} onSubmit={this.onGenerateWallet} />
88+
<WalletImport gateway={gateway} onSubmit={this.onImportWallet} />
6589
<Segment attached styles={{ padding: 0 }}>
6690
<Table data={wallets.list} columns={columns} noDataText={noDataText} />
6791
</Segment>
@@ -70,7 +94,7 @@ class GatewayApplicationWalletComponent extends React.Component {
7094
}
7195
}
7296

73-
const mapStateToProps = (state, { gateway }) => {
97+
const mapStateToProps = (state, { gateway}) => {
7498
const wallets = getGatewayWalletSelector(state, gateway.id);
7599
return { gateway, wallets };
76100
};
@@ -79,6 +103,8 @@ export const GatewayApplicationWallet = connect(
79103
mapStateToProps,
80104
{
81105
generateGatewayApplicationWallet,
82-
removeGatewayApplicationWallet
106+
importGatewayApplicationWallet,
107+
removeGatewayApplicationWallet,
108+
exportApplicationWalletPrivateKey
83109
}
84110
)(GatewayApplicationWalletComponent);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import React, {Component} from "react";
2+
import {Button, Divider, Dropdown, Input, Modal} from "semantic-ui-react";
3+
4+
import {withVisible} from "../components-ui/withVisible";
5+
import {withSaving} from "../components-ui/withSaving";
6+
import styled from "styled-components";
7+
import {t} from "../utils/messageTexts";
8+
import ScaffoldField from "../components-ui/inputs/Field";
9+
import {Field} from "redux-form";
10+
11+
12+
const WalletImportContainer = styled.div`
13+
overflow: hidden;
14+
padding-bottom: 15px;
15+
`;
16+
17+
class WalletImportComponent extends Component {
18+
state = {
19+
walletRequest: null,
20+
blockchain: null,
21+
address: null
22+
};
23+
24+
onInputChange = (e, {value}) => {
25+
this.setState({ address: value });
26+
}
27+
28+
onBlockchainChange = (e, {value}) => {
29+
this.setState({ blockchain: value });
30+
}
31+
32+
onShow = () => {
33+
const { onShow, gateway } = this.props;
34+
35+
this.setState({ walletRequest: { applicationId: gateway.id, webHook: gateway.webHook} });
36+
37+
onShow();
38+
};
39+
40+
onBackgroundClick = e => {
41+
const { onHide, isSaving } = this.props;
42+
const target = e.target;
43+
if (isSaving || !target.classList.contains('modals')) {
44+
return;
45+
}
46+
onHide();
47+
};
48+
49+
onSubmit = async () => {
50+
const { submitWithSaving } = this.props;
51+
const { walletRequest, blockchain, address } = this.state;
52+
this.setState({ isSaving: true });
53+
54+
submitWithSaving({ walletRequest, blockchain, address });
55+
};
56+
57+
render() {
58+
const { isVisible, onHide, isSaving } = this.props;
59+
60+
return (
61+
<WalletImportContainer>
62+
<Button primary type="button" floated="right" onClick={this.onShow}>
63+
Import Address
64+
</Button>
65+
<Modal size="tiny" open={isVisible} onClose={this.onBackgroundClick}>
66+
<Modal.Header>Import Wallet</Modal.Header>
67+
<Modal.Content>
68+
<Input focus fluid={true} placeholder='address' onChange={ this.onInputChange }>
69+
<input style={{
70+
marginTop: '10px',
71+
marginBottom: '5px'
72+
}}/>
73+
</Input>
74+
<Dropdown
75+
placeholder='Select Blockchain'
76+
fluid
77+
selection
78+
options={[
79+
{ key: 'ether', text: 'ETH', value: 'ETH' },
80+
{ key: 'bitcoin', text: 'BTC', value: 'BTC' },
81+
{ key: 'binance', text: 'BNB', value: 'BNB' }
82+
]}
83+
onChange={this.onBlockchainChange}
84+
/>
85+
</Modal.Content>
86+
<Modal.Actions>
87+
<Button negative disabled={isSaving} onClick={onHide}>
88+
Cancel
89+
</Button>
90+
<Button
91+
positive
92+
loading={isSaving}
93+
icon="checkmark"
94+
labelPosition="right"
95+
content="Import"
96+
onClick={this.onSubmit}
97+
/>
98+
</Modal.Actions>
99+
</Modal>
100+
</WalletImportContainer>
101+
);
102+
}
103+
}
104+
105+
export const WalletImport = withVisible(withSaving(WalletImportComponent));

0 commit comments

Comments
 (0)