├── .DS_Store
├── .babelrc
├── .env
├── .eslintrc
├── .gitignore
├── .stylelintrc
├── LICENSE
├── README.md
├── app
├── AppConfig.js
├── CommonComponents
│ ├── BalanceCard.js
│ ├── Chart.js
│ ├── ChartOptions.js
│ ├── ContentColumn
│ │ └── Index.js
│ ├── Modal.js
│ ├── PopUp
│ │ ├── InputForAddres.js
│ │ ├── Search.js
│ │ └── config.js
│ ├── RenderComponents.js
│ ├── RoutingPanel.js
│ └── Select.js
├── Exchange
│ ├── ActionTypes.js
│ ├── Actions.js
│ ├── CommonComponents
│ │ └── Index.js
│ ├── Confirmation.js
│ ├── Exchange.js
│ ├── Reducer.js
│ ├── Saga.js
│ ├── StartExchange.js
│ └── StatusExchange.js
├── Fiat
│ ├── ActionTypes.js
│ ├── Actions.js
│ ├── Fiat.js
│ ├── Reducer.js
│ └── Saga.js
├── InitialPage
│ ├── ActionTypes.js
│ ├── Actions.js
│ ├── Auth.js
│ ├── Dashboard.js
│ ├── Header.js
│ ├── History.js
│ ├── Initial.js
│ ├── ListOfWallets.js
│ ├── Menu.js
│ ├── NewsCard
│ │ ├── ActionTypes.js
│ │ ├── Actions.js
│ │ ├── Container.js
│ │ ├── Layout.js
│ │ ├── Reducer.js
│ │ ├── Saga.js
│ │ ├── Selectors.js
│ │ ├── Store.js
│ │ └── index.js
│ ├── Reducer.js
│ ├── Saga.js
│ ├── SummaryCash.js
│ └── WalletInfo.js
├── InitialSetup
│ ├── RootReducer.js
│ ├── RootSaga.js
│ └── Store.js
├── Providers
│ ├── DateWrapper.js
│ ├── Gaia.js
│ ├── GaiaDicts
│ │ └── Dashbord.js
│ ├── GaiaTemplates
│ │ └── WalletList.js
│ ├── HistoryNormalization.js
│ ├── Wallets.js
│ ├── XHRProvider.js
│ └── config.js
├── Routing
│ ├── ProtectedRoute.js
│ └── Router.js
├── Views
│ ├── Content.js
│ ├── Input.js
│ ├── Popup.js
│ ├── ScrollableCard.js
│ ├── Snackbar.js
│ ├── StyledButton.js
│ ├── TabsWrapper.js
│ └── index.js
├── Wallets
│ ├── Reducer.js
│ ├── Wallet
│ │ ├── ActionTypes.js
│ │ ├── Actions.js
│ │ ├── AddCustomEthToken.js
│ │ ├── OperationSelector.js
│ │ ├── QrPopUp.js
│ │ ├── Receive.js
│ │ ├── Reducer.js
│ │ ├── RenderFunctions.js
│ │ ├── Saga.js
│ │ ├── StepperForSend.js
│ │ ├── StepperRenderFunctions.js
│ │ ├── Tokens.js
│ │ ├── Transactions.js
│ │ ├── Wallet.js
│ │ └── WalletInfo.js
│ ├── WalletList.js
│ └── WalletList
│ │ ├── ActionTypes.js
│ │ ├── Actions.js
│ │ ├── ControlPanel.js
│ │ ├── CreateNewWallet.js
│ │ ├── CreateNewWalletView.js
│ │ ├── Customisation.js
│ │ ├── DeleteWallet.js
│ │ ├── Error.js
│ │ ├── LongMenu.js
│ │ ├── MakeActive.js
│ │ ├── PrivateKey.js
│ │ ├── Receive.js
│ │ ├── Reducer.js
│ │ ├── RenderFunctions.js
│ │ ├── Saga.js
│ │ └── Views.js
├── devIndex.html
├── images
│ ├── common
│ │ ├── icon-add.svg
│ │ ├── icon-arrow-down-grey.svg
│ │ ├── icon-arrow-down.svg
│ │ ├── icon-arrow-green.svg
│ │ ├── icon-checkbox.svg
│ │ ├── icon-cross-grey.svg
│ │ ├── icon-cross-white.svg
│ │ ├── icon-direction.svg
│ │ ├── icon-exchange-loading.svg
│ │ ├── icon-filter.svg
│ │ ├── icon-link-forward-hover.svg
│ │ ├── icon-link-forward.svg
│ │ ├── icon-log-out.svg
│ │ ├── icon-manual-address.svg
│ │ ├── icon-profile.svg
│ │ ├── icon-qr.svg
│ │ ├── icon-scale.svg
│ │ ├── icon-search.svg
│ │ ├── icon-support.svg
│ │ ├── icon-swap.svg
│ │ ├── icon-xl-arrow.svg
│ │ ├── icon-xl-swap.svg
│ │ └── vision-off.svg
│ ├── dappy-logo.svg
│ ├── fiat
│ │ ├── AUD@1x.png
│ │ ├── AUD@2x.png
│ │ ├── BRL@1x.png
│ │ ├── BRL@2x.png
│ │ ├── CAD@1x.png
│ │ ├── CAD@2x.png
│ │ ├── CHF@1x.png
│ │ ├── CHF@2x.png
│ │ ├── CNY@1x.png
│ │ ├── CNY@2x.png
│ │ ├── EUR@1x.png
│ │ ├── EUR@2x.png
│ │ ├── GBP@1x.png
│ │ ├── GBP@2x.png
│ │ ├── HKD@1x.png
│ │ ├── HKD@2x.png
│ │ ├── IDR@1x.png
│ │ ├── IDR@2x.png
│ │ ├── INR@1x.png
│ │ ├── INR@2x.png
│ │ ├── JPY@1x.png
│ │ ├── JPY@2x.png
│ │ ├── KRW@1x.png
│ │ ├── KRW@2x.png
│ │ ├── MXN@1x.png
│ │ ├── MXN@2x.png
│ │ ├── RUB@1x.png
│ │ ├── RUB@2x.png
│ │ ├── USD@1x.png
│ │ ├── USD@2x.png
│ │ └── index.js
│ ├── ic-bch.svg
│ ├── ic-btc.svg
│ ├── ic-btg.svg
│ ├── ic-dash.svg
│ ├── ic-dcr.svg
│ ├── ic-doge.svg
│ ├── ic-etc.svg
│ ├── ic-eth.svg
│ ├── ic-ltc.svg
│ ├── ic-zec.svg
│ ├── index.js
│ └── nav
│ │ ├── icon-dashboard-hover.svg
│ │ ├── icon-dashboard.svg
│ │ ├── icon-exchange-hover.svg
│ │ ├── icon-exchange.svg
│ │ ├── icon-wallet-hover.svg
│ │ └── icon-wallet.svg
├── index.css
├── index.html
└── index.js
├── bundleLibs
├── lib_1.json
└── lib_2.json
├── lib.webpack.config.js
├── package.json
├── postcss.config.js
├── webpack.config.js
└── yarn.lock
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/.DS_Store
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["env", { "targets": { "node": "current" } }], ["react"], ["stage-2"]],
3 | "env": {
4 | "development": {
5 | "plugins": [
6 | ["babel-plugin-transform-react-jsx"],
7 | ["fbjs-scripts/babel-6/dev-expression"],
8 | ["transform-runtime"]
9 | ]
10 | },
11 | "production": {
12 | "plugins": [
13 | [
14 | "transform-react-remove-prop-types",
15 | {
16 | "mode": "wrap",
17 | "ignoreFilenames": ["node_modules"]
18 | }
19 | ]
20 | ]
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | # NODE_ENV should be production or development
2 |
3 | NODE_ENV=development
4 |
5 | API_URL=
6 |
7 | STATIC_URL=
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["airbnb","prettier"],
3 | "parser": "babel-eslint",
4 | "env": {
5 | "browser": true,
6 | "node": true,
7 | "es6": true,
8 | "mocha": true
9 | },
10 | "rules": {
11 | "linebreak-style": 0,
12 | "react/jsx-no-bind": 1,
13 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
14 | "react/prop-types": 0,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18 | .grunt
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Compiled binary addons (http://nodejs.org/api/addons.html)
24 | build/Release
25 |
26 | # Dependency directory
27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
28 | node_modules
29 |
30 | \.idea/ico\.iml
31 |
32 | \.idea/misc\.xml
33 |
34 | \.idea/modules\.xml
35 |
36 | \.idea/workspace\.xml
37 |
38 | public/
39 |
40 | package-lock\.json
41 |
42 | \.idea/
43 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard"
3 | }
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 BCNetio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Blockstack & ShapeShift Signature Bounty Universal Wallet
3 |
4 | ## Getting Started in dev mode.
5 | ```
6 | git clone https://github.com/BCNetio/BlockStackWallet
7 | npm install
8 | npm run start
9 | ```
10 |
11 | ## Production build
12 |
13 | ```
14 | git clone https://github.com/BCNetio/BlockStackWallet
15 | npm install
16 | npm run production
17 | cd public/
18 | mv * /your/public/server/folder
19 | ```
20 |
21 | ## Remember you have to add API keys and Ethereum like nodes.
22 |
23 | ```
24 | app/Providers/config.js - apiKeys and config.exchangeApiKeys
25 | app/AppConfig.js - config.bsNodeProfile (url of blockstack profile) needed in case you run local node
26 | app/AppConfig.js - config.nodes (list of ethereum like nodes)
27 | ```
28 |
29 | ## Manifest file
30 | ```
31 | {
32 | "name": "Dappy Wallet",
33 | "start_url": "https://app.bcnet.io",
34 | "description": "Dappy Wallet is a non-custodial universal wallet",
35 | "icons": [
36 | {
37 | "src": "https://app.bcnet.io/dappy_logo.png",
38 | "sizes": "192x192",
39 | "type": "image/png"
40 | }
41 | ]
42 | }
43 | ```
44 |
45 | ## Nginx example
46 | ```
47 | server {
48 | listen 443 ssl;
49 | server_name app.bcnet.io;
50 | ssl_certificate /etc/crypto/app.bcnet.io/fullchain.pem;
51 | ssl_certificate_key /etc/crypto/app.bcnet.io/privkey.pem;
52 |
53 | location / {
54 | root /cdn/dappy/;
55 | try_files $uri /index.html;
56 | add_header Access-Control-Allow-Origin *;
57 | }
58 | }
59 | server {
60 | if ($host = app.bcnet.io) {
61 | return 301 https://$host$request_uri;
62 | }
63 | listen 80;
64 | listen [::]:80;
65 | server_name app.bcnet.io;
66 | return 404;
67 | }
68 | ```
69 |
--------------------------------------------------------------------------------
/app/AppConfig.js:
--------------------------------------------------------------------------------
1 | export const curNames = {
2 | BTC: "btc",
3 | BCH: "bch",
4 | ETH: "eth",
5 | ETC: "etc",
6 | DOGE: "doge",
7 | LTC: "ltc",
8 | DASH: "dash",
9 | BTG: "btg"
10 | };
11 |
12 | export const config = {};
13 |
14 | config.mediumNewsRoot = "https://medium.com/dappy/";
15 |
16 | config.bsNodeProfile = "https://browser.blockstack.org/profiles";
17 |
18 | config.avCurrencyes = new Map([
19 | [curNames.BTC, { name: "Bitcoin", abbr: "BTC", sysName: curNames.BTC }],
20 | [curNames.BCH, { name: "Bitcoin cash", abbr: "BCH", sysName: curNames.BCH }],
21 | [curNames.ETH, { name: "Ethereum", abbr: "ETH", sysName: curNames.ETH }],
22 | [
23 | curNames.ETC,
24 | { name: "Ethereum classic", abbr: "ETC", sysName: curNames.ETC }
25 | ],
26 | [curNames.DOGE, { name: "Dogecoin", abbr: "DOGE", sysName: curNames.DOGE }],
27 | [curNames.LTC, { name: "Litecoin", abbr: "LTC", sysName: curNames.LTC }],
28 | [curNames.DASH, { name: "Dash", abbr: "DASH", sysName: curNames.DASH }],
29 | [curNames.BTG, { name: "Bitcoin Gold", abbr: "BTG", sysName: curNames.BTG }]
30 | ]);
31 |
32 | config.nodes = new Map([[curNames.ETH, ""], [curNames.ETC, ""]]);
33 |
34 | config.networks = {
35 | [curNames.LTC]: {
36 | messagePrefix: "\x19Litecoin Signed Message:\n",
37 | bip32: {
38 | public: 0x019da462,
39 | private: 0x019d9cfe
40 | },
41 | pubKeyHash: 0x30,
42 | scriptHash: 0x32,
43 | wif: 0xb0
44 | },
45 | [curNames.DCR]: {
46 | messagePrefix: "\x18Bitcoin Signed Message:\n",
47 | bech32: "dc",
48 | bip32: {
49 | public: 0x0488b21e,
50 | private: 0x0488ade4
51 | },
52 | pubKeyHash: 0x00,
53 | scriptHash: 0x05,
54 | wif: 0x80
55 | },
56 | [curNames.BTC]: {
57 | messagePrefix: "\x18Bitcoin Signed Message:\n",
58 | bech32: "bc",
59 | bip32: {
60 | public: 0x0488b21e,
61 | private: 0x0488ade4
62 | },
63 | pubKeyHash: 0x00,
64 | scriptHash: 0x05,
65 | wif: 0x80
66 | },
67 | [curNames.BTG]: {
68 | messagePrefix: "\x18Bitcoin Gold Signed Message:\n",
69 | bip32: {
70 | public: 0x0488b21e,
71 | private: 0x0488ade4
72 | },
73 | pubKeyHash: 0x26,
74 | scriptHash: 0x17,
75 | wif: 0x80
76 | },
77 | [curNames.DOGE]: {
78 | messagePrefix: "\x19Dogecoin Signed Message:\n",
79 | bip32: {
80 | private: 0x02fac398,
81 | public: 0x02facafd
82 | },
83 | wif: 0x9e,
84 | pubKeyHash: 0x1e,
85 | scriptHash: 0x16
86 | },
87 | [curNames.DASH]: {
88 | messagePrefix: "\x19DarkCoin Signed Message:\n",
89 | bip32: {
90 | public: 0x02fe52f8,
91 | private: 0x02fe52cc
92 | },
93 | pubKeyHash: 0x4c,
94 | scriptHash: 0x10,
95 | wif: 0xcc
96 | }
97 | };
98 |
--------------------------------------------------------------------------------
/app/CommonComponents/BalanceCard.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | export const BalanceCard = styled.div`
4 | .title {
5 | color: #f1f1f1;
6 | font-size: 14px;
7 | letter-spacing: 0.26px;
8 | line-height: 16px;
9 | margin: 0;
10 | margin-bottom: 32px;
11 | }
12 | .subtitle {
13 | color: #ffffff;
14 | font-size: 12px;
15 | letter-spacing: 0.3px;
16 | line-height: 14px;
17 | margin: 0;
18 | margin-bottom: 10px;
19 | margin-top: 35px;
20 | span {
21 | font-size: 8px;
22 | text-align: right;
23 | letter-spacing: 0.2px;
24 | color: #8d96b2;
25 | display: inline-block;
26 | margin-left: 5px;
27 | cursor: pointer;
28 | }
29 | }
30 | .total {
31 | color: #ffffff;
32 | font-size: 28px;
33 | font-weight: 300;
34 | letter-spacing: 0.19px;
35 | line-height: 33px;
36 | margin: 0;
37 | margin-bottom: 5px;
38 | }
39 | .currency {
40 | color: #8d96b2;
41 | font-size: 12px;
42 | letter-spacing: 0.3px;
43 | line-height: 14px;
44 | margin: 0;
45 | }
46 | .wallets-number {
47 | background-color: #1f2431;
48 | height: 60px;
49 | width: 65px;
50 | text-align: center;
51 | border-radius: 2px;
52 | p:first-child {
53 | color: #8d96b2;
54 | font-size: 28px;
55 | font-weight: 300;
56 | letter-spacing: 0.25px;
57 | line-height: 33px;
58 | margin: 0;
59 | margin-top: 5px;
60 | }
61 | p:last-child {
62 | color: #8d96b2;
63 | font-size: 12px;
64 | letter-spacing: 0.28px;
65 | line-height: 14px;
66 | margin: 0;
67 | margin-bottom: 10px;
68 | }
69 | }
70 | .address {
71 | margin: 0;
72 | padding: 10px;
73 | background-color: rgba(241, 241, 241, 0.1);
74 | border-radius: 2px 0 0 2px;
75 | height: auto;
76 | width: 90%;
77 | overflow: hidden;
78 | }
79 | `;
80 |
--------------------------------------------------------------------------------
/app/CommonComponents/Chart.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Line } from "react-chartjs-2";
3 | import Card from "@material-ui/core/Card";
4 | import Button from "@material-ui/core/Button";
5 | import { merge, lensPath, over, equals } from "ramda";
6 | import Select from "./Select";
7 | import { config, curNames } from "../AppConfig";
8 | import {
9 | layout,
10 | ChartDrapdawnTitle,
11 | lineOptions,
12 | options,
13 | periods,
14 | ChartBox,
15 | chartOptions,
16 | toolTips
17 | } from "./ChartOptions";
18 |
19 | class Chart extends React.Component {
20 | static currentTime() {
21 | return Math.round(new Date().getTime() / 1000.0);
22 | }
23 |
24 | constructor(props) {
25 | super(props);
26 | const currency = config.avCurrencyes.get(props.currency);
27 |
28 | this.state = {
29 | currency: currency || config.avCurrencyes.get(curNames.BTC),
30 | period: "day",
31 | list: Array.from(config.avCurrencyes)
32 | };
33 |
34 | this.fetchData = this.fetchData.bind(this);
35 | this.onChangePeriod = this.onChangePeriod.bind(this);
36 | this.handleCurrency = this.handleCurrency.bind(this);
37 | this.mergeCallbacksForFiat = this.mergeCallbacksForFiat.bind(this);
38 | }
39 |
40 | componentDidMount() {
41 | this.fetchData();
42 | }
43 |
44 | shouldComponentUpdate(nextProps, nextState) {
45 | return !equals(this.props, nextProps) || !equals(this.state, nextState);
46 | }
47 |
48 | onChangePeriod(period) {
49 | this.setState({ period });
50 | }
51 |
52 | getSnapshotBeforeUpdate(prevProps, prevState) {
53 | if (
54 | !equals(prevProps.selectedFiat, this.props.selectedFiat) ||
55 | !equals(prevState.period, this.state.period) ||
56 | !equals(prevState.currency, this.state.currency)
57 | ) {
58 | this.fetchData();
59 | }
60 | return null;
61 | }
62 |
63 | fetchData() {
64 | this.props.action(
65 | this.state.currency.abbr,
66 | this.state.period,
67 | Chart.currentTime(),
68 | this.props.selectedFiat.abbr
69 | );
70 | }
71 |
72 | handleCurrency(currency) {
73 | this.setState({ currency });
74 | }
75 |
76 | mergeCallbacksForFiat() {
77 | const { name, abbr } = this.props.selectedFiat;
78 | return merge(options(`${name} (${abbr})`), toolTips(abbr));
79 | }
80 |
81 | render() {
82 | return (
83 |
84 |
85 |
86 |
92 |
93 |
94 | {periods.map(period => (
95 | this.onChangePeriod(period)}
97 | key={period}
98 | style={layout.button}
99 | variant={"outlined"}
100 | >
101 | {period}
102 |
103 | ))}
104 |
105 |
106 | {this.props.data.datasets && (
107 | merge(lineOptions, __),
111 | this.props.data
112 | )}
113 | options={this.mergeCallbacksForFiat()}
114 | />
115 | )}
116 |
117 | );
118 | }
119 | }
120 |
121 | const wrapWallet = (
122 | data,
123 | action,
124 | selectedFiat,
125 | currency,
126 | wrappedLayout
127 | ) => Component => (
128 |
135 | );
136 |
137 | const wrapedWallet = (data, action, selectedFiat, currency, wrappedLayout) =>
138 | wrapWallet(data, action, selectedFiat, currency, wrappedLayout)(Chart);
139 |
140 | export default wrapedWallet;
141 |
--------------------------------------------------------------------------------
/app/CommonComponents/ChartOptions.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import IconArrowDown from "../images/common/icon-arrow-down.svg";
3 |
4 | export const layout = {
5 | input: {
6 | display: "none"
7 | },
8 | card: {
9 | backgroundColor: "#2B3649",
10 | color: "#FFFFFF",
11 | fontSize: 12,
12 | textOverflow: "ellipsis",
13 | padding: "0 20px",
14 | boxShadow: "0 25px 40px 0 rgba(0,0,0,0.3)"
15 | },
16 | button: {
17 | color: "#8D96B2",
18 | margin: "1px",
19 | borderRadius: "14px",
20 | borderColor: "#8D96B2",
21 | fontSize: "12px",
22 | minHeight: "auto",
23 | minWidth: "0",
24 | padding: "4px 8px",
25 | letterSpacing: "0.45px",
26 | lineHeight: "14px"
27 | }
28 | };
29 |
30 | export const ChartDrapdawnTitle = styled.div`
31 | > div {
32 | div:first-child {
33 | letter-spacing: 0.21px;
34 | cursor: pointer;
35 | position: relative;
36 | &:after {
37 | content: "";
38 | display: block;
39 | position: absolute;
40 | top: 50%;
41 | right: -20px;
42 | width: 9px;
43 | height: 8px;
44 | transform: translateY(-50%) rotate(-90deg);
45 | background: url(${IconArrowDown}) no-repeat;
46 | }
47 | }
48 | }
49 | `;
50 |
51 | export const ChartBox = styled.div`
52 | display: flex;
53 | align-items: center;
54 | justify-content: space-between;
55 | padding: 15px 0;
56 | `;
57 |
58 | export const lineOptions = {
59 | backgroundColor: "rgba(43, 54, 73, 0.09)",
60 | borderColor: "rgb(122, 194, 49)",
61 | borderCapStyle: "butt",
62 | borderDash: [],
63 | borderDashOffset: 0.0,
64 | borderJoinStyle: "miter",
65 | pointBorderColor: "#7AC231",
66 | pointBackgroundColor: "inherit",
67 | pointBorderWidth: 0,
68 | pointHoverRadius: 3,
69 | pointHoverBackgroundColor: "#FFFFFF",
70 | pointHoverBorderColor: "#7AC231",
71 | pointHoverBorderWidth: 2,
72 | pointRadius: 0,
73 | pointHitRadius: 10,
74 | fill: false,
75 | lineTension: 0,
76 | borderWidth: 2
77 | };
78 |
79 | export const options = currency => ({
80 | scales: {
81 | xAxes: [
82 | {
83 | gridLines: {
84 | display: false
85 | },
86 | ticks: {
87 | fontColor: "#8D96B2",
88 | fontFamily: "Roboto",
89 | fontStyle: "bold",
90 | fontSize: 11
91 | },
92 | type: "time",
93 | distribution: "linear",
94 | drawOnChartArea: false,
95 | color: "#FFFFFF"
96 | }
97 | ],
98 | yAxes: [
99 | {
100 | scaleLabel: {
101 | display: true,
102 | labelString: currency
103 | },
104 | gridLines: {
105 | color: "rgba(141,150,178,0.1)"
106 | },
107 | ticks: {
108 | fontSize: 11,
109 | fontColor: "#8D96B2",
110 | fontFamily: "Roboto",
111 | fontStyle: "bold"
112 | }
113 | }
114 | ]
115 | },
116 | legend: { display: false }
117 | });
118 |
119 | export const toolTips = abbr => ({
120 | tooltips: {
121 | backgroundColor: "#FFFFFF",
122 | titleFontColor: "rgba(0, 0, 0, 0.87)",
123 | bodyFontColor: "rgba(0, 0, 0, 0.87)",
124 | displayColors: false,
125 | position: "nearest",
126 | callbacks: {
127 | label: tooltipItems => `${abbr} ${tooltipItems.yLabel} `
128 | }
129 | }
130 | });
131 |
132 | export const chartOptions = { search: true, input: false, type: "chart" };
133 |
134 | export const periods = ["day", "week", "month", "year"];
135 |
--------------------------------------------------------------------------------
/app/CommonComponents/ContentColumn/Index.js:
--------------------------------------------------------------------------------
1 | import styled, { css } from "styled-components";
2 |
3 | export const Column = styled.div`
4 |
5 | ${props =>
6 | props.left &&
7 | css`
8 | width: 29%;
9 | @media (max-width: 1200px) {
10 | width: 49%;
11 | height: auto;
12 | }
13 | @media (max-width: 992px) {
14 | width: 100%;
15 | margin-bottom: 20px;
16 | }
17 | @media (max-width: 768px) {
18 | width: 100%;
19 | margin-top: 20px;
20 | margin-right: 0;
21 | }
22 | `}
23 |
24 | ${props =>
25 | props.middle &&
26 | css`
27 | width: 39%;
28 | @media (max-width: 1200px) {
29 | width: 49%;
30 | height: auto;
31 | }
32 | @media (max-width: 992px) {
33 | width: 100%;
34 | }
35 | @media (max-width: 768px) {
36 | width: 100%;
37 | margin-right: 0;
38 | }
39 | `}
40 |
41 | ${props =>
42 | props.right &&
43 | css`
44 | width: 29%;
45 | @media (max-width: 1200px) {
46 | width: 100%;
47 | margin-top: 20px;
48 | }
49 | @media (max-width: 768px) {
50 | margin-right: 0;
51 | }
52 | `}
53 | `;
54 |
--------------------------------------------------------------------------------
/app/CommonComponents/Modal.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 |
4 | const modalRoot = document.getElementById("modal-root");
5 |
6 | export default class Modal extends React.Component {
7 | constructor(props) {
8 | super(props);
9 | this.el = document.createElement("div");
10 | }
11 |
12 | componentDidMount() {
13 | modalRoot.appendChild(this.el);
14 | }
15 |
16 | componentWillUnmount() {
17 | modalRoot.removeChild(this.el);
18 | }
19 |
20 | render() {
21 | return ReactDOM.createPortal(this.props.children, this.el);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/CommonComponents/PopUp/InputForAddres.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import IconManualAddress from "../../images/common/icon-manual-address.svg";
4 |
5 | export const InputManualAddressWrapper = styled.div`
6 | background: #e2e4e8 url(${IconManualAddress}) no-repeat 5% 50%;
7 | font-size: 10px;
8 | letter-spacing: 0.230769px;
9 | color: #2b3649;
10 | `;
11 |
12 | const InputForAddres = ({ onClick }) => (
13 |
18 | Manual addres input
19 |
20 | );
21 |
22 | export default InputForAddres;
23 |
--------------------------------------------------------------------------------
/app/CommonComponents/PopUp/Search.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class SearchBar extends React.Component {
4 | constructor() {
5 | super();
6 | this.state = { searchPredicate: "" };
7 | this.onChangeSerachPredicate = this.onChangeSerachPredicate.bind(this);
8 | }
9 |
10 | onChangeSerachPredicate(e) {
11 | this.setState({ searchPredicate: e.target.value });
12 | this.props.onSearchItem(e.target.value);
13 | }
14 |
15 | render() {
16 | return (
17 |
24 | );
25 | }
26 | }
27 |
28 | export default SearchBar;
29 |
--------------------------------------------------------------------------------
/app/CommonComponents/PopUp/config.js:
--------------------------------------------------------------------------------
1 | import { filter } from "ramda";
2 |
3 | export const searachFunctions = {
4 | transactions: (searchPredicate, list) =>
5 | filter(
6 | wallet =>
7 | wallet.alias.toUpperCase().includes(searchPredicate.toUpperCase()),
8 | list
9 | ),
10 | fiat: (searchPredicate, list) =>
11 | filter(
12 | fiat =>
13 | fiat.name.toUpperCase().includes(searchPredicate.toUpperCase()) ||
14 | fiat.abbr.toUpperCase().includes(searchPredicate.toUpperCase()),
15 | list
16 | ),
17 | chart: (searchPredicate, list) =>
18 | filter(
19 | currency =>
20 | currency[1].name
21 | .toUpperCase()
22 | .includes(searchPredicate.toUpperCase()) ||
23 | currency[1].abbr.toUpperCase().includes(searchPredicate.toUpperCase()),
24 | list
25 | ),
26 | wallet: (searchPredicate, list) =>
27 | filter(
28 | currency =>
29 | currency[1].name
30 | .toUpperCase()
31 | .includes(searchPredicate.toUpperCase()) ||
32 | currency[1].abbr.toUpperCase().includes(searchPredicate.toUpperCase()),
33 | list
34 | )
35 | };
36 |
--------------------------------------------------------------------------------
/app/CommonComponents/RoutingPanel.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { withStyles } from "@material-ui/core/styles";
3 |
4 | import NavbarWrapper from "../InitialPage/Menu";
5 |
6 | const styles = {
7 | navItem: {
8 | color: "#FFFFFF"
9 | }
10 | };
11 |
12 | export const RoutingPanel = withStyles(styles)(({}) => );
13 |
--------------------------------------------------------------------------------
/app/Exchange/ActionTypes.js:
--------------------------------------------------------------------------------
1 | export const types = {
2 | FETCH_WALLETS: "@@exchange/FETCH_WALLETS",
3 | MOUNT_WALLETS: "@@exchange/MOUNT_WALLETS",
4 | FETCH_WALLET_BALANCE: "@@exchange/FETCH_WALLET_BALANCE",
5 | MOUNT_WALLET_BALANCE: "@@exchange/MOUNT_WALLET_BALANCE",
6 | FETCH_MARKET_INFO: "@@exchange/FETCH_MARKET_INFO",
7 | MOUNT_MARKET_INFO: "@@exchange/MOUNT_MARKET_INFO",
8 | FETCH_CHECK_EXCHANGE: "@@exchange/FETCH_CHECK_EXCHANGE",
9 | MOUNT_EXCHANGE_CHECK: "@@exchange/MOUNT_EXCHANGE_CHECK",
10 | MOUNT_EXCHANGE_CHECK_ERROR: "@@exchange/MOUNT_EXCHANGE_CHECK_ERROR",
11 | MOUNT_ACTIVE_TAB: "@@exchange/MOUNT_ACTIVE_TAB",
12 | MOUNT_EXCHANE_DETAILS: "@@exchange/MOUNT_EXCHANE_DETAILS",
13 | MAKE_TRANSACTION: "@@exchange/MAKE_TRANSACTION",
14 | FETTCH_STATUS_DEPOSIT: "@@exchange/FETTCH_STATUS_DEPOSIT",
15 | MOUNT_STATUS_DEPOSIT: "@@exchange/MOUNT_STATUS_DEPOSIT"
16 | };
17 |
--------------------------------------------------------------------------------
/app/Exchange/Actions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | export const fetchWallets = createAction(types.FETCH_WALLETS, () => ({}));
5 |
6 | export const fetchMarketInfo = createAction(types.FETCH_MARKET_INFO, pair => ({
7 | pair
8 | }));
9 |
10 | export const fetchWalletBalance = createAction(
11 | types.FETCH_WALLET_BALANCE,
12 | (type, address) => ({
13 | type,
14 | address
15 | })
16 | );
17 |
18 | export const mountActiveTab = createAction(types.MOUNT_ACTIVE_TAB, tabId => ({
19 | tabId
20 | }));
21 |
22 | export const mountExchangeDetails = createAction(
23 | types.MOUNT_EXCHANE_DETAILS,
24 | details => ({
25 | details
26 | })
27 | );
28 |
29 | export const fetchStatusExchange = createAction(
30 | types.FETCH_CHECK_EXCHANGE,
31 | params => ({
32 | params
33 | })
34 | );
35 |
36 | export const makeTransaction = createAction(
37 | types.MAKE_TRANSACTION,
38 | (wallet, receivers) => ({
39 | wallet,
40 | receivers
41 | })
42 | );
43 |
44 | export const fetchStatusDeposit = createAction(
45 | types.FETTCH_STATUS_DEPOSIT,
46 | address => ({
47 | address
48 | })
49 | );
50 |
--------------------------------------------------------------------------------
/app/Exchange/CommonComponents/Index.js:
--------------------------------------------------------------------------------
1 | import styled, { css } from "styled-components";
2 |
3 | // Icons
4 | import IconArrowDown from "../../images/common/icon-arrow-down.svg";
5 |
6 | // Styled
7 | // One string in form
8 | export const Row = styled.div`
9 | display: flex;
10 | justify-content: space-between;
11 | align-items: center;
12 | @media (max-width: 768px) {
13 | flex-wrap: wrap;
14 | }
15 |
16 | ${props =>
17 | props.mt20 &&
18 | css`
19 | margin-top: 20px;
20 | `}
21 | `;
22 |
23 | // Wrapper for input + select
24 | export const DoubleInputSelectWrapper = styled.div`
25 | display: flex;
26 | justify-content: flex-end;
27 | align-items: stretch;
28 | @media (max-width: 768px) {
29 | width: 100%;
30 | justify-content: flex-start;
31 | }
32 | `;
33 |
34 | // Input for exchange
35 | export const Input = styled.input`
36 | border-radius: 2px 0 0 2px;
37 | background-color: #1f2431;
38 | border: none;
39 | height: auto;
40 | padding-left: 20px;
41 | color: #fff;
42 | width: 194px;
43 | @media (max-width: 768px) {
44 | width: 40%;
45 | min-width: 50px;
46 | }
47 | `;
48 |
49 | // Dropdawn list
50 | export const SelectWrapper = styled.div`
51 | height: auto;
52 | background-color: #273041;
53 | position: relative;
54 | cursor: pointer;
55 | &:after {
56 | content: "";
57 | display: block;
58 | height: 9px;
59 | width: 6px;
60 | position: absolute;
61 | right: 10px;
62 | top: 42%;
63 | background: url(${IconArrowDown}) no-repeat;
64 | transform: rotate(-90deg) translateY(-50%);
65 | }
66 | &:hover {
67 | background-color: rgba(0, 0, 0, 0.08);
68 | }
69 | > div {
70 | padding: 8px 10px;
71 | width: 156px;
72 | > div:first-child {
73 | display: flex;
74 | align-items: center;
75 | justify-content: flex-start;
76 | font-size: 11px;
77 | letter-spacing: 0.4125px;
78 | color: #ffffff;
79 | div {
80 | width: 20%;
81 | height: 20px;
82 | margin-right: 10px;
83 | img {
84 | width: 100%;
85 | height: 100%;
86 | object-fit: contain;
87 | }
88 | }
89 | p {
90 | white-space: nowrap;
91 | text-overflow: ellipsis;
92 | overflow: hidden;
93 | padding-right: 20px;
94 | width: 80%;
95 | }
96 | }
97 | }
98 | `;
99 |
100 | // Label for DoubleInputSelectWrapper
101 | export const Label = styled.p`
102 | font-size: 11px;
103 | letter-spacing: 0.41px;
104 | line-height: 13px;
105 | @media (max-width: 768px) {
106 | margin-bottom: 10px;
107 | }
108 | `;
109 |
110 | // Span for avalaible amount + error
111 | export const Tooltip = styled.span`
112 | color: #8d96b2;
113 | font-size: 8px;
114 | letter-spacing: 0.2px;
115 | line-height: 9px;
116 | margin-left: 61px;
117 | @media (max-width: 768px) {
118 | margin-left: 0;
119 | }
120 | &.error {
121 | color: red;
122 | display: block;
123 | margin-top: 10px;
124 | }
125 | `;
126 |
127 | // Button to next screen
128 | export const NextButtonWrapper = styled.div`
129 | margin-top: 35px;
130 | text-align: right;
131 | `;
132 |
133 | export const Next = styled.button`
134 | border: 1px solid #8d96b2;
135 | border-radius: 14px;
136 | background: transparent;
137 | color: #8d96b2;
138 | padding: 5px 20px;
139 | cursor: pointer;
140 | margin-right: 5px;
141 | outline: none;
142 | `;
143 |
144 | // Info tabs
145 | export const Tabs = styled.div`
146 | border-top: 1px solid rgba(141, 150, 178, 0.1);
147 | display: flex;
148 | justify-content: space-between;
149 | width: 100%;
150 | margin-left: -20px;
151 | position: absolute;
152 | bottom: 0;
153 | div {
154 | width: 33.9%;
155 | text-align: center;
156 | padding: 15px 0;
157 | &:not(:last-child) {
158 | border-right: 1px solid rgba(141, 150, 178, 0.1);
159 | }
160 | p {
161 | color: #8d96b2;
162 | font-size: 10px;
163 | letter-spacing: 0.25px;
164 | line-height: 11px;
165 | margin-bottom: 4px;
166 | }
167 | span {
168 | color: #f1f1f1;
169 | font-size: 10px;
170 | letter-spacing: 0.25px;
171 | line-height: 11px;
172 | text-transform: uppercase;
173 | }
174 | }
175 | `;
176 |
177 | //
178 | const Button = styled.button`
179 | border: 1px solid #7ed321;
180 | border-radius: 14px;
181 | background: transparent;
182 | color: #8d96b2;
183 | padding: 5px 20px;
184 | cursor: pointer;
185 | margin-right: 5px;
186 | outline: none;
187 | `;
188 |
--------------------------------------------------------------------------------
/app/Exchange/Exchange.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import { withStyles } from "@material-ui/core/styles";
4 | import Divider from "@material-ui/core/Divider";
5 | import styled from "styled-components";
6 | import * as actions from "./Actions";
7 | import StartExchange from "./StartExchange";
8 | import Confirmation from "./Confirmation";
9 | import StatusExchange from "./StatusExchange";
10 | import IconSwap from "../images/common/icon-swap.svg";
11 |
12 | // Import components
13 | import { Button } from "./CommonComponents/Index";
14 |
15 | const styles = {};
16 |
17 | // Styled
18 | const ExchangeWrapper = styled.div`
19 | width: 450px;
20 | height: 380px;
21 | background-color: #2b3649;
22 | color: #fff;
23 | text-overflow: ellipsis;
24 | position: relative;
25 | overflow: visible;
26 | @media (max-width: 768px) {
27 | order: 3;
28 | margin: 0 auto;
29 | width: auto;
30 | }
31 | `;
32 |
33 | const Title = styled.div`
34 | padding: 20px;
35 | display: flex;
36 | justify-content: space-between;
37 | align-items: center;
38 | span {
39 | font-size: 14px;
40 | letter-spacing: 0.26px;
41 | line-height: 16px;
42 | position: relative;
43 | &:after {
44 | content: "";
45 | display: block;
46 | position: absolute;
47 | right: -30px;
48 | top: 50%;
49 | transform: translateY(-50%);
50 | width: 16px;
51 | height: 12px;
52 | background-image: url(${IconSwap});
53 | }
54 | }
55 | `;
56 |
57 | const tabs = [
58 | { name: "Start Exchange", value: 1, render: },
59 | { name: "Confirmation", value: 2, render: },
60 | { name: "Exchange detalls", value: 3, render: }
61 | ];
62 |
63 | class Exchange extends React.Component {
64 | render() {
65 | return (
66 |
67 |
68 | Exchange your funds
69 | {this.props.activeTabId === 2 && (
70 | this.props.mountActiveTab(0)}>
71 | New Order
72 |
73 | )}
74 |
75 |
76 |
77 | {tabs[this.props.activeTabId].render}
78 |
79 |
80 | );
81 | }
82 | }
83 |
84 | const mapStateToProps = state => ({
85 | wallets: state.exchange.wallets,
86 | activeTabId: state.exchange.activeTabId
87 | });
88 |
89 | const mapDispatchToProps = dispatch => ({
90 | fetchWallets: () => dispatch(actions.fetchWallets()),
91 | mountActiveTab: tabId => dispatch(actions.mountActiveTab(tabId))
92 | });
93 |
94 | export default withStyles(styles)(
95 | connect(
96 | mapStateToProps,
97 | mapDispatchToProps
98 | )(Exchange)
99 | );
100 |
--------------------------------------------------------------------------------
/app/Exchange/Reducer.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | const initialState = {
5 | amount: null,
6 | depositWallet: null,
7 | reciveAddr: null,
8 | balanceDeposit: null,
9 | wallets: [],
10 | marketInfo: {},
11 | activeTabId: 0,
12 | exchangeDetails: {},
13 | trx: {},
14 | shapeShiftError: "",
15 | statusDeposit: ""
16 | };
17 |
18 | export const exchange = handleActions(
19 | {
20 | [types.MOUNT_WALLETS]: (state, action) => ({
21 | ...state,
22 | wallets: action.payload
23 | }),
24 | [types.MOUNT_WALLET_BALANCE]: (state, action) => ({
25 | ...state,
26 | balanceDeposit: action.payload
27 | }),
28 | [types.MOUNT_MARKET_INFO]: (state, action) => ({
29 | ...state,
30 | marketInfo: action.payload
31 | }),
32 | [types.MOUNT_ACTIVE_TAB]: (state, action) => ({
33 | ...state,
34 | activeTabId: action.payload.tabId
35 | }),
36 | [types.MOUNT_EXCHANE_DETAILS]: (state, action) => ({
37 | ...state,
38 | exchangeDetails: action.payload.details,
39 | statusDeposit: ""
40 | }),
41 | [types.MOUNT_EXCHANGE_CHECK]: (state, action) => ({
42 | ...state,
43 | trx: action.payload,
44 | shapeShiftError: ""
45 | }),
46 | [types.MOUNT_STATUS_DEPOSIT]: (state, action) => ({
47 | ...state,
48 | statusDeposit: action.payload
49 | }),
50 | [types.MOUNT_EXCHANGE_CHECK_ERROR]: (state, action) => ({
51 | ...state,
52 | shapeShiftError: action.payload,
53 | trx: {}
54 | })
55 | },
56 |
57 | initialState
58 | );
59 |
--------------------------------------------------------------------------------
/app/Exchange/Saga.js:
--------------------------------------------------------------------------------
1 | import { put, call, takeLatest } from "redux-saga/effects";
2 | import { delay } from "redux-saga";
3 | import { has } from "ramda";
4 | import { types } from "./ActionTypes";
5 | import XHRProvider from "../Providers/XHRProvider";
6 | import { getWalletList } from "../Providers/Gaia";
7 | import { transactionByType } from "../Providers/Wallets";
8 |
9 | const xhr = new XHRProvider();
10 |
11 | function* fetchWallets(action) {
12 | try {
13 | const walletList = yield call(getWalletList);
14 | yield put({
15 | type: types.MOUNT_WALLETS,
16 | payload: walletList.kpList
17 | });
18 | } catch (error) {
19 | console.log(error);
20 | }
21 | }
22 |
23 | function* fecthWalletBalance(action) {
24 | const wallet = yield call(
25 | xhr.getWalletInfo,
26 | action.payload.type,
27 | action.payload.address
28 | );
29 | yield put({ type: types.MOUNT_WALLET_BALANCE, payload: wallet });
30 | }
31 |
32 | function* fetchMarketInfo(action) {
33 | const marketInfo = yield call(xhr.getMarketInfo, action.payload.pair);
34 | yield put({ type: types.MOUNT_MARKET_INFO, payload: marketInfo });
35 | }
36 |
37 | function* fetchCheckExchange(action) {
38 | try {
39 | const exchange = yield call(xhr.checkExchange, action.payload.params);
40 | has("success", exchange)
41 | ? yield put({
42 | type: types.MOUNT_EXCHANGE_CHECK,
43 | payload: exchange.success
44 | })
45 | : yield put({
46 | type: types.MOUNT_EXCHANGE_CHECK_ERROR,
47 | payload: exchange.error
48 | });
49 | } catch (error) {
50 | console.log(error);
51 | }
52 | }
53 |
54 | function* makeTransaction(action) {
55 | const { wallet, receivers } = action.payload;
56 | const { data } = yield call(xhr.getUtxo, wallet.type, wallet.address);
57 | const hash = transactionByType.get(wallet.type)(
58 | wallet.privateKey,
59 | data,
60 | receivers,
61 | wallet.type
62 | );
63 | const e = yield call(xhr.broadcastTX, wallet.type, hash);
64 | yield e;
65 | }
66 |
67 | function* fetchStatusDeposit(action) {
68 | yield put({
69 | type: types.MOUNT_STATUS_DEPOSIT,
70 | payload: "Pending"
71 | });
72 | try {
73 | while (true) {
74 | const data = yield call(xhr.checkStatusDeposit, action.payload.address);
75 | yield call(delay, 10000);
76 | if (data.status === "complete") {
77 | yield put({
78 | type: types.MOUNT_STATUS_DEPOSIT,
79 | payload: "Finished"
80 | });
81 | break;
82 | }
83 | }
84 | } catch (error) {
85 | yield put({
86 | type: types.MOUNT_STATUS_DEPOSIT,
87 | payload: "Failed"
88 | });
89 | }
90 | }
91 |
92 | export function* exchangeSaga() {
93 | yield takeLatest(types.FETCH_WALLET_BALANCE, fecthWalletBalance);
94 | yield takeLatest(types.FETCH_WALLETS, fetchWallets);
95 | yield takeLatest(types.FETCH_MARKET_INFO, fetchMarketInfo);
96 | yield takeLatest(types.FETCH_CHECK_EXCHANGE, fetchCheckExchange);
97 | yield takeLatest(types.MAKE_TRANSACTION, makeTransaction);
98 | yield takeLatest(types.FETTCH_STATUS_DEPOSIT, fetchStatusDeposit);
99 | }
100 |
--------------------------------------------------------------------------------
/app/Exchange/StatusExchange.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import CircularProgress from "@material-ui/core/CircularProgress";
4 | import styled, { css } from "styled-components";
5 |
6 | import * as actions from "./Actions";
7 |
8 | const Dots = styled.span``;
9 |
10 | const waitingSucces = () => {
11 |
12 |
Awaiting exchange
13 |
14 |
;
15 | };
16 |
17 | const Awaiting = styled.div`
18 | height: 310px;
19 | position: relative;
20 | padding: 20px;
21 | p {
22 | font-size: 12px;
23 | letter-spacing: 0.225px;
24 | color: #f1f1f1;
25 | }
26 | .result {
27 | p {
28 | &:first-child {
29 | font-size: 12px;
30 | line-height: 19px;
31 | letter-spacing: 0.225px;
32 | color: #f1f1f1;
33 | span {
34 | color: #8d96b2;
35 | }
36 | }
37 | &:last-child {
38 | font-size: 18px;
39 | letter-spacing: 0.3375px;
40 | color: #7ac231;
41 | margin: 0;
42 | }
43 | }
44 | }
45 | .loading:after {
46 | left: 0;
47 | }
48 | .awaiting-info {
49 | position: absolute;
50 | bottom: 20px;
51 | width: 100%;
52 | div {
53 | display: flex;
54 | align-items: center;
55 | &:not(:last-child) {
56 | margin-bottom: 10px;
57 | }
58 | p {
59 | font-size: 10px;
60 | letter-spacing: 0.1875px;
61 | color: #f1f1f1;
62 | &:first-child {
63 | width: 12%;
64 | }
65 | &:last-child {
66 | width: 80%;
67 | }
68 | }
69 | .order-value {
70 | font-size: 10px;
71 | letter-spacing: 0.1875px;
72 | color: #7ac231;
73 | }
74 | .order-status {
75 | color: #8d96b2;
76 | }
77 | }
78 | }
79 | `;
80 |
81 | class StatusExchange extends React.Component {
82 | render() {
83 | return (
84 |
85 | {this.props.statusDeposit === "Pending" && (
86 |
87 |
Awaiting Exchange
88 |
89 |
90 | )}
91 | {this.props.statusDeposit === "Finished" && (
92 |
93 |
94 | Congratulations! You just exchange
95 |
96 |
97 | {this.props.exchangeDetails.amount}{" "}
98 | {this.props.exchangeDetails.walletFrom.type.toUpperCase()}
99 | {" "}
100 | to
101 |
102 |
103 | {(this.props.exchangeDetails.amount -
104 | this.props.marketInfo.minimum) *
105 | this.props.marketInfo.rate}
106 | {this.props.exchangeDetails.walletTo.type.toUpperCase()}
107 |
108 |
109 | )}
110 |
111 |
121 |
122 |
Status
123 |
{this.props.statusDeposit}
124 |
125 |
126 |
127 | );
128 | }
129 | }
130 |
131 | const mapStateToProps = state => ({
132 | marketInfo: state.exchange.marketInfo,
133 | exchangeDetails: state.exchange.exchangeDetails,
134 | trx: state.exchange.trx,
135 | statusDeposit: state.exchange.statusDeposit
136 | });
137 |
138 | const mapDispatchToProps = dispatch => ({
139 | mountActiveTab: tabId => dispatch(actions.mountActiveTab(tabId)),
140 | makeTransaction: (wallet, receivers) =>
141 | dispatch(actions.makeTransaction(wallet, receivers))
142 | });
143 |
144 | export default connect(
145 | mapStateToProps,
146 | mapDispatchToProps
147 | )(StatusExchange);
148 |
--------------------------------------------------------------------------------
/app/Fiat/ActionTypes.js:
--------------------------------------------------------------------------------
1 | export const types = {
2 | FETCH_COURSE: "@@fiat/FETCH_COURSE",
3 | MOUNT_COURSE: "@@fiat/MOUNT_COURSE",
4 | MOUNT_FIAT: "@@fiat/MOUNT_FIAT",
5 | FETCH_COURSE_COMISSION: "@@fiat/FETCH_COURSE_COMISSION",
6 | MOUNT_COURSE_COMISSION: "@@fiat/MOUNT_COURSE_COMISSION"
7 | };
8 |
--------------------------------------------------------------------------------
/app/Fiat/Actions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | export const fetchCourse = createAction(types.FETCH_COURSE, fiat => ({ fiat }));
5 |
6 | export const mountFiat = createAction(types.MOUNT_FIAT, fiat => ({ fiat }));
7 |
8 | export const fetchCourseComission = createAction(
9 | types.FETCH_COURSE_COMISSION,
10 | () => ({})
11 | );
12 |
--------------------------------------------------------------------------------
/app/Fiat/Fiat.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import Select from "../CommonComponents/Select";
4 | import * as actions from "./Actions";
5 |
6 | const fiat = [
7 | { name: "United States Dollar", abbr: "USD" },
8 | { name: "Euro", abbr: "EUR" },
9 | { name: "Russian ruble", abbr: "RUB" },
10 | { name: "Australian Dollar", abbr: "AUD" },
11 | { name: "Brazilian Real", abbr: "BRL" },
12 | { name: "Canadian dollar", abbr: "CAD" },
13 | { name: "Swiss Franc", abbr: "CHF" },
14 | { name: "Chinese Yuan", abbr: "CNY" },
15 | { name: "British Pound", abbr: "GBP" },
16 | { name: "Hong Kong dollar", abbr: "HKD" },
17 | { name: "Indonesian Rupiah", abbr: "IDR" },
18 | { name: "Indian Rupee", abbr: "INR" },
19 | { name: "Japanese Yen", abbr: "JPY" },
20 | { name: "Korean Won", abbr: "KRW" },
21 | { name: "Mexican Peso", abbr: "MXN" }
22 | ];
23 |
24 | class Fiat extends React.Component {
25 | componentDidMount() {
26 | this.props.fetchCourse(this.props.selectedFiat.abbr);
27 | this.props.fetchCourseComission();
28 | }
29 |
30 | handleMenuItemClick = fiat => {
31 | this.props.mountFiat(fiat);
32 | this.props.fetchCourse(fiat.abbr);
33 | };
34 |
35 | render() {
36 | return (
37 |
43 | );
44 | }
45 | }
46 |
47 | const mapStateToProps = state => ({
48 | selectedFiat: state.fiat.selectedFiat,
49 | course: state.fiat.course
50 | });
51 |
52 | const mapDispatchToProps = dispatch => ({
53 | fetchCourse: fiat => dispatch(actions.fetchCourse(fiat)),
54 | fetchCourseComission: () => dispatch(actions.fetchCourseComission()),
55 | mountFiat: fiat => dispatch(actions.mountFiat(fiat))
56 | });
57 |
58 | export default connect(
59 | mapStateToProps,
60 | mapDispatchToProps
61 | )(Fiat);
62 |
--------------------------------------------------------------------------------
/app/Fiat/Reducer.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | const initialState = {
5 | course: {},
6 | selectedFiat: { name: "United States Dollar", abbr: "USD" },
7 | fee: 0,
8 | gas: 0
9 | };
10 |
11 | const TYPICAL_TX_SIZE = 226;
12 |
13 | export const fiat = handleActions(
14 | {
15 | [types.MOUNT_COURSE]: (state, action) => ({
16 | ...state,
17 | course: action.payload
18 | }),
19 | [types.MOUNT_FIAT]: (state, action) => ({
20 | ...state,
21 | selectedFiat: action.payload.fiat
22 | }),
23 | [types.MOUNT_COURSE_COMISSION]: (state, action) => ({
24 | ...state,
25 | fee: action.payload.fee.hourFee * TYPICAL_TX_SIZE,
26 | gas: 20
27 | })
28 | },
29 |
30 | initialState
31 | );
32 |
--------------------------------------------------------------------------------
/app/Fiat/Saga.js:
--------------------------------------------------------------------------------
1 | import { put, call, takeLatest, all } from "redux-saga/effects";
2 | import { types } from "./ActionTypes";
3 | import XHRProvider from "../Providers/XHRProvider";
4 |
5 | const xhr = new XHRProvider();
6 |
7 | function* fetchСourse(action) {
8 | try {
9 | const course = yield call(xhr.getCourse, action.payload.fiat);
10 | yield put({
11 | type: types.MOUNT_COURSE,
12 | payload: course
13 | });
14 | } catch (error) {
15 | console.log(error);
16 | }
17 | }
18 |
19 | function* fetchCourseComission(action) {
20 | try {
21 | const [fee, gas] = yield all([call(xhr.fetchFee), call(xhr.fetchGas)]);
22 | yield put({ type: types.MOUNT_COURSE_COMISSION, payload: { fee, gas } });
23 | } catch (error) {
24 | console.log(error);
25 | }
26 | }
27 |
28 | export function* fiatSaga() {
29 | yield takeLatest(types.FETCH_COURSE, fetchСourse);
30 | yield takeLatest(types.FETCH_COURSE_COMISSION, fetchCourseComission);
31 | }
32 |
--------------------------------------------------------------------------------
/app/InitialPage/ActionTypes.js:
--------------------------------------------------------------------------------
1 | export const types = {
2 | CHECKOUT_WALLETS: "@@initialPage/CHECKOUT_WALLETS",
3 | MOUNT_WALLETS: "@@initialPage/MOUNT_WALLETS",
4 | CREATE_WALLET: "@@initialPage/CREATE_WALLET",
5 | DELETE_WALLET: "@@initialPage/DELETE_WALLET",
6 | SELECT_WALLET: "@@initalPage/SELECT_WALLET",
7 | FETCH_WALLET_INFO: "@@initalPage/FETCH_WALLET_INFO",
8 | MOUNT_WALLET_INFO: "@@initalPage/MOUNT_WALLET_INFO",
9 | FETCH_TOTAL_BALANCE: "@@initialPage/FETCH_TOTAL_BALANCE",
10 | MOUNT_TOTAL_BALANCE: "@@initialPage/MOUNT_TOTAL_BALANCE",
11 | MOUNT_HISTORY: "@@initialPage/MOUNT_HISTORY",
12 | CHECKOUT_HISTORY: "@@initialPage/CHECKOUT_HISTORY"
13 | };
14 |
--------------------------------------------------------------------------------
/app/InitialPage/Actions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | export const checkoutWalletList = createAction(
5 | types.CHECKOUT_WALLETS,
6 | () => {}
7 | );
8 |
9 | export const deleteWallet = createAction(
10 | types.DELETE_WALLET,
11 | (walletList, toBeDeleted) => ({
12 | walletList,
13 | toBeDeleted
14 | })
15 | );
16 |
17 | export const selectWallet = createAction(types.SELECT_WALLET, wallet => wallet);
18 |
19 | export const fetchWalletInfo = createAction(
20 | types.FETCH_WALLET_INFO,
21 | wallet => wallet
22 | );
23 |
24 | export const checkoutHistory = createAction(
25 | types.CHECKOUT_HISTORY,
26 | () => undefined
27 | );
28 |
29 | export const fetchTotalBalance = createAction(
30 | types.FETCH_TOTAL_BALANCE,
31 | (listOfAddress, course) => ({
32 | listOfAddress,
33 | course
34 | })
35 | );
36 |
--------------------------------------------------------------------------------
/app/InitialPage/Auth.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import { redirectToSignIn } from "blockstack";
4 | import Logo from "../images/dappy-logo.svg";
5 | import { BackButton } from "../Views";
6 |
7 | const LogoWrapper = styled.div`
8 | margin-bottom: 75px;
9 | margin-top: 60px;
10 | img {
11 | width: 127px;
12 | height: 25px;
13 | }
14 | `;
15 |
16 | const Greetings = styled.div`
17 | text-align: center;
18 | width: 100%;
19 | padding-top: 30px;
20 | p {
21 | margin: 0;
22 | }
23 | .btn-wrapper {
24 | width: 100%;
25 | text-align: right;
26 | padding-right: 45px;
27 | @media (max-width: 768px) {
28 | padding-right: 0;
29 | }
30 | }
31 | .information {
32 | background-color: #2b3649;
33 | padding: 20px;
34 | padding-top: 35px;
35 | max-width: 330px;
36 | box-shadow: 0 25px 40px 0 rgba(0, 0, 0, 0.3);
37 | margin: 0 auto;
38 | p {
39 | text-align: left;
40 | &:first-child {
41 | color: #f1f1f1;
42 | font-size: 14px;
43 | font-weight: 500;
44 | letter-spacing: 0.32px;
45 | line-height: 16px;
46 | margin-bottom: 15px;
47 | }
48 | &:nth-of-type(2) {
49 | color: #f1f1f1;
50 | font-size: 10px;
51 | letter-spacing: 0.23px;
52 | line-height: 16px;
53 | margin-bottom: 30px;
54 | }
55 | }
56 | button {
57 | border-radius: 2px;
58 | border: none;
59 | padding: 10px 0;
60 | background-color: #315efb;
61 | color: #f1f1f1;
62 | font-size: 12px;
63 | letter-spacing: 0.3px;
64 | line-height: 14px;
65 | width: 100%;
66 | cursor: pointer;
67 | }
68 | + p {
69 | font-size: 12px;
70 | font-weight: 500;
71 | letter-spacing: 0.28px;
72 | line-height: 14px;
73 | color: #8d96b2;
74 | margin-top: 25px;
75 | a {
76 | font-weight: 500;
77 | color: #f1f1f1;
78 | text-decoration: none;
79 | }
80 | }
81 | }
82 | `;
83 |
84 | export const Auth = () => (
85 |
86 |
87 | Back to homepage
88 |
89 |
90 |
91 |
92 |
93 |
94 |
Welcome to Dappy Wallet!
95 |
96 | Dappy Wallet is a non-custodial universal wallet. It doesn’t proceed
97 | user’s private key, it means that the customer is only the single
98 | person who is able to control the assets.
99 |
100 |
{
102 | const origin = window.location.origin;
103 | redirectToSignIn(origin, origin + "/manifest.json", [
104 | "store_write",
105 | "publish_data"
106 | ]);
107 | }}
108 | >
109 | {" "}
110 | Sign in with Blockstack ID
111 |
112 |
113 |
114 | New to Blockstack?{" "}
115 | Sign up in Blockstack
116 |
117 |
118 |
119 | );
120 |
--------------------------------------------------------------------------------
/app/InitialPage/Dashboard.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import * as actions from "./Actions";
4 | import { fiatCurrency, getDataForChart } from "../Wallets/Wallet/Actions";
5 | import ListOfWallets from "./ListOfWallets";
6 | import wrapedWallet from "../CommonComponents/Chart";
7 | import { SummaryCash } from "./SummaryCash";
8 | import { config, curNames } from "../AppConfig";
9 | import History from "./History";
10 | import Modal from "../CommonComponents/Modal";
11 | import NewsPanel from "./NewsCard/Container";
12 | import { Content } from "../Views";
13 | import { Column } from "../CommonComponents/ContentColumn/Index";
14 |
15 | const mapDispatchToProps = dispatch => ({
16 | checkoutWallets: () => dispatch(actions.checkoutWalletList()),
17 | deleteWallet: (walletList, wallet) =>
18 | dispatch(actions.deleteWallet(walletList, wallet)),
19 | createWallet: (walletList, wType) =>
20 | dispatch(actions.createWallet(walletList, wType)),
21 | selectWallet: wallet => dispatch(actions.selectWallet(wallet)),
22 | fetchWalletInfo: wallet => dispatch(actions.fetchWalletInfo(wallet)),
23 | fetchFiat: type => dispatch(fiatCurrency(type)),
24 | getDataForChart: (currency, period, timestamp, fiat) =>
25 | dispatch(getDataForChart(currency, period, timestamp, fiat)),
26 | fetchTotalBalance: (type, listOfAddress) =>
27 | dispatch(actions.fetchTotalBalance(type, listOfAddress)),
28 | checkoutHistory: () => dispatch(actions.checkoutHistory())
29 | });
30 |
31 | const mapStateToProps = state => ({
32 | chartData: state.wallets.wallet.chartData,
33 | dappyHistory: state.initialPage.dappyHistory,
34 | wallets: state.initialPage.walletList,
35 | selectedWallet: state.initialPage.selectedWallet,
36 | fiat: state.wallets.wallet.fiat,
37 | totalBalance: state.initialPage.totalBalance,
38 | selectedFiat: state.fiat.selectedFiat,
39 | course: state.fiat.course
40 | });
41 |
42 | class Dashboard extends React.Component {
43 | constructor(props) {
44 | super(props);
45 | props.checkoutWallets();
46 |
47 | this.state = {
48 | selectedCoin: config.avCurrencyes.get(curNames.BTC).sysName,
49 | modalContent: null,
50 | modalOptions: undefined
51 | };
52 |
53 | setTimeout(() => {
54 | if (this.props.wallets && this.props.wallets.length) {
55 | this.props.fetchFiat(this.state.selectedCoin);
56 | this.props.fetchTotalBalance(this.props.wallets, this.props.course);
57 | }
58 | }, 3000);
59 |
60 | this.pollInterval = setInterval(() => {
61 | if (this.props.wallets.length) {
62 | this.props.fetchFiat(this.state.selectedCoin);
63 | this.props.fetchTotalBalance(this.props.wallets, this.props.course);
64 | }
65 | }, 300000);
66 | }
67 |
68 | selectWallet = wallet => {
69 | this.props.fetchWalletInfo(wallet);
70 | this.props.selectWallet(wallet);
71 | };
72 |
73 | componentWillUnmount() {
74 | this.pollInterval = null;
75 | }
76 |
77 | componentDidMount() {
78 | this.props.checkoutHistory();
79 | this.props.fetchTotalBalance(this.props.wallets, this.props.course);
80 | }
81 |
82 | callModal = (Component, optionalData) => {
83 | this.setState({ modalContent: Component, modalOptions: optionalData });
84 | };
85 |
86 | closeModal = () => {
87 | this.setState({ modalContent: null });
88 | };
89 |
90 | render() {
91 | const ModalContent = this.state.modalContent;
92 | return (
93 |
94 |
95 | {this.state.modalContent ? (
96 |
100 | ) : null}
101 |
102 |
103 |
111 |
112 |
113 |
114 | {this.props.chartData &&
115 | wrapedWallet(
116 | this.props.chartData,
117 | this.props.getDataForChart,
118 | this.props.selectedFiat
119 | )}
120 |
121 |
122 |
123 |
130 |
131 |
132 | );
133 | }
134 | }
135 | export default connect(
136 | mapStateToProps,
137 | mapDispatchToProps
138 | )(Dashboard);
139 |
--------------------------------------------------------------------------------
/app/InitialPage/History.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Card from "@material-ui/core/Card";
3 | import RemoveIcon from "@material-ui/icons/Remove";
4 | import Open from "@material-ui/icons/KeyboardArrowDown";
5 | import styled from "styled-components";
6 | import { v4 } from "uuid";
7 | import { head } from "ramda";
8 | import { Scroll, ScrollableItem } from "../Views";
9 | const styles = {
10 | card: {
11 | width: "100%",
12 | position: "relative",
13 | backgroundColor: "#2B3649",
14 | color: "#FFFFFF",
15 | fontSize: 12,
16 | textOverflow: "ellipsis",
17 | marginTop: "20px",
18 | boxShadow: "0 25px 40px 0 rgba(0,0,0,0.3)",
19 | transition: "background-color 0.7s ease"
20 | },
21 | button: {
22 | color: "#fff",
23 | margin: "1px",
24 | borderRadius: "30px",
25 | borderColor: "#fff",
26 | fontSize: "11px",
27 | minWidth: "40px"
28 | }
29 | };
30 |
31 | export const TransactionHover = styled.div`
32 | &:hover {
33 | .transaction-info {
34 | background: rgba(141, 150, 178, 0.1);
35 | div:last-child {
36 | display: block;
37 | }
38 | }
39 | }
40 | `;
41 |
42 | const monthNames = [
43 | "jan",
44 | "feb",
45 | "mar",
46 | "apr",
47 | "may",
48 | "jun",
49 | "jul",
50 | "aug",
51 | "sep",
52 | "oct",
53 | "nov",
54 | "dec"
55 | ];
56 |
57 | const lessThenTen = v => (parseInt(v, 10) < 10 ? `0${v}` : v.toString());
58 |
59 | const dateToRedeble = date => {
60 | const d = new Date(date);
61 | return `${lessThenTen(d.getHours())}:${lessThenTen(
62 | d.getMinutes()
63 | )}, ${d.getDate()} ${monthNames[d.getMonth()]} ${d.getFullYear()} `;
64 | };
65 |
66 | export const TransactionBasicInfo = ({ text, type, date }) => (
67 |
68 |
69 | {dateToRedeble(date)}
70 |
71 | {head(text.receivers).amount}
72 | {text.wallet.type.toUpperCase()}
73 |
74 |
75 |
76 |
77 |
78 |
79 | );
80 |
81 | const walletCRUD = wallet => (
82 |
83 | {dateToRedeble(wallet.date)}
84 | {wallet.text}
85 |
86 |
87 | );
88 |
89 | const eventSelector = new Map([
90 | ["txPerformed", TransactionBasicInfo],
91 | ["walletCreate", walletCRUD]
92 | ]);
93 |
94 | const History = ({ dappyHistory }) => (
95 |
96 |
104 |
Wallets history
105 |
106 |
107 | {dappyHistory.map(event => {
108 | const LayoutComponent = eventSelector.get(event.type);
109 | return LayoutComponent ? (
110 |
111 | ) : null;
112 | })}
113 |
114 |
115 | );
116 |
117 | export default History;
118 |
--------------------------------------------------------------------------------
/app/InitialPage/Initial.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | isSignInPending,
4 | isUserSignedIn,
5 | handlePendingSignIn
6 | } from "blockstack";
7 | import Home from "./Dashboard";
8 | import { Auth } from "./Auth";
9 |
10 | export const Initial = () => {
11 | if (isSignInPending()) {
12 | handlePendingSignIn().then(
13 | () => (window.location = window.location.origin)
14 | );
15 | return Login verification in progress
;
16 | }
17 | return isUserSignedIn() ? : ;
18 | };
19 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/ActionTypes.js:
--------------------------------------------------------------------------------
1 | export const FETCH_LATEST = "@@InitialPage/NewsCard/FETCH_LATEST";
2 |
3 | export const MOUNT_FETCHED = "@@InitialPage/NewsCard/MOUNT_FETCHED";
4 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Actions.js:
--------------------------------------------------------------------------------
1 | import { createActions } from "redux-actions";
2 | import { FETCH_LATEST, MOUNT_FETCHED } from "./ActionTypes";
3 |
4 | const newsCardActions = createActions({
5 | [FETCH_LATEST]: () => {},
6 | [MOUNT_FETCHED]: news => news
7 | });
8 |
9 | export default newsCardActions;
10 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Container.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import { bindActionCreators } from "redux";
4 | import NewsCard from "./Layout";
5 | import newsCardStoreMapping from "./Selectors";
6 | import newsCardActions from "./Actions";
7 |
8 | class NewsPanel extends React.Component {
9 | constructor(props) {
10 | super(props);
11 | props.fetchLatest();
12 | }
13 |
14 | render() {
15 | const { posts } = this.props;
16 | return ;
17 | }
18 | }
19 | const mapDispatchToProps = dispatch =>
20 | bindActionCreators(newsCardActions.initialPage.newsCard, dispatch);
21 |
22 | export default connect(
23 | newsCardStoreMapping,
24 | mapDispatchToProps
25 | )(NewsPanel);
26 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Layout.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import { config } from "../../AppConfig";
4 | import IconForward from "../../images/common/icon-link-forward.svg";
5 | import IconForwardHover from "../../images/common/icon-link-forward-hover.svg";
6 | import { newsDateConverter } from "../../Providers/DateWrapper";
7 |
8 | const Card = styled.div`
9 | padding: 10px;
10 | height: auto;
11 | background: linear-gradient(
12 | 42.6deg,
13 | #2b3649 0%,
14 | #342f58 56.09%,
15 | #5c1b57 80.31%,
16 | #812359 100%
17 | );
18 | box-shadow: 0 25px 40px 0 rgba(0, 0, 0, 0.3);
19 | color: #ffffff;
20 | fontsize: 12;
21 | textoverflow: ellipsis;
22 | padding: 20px;
23 | paddingbottom: 30px;
24 | p {
25 | fontsize: "15px";
26 | lineheight: "20px";
27 | }
28 | .empty-news {
29 | line-height: 14px;
30 | font-size: 10px;
31 | text-align: center;
32 | letter-spacing: 0.375px;
33 | color: #8d96b2;
34 | padding-top: 50px;
35 | padding-bottom: 40px;
36 | }
37 | &:hover {
38 | a {
39 | color: #f1f1f1;
40 | background: url(${IconForwardHover}) no-repeat 100% top;
41 | }
42 | }
43 | `;
44 |
45 | const Header = styled.div`
46 | display: flex;
47 | justify-content: space-between;
48 | align-items: center;
49 | p {
50 | font-size: 14px;
51 | letter-spacing: 0.2625px;
52 | color: #f1f1f1;
53 | }
54 | a {
55 | font-size: 12px;
56 | line-height: 12px;
57 | text-align: center;
58 | letter-spacing: 0.3px;
59 | color: #8d96b2;
60 | text-decoration: none;
61 | padding-right: 20px;
62 | background: url(${IconForward}) no-repeat 100% top;
63 | }
64 | `;
65 |
66 | const Post = styled.div`
67 | margin-left: -20px;
68 | margin-right: -20px;
69 | padding: 20px;
70 | &:nth-child(2) {
71 | margin-top: 15px;
72 | }
73 | a {
74 | height: 30px;
75 | lineheight: 20px;
76 | color: #ffffff;
77 | text-decoration: none;
78 | }
79 | .text {
80 | span {
81 | vertical-align: middle;
82 | }
83 | span:first-child {
84 | font-size: 14px;
85 | letter-spacing: 0.35px;
86 | color: #ffffff;
87 | }
88 | .icon-link {
89 | display: none;
90 | width: 12px;
91 | height: 14px;
92 | margin-left: 5px;
93 | background: url(${IconForwardHover}) no-repeat 100% top;
94 | }
95 | }
96 | .date {
97 | color: #8d96b2;
98 | letter-spacing: 0.3px;
99 | margin-top: 10px;
100 | }
101 | &:hover {
102 | background: rgba(241, 241, 241, 0.1);
103 | .text {
104 | .icon-link {
105 | display: inline-block;
106 | }
107 | }
108 | }
109 | `;
110 |
111 | const Failed = () => (
112 |
113 |
114 |
115 | Certain conditions would cause the asset units to be incorrect
116 |
117 |
118 |
119 | May 17, 2018
120 |
121 | );
122 |
123 | const NewsHeader = () => (
124 |
134 | );
135 |
136 | const NewsPost = ({ uniqueSlug, title, createdAt }) => (
137 |
138 |
143 |
144 | {title}
145 |
146 |
147 | {newsDateConverter(createdAt)}
148 |
149 |
150 | );
151 |
152 | const News = ({ posts }) => (
153 |
154 |
155 | {posts ? (
156 | posts.map(post => )
157 | ) : (
158 |
159 | )}
160 |
161 | );
162 |
163 | export default News;
164 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Reducer.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 | import newsCardStore from "./Store";
3 | import { MOUNT_FETCHED } from "./ActionTypes";
4 |
5 | const newsCard = handleActions(
6 | {
7 | [MOUNT_FETCHED]: (state, { payload }) => state.set("posts", payload)
8 | },
9 | newsCardStore
10 | );
11 |
12 | export default newsCard;
13 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Saga.js:
--------------------------------------------------------------------------------
1 | import { put, call, takeLatest } from "redux-saga/effects";
2 | import { FETCH_LATEST, MOUNT_FETCHED } from "./ActionTypes";
3 | import XHRProvider from "../../Providers/XHRProvider";
4 |
5 | function* fetchNews() {
6 | let news;
7 | try {
8 | const response = yield call(XHRProvider.getMediumPosts);
9 | news = response.map(({ title, uniqueSlug, createdAt }) => ({
10 | title,
11 | uniqueSlug,
12 | createdAt
13 | }));
14 | } catch (e) {
15 | console.log("Failed to fetch Dappy news from medium");
16 | }
17 | yield put({ type: MOUNT_FETCHED, payload: news });
18 | }
19 |
20 | export default function* newsCardSaga() {
21 | yield takeLatest(FETCH_LATEST, fetchNews);
22 | }
23 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Selectors.js:
--------------------------------------------------------------------------------
1 | import { createSelector } from "reselect";
2 |
3 | const postsSelector = state => state.newsCard.getIn(["posts"]);
4 |
5 | const newsCardSelector = createSelector(
6 | postsSelector,
7 | posts => ({ posts })
8 | );
9 |
10 | const newsCardStoreMapping = state => newsCardSelector(state);
11 |
12 | export default newsCardStoreMapping;
13 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/Store.js:
--------------------------------------------------------------------------------
1 | import { Map } from "immutable";
2 |
3 | const newsCardStore = Map({
4 | posts: []
5 | });
6 |
7 | export default newsCardStore;
8 |
--------------------------------------------------------------------------------
/app/InitialPage/NewsCard/index.js:
--------------------------------------------------------------------------------
1 | export { default as NewsPanel } from "./Container";
2 | export { default as newsCard } from "./Reducer";
3 | export { default as newsCardSaga } from "./Saga";
4 |
--------------------------------------------------------------------------------
/app/InitialPage/Reducer.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | const initialState = {
5 | walletList: [],
6 | selectedWallet: null,
7 | selectedWalletInfo: {},
8 | totalBalance: 0,
9 | dappyHistory: []
10 | };
11 |
12 | export const initialPage = handleActions(
13 | {
14 | [types.MOUNT_WALLETS]: (state, action) => ({
15 | ...state,
16 | walletList: action.payload
17 | }),
18 | [types.SELECT_WALLET]: (state, action) => ({
19 | ...state,
20 | selectedWallet: action.payload
21 | }),
22 | [types.MOUNT_TOTAL_BALANCE]: (state, action) => ({
23 | ...state,
24 | totalBalance: action.payload
25 | }),
26 | [types.MOUNT_WALLET_INFO]: (state, action) => ({
27 | ...state,
28 | selectedWalletInfo: action.payload
29 | }),
30 | [types.MOUNT_HISTORY]: (state, action) => ({
31 | ...state,
32 | dappyHistory: action.payload
33 | })
34 | },
35 | initialState
36 | );
37 |
--------------------------------------------------------------------------------
/app/InitialPage/Saga.js:
--------------------------------------------------------------------------------
1 | import { put, call, takeLatest } from "redux-saga/effects";
2 | import { delay } from "redux-saga";
3 | import {
4 | getWalletList,
5 | setWalletList,
6 | initLog,
7 | getLogs,
8 | logEvent
9 | } from "../Providers/Gaia";
10 | import { types } from "./ActionTypes";
11 | import { walletGenerator, calculateTotalBalance } from "../Providers/Wallets";
12 | import XHRProvider from "../Providers/XHRProvider";
13 |
14 | const xhr = new XHRProvider();
15 |
16 | function* checkoutWallets() {
17 | const walletList = yield call(getWalletList);
18 | if (walletList) {
19 | yield put({ type: types.MOUNT_WALLETS, payload: walletList.kpList });
20 | } else {
21 | const newWallet = yield setWalletList();
22 | yield put({ type: types.MOUNT_WALLETS, payload: newWallet });
23 | }
24 | }
25 |
26 | function* checkoutHistory() {
27 | let logs = yield call(getLogs);
28 | if (!logs) {
29 | yield call(initLog);
30 | logs = [];
31 | }
32 | yield put({
33 | type: types.MOUNT_HISTORY,
34 | payload: Array.isArray(logs) ? logs : [logs]
35 | });
36 | }
37 |
38 | function* createWallet(action) {
39 | const { walletList, wType } = action.payload;
40 | const newWalletList = yield setWalletList([
41 | ...walletList,
42 | ...walletGenerator([wType])
43 | ]);
44 | yield call(logEvent, {
45 | date: new Date(),
46 | type: "walletCreate",
47 | text: `${wType} wallet was created`
48 | });
49 | yield put({ type: types.MOUNT_WALLETS, payload: newWalletList });
50 | }
51 |
52 | function* deleteWallet(action) {
53 | const { walletList, toBeDeleted } = action.payload;
54 | const newWalletList = yield setWalletList(
55 | walletList.filter(wallet => wallet.wid !== toBeDeleted)
56 | );
57 | yield put({ type: types.MOUNT_WALLETS, payload: newWalletList });
58 | }
59 |
60 | function* fetchWalletInfo(action) {
61 | let walletInfo;
62 | try {
63 | walletInfo = yield call(xhr.get, action.payload);
64 | } catch (e) {
65 | yield delay(5000);
66 | yield put(action);
67 | }
68 | yield put({ type: types.MOUNT_WALLET_INFO, payload: walletInfo.data });
69 | }
70 |
71 | function* fetchTotalBalance(action) {
72 | const { listOfAddress, course } = action.payload;
73 | let sumOfType;
74 | try {
75 | sumOfType = yield call(xhr.getTotalBalance, listOfAddress, course);
76 | const balanceObj = sumOfType.reduce(
77 | (acc, { wid, balance }) => ({ ...acc, [wid]: balance }),
78 | {}
79 | );
80 | const walletsWithBalance = listOfAddress.map(wallet => ({
81 | ...wallet,
82 | balance: {
83 | updated: new Date(),
84 | value: balanceObj[wallet.wid]
85 | }
86 | }));
87 | listOfAddress.length ? yield setWalletList(walletsWithBalance) : null;
88 | yield put({
89 | type: types.MOUNT_TOTAL_BALANCE,
90 | payload: calculateTotalBalance(sumOfType)
91 | });
92 | } catch (e) {
93 | yield delay(5000);
94 | yield put(action);
95 | }
96 | }
97 |
98 | export function* initialPageSaga() {
99 | yield takeLatest(types.CHECKOUT_WALLETS, checkoutWallets);
100 | yield takeLatest(types.CREATE_WALLET, createWallet);
101 | yield takeLatest(types.DELETE_WALLET, deleteWallet);
102 | yield takeLatest(types.FETCH_WALLET_INFO, fetchWalletInfo);
103 | yield takeLatest(types.FETCH_TOTAL_BALANCE, fetchTotalBalance);
104 | yield takeLatest(types.CHECKOUT_HISTORY, checkoutHistory);
105 | }
106 |
--------------------------------------------------------------------------------
/app/InitialPage/SummaryCash.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Card from "@material-ui/core/Card";
3 | import styled from "styled-components";
4 | import { has } from "ramda";
5 | import { toFiat } from "../Providers/Wallets";
6 | import { BalanceCard } from "../Views";
7 |
8 | const styles = {
9 | card: {
10 | backgroundColor: "#2B3649",
11 | color: "#FFFFFF",
12 | fontSize: 12,
13 | marginBottom: "20px",
14 | boxShadow: "0 25px 40px 0 rgba(0,0,0,0.3)",
15 | transition: "background-color 0.7s ease",
16 | padding: "20px"
17 | }
18 | };
19 |
20 | const Dots = styled.span``;
21 |
22 | export const SummaryCash = ({
23 | currencySum,
24 | countOfWallets,
25 | selectedFiat,
26 | course
27 | }) => {
28 | const sum = currencySum || 0;
29 | return (
30 |
31 |
32 |
35 |
42 |
43 |
{sum} BTC
44 |
45 | {has("BTC", course) ? (
46 | toFiat(currencySum, course.BTC[selectedFiat.abbr])
47 | ) : (
48 |
49 | )}{" "}
50 | {selectedFiat.abbr}
51 |
52 |
53 |
54 |
{countOfWallets.length}
55 |
wallets
56 |
57 |
58 |
59 |
60 | );
61 | };
62 |
--------------------------------------------------------------------------------
/app/InitialPage/WalletInfo.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import { has } from "ramda";
4 |
5 | const WalletInfo = ({ selectedWalletInfo }) => (
6 |
7 | Wallet Info
8 | {has("transactions", selectedWalletInfo) && (
9 |
10 |
Balance {selectedWalletInfo.balance}
11 |
History
12 | {selectedWalletInfo.transactions.length
13 | ? selectedWalletInfo.transactions
14 | : "not found"}
15 |
16 | )}
17 |
18 | );
19 |
20 | const mapStateToProps = state => ({
21 | selectedWalletInfo: state.initialPage.selectedWalletInfo
22 | });
23 |
24 | export default connect(
25 | mapStateToProps,
26 | undefined
27 | )(WalletInfo);
28 |
--------------------------------------------------------------------------------
/app/InitialSetup/RootReducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "redux";
2 | import { wallets } from "../Wallets/Reducer";
3 | import { initialPage } from "../InitialPage/Reducer";
4 | import { exchange } from "../Exchange/Reducer";
5 | import { fiat } from "../Fiat/Reducer";
6 | import { newsCard } from "../InitialPage/NewsCard";
7 |
8 | export const rootReducer = combineReducers({
9 | wallets,
10 | initialPage,
11 | exchange,
12 | fiat,
13 | newsCard
14 | });
15 |
--------------------------------------------------------------------------------
/app/InitialSetup/RootSaga.js:
--------------------------------------------------------------------------------
1 | import { all, call } from "redux-saga/effects";
2 | import { initialPageSaga } from "../InitialPage/Saga";
3 | import { walletSaga } from "../Wallets/Wallet/Saga";
4 | import { walletListSaga } from "../Wallets/WalletList/Saga";
5 | import { exchangeSaga } from "../Exchange/Saga";
6 | import { fiatSaga } from "../Fiat/Saga";
7 | import { newsCardSaga } from "../InitialPage/NewsCard";
8 |
9 | export default function* rootSaga() {
10 | yield all([
11 | call(initialPageSaga),
12 | call(walletListSaga),
13 | call(walletSaga),
14 | call(exchangeSaga),
15 | call(fiatSaga),
16 | call(newsCardSaga)
17 | ]);
18 | }
19 |
--------------------------------------------------------------------------------
/app/InitialSetup/Store.js:
--------------------------------------------------------------------------------
1 | import createSagaMiddleware from "redux-saga";
2 | import { createStore, applyMiddleware } from "redux";
3 | import rootSaga from "./RootSaga";
4 | import { rootReducer } from "./RootReducer";
5 |
6 | const initialState = {};
7 |
8 | const sagaMiddleware = createSagaMiddleware();
9 |
10 | export const store = createStore(
11 | rootReducer,
12 | initialState,
13 | applyMiddleware(sagaMiddleware)
14 | );
15 |
16 | sagaMiddleware.run(rootSaga);
17 |
--------------------------------------------------------------------------------
/app/Providers/DateWrapper.js:
--------------------------------------------------------------------------------
1 | const monthNames = [
2 | { abbr: "jan", fill: "January" },
3 | { abbr: "feb", full: "February" },
4 | { abbr: "mar", full: "March" },
5 | { abbr: "apr", full: "April" },
6 | { abbr: "may", full: "May" },
7 | { abbr: "jun", full: "June" },
8 | { abbr: "jul", full: "July" },
9 | { abbr: "aug", full: "August" },
10 | { abbr: "sep", full: "September" },
11 | { abbr: "oct", full: "October" },
12 | { abbr: "nov", full: "November" },
13 | { abbr: "dec", full: "December" }
14 | ];
15 |
16 | export const newsDateConverter = date => {
17 | const d = new Date(date);
18 | return `${monthNames[d.getMonth()].full} ${d.getDate()}, ${d.getFullYear()} `;
19 | };
20 |
21 | const lessThenTen = v => (parseInt(v, 10) < 10 ? `0${v}` : v.toString());
22 |
23 | export const dateToRedeble = date => {
24 | const d = new Date(date);
25 | return `${lessThenTen(d.getHours())}:${lessThenTen(
26 | d.getMinutes()
27 | )}, ${d.getDate()} ${monthNames[d.getMonth()].abbr} ${d.getFullYear()} `;
28 | };
29 |
--------------------------------------------------------------------------------
/app/Providers/Gaia.js:
--------------------------------------------------------------------------------
1 | import { getFile, putFile } from "blockstack";
2 | import { take } from "ramda";
3 | import { generateInitialWalletList } from "./Wallets";
4 | import * as dashbord from "./GaiaDicts/Dashbord";
5 | import * as wlTMPL from "./GaiaTemplates/WalletList";
6 |
7 | const PUT_OPTIONS = { encrypt: true };
8 |
9 | const GET_OPTIONS = { decrypt: true };
10 |
11 | const jsonParse = json => {
12 | let parsed;
13 | try {
14 | parsed = JSON.parse(json);
15 | } catch (e) {}
16 | return parsed;
17 | };
18 |
19 | export const setWalletList = (walletList = generateInitialWalletList()) =>
20 | putFile(
21 | dashbord.WALLET_LIST,
22 | wlTMPL.walletListTMPL(walletList),
23 | PUT_OPTIONS
24 | ).then(() => walletList);
25 |
26 | export const initLog = () =>
27 | putFile(dashbord.DAPPY_LOG, JSON.stringify([]), PUT_OPTIONS).then(() => []);
28 |
29 | export const getLogs = () =>
30 | getFile(dashbord.DAPPY_LOG, GET_OPTIONS)
31 | .then(json => (json ? jsonParse(json) : null))
32 | .catch(() => initLog());
33 |
34 | export const logEvent = event =>
35 | getFile(dashbord.DAPPY_LOG, GET_OPTIONS).then(log => {
36 | const logList = take(29, JSON.parse(log));
37 | putFile(
38 | dashbord.DAPPY_LOG,
39 | JSON.stringify([event, ...logList]),
40 | PUT_OPTIONS
41 | );
42 | });
43 |
44 | export const getWalletList = () =>
45 | getFile(dashbord.WALLET_LIST, GET_OPTIONS).then(json =>
46 | json ? jsonParse(json) : null
47 | );
48 |
--------------------------------------------------------------------------------
/app/Providers/GaiaDicts/Dashbord.js:
--------------------------------------------------------------------------------
1 | export const WALLET_LIST = "wallet_list.json";
2 |
3 | export const DAPPY_LOG = "dappyLog.json";
4 |
--------------------------------------------------------------------------------
/app/Providers/GaiaTemplates/WalletList.js:
--------------------------------------------------------------------------------
1 | export const walletListTMPL = kpList => JSON.stringify({ kpList });
2 |
--------------------------------------------------------------------------------
/app/Routing/ProtectedRoute.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Route, Redirect } from "react-router-dom";
3 | import { isUserSignedIn } from "blockstack";
4 |
5 | export const ProtectedRoute = ({ Component, ...props }) => (
6 |
9 | isUserSignedIn() ? (
10 |
11 | ) : (
12 |
13 | )
14 | }
15 | />
16 | );
17 |
--------------------------------------------------------------------------------
/app/Routing/Router.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Route, Switch, withRouter } from "react-router-dom";
3 | import { connect } from "react-redux";
4 | import { isUserSignedIn } from "blockstack";
5 | import { ProtectedRoute } from "./ProtectedRoute";
6 | import { Initial } from "../InitialPage/Initial";
7 | import { RoutingPanel } from "../CommonComponents/RoutingPanel";
8 | import Wallet from "../Wallets/Wallet/Wallet";
9 | import WalletList from "../Wallets/WalletList";
10 | import Exchange from "../Exchange/Exchange";
11 |
12 | import Header from "../InitialPage/Header";
13 |
14 | const Router = props => (
15 |
16 | {isUserSignedIn() &&
}
17 | {isUserSignedIn() &&
}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | );
27 |
28 | export default withRouter(connect()(Router));
29 |
--------------------------------------------------------------------------------
/app/Views/Content.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | export const Content = styled.div`
4 | display: flex;
5 | justify-content: space-between;
6 | width: 85%;
7 | padding: 0 20px;
8 |
9 | @media (max-width: 1200px) {
10 | align-items: stretch;
11 | flex-wrap: wrap;
12 | width: 80%;
13 | }
14 | @media (max-width: 768px) {
15 | width: 100%;
16 | order: 3;
17 | padding: 0 10px;
18 | }
19 | `;
20 |
--------------------------------------------------------------------------------
/app/Views/Input.js:
--------------------------------------------------------------------------------
1 | import styled, { css } from "styled-components";
2 | import IconSearch from "../images/common/icon-search.svg";
3 | import IconManualAddress from "../images/common/icon-manual-address.svg";
4 |
5 | export const Input = styled.input`
6 | border-radius: 2px;
7 | background-color: #1f2431;
8 | border: none;
9 | padding: 10px;
10 | color: #fff;
11 | &.light-grey {
12 | background-color: #e2e4e8;
13 | width: 100%;
14 | color: #000;
15 | padding: 20px 10px;
16 | font-size: 12px;
17 | letter-spacing: 0.276923px;
18 | color: #8d96b2;
19 | }
20 | `;
21 |
22 | export const InputSearch = styled.input`
23 | border-radius: 2px;
24 | background-color: #1f2431;
25 | border: none;
26 | padding: 10px;
27 | padding-left: 20px;
28 | padding-right: 20px;
29 | color: #fff;
30 | position: relative;
31 | width: 137px;
32 | background: #273041 url(${IconSearch}) no-repeat 95% center;
33 |
34 | ${props =>
35 | props.walletListSearch &&
36 | css`
37 | @media (max-width: 768px) {
38 | width: 100%;
39 | max-width: 350px;
40 | background-position: 98% center;
41 | }
42 | `}
43 | `;
44 |
45 | export const InputManualAddress = styled.input`
46 | background: #e2e4e8 url(${IconManualAddress}) no-repeat 5% 50%;
47 | padding: 10px;
48 | padding-left: 41px;
49 | border: none;
50 | outline: none;
51 | `;
52 |
53 | export const InputGrey = styled.input`
54 | border: 1px solid #d5d9e5;
55 | border-radius: 2px;
56 | padding: 0 12px;
57 | height: 31px;
58 | width: 100%;
59 | &::-webkit-input-placeholder {
60 | font-size: 10px;
61 | letter-spacing: 0.25px;
62 | color: #8d96b2;
63 | }
64 | &::-moz-placeholder {
65 | font-size: 10px;
66 | letter-spacing: 0.25px;
67 | color: #8d96b2;
68 | }
69 | &:-ms-input-placeholder {
70 | font-size: 10px;
71 | letter-spacing: 0.25px;
72 | color: #8d96b2;
73 | }
74 | &:-moz-placeholder {
75 | font-size: 10px;
76 | letter-spacing: 0.25px;
77 | color: #8d96b2;
78 | }
79 | &:not(:first-child) {
80 | margin-top: 10px;
81 | }
82 | `;
83 |
--------------------------------------------------------------------------------
/app/Views/Popup.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | import ArrowDown from "../images/common/icon-arrow-down.svg";
4 | import Eye from "../images/common/vision-off.svg";
5 |
6 | export const PopupLayout = styled.div`
7 | position: absolute;
8 | top: 0;
9 | bottom: 0;
10 | left: 0;
11 | right: 0;
12 | width: 100%;
13 | height: 100%;
14 | background: rgba(43, 54, 73, 0.87);
15 | `;
16 |
17 | export const Popup = styled.div`
18 | background: #f1f2fa;
19 | box-shadow: 0px 25px 40px rgba(0, 0, 0, 0.3);
20 | border-radius: 2px;
21 | background-color: #fffffb;
22 | width: 330px;
23 | height: auto;
24 | position: absolute;
25 | top: 50%;
26 | left: 50%;
27 | transform: translate(-50%, -50%);
28 | z-index: 100;
29 | transition: background-color, opacity 0.7s ease;
30 | padding: ${props => (props.create ? "0" : "20px")};
31 | .title {
32 | font-weight: 500;
33 | line-height: normal;
34 | font-size: 14px;
35 | letter-spacing: 0.323077px;
36 | color: #2b3649;
37 | margin-bottom: 15px;
38 | }
39 | .description {
40 | line-height: 16px;
41 | font-size: 10px;
42 | letter-spacing: 0.230769px;
43 | color: #2b3649;
44 | margin-bottom: 20px;
45 | &.key {
46 | white-space: nowrap;
47 | overflow: hidden;
48 | text-overflow: ellipsis;
49 | }
50 | }
51 | .pseudo-select-wrapper {
52 | cursor: pointer;
53 | &:not(:first-child) {
54 | margin-top: 10px;
55 | }
56 | .pseudo-select {
57 | padding: 10px;
58 | padding-right: 0;
59 | border: 1px solid #d5d9e5;
60 | border-radius: 2px;
61 | height: 31px;
62 | display: flex;
63 | justify-content: space-between;
64 | align-items: center;
65 | position: relative;
66 | .wallet-name {
67 | display: flex;
68 | align-items: center;
69 | img {
70 | width: 20px;
71 | height: 20px;
72 | margin-right: 5px;
73 | }
74 | p {
75 | font-size: 10px;
76 | text-align: center;
77 | letter-spacing: 0.230769px;
78 | color: #2b3649;
79 | span {
80 | color: #8d96b2;
81 | display: inline-block;
82 | margin-left: 4px;
83 | }
84 | }
85 | }
86 | &:after {
87 | content: "";
88 | display: block;
89 | width: 31px;
90 | height: 100%;
91 | border-radius: 0px 0px 2px 2px;
92 | background: #315efb url(${ArrowDown}) no-repeat center;
93 | transform: rotate(-90deg);
94 | position: absolute;
95 | right: -2px;
96 | top: 0;
97 | }
98 | }
99 | }
100 | .private-key {
101 | background: url(${Eye}) no-repeat 95% 50%;
102 | width: 100%;
103 | border: 1px solid #d5d9e5;
104 | margin-top: 10px;
105 | border-radius: 2px;
106 | height: 31px;
107 | padding-left: 10px;
108 | }
109 | .btn-wrapper {
110 | display: flex;
111 | justify-content: space-between;
112 | align-items: center;
113 | button {
114 | width: 47%;
115 | }
116 | }
117 | .key-wrapper {
118 | margin: 20px 0;
119 | border: 1px solid #8d96b2;
120 | box-sizing: border-box;
121 | border-radius: 2px;
122 | padding: 20px 40px;
123 | p {
124 | font-size: 10px;
125 | letter-spacing: 0.25px;
126 | }
127 | .name {
128 | color: #8d96b2;
129 | }
130 | .value {
131 | color: #2b3649;
132 | width: 100%;
133 | overflow: hidden;
134 | text-overflow: ellipsis;
135 | }
136 | }
137 | `;
138 |
--------------------------------------------------------------------------------
/app/Views/ScrollableCard.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import IconFilter from "../images/common/icon-filter.svg";
3 |
4 | export const Scroll = styled.div`
5 | height: ${props => (props.height ? props.height : "auto")};
6 | max-height: 370px;
7 | overflow-y: scroll;
8 | overflow-x: hidden;
9 | background: linear-gradient(180deg, #1f2431 0%, #2b3649 100%);
10 | background-size: 100% 7px;
11 | background-repeat: no-repeat;
12 | `;
13 |
14 | export const ScrollableItem = styled.div`
15 | display: flex;
16 | align-items: center;
17 | justify-content: space-between;
18 | flex-wrap: wrap;
19 | padding: 15px 20px;
20 | border-top: 1px solid rgba(141, 150, 178, 0.1);
21 | border-bottom: 1px solid rgba(141, 150, 178, 0.1);
22 | position: relative;
23 | &.transaction-info {
24 | div:first-child {
25 | font-size: 12px;
26 | letter-spacing: 0.25px;
27 | line-height: 11px;
28 | display: flex;
29 | align-items: center;
30 | }
31 | div:nth-child(2) {
32 | display: flex;
33 | align-items: center;
34 | font-size: 12px;
35 | letter-spacing: 0.3px;
36 | line-height: 14px;
37 | text-transform: uppercase;
38 | margin-left: 20px;
39 | height: 15px;
40 | svg {
41 | margin-right: 5px;
42 | &.received {
43 | fill: #7ac231;
44 | width: 15px;
45 | }
46 | &.send {
47 | fill: #c11e0f;
48 | width: 15px;
49 | }
50 | }
51 | }
52 | div:last-child {
53 | text-align: center;
54 | position: absolute;
55 | width: 65px;
56 | height: 15px;
57 | bottom: -1px;
58 | left: 0;
59 | right: 0;
60 | margin: auto;
61 | border: 1px solid #485264;
62 | border-radius: 5px 5px 0 0;
63 | display: none;
64 | svg {
65 | width: 21px;
66 | height: 16px;
67 | cursor: pointer;
68 | }
69 | }
70 | }
71 | &.wallet-info {
72 | &:not(:first-child) {
73 | cursor: pointer;
74 | }
75 | &:not(:first-child):hover {
76 | background-color: rgba(141, 150, 178, 0.1);
77 | }
78 | div:first-child {
79 | display: flex;
80 | align-items: center;
81 | width: 50%;
82 | img {
83 | margin-right: 15px;
84 | }
85 | div {
86 | text-align: left;
87 | width: 100%;
88 | p:first-child {
89 | font-size: 16px;
90 | letter-spacing: 0.4px;
91 | color: #fefefe;
92 | text-overflow: ellipsis;
93 | overflow: hidden;
94 | white-space: nowrap;
95 | padding-right: 20px;
96 | }
97 | p:last-child {
98 | font-size: 10px;
99 | letter-spacing: 0.25px;
100 | color: #8d96b2;
101 | }
102 | }
103 | }
104 | div:last-child {
105 | text-align: right;
106 | .title {
107 | font-size: 12px;
108 | letter-spacing: 0.3px;
109 | line-height: 14px;
110 | margin-bottom: 3px;
111 | margin-top: 0;
112 | }
113 | .subtitle {
114 | font-size: 10px;
115 | letter-spacing: 0.25px;
116 | line-height: 11px;
117 | color: #8d96b2;
118 | margin: 0;
119 | width: 60px;
120 | text-overflow: ellipsis;
121 | overflow: hidden;
122 | }
123 | }
124 | }
125 | `;
126 |
127 | export const Filter = styled.button`
128 | font-size: 12px;
129 | letter-spacing: 0.3px;
130 | line-height: 14px;
131 | text-transform: uppercase;
132 | height: 15px;
133 | background: url(${IconFilter});
134 | background-repeat: no-repeat;
135 | background-position: center;
136 | width: 12px
137 | border: none;
138 | `;
139 |
140 | export const TransactionHover = styled.div`
141 | &:hover {
142 | .transaction-info {
143 | background: rgba(141, 150, 178, 0.1);
144 | div:last-child {
145 | display: block;
146 | }
147 | }
148 | }
149 | `;
150 |
--------------------------------------------------------------------------------
/app/Views/Snackbar.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import IconCrossGrey from "../images/common/icon-cross-grey.svg";
3 | import IconCrossWhite from "../images/common/icon-cross-white.svg";
4 |
5 | // possible props for snackbars :
6 | // base
7 | // alert
8 | // confirm
9 |
10 | // snackbar's example :
11 | //
12 | // Ready!
13 | //
14 | //
15 |
16 | export const Snackbar = styled.div`
17 | min-width: 330px;
18 | max-width: 550px;
19 | padding: 15px 20px;
20 | box-shadow: 0px 25px 40px rgba(0, 0, 0, 0.3);
21 | border-radius: 2px;
22 | display: flex;
23 | justify-content: space-between;
24 | align-items: center;
25 | z-index: 100;
26 | position: absolute;
27 | bottom: 35px;
28 | left: 0;
29 | right: 0;
30 | margin: auto;
31 | background: ${props =>
32 | props.base
33 | ? "#F1F2FA"
34 | : props.alert
35 | ? "#C11E0F"
36 | : props.confirm
37 | ? "#7AC231"
38 | : "white"};
39 | p {
40 | margin: 0;
41 | font-size: 14px;
42 | letter-spacing: 0.323077px;
43 | color: ${props => (props.base ? "#2B3649" : "#F1F1F1")};
44 | }
45 | button {
46 | border: none;
47 | outline: none;
48 | cursor: pointer;
49 | width: 10px;
50 | height: 10px;
51 | margin-left: 10px;
52 | background: transparent
53 | url(${props => (props.base ? IconCrossGrey : IconCrossWhite)}) no-repeat
54 | center;
55 | }
56 | `;
57 |
--------------------------------------------------------------------------------
/app/Views/StyledButton.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | import ArrowLeft from "../images/common/icon-arrow-down.svg";
4 | import IconCrossGrey from "../images/common/icon-cross-grey.svg";
5 | import IconQr from "../images/common/icon-qr.svg";
6 | import IconAdd from "../images/common/icon-add.svg";
7 |
8 | /* Classic button */
9 | export const StyledButton = styled.button`
10 | border: 1px solid #8d96b2;
11 | border-radius: 14px;
12 | background: transparent;
13 | color: #8d96b2;
14 | padding: 5px 20px;
15 | margin-right: 5px;
16 | outline: none;
17 | `;
18 |
19 | /* Tap button */
20 | export const TapButton = styled.button`
21 | border-radius: 0 2px 2px 0;
22 | background-color: #315efb;
23 | cursor: pointer;
24 | border: none;
25 | height: auto;
26 | outline: none;
27 | width: 10%;
28 | padding: 10px 15px;
29 | background-image: url(${IconQr});
30 | background-position: center;
31 | background-repeat: no-repeat;
32 | margin: 0;
33 | &:active {
34 | background-color: rgba(241, 241, 241, 0.1);
35 | }
36 | `;
37 |
38 | /* Add button */
39 | export const AddButton = styled.button`
40 | border: none;
41 | outline: none;
42 | height: 49px;
43 | width: 48px;
44 | border-radius: 25px;
45 | box-shadow: 0 15px 28px 0 rgba(0, 0, 0, 0.7);
46 | background: #315efb url(${IconAdd});
47 | background-repeat: no-repeat;
48 | background-position: center;
49 | `;
50 |
51 | /* /* Return ( back ) button. Possible states : HoverBase */
52 | export const BackButton = styled.button`
53 | border: none;
54 | background: transparent;
55 | color: #fff;
56 | margin-right: 5px;
57 | margin-left: 5px;
58 | padding: 10px 15px 10px 30px;
59 | outline: none;
60 | position: relative;
61 | &:after {
62 | content: "";
63 | display: block;
64 | position: absolute;
65 | top: 50%;
66 | left: 10px;
67 | height: 9px;
68 | width: 6px;
69 | background: url(${ArrowLeft}) no-repeat;
70 | transform: rotate(0deg) translateY(-50%);
71 | }
72 | &:hover {
73 | background: ${props => (props.HoverBase ? "#2B3649" : "#343f53")};
74 | border-radius: 2px;
75 | }
76 | `;
77 |
78 | /* Popup buttons */
79 | /* close popup */
80 | export const CloseUpButton = styled.button`
81 | background: transparent url(${IconCrossGrey}) no-repeat center;
82 | background-size: cover;
83 | padding: 0;
84 | width: 20px;
85 | height: 20px;
86 | border: none;
87 | outline: none;
88 | position: absolute;
89 | top: -30px;
90 | right: -30px;
91 | `;
92 |
93 | /* popup blue button */
94 | export const PopupButton = styled.button`
95 | background: #315efb;
96 | border-radius: 2px;
97 | font-size: 12px;
98 | text-align: center;
99 | letter-spacing: 0.3px;
100 | color: #f1f1f1;
101 | border: none;
102 | padding: 10px 0;
103 | width: 100%;
104 | margin-top: 20px;
105 | `;
106 |
107 | /* popup grey button */
108 | export const PopupGreyButton = styled.button`
109 | background: #d2d5e3;
110 | border-radius: 2px;
111 | font-size: 12px;
112 | text-align: center;
113 | letter-spacing: 0.3px;
114 | color: #2b3649;
115 | border: none;
116 | padding: 10px 0;
117 | width: 100%;
118 | margin-top: 20px;
119 | `;
120 |
--------------------------------------------------------------------------------
/app/Views/TabsWrapper.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | export const TabsWrapper = styled.div`
4 | header {
5 | background-color: #fffffb;
6 | box-shadow: none;
7 | border-bottom: 1px solid #8d96b2;
8 | button {
9 | width: auto;
10 | min-width: auto;
11 | &:first-child {
12 | width: 28%;
13 | }
14 | &:nth-child(2) {
15 | width: 27%;
16 | }
17 | &:last-child {
18 | width: 45%;
19 | }
20 | > span {
21 | padding: 0;
22 | > span {
23 | padding: 0;
24 | span {
25 | font-size: 14px;
26 | text-align: center;
27 | letter-spacing: 0.323077px;
28 | color: #2b3649;
29 | padding: 0;
30 | }
31 | }
32 | }
33 | }
34 | span[class*="TabIndicator"] {
35 | background-color: #315efb;
36 | height: 4px;
37 | }
38 | }
39 | `;
40 |
--------------------------------------------------------------------------------
/app/Views/index.js:
--------------------------------------------------------------------------------
1 | import {
2 | Scroll,
3 | ScrollableItem,
4 | Filter,
5 | TransactionHover
6 | } from "./ScrollableCard";
7 | import { InputSearch, InputManualAddress, InputGrey, Input } from "./Input";
8 | import { Popup, PopupLayout } from "./Popup";
9 | import { Snackbar } from "./Snackbar";
10 | import { TabsWrapper } from "./TabsWrapper";
11 | import { Column } from "../CommonComponents/ContentColumn/Index";
12 | import { BalanceCard } from "../CommonComponents/BalanceCard.js";
13 | import { Content } from "./Content";
14 |
15 | import {
16 | StyledButton,
17 | AddButton,
18 | BackButton,
19 | TapButton,
20 | CloseUpButton,
21 | PopupButton,
22 | PopupGreyButton
23 | } from "./StyledButton";
24 |
25 | // div with scroll
26 | export { Scroll, ScrollableItem, Filter, TransactionHover };
27 |
28 | // classic button
29 | export { StyledButton };
30 |
31 | // add button
32 | export { AddButton };
33 |
34 | // button 'back' with arrow-left
35 | export { BackButton };
36 |
37 | // tap button
38 | export { TapButton };
39 |
40 | // close button
41 | export { CloseUpButton };
42 |
43 | // popup button
44 | export { PopupButton };
45 |
46 | // popup grey button
47 | export { PopupGreyButton };
48 |
49 | // classic input
50 | export { Input };
51 |
52 | // search input + manual address + grey input
53 | export { InputSearch, InputManualAddress, InputGrey };
54 |
55 | // container for main content
56 | export { Content };
57 |
58 | // columns for Cards at Content
59 | export { Column };
60 |
61 | // Balance card
62 | export { BalanceCard };
63 |
64 | // snackbar
65 | export { Snackbar };
66 |
67 | // popup layout
68 | export { PopupLayout };
69 |
70 | // popup
71 | export { Popup };
72 |
73 | // tabs
74 | export { TabsWrapper };
75 |
--------------------------------------------------------------------------------
/app/Wallets/Reducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "redux";
2 | import { wallet } from "./Wallet/Reducer";
3 | import { walletList } from "./WalletList/Reducer";
4 |
5 | export const wallets = combineReducers({
6 | wallet,
7 | walletList
8 | });
9 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/ActionTypes.js:
--------------------------------------------------------------------------------
1 | export const types = {
2 | CHECK_OUT_INITIAL: "@@wallet/CHECK_OUT_INITIAL",
3 | GET_DATA_FOR_CHART: "@@wallet/GET_DATA_FOR_CHART",
4 | MOUNT_DATA_FOR_CHART: "@@wallet/MOUNT_DATA_FOR_CHART",
5 | GET_WALLET: "@@wallet/GET_WALLET",
6 | FETCH_WALLET_INFO: "@@wallet/FETCH_WALLET_INFO",
7 | MOUNT_WALLET_INFO: "@@wallet/MOUNT_WALLET_INFO",
8 | FECTH_TRANSACTIONS: "@@wallet/FECTH_TRANSACTIONS",
9 | MOUNT_TRANSACTIONS: "@@wallet/MOUNT_TRANSACTIONS",
10 | GET_WALLET_IN_GAIA: "@@wallet/GET_WALLET_IN_GAIA",
11 | MAKE_TRANSACTION: "@@wallet/MAKE_TRANSACTION",
12 | GET_FIAT_CURRENCY: "@@wallet/GET_FIAT_CURRENCY",
13 | MOUNT_FIAT: "@@wallet/MOUNT_FIAT",
14 | MOUNT_TRX_ID: "@@wallet/MOUNT_TRX_ID",
15 | FETCH_TOKEN_INFO: "@@wallet/FETCH_TOKEN_INFO",
16 | MOUNT_TOKEN_INFO: "@@wallet/MOUNT_TOKEN_INFO",
17 | UPDATE_WALLET_BY_ADDRESS: "@@wallet/UPDATE_WALLET_BY_ADDRESS"
18 | };
19 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/Actions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | export const getDataForChart = createAction(
5 | types.GET_DATA_FOR_CHART,
6 | (currency, period, timestamp, fiat) => ({
7 | currency,
8 | period,
9 | timestamp,
10 | fiat
11 | })
12 | );
13 |
14 | export const getWalletInGaia = createAction(
15 | types.GET_WALLET_IN_GAIA,
16 | selectedWallet => ({
17 | selectedWallet
18 | })
19 | );
20 |
21 | export const getWallet = createAction(types.GET_WALLET, wallet => ({ wallet }));
22 |
23 | export const fetchTransactions = createAction(
24 | types.FECTH_TRANSACTIONS,
25 | (address, type) => ({
26 | address,
27 | type
28 | })
29 | );
30 |
31 | export const makeTransaction = createAction(
32 | types.MAKE_TRANSACTION,
33 | (wallet, receivers, options) => ({
34 | wallet,
35 | receivers,
36 | options
37 | })
38 | );
39 |
40 | export const fiatCurrency = createAction(types.GET_FIAT_CURRENCY, type => ({
41 | type
42 | }));
43 |
44 | export const fetchWalletInfo = createAction(
45 | types.FETCH_WALLET_INFO,
46 | (type, addr) => ({
47 | type,
48 | addr
49 | })
50 | );
51 |
52 | export const updateWalletByAddress = createAction(
53 | types.UPDATE_WALLET_BY_ADDRESS,
54 | (address, key, value) => ({
55 | address,
56 | key,
57 | value
58 | })
59 | );
60 |
61 | export const fetchTokenInfo = createAction(
62 | types.FETCH_TOKEN_INFO,
63 | (type, addr) => ({
64 | type,
65 | addr
66 | })
67 | );
68 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/AddCustomEthToken.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import {
4 | Popup,
5 | PopupLayout,
6 | CloseUpButton,
7 | PopupButton,
8 | InputGrey
9 | } from "../../Views";
10 | import { updateWalletByAddress } from "./Actions";
11 |
12 | const mapStateToProps = state => ({
13 | wallets: state.wallets.walletList.walletList
14 | });
15 |
16 | const mapDispatchToProps = dispatch => ({
17 | update: (address, key, value) =>
18 | dispatch(updateWalletByAddress(address, key, value))
19 | });
20 |
21 | class AddCustomEthToken extends React.Component {
22 | constructor(props) {
23 | super(props);
24 | this.state = {
25 | address: "",
26 | name: "",
27 | symbol: "",
28 | decimals: "",
29 | price: {}
30 | };
31 | }
32 |
33 | handleChange = (target, value) => {
34 | this.setState({ [target]: value });
35 | };
36 |
37 | update = () => {
38 | const { options } = this.props;
39 | const tokens = options.wallet.tokens
40 | ? {
41 | ...options.wallet.tokens,
42 | tokenList: [
43 | ...options.wallet.tokens.tokenList,
44 | { balance: 0, tokenInfo: this.state }
45 | ]
46 | }
47 | : {
48 | updated: new Date(),
49 | tokenList: [{ balance: 0, tokenInfo: this.state }]
50 | };
51 | this.props.update(options.wallet.address, "tokens", tokens);
52 | this.props.closeModal();
53 | };
54 |
55 | render() {
56 | return (
57 |
58 |
59 |
60 |
61 | Add custom token to {this.props.options.wallet.alias}
62 |
63 | this.handleChange("address", e.currentTarget.value)}
68 | />
69 | this.handleChange("name", e.currentTarget.value)}
74 | />
75 | this.handleChange("symbol", e.currentTarget.value)}
80 | />
81 | this.handleChange("decimals", e.currentTarget.value)}
86 | />
87 | OK
88 |
89 |
90 | );
91 | }
92 | }
93 |
94 | export default connect(
95 | mapStateToProps,
96 | mapDispatchToProps
97 | )(AddCustomEthToken);
98 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/OperationSelector.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { withStyles } from "@material-ui/core/styles";
3 | import Stepper from "./StepperForSend";
4 |
5 | const styles = {
6 | card: {
7 | backgroundColor: "#2B3649",
8 | color: "#FFFFFF",
9 | fontSize: 12,
10 | textOverflow: "ellipsis",
11 | marginBottom: "20px",
12 | borderRadius: "2px",
13 | boxShadow: "0 25px 40px 0 rgba(0,0,0,0.3)",
14 | transition: "background-color 0.7s ease"
15 | }
16 | };
17 |
18 | const Operations = ({ wallet }) => ;
19 |
20 | export default withStyles(styles)(Operations);
21 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/QrPopUp.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import config from "../../Providers/config";
3 | import { PopupLayout, CloseUpButton, Popup } from "../../Views";
4 |
5 | const QrPopUp = ({ options, closeModal }) => (
6 |
7 |
8 |
9 |
10 |
11 |
12 | );
13 |
14 | export default QrPopUp;
15 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/Receive.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const Receive = () => Receive
;
4 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/Reducer.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | const initialState = {
5 | chartData: [],
6 | walletInfo: {},
7 | wallet: {},
8 | transactions: [],
9 | fiat: {},
10 | walletList: [],
11 | trxId: "",
12 | status: "Pending"
13 | };
14 |
15 | export const wallet = handleActions(
16 | {
17 | [types.CHECK_OUT_INITIAL]: (state, action) => ({ ...action.payload }),
18 | [types.MOUNT_DATA_FOR_CHART]: (state, action) => ({
19 | ...state,
20 | chartData: action.payload
21 | }),
22 | [types.GET_WALLET]: (state, action) => ({
23 | ...state,
24 | wallet: action.payload.wallet,
25 | walletList: action.payload.walletList
26 | }),
27 | [types.MOUNT_WALLET_INFO]: (state, action) => ({
28 | ...state,
29 | walletInfo: action.payload
30 | }),
31 | [types.MOUNT_TRX_ID]: (state, action) => ({
32 | ...state,
33 | trxId: action.payload.txid,
34 | status: action.payload.status
35 | }),
36 | [types.MOUNT_TRANSACTIONS]: (state, action) => ({
37 | ...state,
38 | transactions: action.payload
39 | }),
40 | [types.MOUNT_FIAT]: (state, action) => ({ ...state, fiat: action.payload }),
41 | [types.MOUNT_TOKEN_INFO]: (state, action) => ({
42 | ...state,
43 | wallet: {
44 | ...state.wallet,
45 | tokens: {
46 | updated: new Date(),
47 | tokenList: action.payload
48 | }
49 | }
50 | })
51 | },
52 | initialState
53 | );
54 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/Transactions.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import Card from "@material-ui/core/Card";
4 | import { withStyles } from "@material-ui/core/styles";
5 | import Button from "@material-ui/core/Button";
6 | import { v4 } from "uuid";
7 | import { reverse, has } from "ramda";
8 | import * as actions from "./Actions";
9 | import { Scroll, StyledButton } from "../../Views";
10 | import { TransactionBasicInfo } from "./RenderFunctions";
11 |
12 | const styles = {
13 | card: {
14 | height: 528,
15 | position: "relative",
16 | backgroundColor: "#2B3649",
17 | color: "#FFFFFF",
18 | fontSize: 12,
19 | textOverflow: "ellipsis",
20 | boxShadow: "0 25px 40px 0 rgba(0,0,0,0.3)",
21 | transition: "background-color 0.7s ease"
22 | },
23 | button: {
24 | color: "#8D96B2",
25 | margin: "1px",
26 | borderRadius: "14px",
27 | borderColor: "#8D96B2",
28 | fontSize: "12px",
29 | minHeight: "auto",
30 | minWidth: "0",
31 | padding: "4px 8px",
32 | letterSpacing: "0.45px",
33 | lineHeight: "14px"
34 | }
35 | };
36 |
37 | const filters = [
38 | { btn: "All", value: "all" },
39 | { btn: "Receive", value: "received" },
40 | { btn: "Send", value: "sent" }
41 | ];
42 |
43 | class Transactions extends React.Component {
44 | constructor(props) {
45 | super(props);
46 | this.state = { filter: "all", openedTrx: null };
47 | }
48 |
49 | getSnapshotBeforeUpdate(prevProps, prevState) {
50 | has("address", this.props.wallet) &&
51 | prevProps.wallet.address !== this.props.wallet.address
52 | ? this.props.fetchTransactions(
53 | this.props.wallet.address,
54 | this.props.wallet.type
55 | )
56 | : null;
57 | return prevState;
58 | }
59 |
60 | onChnageFilter = filter => {
61 | this.setState({ filter });
62 | };
63 |
64 | filterTransactions = transactions =>
65 | this.state.filter !== "all"
66 | ? transactions.filter(trx => trx.type === this.state.filter)
67 | : transactions;
68 |
69 | sortTrx = transactions =>
70 | this.props.wallet.type === "etc" || this.props.wallet.type === "bch"
71 | ? this.filterTransactions(transactions)
72 | : this.filterTransactions(reverse(transactions));
73 |
74 | openTrxInfo = index => {
75 | this.setState({ openedTrx: index });
76 | };
77 |
78 | render() {
79 | return (
80 |
81 |
89 |
Transactions
90 |
91 | {filters.map(filter => (
92 | this.onChnageFilter(filter.value)}
95 | key={v4()}
96 | variant={this.state.filter === filter.value ? "outlined" : null}
97 | >
98 | {filter.btn}
99 |
100 | ))}
101 |
102 |
103 |
104 | {this.props.transactions && this.props.transactions.length ? (
105 | this.sortTrx(this.props.transactions).map((trx, index) => (
106 |
114 | ))
115 | ) : (
116 |
117 | the blockchain explorer temporary unavailable. Your assets are
118 | absolutely safe. Please try to repeat you request a bit later.
119 | Sorry for the inconvenience
120 |
121 | )}
122 |
123 |
131 | More
132 |
133 |
134 | );
135 | }
136 | }
137 |
138 | const mapStateToProps = state => ({
139 | chartData: state.wallets.wallet.chartData,
140 | selectedWalletInfo: state.initialPage.selectedWalletInfo,
141 | wallet: state.wallets.wallet.wallet,
142 | transactions: state.wallets.wallet.transactions
143 | });
144 |
145 | const mapDispatchToProps = dispatch => ({
146 | fetchTransactions: (addres, offset) =>
147 | dispatch(actions.fetchTransactions(addres, offset))
148 | });
149 |
150 | export default withStyles(styles)(
151 | connect(
152 | mapStateToProps,
153 | mapDispatchToProps
154 | )(Transactions)
155 | );
156 |
--------------------------------------------------------------------------------
/app/Wallets/Wallet/Wallet.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import CircularProgress from "@material-ui/core/CircularProgress";
4 | import { has } from "ramda";
5 | import wrapedWallet from "../../CommonComponents/Chart";
6 | import * as actions from "./Actions";
7 | import Operations from "./OperationSelector";
8 | import Transactions from "./Transactions";
9 | import WalletInfo from "./WalletInfo";
10 | import { Tokens } from "./Tokens";
11 | import Modal from "../../CommonComponents/Modal";
12 | import { Content } from "../../Views";
13 | import { Column } from "../../CommonComponents/ContentColumn/Index";
14 |
15 | class Wallet extends React.Component {
16 | constructor(props) {
17 | super(props);
18 | if (props.wallet.wid !== props.match.params.id) {
19 | props.getWalletInGaia(props.match.params.id);
20 | }
21 | this.state = {
22 | modalContent: null,
23 | modalOptions: undefined
24 | };
25 | this.wallet = props.history.location.state
26 | ? props.history.location.state
27 | : props.wallet;
28 | }
29 |
30 | callModal = (Component, optionalData) => {
31 | this.setState({ modalContent: Component, modalOptions: optionalData });
32 | };
33 |
34 | closeModal = () => {
35 | this.setState({ modalContent: null });
36 | };
37 |
38 | render() {
39 | const ModalContent = this.state.modalContent;
40 | return has("wid", this.wallet) &&
41 | this.props.match.params.id === this.wallet.wid ? (
42 |
43 |
44 | {this.state.modalContent ? (
45 |
49 | ) : null}
50 |
51 |
52 |
57 |
62 |
63 |
64 |
65 | {wrapedWallet(
66 | this.props.chartData,
67 | this.props.getDataForChart,
68 | this.props.selectedFiat,
69 | this.wallet.type
70 | )}
71 |
72 |
73 |
74 |
75 |
76 | ) : (
77 |
78 | );
79 | }
80 | }
81 |
82 | const mapStateToProps = state => ({
83 | chartData: state.wallets.wallet.chartData,
84 | wallet: state.wallets.wallet.wallet,
85 | fiat: state.wallets.wallet.fiat,
86 | selectedFiat: state.fiat.selectedFiat
87 | });
88 |
89 | const mapDispatchToProps = dispatch => ({
90 | getDataForChart: (currency, period, timestamp, fiat) =>
91 | dispatch(actions.getDataForChart(currency, period, timestamp, fiat)),
92 |
93 | fetchTokenInfo: (type, address) =>
94 | dispatch(actions.fetchTokenInfo(type, address)),
95 |
96 | getWalletInGaia: selectedWallet =>
97 | dispatch(actions.getWalletInGaia(selectedWallet))
98 | });
99 |
100 | export default connect(
101 | mapStateToProps,
102 | mapDispatchToProps
103 | )(Wallet);
104 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/ActionTypes.js:
--------------------------------------------------------------------------------
1 | export const types = {
2 | CHECKOUT_WALLETS: "@@walletList/CHECKOUT_WALLETS",
3 | MOUNT_WALLETS: "@@walletList/MOUNT_WALLETS",
4 | CREATE_WALLET: "@@walletList/CREATE_WALLET",
5 | DELETE_WALLET: "@@walletList/DELETE_WALLET",
6 | UPDATE_WALLET_LIST: "@@walletList/UPDATE_WALLET_LIST",
7 | FETCH_WALLET_INFO: "@@walletList/FETCH_WALLET_INFO",
8 | MOUNT_WALLET_INFO: "@@walletList/MOUNT_WALLET_INFO",
9 | UPDATE_WALLET_BY_WID: "@@walletList/UPDATE_WALLET_BY_WID"
10 | };
11 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/Actions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | export const checkoutWalletList = createAction(
5 | types.CHECKOUT_WALLETS,
6 | () => {}
7 | );
8 |
9 | export const fetchWalletInfo = createAction(
10 | types.FETCH_WALLET_INFO,
11 | wallet => wallet
12 | );
13 |
14 | export const createWallet = createAction(
15 | types.CREATE_WALLET,
16 | (walletList, wallet) => ({ walletList, wallet })
17 | );
18 |
19 | export const updateWalletList = createAction(
20 | types.UPDATE_WALLET_LIST,
21 | walletList => ({ walletList })
22 | );
23 |
24 | export const updateWalletByWID = createAction(
25 | types.UPDATE_WALLET_BY_WID,
26 | wallet => ({ wallet })
27 | );
28 |
29 | export const deleteWallet = createAction(
30 | types.DELETE_WALLET,
31 | (walletList, toBeDeleted) => ({
32 | walletList,
33 | toBeDeleted
34 | })
35 | );
36 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/ControlPanel.js:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | // Icons
4 | import IconSupport from "../../images/common/icon-support.svg";
5 | import IconArrowDown from "../../images/common/icon-arrow-down.svg";
6 |
7 | // Styled
8 | export const WalletsControl = styled.div`
9 | width: 100%;
10 | display: flex;
11 | justify-content: flex-start;
12 | align-items: center;
13 | padding-bottom: 40px;
14 | color: #fff;
15 | @media (max-width: 768px) {
16 | align-items: flex-start;
17 | flex-direction: column;
18 | & > input,
19 | > div {
20 | margin-bottom: 20px;
21 | }
22 | }
23 | `;
24 |
25 | export const Filter = styled.div`
26 | margin-left: 15px;
27 | @media (max-width: 768px) {
28 | margin-left: 0;
29 | }
30 | `;
31 |
32 | export const Switcher = styled.div`
33 | margin-left: 20px;
34 | margin-right: 20px;
35 | @media (max-width: 768px) {
36 | margin: 0;
37 | }
38 | .text {
39 | font-size: 12px;
40 | margin-left: 10px;
41 | cursor: pointer;
42 | }
43 | label {
44 | display: inline-block;
45 | vertical-align: middle;
46 | }
47 | `;
48 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/CreateNewWalletView.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import TextField from "@material-ui/core/TextField";
3 | import Select from "../../CommonComponents/Select";
4 | import { config } from "../../AppConfig";
5 | import { PopupButton } from "../../Views";
6 |
7 | const styles = {
8 | select: {
9 | width: "100%"
10 | },
11 | input: {
12 | width: "100%"
13 | },
14 | notification: {
15 | color: "red"
16 | }
17 | };
18 |
19 | export const CurrencySelect = ({ currency, handleChange }) => (
20 |
26 | );
27 |
28 | export const WalletTypeSelect = ({ wType, handleChange }) => (
29 |
35 | );
36 |
37 | export const PrivateKeyInput = ({ currency, value, handleChange }) =>
38 | currency ? (
39 |
47 | ) : null;
48 |
49 | const GenerationButton = ({ action, text }) => (
50 |
51 | {" "}
52 | {text}
53 |
54 | );
55 |
56 | export const ButtonControl = ({ currency, pk, generate, recover }) => {
57 | if (!currency) {
58 | return null;
59 | }
60 | return pk ? (
61 |
62 | ) : (
63 |
64 | );
65 | };
66 |
67 | const ServiceMessage = ({ text }) => (
68 | {text}
69 | );
70 |
71 | const WalletPreview = ({ wallet, save }) => (
72 |
73 |
74 | {wallet.readOnly ? (
75 |
76 | This will be read only wallet!
77 |
78 |
79 |
80 | ) : null}
81 |
82 |
private:
83 |
{wallet.privateKey}
84 |
85 |
86 |
public:
87 |
{wallet.address}
88 |
89 |
90 |
type:
91 |
{wallet.type}
92 |
93 |
94 |
dappy id:
95 |
{wallet.wid}
96 |
97 |
98 |
99 | {" "}
100 | Save{" "}
101 |
102 |
103 | );
104 |
105 | export const PrepareToSave = ({ serviceMessage, walletPreview, save }) => {
106 | if (!serviceMessage && !walletPreview) {
107 | return null;
108 | }
109 | return serviceMessage ? (
110 |
111 | ) : (
112 |
113 | );
114 | };
115 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/Customisation.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import TextField from "@material-ui/core/TextField";
3 | import { connect } from "react-redux";
4 | import { head, take } from "ramda";
5 | import { generateMnemonic } from "bip39";
6 | import { updateWalletList } from "./Actions";
7 | import { PopupLayout, PopupButton, Popup, CloseUpButton } from "../../Views";
8 | import { config } from "../../AppConfig";
9 |
10 | const mapStateToProps = state => ({
11 | wallets: state.wallets.walletList.walletList
12 | });
13 |
14 | const mapDispatchToProps = dispatch => ({
15 | update: wallets => dispatch(updateWalletList(wallets))
16 | });
17 |
18 | const styles = {
19 | input: {
20 | width: "100%"
21 | }
22 | };
23 |
24 | class Customisation extends React.Component {
25 | constructor(props) {
26 | super(props);
27 | const gaiaWallet = head(
28 | props.wallets.filter(wallet => wallet.wid === props.options.wid)
29 | );
30 | this.state = {
31 | wallet: gaiaWallet,
32 | alias: gaiaWallet.alias ? gaiaWallet.alias : ""
33 | };
34 | }
35 |
36 | generateRandomPair = () =>
37 | config.avCurrencyes.get(this.state.wallet.type).name +
38 | " " +
39 | take(2, generateMnemonic().split(" ")).join("-");
40 |
41 | handleChange = e => {
42 | const value = e.currentTarget.value;
43 | this.setState({ alias: value });
44 | };
45 |
46 | saveUpdates = () => {
47 | const newWallets = this.props.wallets.map(wallet =>
48 | wallet.wid === this.props.options.wid
49 | ? {
50 | ...this.state.wallet,
51 | alias: this.state.alias
52 | ? this.state.alias
53 | : this.generateRandomPair()
54 | }
55 | : wallet
56 | );
57 | this.props.update(newWallets);
58 | this.props.closeModal();
59 | };
60 |
61 | render() {
62 | return (
63 |
64 |
65 |
66 |
73 | Rename wallet
74 |
75 |
76 | );
77 | }
78 | }
79 |
80 | export default connect(
81 | mapStateToProps,
82 | mapDispatchToProps
83 | )(Customisation);
84 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/DeleteWallet.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import TextField from "@material-ui/core/TextField";
4 | import Button from "@material-ui/core/Button";
5 | import InputLabel from "@material-ui/core/InputLabel";
6 | import { deleteWallet } from "./Actions";
7 | import { PopupLayout } from "../../Views";
8 | import { Popup } from "../../Views";
9 | import { CloseUpButton } from "../../Views";
10 | import { PopupButton } from "../../Views";
11 | import { PopupGreyButton } from "../../Views";
12 |
13 | const mapStateToProps = state => ({
14 | wallets: state.wallets.walletList.walletList
15 | });
16 |
17 | const mapDispatchToProps = dispatch => ({
18 | delete: (wallets, toBeDeleted) => dispatch(deleteWallet(wallets, toBeDeleted))
19 | });
20 |
21 | const styles = {
22 | input: {
23 | width: "100%"
24 | }
25 | };
26 |
27 | class DeleteWallet extends React.Component {
28 | constructor(props) {
29 | super(props);
30 | this.state = {
31 | confirmation: "",
32 | isConfirmed: false
33 | };
34 | this.origin = "Yes, I really want to delete this wallet!";
35 | }
36 |
37 | handleConfirmation = e => {
38 | this.setState({
39 | confirmation: e.currentTarget.value,
40 | isConfirmed: this.origin === e.currentTarget.value
41 | });
42 | };
43 |
44 | render() {
45 | return (
46 |
47 |
48 |
49 | Are you sure?
50 |
51 | For deletion please type:
52 | {this.origin}
53 |
54 |
60 |
61 |
62 | No
63 |
64 |
{
66 | this.props.delete(this.props.wallets, this.props.options.wid);
67 | this.props.closeModal();
68 | }}
69 | disabled={!this.state.isConfirmed}
70 | >
71 | Delete
72 |
73 |
74 |
75 |
76 | );
77 | }
78 | }
79 | export default connect(
80 | mapStateToProps,
81 | mapDispatchToProps
82 | )(DeleteWallet);
83 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/Error.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import TextField from "@material-ui/core/TextField";
3 | import { connect } from "react-redux";
4 | import Button from "@material-ui/core/Button";
5 | import { head } from "ramda";
6 | import { updateWalletList } from "./Actions";
7 | import { PopupLayout } from "../../Views";
8 | import { Popup } from "../../Views";
9 | import { CloseUpButton } from "../../Views";
10 | import { PopupButton } from "../../Views";
11 |
12 | class Error extends React.Component {
13 | render() {
14 | return (
15 |
16 |
17 |
18 | Error message
19 |
20 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste
21 | cupiditate molestias laboriosam blanditiis similique! Distinctio
22 | placeat odit magnam nihil pariatur.
23 |
24 | Ok
25 |
26 |
27 | );
28 | }
29 | }
30 |
31 | export default Error;
32 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/LongMenu.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import IconButton from "@material-ui/core/IconButton";
3 | import { head, last } from "ramda";
4 | import Menu from "@material-ui/core/Menu";
5 | import MenuItem from "@material-ui/core/MenuItem";
6 | import MoreVertIcon from "@material-ui/icons/MoreVert";
7 | import styled, { css } from "styled-components";
8 | import PrivateKey from "./PrivateKey";
9 | import MakeActive from "./MakeActive";
10 | import DeleteWallet from "./DeleteWallet";
11 | import Customisation from "./Customisation";
12 |
13 | const Dropdown = styled.div`
14 | position: absolute;
15 | right: 0;
16 | top: -5px;
17 | transform: rotate(90deg);
18 | button {
19 | width: 25px;
20 | height: 25px;
21 | }
22 | svg {
23 | fill: #8d96b2;
24 | }
25 | `;
26 |
27 | const optionList = (wallet = null) => {
28 | const makeActive =
29 | wallet && wallet.readOnly
30 | ? ["Read to Write", MakeActive]
31 | : ["Private Key", PrivateKey];
32 |
33 | return new Map([
34 | makeActive,
35 | ["Delete", DeleteWallet],
36 | ["Customize", Customisation]
37 | ]);
38 | };
39 |
40 | class LongMenu extends React.Component {
41 | constructor(props) {
42 | super(props);
43 | this.state = {
44 | anchorEl: null
45 | };
46 | }
47 | handleClick = event => {
48 | this.setState({ anchorEl: event.currentTarget });
49 | };
50 |
51 | handleClose = option => {
52 | if (typeof option === "function")
53 | this.props.callModal(option, { wid: this.props.wid });
54 | this.setState({ anchorEl: null });
55 | };
56 |
57 | render() {
58 | const { anchorEl } = this.state;
59 | return (
60 |
61 |
67 |
68 |
69 |
90 |
91 | );
92 | }
93 | }
94 |
95 | export default LongMenu;
96 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/MakeActive.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import FormControl from "@material-ui/core/FormControl";
4 | import AppBar from "@material-ui/core/AppBar";
5 | import Tabs from "@material-ui/core/Tabs";
6 | import Tab from "@material-ui/core/Tab";
7 | import Typography from "@material-ui/core/Typography";
8 | import {
9 | PopupLayout,
10 | PopupButton,
11 | CloseUpButton,
12 | Popup,
13 | TabsWrapper
14 | } from "../../Views";
15 | import { updateWalletByWID } from "./Actions";
16 | import { recoverWallet } from "../../Providers/Wallets";
17 |
18 | const mapDispatchToProps = dispatch => ({
19 | update: wallet => dispatch(updateWalletByWID(wallet))
20 | });
21 |
22 | const mapStateToProps = state => ({
23 | wallets: state.wallets.walletList.walletList
24 | });
25 |
26 | function TabContainer(props) {
27 | return (
28 |
29 | {props.children}
30 |
31 | );
32 | }
33 |
34 | class MakeActive extends React.Component {
35 | constructor(props) {
36 | super(props);
37 | this.state = { pKey: "", warning: null };
38 | }
39 |
40 | changePkey = e => {
41 | this.setState({ pKey: e.currentTarget.value, warning: null });
42 | };
43 |
44 | updateWallet = () => {
45 | const currentWallet = this.props.wallets.find(
46 | w => w.wid === this.props.options.wid
47 | );
48 | try {
49 | const { address } = recoverWallet(currentWallet.type, this.state.pKey);
50 | if (address === currentWallet.address) {
51 | this.props.update({
52 | ...currentWallet,
53 | readOnly: false,
54 | privateKey: this.state.pKey
55 | });
56 | this.props.closeModal();
57 | } else {
58 | this.setState({ warning: "Wrong private key!" });
59 | }
60 | } catch (e) {
61 | this.setState({ warning: "Wrong private key!" });
62 | }
63 | };
64 |
65 | render() {
66 | return (
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | {
78 |
79 |
80 | Please enter the private key to change the wallet state
81 |
82 |
83 |
90 |
91 | Read to Write
92 |
93 | {this.state.warning ? {this.state.warning} : null}
94 |
95 |
96 | }
97 |
98 |
99 | );
100 | }
101 | }
102 | export default connect(
103 | mapStateToProps,
104 | mapDispatchToProps
105 | )(MakeActive);
106 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/PrivateKey.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { connect } from "react-redux";
3 | import { head } from "ramda";
4 | import { Popup, PopupLayout, CloseUpButton, PopupButton } from "../../Views";
5 |
6 | const mapStateToProps = state => ({
7 | wallets: state.wallets.walletList.walletList
8 | });
9 |
10 | class PrivateKey extends React.Component {
11 | constructor(props) {
12 | super(props);
13 | this.gaiaWallet = head(
14 | props.wallets.filter(wallet => wallet.wid === props.options.wid)
15 | );
16 | }
17 |
18 | render() {
19 | return (
20 |
21 |
22 |
23 | The wallet private key
24 | {this.gaiaWallet.privateKey}
25 | OK
26 |
27 |
28 | );
29 | }
30 | }
31 |
32 | export default connect(mapStateToProps)(PrivateKey);
33 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/Receive.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const Receive = () => Receive
;
4 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/Reducer.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from "redux-actions";
2 | import { types } from "./ActionTypes";
3 |
4 | const initialState = {
5 | walletList: [],
6 | selectedWallet: null,
7 | selectedWalletInfo: {}
8 | };
9 |
10 | export const walletList = handleActions(
11 | {
12 | [types.MOUNT_WALLETS]: (state, action) => ({
13 | ...state,
14 | walletList: action.payload
15 | }),
16 | [types.SELECT_WALLET]: (state, action) => ({
17 | ...state,
18 | selectedWallet: action.payload
19 | }),
20 | [types.MOUNT_WALLET_INFO]: (state, action) => ({
21 | ...state,
22 | selectedWalletInfo: action.payload
23 | })
24 | },
25 | initialState
26 | );
27 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/RenderFunctions.js:
--------------------------------------------------------------------------------
1 | export const SEND = 1;
2 |
--------------------------------------------------------------------------------
/app/Wallets/WalletList/Saga.js:
--------------------------------------------------------------------------------
1 | import { put, call, takeLatest } from "redux-saga/effects";
2 | import { delay } from "redux-saga";
3 | import { getWalletList, logEvent, setWalletList } from "../../Providers/Gaia";
4 | import { types } from "./ActionTypes";
5 | import * as dashboard from "../../InitialPage/ActionTypes";
6 | import XHRProvider from "../../Providers/XHRProvider";
7 |
8 | const xhr = new XHRProvider();
9 |
10 | function* checkoutWallets() {
11 | const walletList = yield call(getWalletList);
12 | if (walletList.kpList && walletList.kpList.length) {
13 | yield put({ type: types.MOUNT_WALLETS, payload: walletList.kpList });
14 | } else {
15 | const newWallet = yield setWalletList();
16 | yield put({ type: types.MOUNT_WALLETS, payload: newWallet });
17 | }
18 | }
19 |
20 | function* createWallet(action) {
21 | const { walletList, wallet } = action.payload;
22 | const newWalletList = yield setWalletList([...walletList, wallet]);
23 | yield call(logEvent, {
24 | date: new Date(),
25 | type: "walletCreate",
26 | text: `${wallet.type} was created`
27 | });
28 | yield put({ type: dashboard.types.MOUNT_WALLETS, payload: newWalletList });
29 | yield put({ type: types.MOUNT_WALLETS, payload: newWalletList });
30 | yield delay(3000);
31 | yield put({ type: dashboard.types.CHECKOUT_HISTORY, payload: undefined });
32 | }
33 |
34 | function* updateWalletByWID(action) {
35 | const { wallet } = action.payload;
36 | const { kpList } = yield call(getWalletList);
37 | const newWalletList = yield setWalletList([
38 | ...kpList.filter(w => w.wid !== wallet.wid),
39 | wallet
40 | ]);
41 | yield put({ type: types.MOUNT_WALLETS, payload: newWalletList });
42 | }
43 |
44 | function* updateWalletList(action) {
45 | const { walletList } = action.payload;
46 | const newWalletList = yield setWalletList(walletList);
47 | yield put({ type: types.MOUNT_WALLETS, payload: newWalletList });
48 | }
49 |
50 | function* deleteWallet(action) {
51 | const { walletList, toBeDeleted } = action.payload;
52 | const wallet = walletList.find(wallet => wallet.wid === toBeDeleted);
53 |
54 | const newWalletList = yield setWalletList(
55 | walletList.filter(wallet => wallet.wid !== toBeDeleted)
56 | );
57 | yield call(logEvent, {
58 | date: new Date(),
59 | type: "walletCreate",
60 | text: `${wallet.type} wallet was deleted`
61 | });
62 | yield put({ type: dashboard.types.CHECKOUT_HISTORY, payload: undefined });
63 | yield put({ type: types.MOUNT_WALLETS, payload: newWalletList });
64 | yield delay(3000);
65 | yield put({ type: dashboard.types.CHECKOUT_HISTORY, payload: undefined });
66 | }
67 |
68 | function* fetchWalletInfo(action) {
69 | let walletInfo;
70 | try {
71 | walletInfo = yield call(xhr.get, action.payload);
72 | } catch (e) {
73 | yield delay(5000);
74 | yield put(action);
75 | }
76 | yield put({ type: types.MOUNT_WALLET_INFO, payload: walletInfo.data });
77 | }
78 |
79 | export function* walletListSaga() {
80 | yield takeLatest(types.CHECKOUT_WALLETS, checkoutWallets);
81 | yield takeLatest(types.CREATE_WALLET, createWallet);
82 | yield takeLatest(types.DELETE_WALLET, deleteWallet);
83 | yield takeLatest(types.FETCH_WALLET_INFO, fetchWalletInfo);
84 | yield takeLatest(types.UPDATE_WALLET_LIST, updateWalletList);
85 | yield takeLatest(types.UPDATE_WALLET_BY_WID, updateWalletByWID);
86 | }
87 |
--------------------------------------------------------------------------------
/app/devIndex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Dappy
9 |
10 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/images/common/icon-add.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 6D79490F-36F7-4DA4-8C64-857D0CE3548E
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/images/common/icon-arrow-down-grey.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-arrow-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 545EBAA7-0ACF-45D8-9696-89BB9EFD07C1
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/images/common/icon-arrow-green.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-checkbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | E69A28E9-0B59-4E8A-8B8B-5264F42F2409
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/images/common/icon-cross-grey.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-cross-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-direction.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4F43218C-2B09-4603-9942-75A3A59038C3
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/images/common/icon-exchange-loading.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-filter.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 86B1B81B-CC72-4846-A57E-028C3A61015C
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/images/common/icon-link-forward-hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-link-forward.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-log-out.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-manual-address.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/images/common/icon-profile.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/images/common/icon-scale.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-search.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 3DD5EE58-01AA-4DDE-899C-0679E9A13187
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/images/common/icon-support.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-swap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 02D0D12B-B589-4FBC-B2BA-F6DCD20F4F91
5 | Created with sketchtool.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/images/common/icon-xl-arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/icon-xl-swap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/common/vision-off.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/fiat/AUD@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/AUD@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/AUD@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/AUD@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/BRL@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/BRL@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/BRL@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/BRL@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/CAD@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/CAD@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/CAD@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/CAD@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/CHF@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/CHF@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/CHF@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/CHF@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/CNY@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/CNY@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/CNY@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/CNY@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/EUR@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/EUR@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/EUR@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/EUR@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/GBP@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/GBP@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/GBP@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/GBP@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/HKD@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/HKD@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/HKD@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/HKD@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/IDR@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/IDR@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/IDR@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/IDR@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/INR@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/INR@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/INR@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/INR@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/JPY@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/JPY@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/JPY@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/JPY@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/KRW@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/KRW@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/KRW@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/KRW@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/MXN@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/MXN@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/MXN@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/MXN@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/RUB@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/RUB@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/RUB@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/RUB@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/USD@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/USD@1x.png
--------------------------------------------------------------------------------
/app/images/fiat/USD@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BCNetio/BlockStackWallet/59a4ac2ec3fe06d690643f0e5a1ddc5e6179e045/app/images/fiat/USD@2x.png
--------------------------------------------------------------------------------
/app/images/fiat/index.js:
--------------------------------------------------------------------------------
1 | import USD1x from "./USD@1x.png";
2 | import USD2x from "./USD@2x.png";
3 | import EUR1x from "./EUR@1x.png";
4 | import EUR2x from "./EUR@2x.png";
5 | import RUB1x from "./RUB@1x.png";
6 | import RUB2x from "./RUB@2x.png";
7 | import AUD1x from "./AUD@1x.png";
8 | import AUD2x from "./AUD@2x.png";
9 | import BRL1x from "./BRL@1x.png";
10 | import BRL2x from "./BRL@2x.png";
11 | import CAD1x from "./CAD@1x.png";
12 | import CAD2x from "./CAD@2x.png";
13 | import CHF1x from "./CHF@1x.png";
14 | import CHF2x from "./CHF@2x.png";
15 | import CNY1x from "./CNY@1x.png";
16 | import CNY2x from "./CNY@2x.png";
17 | import GBP1x from "./GBP@1x.png";
18 | import GBP2x from "./GBP@2x.png";
19 | import HKD1x from "./HKD@1x.png";
20 | import HKD2x from "./HKD@2x.png";
21 | import IDR1x from "./IDR@1x.png";
22 | import IDR2x from "./IDR@2x.png";
23 | import INR1x from "./INR@1x.png";
24 | import INR2x from "./INR@2x.png";
25 | import JPY1x from "./JPY@1x.png";
26 | import JPY2x from "./JPY@2x.png";
27 | import KRW1x from "./KRW@1x.png";
28 | import KRW2x from "./KRW@2x.png";
29 | import MXN1x from "./MXN@1x.png";
30 | import MXN2x from "./MXN@2x.png";
31 |
32 | export const fiats = {
33 | USD: { x1: USD1x, x2: USD2x },
34 | EUR: { x1: EUR1x, x2: EUR2x },
35 | RUB: { x1: RUB1x, x2: RUB2x },
36 | AUD: { x1: AUD1x, x2: AUD2x },
37 | BRL: { x1: BRL1x, x2: BRL2x },
38 | CAD: { x1: CAD1x, x2: CAD2x },
39 | CHF: { x1: CHF1x, x2: CHF2x },
40 | CNY: { x1: CNY1x, x2: CNY2x },
41 | GBP: { x1: GBP1x, x2: GBP2x },
42 | HKD: { x1: HKD1x, x2: HKD2x },
43 | IDR: { x1: IDR1x, x2: IDR2x },
44 | INR: { x1: INR1x, x2: INR2x },
45 | JPY: { x1: JPY1x, x2: JPY2x },
46 | KRW: { x1: KRW1x, x2: KRW2x },
47 | MXN: { x1: MXN1x, x2: MXN2x }
48 | };
49 |
--------------------------------------------------------------------------------
/app/images/ic-bch.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/images/ic-btc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/images/ic-btg.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/images/ic-dash.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/images/ic-dcr.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/images/ic-doge.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/images/ic-etc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/images/ic-eth.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/images/ic-ltc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/images/ic-zec.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/images/index.js:
--------------------------------------------------------------------------------
1 | import { curNames } from "../AppConfig";
2 | import icBtc from "./ic-btc.svg";
3 | import icBch from "./ic-bch.svg";
4 | import icEth from "./ic-eth.svg";
5 | import icEtc from "./ic-etc.svg";
6 | import icDoge from "./ic-doge.svg";
7 | import icLtc from "./ic-ltc.svg";
8 | import icZec from "./ic-zec.svg";
9 | import icDcr from "./ic-dcr.svg";
10 | import icDash from "./ic-dash.svg";
11 | import icBtg from "./ic-btg.svg";
12 |
13 | export const logos = {
14 | [curNames.BTC]: icBtc,
15 | [curNames.BCH]: icBch,
16 | [curNames.ETH]: icEth,
17 | [curNames.ETC]: icEtc,
18 | [curNames.DOGE]: icDoge,
19 | [curNames.LTC]: icLtc,
20 | [curNames.ZEC]: icZec,
21 | [curNames.DCR]: icDcr,
22 | [curNames.DASH]: icDash,
23 | [curNames.BTG]: icBtg
24 | };
25 |
--------------------------------------------------------------------------------
/app/images/nav/icon-dashboard-hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/nav/icon-dashboard.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/nav/icon-exchange-hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/nav/icon-exchange.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/nav/icon-wallet-hover.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/images/nav/icon-wallet.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/index.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700");
2 |
3 | /* body color */
4 | * {
5 | box-sizing: border-box;
6 | }
7 |
8 | body {
9 | background-color: #1f2431;
10 | margin: 0;
11 | }
12 |
13 | p,
14 | span,
15 | div,
16 | label,
17 | input,
18 | button,
19 | a,
20 | li,
21 | h1,
22 | h2,
23 | h3,
24 | h4,
25 | h5,
26 | h6 {
27 | font-family: "Roboto";
28 | }
29 |
30 | p,
31 | input {
32 | margin: 0;
33 | }
34 |
35 | button {
36 | cursor: pointer;
37 | outline: none;
38 | &[disabled] {
39 | cursor: no-drop;
40 | }
41 | }
42 |
43 | ul {
44 | margin: 0;
45 | padding: 0;
46 | list-style: none;
47 | }
48 |
49 | /* styles for scrollbar */
50 | .scroll-wrapper::-webkit-scrollbar {
51 | width: 10px;
52 | }
53 |
54 | .scroll-wrapper::-webkit-scrollbar-track {
55 | background-color: #e2e4e8;
56 | }
57 |
58 | .scroll-wrapper.dark::-webkit-scrollbar-track {
59 | background-color: #273041;
60 | width: 10px;
61 | }
62 |
63 | .scroll-wrapper::-webkit-scrollbar-thumb {
64 | background-color: #8d96b2;
65 | border: 3px solid transparent;
66 | border-radius: 9px;
67 | background-clip: content-box;
68 | }
69 |
70 | .bg-swap {
71 | background-image: url(images/common/icon-xl-swap.svg);
72 | background-position: center right;
73 | background-repeat: no-repeat;
74 | background-size: 65%;
75 | margin: -20px;
76 | }
77 |
78 | .bg-arrow {
79 | background-image: url(images/common/icon-xl-arrow.svg);
80 | background-position: 100%;
81 | background-repeat: no-repeat;
82 | background-size: 43%;
83 | height: 240px;
84 | padding: 20px;
85 | position: relative;
86 | }
87 |
88 | /* checkbox */
89 | .checkbox {
90 | display: none;
91 | }
92 |
93 | .checkbox-custom {
94 | position: relative;
95 | height: 16px;
96 | width: 16px;
97 | border-radius: 4px;
98 | background-color: #1f2431;
99 | margin-right: 10px;
100 | }
101 |
102 | .checkbox-custom.header {
103 | border: 1px solid #2b3649;
104 | }
105 |
106 | .checkbox-custom,
107 | .label {
108 | display: inline-block;
109 | vertical-align: middle;
110 | cursor: pointer;
111 | }
112 |
113 | .checkbox:checked + .checkbox-custom::before {
114 | content: "";
115 | display: block;
116 | position: absolute;
117 | top: 0px;
118 | right: 0px;
119 | bottom: 0px;
120 | left: 0px;
121 | background: url(images/common/icon-checkbox.svg) no-repeat;
122 | border-radius: 4px;
123 | }
124 |
125 | .loading {
126 | position: relative;
127 | display: block;
128 | height: 1px;
129 | width: 100%;
130 | &:after {
131 | content: " .";
132 | display: block;
133 | animation: dots 1s steps(5, end) infinite;
134 | font-size: 30px;
135 | line-height: 0px;
136 | position: absolute;
137 | top: -8px;
138 | left: -11px;
139 | }
140 | }
141 |
142 | @keyframes dots {
143 | 0%,
144 | 20% {
145 | color: rgba(0, 0, 0, 0);
146 | text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0);
147 | }
148 | 40% {
149 | color: white;
150 | text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0);
151 | }
152 | 60% {
153 | text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0);
154 | }
155 | 80%,
156 | 100% {
157 | text-shadow: 0.25em 0 0 #7ac231, 0.5em 0 0 #7ac231;
158 | }
159 | }
160 |
161 | /* switch chexbox */
162 | .switch {
163 | position: relative;
164 | display: inline-block;
165 | width: 30px;
166 | height: 16px;
167 | }
168 |
169 | .switch input {
170 | display: none;
171 | }
172 |
173 | .slider {
174 | position: absolute;
175 | cursor: pointer;
176 | top: 0;
177 | left: 0;
178 | right: 0;
179 | bottom: 0;
180 | -webkit-transition: 0.4s;
181 | transition: 0.4s;
182 | border: 1px solid #2b3649;
183 | }
184 |
185 | .slider:before {
186 | position: absolute;
187 | content: "";
188 | height: 10px;
189 | width: 10px;
190 | left: 4px;
191 | bottom: 2px;
192 | background-color: white;
193 | -webkit-transition: 0.4s;
194 | transition: 0.4s;
195 | }
196 |
197 | input:focus + .slider {
198 | box-shadow: 0 0 1px #2196f3;
199 | }
200 |
201 | input:checked + .slider:before {
202 | -webkit-transform: translateX(26px);
203 | -ms-transform: translateX(26px);
204 | transform: translateX(11px);
205 | }
206 |
207 | input:checked + .slider {
208 | background-color: #7ac231;
209 | }
210 |
211 | .slider.round {
212 | border-radius: 34px;
213 | }
214 |
215 | .slider.round:before {
216 | border-radius: 50%;
217 | }
218 |
219 | .long-menu {
220 | div:last-child {
221 | box-shadow: none;
222 | ul {
223 | padding: 4px 0;
224 | }
225 | li {
226 | padding: 5px 50px 5px 12px;
227 | font-size: 10px;
228 | line-height: 10px;
229 | letter-spacing: 0.230769px;
230 | color: #2b3649;
231 | height: auto;
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Dappy
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Provider } from "react-redux";
3 | import { BrowserRouter } from "react-router-dom";
4 | import ReactDOM from "react-dom";
5 | import Router from "./Routing/Router";
6 | import { store } from "./InitialSetup/Store";
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 |
13 | ,
14 | document.getElementById("root")
15 | );
16 |
--------------------------------------------------------------------------------
/bundleLibs/lib_2.json:
--------------------------------------------------------------------------------
1 | {"name":"lib_2","content":{"./node_modules/react-dom/index.js":{"id":"./node_modules/react-dom/index.js","buildMeta":{"providedExports":true}},"./node_modules/react/cjs/react.development.js":{"id":"./node_modules/react/cjs/react.development.js","buildMeta":{"providedExports":true}},"./node_modules/object-assign/index.js":{"id":"./node_modules/object-assign/index.js","buildMeta":{"providedExports":true}},"./node_modules/prop-types/checkPropTypes.js":{"id":"./node_modules/prop-types/checkPropTypes.js","buildMeta":{"providedExports":true}},"./node_modules/prop-types/lib/ReactPropTypesSecret.js":{"id":"./node_modules/prop-types/lib/ReactPropTypesSecret.js","buildMeta":{"providedExports":true}},"./node_modules/react/index.js":{"id":"./node_modules/react/index.js","buildMeta":{"providedExports":true}},"./node_modules/react-dom/cjs/react-dom.development.js":{"id":"./node_modules/react-dom/cjs/react-dom.development.js","buildMeta":{"providedExports":true}},"./node_modules/scheduler/index.js":{"id":"./node_modules/scheduler/index.js","buildMeta":{"providedExports":true}},"./node_modules/scheduler/cjs/scheduler.development.js":{"id":"./node_modules/scheduler/cjs/scheduler.development.js","buildMeta":{"providedExports":true}},"./node_modules/webpack/buildin/global.js":{"id":"./node_modules/webpack/buildin/global.js","buildMeta":{"providedExports":true}},"./node_modules/scheduler/tracing.js":{"id":"./node_modules/scheduler/tracing.js","buildMeta":{"providedExports":true}},"./node_modules/scheduler/cjs/scheduler-tracing.development.js":{"id":"./node_modules/scheduler/cjs/scheduler-tracing.development.js","buildMeta":{"providedExports":true}}}}
--------------------------------------------------------------------------------
/lib.webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | require('dotenv').config();
4 | const publicFolder = path.resolve(__dirname, 'public');
5 | module.exports = {
6 | mode: process.env.NODE_ENV,
7 | context: process.cwd(),
8 | resolve: {
9 | extensions: ['.js', '.jsx', '.json', '.less', '.css'],
10 | modules: [__dirname, 'node_modules']
11 | },
12 |
13 | entry: {
14 | lib_1: ["redux", "ramda", "redux-saga", "react-redux", "lodash"],
15 | lib_2: ["react", "react-dom"],
16 | },
17 | output: {
18 | filename: '[name].dll.js',
19 | path: publicFolder,
20 | library: '[name]'
21 | },
22 | plugins: [
23 | new webpack.DllPlugin({
24 | name: '[name]',
25 | path: `bundleLibs/[name].json`
26 | })
27 | ]
28 | };
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bcnet.io",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "prettier": "prettier --write './app/**/{*.js,*.css, *json}'",
8 | "production": "NODE_ENV=production node node_modules/webpack/bin/webpack.js -p",
9 | "prestart": "node node_modules/webpack/bin/webpack.js --config lib.webpack.config.js",
10 | "start": "node node_modules/webpack-dev-server/bin/webpack-dev-server.js"
11 | },
12 | "author": "",
13 | "license": "MIT",
14 | "dependencies": {
15 | "@material-ui/core": "^1.0.0",
16 | "@material-ui/icons": "^1.0.0",
17 | "axios": "^0.18.0",
18 | "babel-cli": "^6.26.0",
19 | "bigi": "^1.4.2",
20 | "bip39": "^2.5.0",
21 | "bitcoinjs-lib": "^4.0.1",
22 | "bitcore-lib-cash": "^0.19.0",
23 | "blockstack": "^18.2.0",
24 | "chart.js": "^2.7.2",
25 | "classnames": "^2.2.5",
26 | "dotenv": "^4.0.0",
27 | "ethereumjs-tx": "^1.3.4",
28 | "ethereumjs-util": "^5.2.0",
29 | "ethereumjs-wallet": "^0.6.0",
30 | "file-loader": "^1.1.11",
31 | "human-standard-token-abi": "^1.0.2",
32 | "immutable": "^4.0.0-rc.12",
33 | "normalize-css": "^2.3.1",
34 | "postcss-nested": "^3.0.0",
35 | "prettier": "1.15.3",
36 | "prop-types": "^15.6.1",
37 | "ramda": "^0.25.0",
38 | "react": "^16.4.0",
39 | "react-chartjs-2": "^2.7.2",
40 | "react-copy-to-clipboard": "^5.0.1",
41 | "react-dom": "^16.2.0",
42 | "react-icons": "^2.2.7",
43 | "react-prefixer": "^2.0.0",
44 | "react-redux": "^5.0.2",
45 | "react-router": "^4.2.0",
46 | "react-router-dom": "^4.2.2",
47 | "redux": "^4.0.0",
48 | "redux-action": "^1.2.2",
49 | "redux-actions": "^2.3.0",
50 | "redux-devtools-extension": "^2.13.2",
51 | "redux-saga": "^0.16.0",
52 | "reselect": "^4.0.0",
53 | "styled-components": "^3.2.6",
54 | "stylelint-config-standard": "^18.2.0",
55 | "stylelint-webpack-plugin": "^0.10.3",
56 | "uglifyjs-webpack-plugin": "^1.3.0",
57 | "uuid": "^3.2.1",
58 | "web3": "^1.0.0-beta.34",
59 | "whatwg-fetch": "^2.0.3"
60 | },
61 | "devDependencies": {
62 | "autoprefixer": "^7.2.6",
63 | "babel-core": "^6.21.0",
64 | "babel-eslint": "^7.2.3",
65 | "babel-jest": "^18.0.0",
66 | "babel-loader": "^7.1.4",
67 | "babel-plugin-transform-react-jsx": "^6.24.1",
68 | "babel-plugin-transform-react-remove-prop-types": "^0.4.13",
69 | "babel-plugin-transform-runtime": "^6.15.0",
70 | "babel-polyfill": "^6.26.0",
71 | "babel-preset-env": "^1.6.1",
72 | "babel-preset-react": "^6.24.1",
73 | "babel-preset-stage-2": "^6.24.1",
74 | "clean-webpack-plugin": "^0.1.15",
75 | "compression-webpack-plugin": "^1.1.11",
76 | "css-hot-loader": "^1.1.1",
77 | "css-loader": "^0.28.11",
78 | "eslint": "^3.19.0",
79 | "eslint-config-airbnb": "^14.0.0",
80 | "eslint-config-prettier": "^3.3.0",
81 | "eslint-plugin-import": "^2.2.0",
82 | "eslint-plugin-jsx-a11y": "^3.0.2",
83 | "eslint-plugin-prettier": "^3.0.0",
84 | "eslint-plugin-react": "^6.9.0",
85 | "extract-text-webpack-plugin": "^4.0.0-beta.0",
86 | "fbjs-scripts": "^0.6.0-alpha.3",
87 | "html-webpack-plugin": "^3.1.0",
88 | "jest": "^18.1.0",
89 | "normalize.css": "^8.0.0",
90 | "postcss": "^6.0.21",
91 | "postcss-css-variables": "^0.8.1",
92 | "postcss-cssnext": "^3.1.0",
93 | "postcss-extend": "^1.0.5",
94 | "postcss-import": "^11.1.0",
95 | "postcss-loader": "^2.1.3",
96 | "postcss-mixins": "^6.2.0",
97 | "postcss-partial-import": "^4.1.0",
98 | "postcss-utilities": "^0.8.0",
99 | "precss": "^3.1.2",
100 | "prettier-eslint": "^8.2.2",
101 | "react-hot-loader": "^4.0.0",
102 | "style-loader": "^0.20.3",
103 | "stylelint": "^9.2.0",
104 | "sugarss": "^1.0.1",
105 | "webpack": "^4.28.2",
106 | "webpack-cli": "^3.1.1",
107 | "webpack-dev-server": "^3.1.1",
108 | "webpack-manifest-plugin": "^2.0.2"
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'postcss-import': {},
4 | 'postcss-nested': {},
5 | 'postcss-partial-import': {},
6 | 'postcss-mixins': {},
7 | 'postcss-css-variables': {},
8 | 'postcss-preset-env': {},
9 | 'postcss-extend': {},
10 | 'precss':{},
11 | 'postcss-cssnext': {},
12 | 'postcss-utilities': {},
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------