├── .circleci
├── ci_increase_chart_version.sh
└── config.yml
├── .dockerignore
├── .env.template
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .npmrc
├── .nvmrc
├── Dockerfile
├── LICENSE
├── README.md
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── ether.png
├── favicon.png
├── index.html
├── manifest.json
├── omg_logo.svg
├── robots.txt
└── serve.json
└── src
├── actions
├── __tests__
│ ├── createAction.test.js
│ ├── networkAction.test.js
│ ├── setupAction.test.js
│ ├── tokenAction.test.js
│ └── uiAction.test.js
├── createAction.js
├── networkAction.js
├── setupAction.js
├── tokenAction.js
└── uiAction.js
├── components
├── alert
│ ├── Alert.js
│ └── Alert.module.scss
├── button
│ ├── Button.js
│ └── Button.module.scss
├── copy
│ ├── Copy.js
│ └── Copy.module.scss
├── gaspicker
│ ├── GasPicker.js
│ └── GasPicker.module.scss
├── hamburger
│ ├── Hamburger.js
│ └── Hamburger.module.scss
├── info
│ ├── Info.js
│ └── Info.module.scss
├── input
│ ├── Input.js
│ └── Input.module.scss
├── inputselect
│ ├── InputSelect.js
│ └── InputSelect.module.scss
├── mobileheader
│ ├── MobileHeader.js
│ └── MobileHeader.module.scss
├── mobilemenu
│ ├── MobileMenu.js
│ └── MobileMenu.module.scss
├── modal
│ └── Modal.js
├── pager
│ ├── Pager.js
│ └── Pager.module.scss
├── select
│ ├── Select.js
│ └── Select.module.scss
├── tabs
│ ├── Tabs.js
│ └── Tabs.module.scss
├── tooltip
│ ├── Tooltip.js
│ └── Tooltip.module.scss
├── transaction
│ ├── Transaction.js
│ └── Transaction.module.scss
└── walletpicker
│ ├── WalletPicker.js
│ └── WalletPicker.module.scss
├── containers
├── account
│ ├── Account.js
│ └── Account.module.scss
├── app
│ ├── App.js
│ └── App.module.scss
├── home
│ ├── Home.js
│ └── Home.module.scss
├── modals
│ ├── deposit
│ │ ├── DepositModal.js
│ │ ├── DepositModal.module.scss
│ │ └── steps
│ │ │ ├── ApproveStep.js
│ │ │ └── InputStep.js
│ ├── exit
│ │ ├── ExitModal.js
│ │ ├── ExitModal.module.scss
│ │ └── steps
│ │ │ ├── AddTokenStep.js
│ │ │ ├── DoExitStep.js
│ │ │ └── SelectStep.js
│ ├── ledger
│ │ ├── LedgerConnect.js
│ │ ├── LedgerConnect.module.scss
│ │ ├── LedgerPrompt.js
│ │ └── LedgerPrompt.module.scss
│ ├── merge
│ │ ├── MergeModal.js
│ │ └── MergeModal.module.scss
│ ├── processexit
│ │ ├── ProcessExitsModal.js
│ │ └── ProcessExitsModal.module.scss
│ ├── transfer
│ │ ├── TransferModal.js
│ │ └── TransferModal.module.scss
│ └── wrongnetwork
│ │ ├── WrongNetworkModal.js
│ │ └── WrongNetworkModal.module.scss
├── status
│ ├── Status.js
│ └── Status.module.scss
└── transactions
│ ├── Deposits.js
│ ├── Exits.js
│ ├── Transactions.js
│ └── Transactions.module.scss
├── fonts
├── MessinaSans-Regular.otf
└── MessinaSansMono-Regular.otf
├── images
├── arrow.png
├── boxarrow.svg
├── browserwallet.png
├── chevron.svg
├── close.png
├── coinbase.jpg
├── connect.svg
├── eth.svg
├── key.svg
├── ledger.png
├── ledger_connect.png
├── lock.svg
├── omg_logo.svg
└── walletconnect.png
├── index.js
├── index.module.scss
├── reducers
├── __tests__
│ ├── balanceReducer.test.js
│ ├── depositReducer.test.js
│ ├── exitReducer.test.js
│ ├── feeReducer.test.js
│ ├── gasReducer.test.js
│ ├── loadingReducer.test.js
│ ├── queueReducer.test.js
│ ├── setupReducer.test.js
│ ├── statusReducer.test.js
│ ├── tokenReducer.test.js
│ ├── transactionReducer.test.js
│ └── uiReducer.test.js
├── balanceReducer.js
├── depositReducer.js
├── exitReducer.js
├── feeReducer.js
├── gasReducer.js
├── index.js
├── loadingReducer.js
├── queueReducer.js
├── setupReducer.js
├── statusReducer.js
├── tokenReducer.js
├── transactionReducer.js
└── uiReducer.js
├── selectors
├── balanceSelector.js
├── exitSelector.js
├── feeSelector.js
├── gasSelector.js
├── loadingSelector.js
├── queueSelector.js
├── setupSelector.js
├── statusSelector.js
├── transactionSelector.js
└── uiSelector.js
├── services
├── __mocks__
│ └── networkService.js
├── errorService.js
└── networkService.js
├── store
├── __mocks__
│ └── index.js
└── index.js
└── util
├── __tests__
└── amountConvert.test.js
├── amountConvert.js
├── config.js
├── networkName.js
└── useInterval.js
/.circleci/ci_increase_chart_version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | """
4 | This is the script that would send a dispatch event to the helm chart repo to auto increase chart version.
5 | You can set the UPDATE_DEV flag to decide whether to update to dev too.
6 | For master, we increase the chart version and update dev together. The app version should be short git sha with length 7.
7 | For release, we increase the chart version only. The app version should be semver. (eg. 1.0.3-pre.0)
8 | Required env vars:
9 | - CHART_NAME (eg. webwallet)
10 | - APP_VERSION (eg. 3d75118)
11 | - HELM_CHART_REPO (eg. helm-devlopement)
12 | - UPDATE_DEV (true/false)
13 | - GITHUB_API_TOKEN
14 | """
15 |
16 | set -ex
17 |
18 | [ -z "$CHART_NAME" ] && echo "CHART_NAME should be set" && exit 1
19 | [ -z "$APP_VERSION" ] && echo "APP_VERSION should be set" && exit 1
20 | [ -z "$HELM_CHART_REPO" ] && echo "HELM_CHART_REPO should be set" && exit 1
21 | [ -z "$UPDATE_DEV" ] && echo "UPDATE_DEV should be set" && exit 1
22 | [ -z "$GITHUB_API_TOKEN" ] && echo "GITHUB_API_TOKEN should be set" && exit 1
23 |
24 |
25 | echo "increase chart version: chart [${CHART_NAME}], appVersion: [${APP_VERSION}], update_dev: [${UPDATE_DEV}]"
26 |
27 | curl --location --request POST "https://api.github.com/repos/omgnetwork/${HELM_CHART_REPO}/dispatches" \
28 | --header "Accept: application/vnd.github.v3+json" \
29 | --header "authorization: token ${GITHUB_API_TOKEN}" \
30 | --header "Content-Type: application/json" \
31 | --data-raw " { \
32 | \"event_type\": \"increase-chart-version\", \
33 | \"client_payload\": { \
34 | \"chart_name\": \"${CHART_NAME}\", \
35 | \"app_version\": \"${APP_VERSION}\", \
36 | \"update_dev\": \"${UPDATE_DEV}\" \
37 | } \
38 | }"
39 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | increase_chart_version:
3 | docker:
4 | - image: cimg/base:2020.01
5 | environment:
6 | CHART_NAME: webwallet
7 | HELM_CHART_REPO: helm-development
8 | UPDATE_DEV: true
9 | steps:
10 | - checkout
11 | - run: APP_VERSION="${CIRCLE_TAG}" sh .circleci/ci_increase_chart_version.sh
12 |
13 | release:
14 | docker:
15 | - image: node:15.2.1
16 | steps:
17 | - checkout
18 | - run: npx -y semantic-release@17.2.3
19 | test:
20 | docker:
21 | - image: node:12.16.1-alpine3.11
22 | steps:
23 | - checkout
24 | - run: |
25 | apk update && apk upgrade
26 | apk add --no-cache git openssh make gcc g++ python
27 | - run: npm install --unsafe-perm
28 | - run: npm run audit-check
29 | - run: npm run lint
30 | - run: npm run test
31 | - run: npm run build
32 | orbs:
33 | gcp-gcr: circleci/gcp-gcr@0.8.0
34 | version: 2.1
35 | workflows:
36 | tagged:
37 | jobs:
38 | - gcp-gcr/add-image-tag:
39 | context:
40 | - production-docker-push
41 | filters:
42 | tags:
43 | only: /.*/
44 | branches:
45 | ignore: /.*/
46 | gcloud-service-key: PRODUCTION_DOCKER_GCLOUD_KEY
47 | image: $CIRCLE_PROJECT_REPONAME
48 | source-tag: $CIRCLE_SHA1
49 | target-tag: $CIRCLE_TAG
50 | - increase_chart_version:
51 | filters:
52 | tags:
53 | only: /.*/
54 | branches:
55 | ignore: /.*/
56 | requires:
57 | - gcp-gcr/add-image-tag
58 | untagged:
59 | jobs:
60 | - test:
61 | filters:
62 | tags:
63 | ignore: /.*/
64 | - gcp-gcr/build-and-push-image:
65 | context:
66 | - production-docker-push
67 | filters:
68 | branches:
69 | only: /^master$/
70 | tags:
71 | ignore: /.*/
72 | gcloud-service-key: PRODUCTION_DOCKER_GCLOUD_KEY
73 | image: $CIRCLE_PROJECT_REPONAME
74 | requires:
75 | - test
76 | tag: $CIRCLE_SHA1
77 | - release:
78 | filters:
79 | branches:
80 | only: /^master$/
81 | tags:
82 | ignore: /.*/
83 | requires:
84 | - gcp-gcr/build-and-push-image
85 | version: 2
86 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # add git-ignore syntax here of things you don't want copied into docker image
2 |
3 | .git
4 | *Dockerfile*
5 | *docker-compose*
6 | node_modules
7 | build
8 | .circleci
9 | .nvmrc
10 |
--------------------------------------------------------------------------------
/.env.template:
--------------------------------------------------------------------------------
1 | REACT_APP_WATCHER_URL= https://watcher-info.omg.network
2 | REACT_APP_PLASMA_ADDRESS= 0xplasmaframeworkaddress
3 | REACT_APP_BLOCKEXPLORER_URL= https://blockexplorer.omg.network
4 | REACT_APP_ETHERSCAN_URL= https://ropsten.etherscan.io
5 | REACT_APP_SYNC_INTERVAL= 120
6 | REACT_APP_POLL_INTERVAL= 20
7 | REACT_APP_NETWORK= ropsten
8 |
9 | REACT_APP_ALTERNATE_WALLETS= Mainnet,https://webwallet.mainnet.omg.network|Rinkeby,https://webwallet.rinkeby.omg.network
10 | REACT_APP_SENTRY_DSN= https://sentrydsn.com
11 | REACT_APP_GTM_ID= GTM-XXXXXX
12 | REACT_APP_RPC_PROXY= https://customnode.com
13 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*
2 | node_modules/
3 | public/
4 | .circleci
5 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "eslint:recommended",
4 | "plugin:react/recommended"
5 | ],
6 | "plugins": [
7 | "react"
8 | ],
9 | "env": {
10 | "browser": true,
11 | "node": true,
12 | "jest": true,
13 | "es6": true
14 | },
15 | "rules": {
16 | "eol-last": ["error", "always"],
17 | "object-curly-spacing": ["error", "always"],
18 | "array-bracket-spacing": ["error", "always"],
19 | "space-before-function-paren": ["error", "always"],
20 | "comma-dangle": ["error", "never"],
21 | "semi": ["error", "always"],
22 | "quotes": ["error", "single"],
23 | "no-case-declarations": "off",
24 | "react/prop-types": "off",
25 | "no-unused-vars": "off",
26 | "indent": ["error", 2, { "SwitchCase": 1 }],
27 | "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
28 | "no-trailing-spaces": "error"
29 | },
30 | "parserOptions": {
31 | "ecmaFeatures": {
32 | "jsx": true
33 | },
34 | "ecmaVersion": 11,
35 | "sourceType": "module"
36 | },
37 | "settings": {
38 | "react": {
39 | "pragma": "React",
40 | "version": "detect"
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env
17 | .env.development
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
23 | # generated runtime envs
24 | public/env.js
25 |
26 | # enforce npm
27 | yarn.lock
28 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 12.16.1
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:12.16.1-alpine3.11
2 |
3 | RUN apk update && apk upgrade && \
4 | apk add --no-cache git openssh make gcc g++ python
5 |
6 | RUN addgroup -g 10000 -S omg && \
7 | adduser -u 10000 -S omg -G omg
8 | USER omg
9 | WORKDIR /home/omg
10 | COPY --chown=omg:omg package.json .
11 | COPY --chown=omg:omg package-lock.json .
12 |
13 | RUN npm install
14 |
15 | COPY --chown=omg:omg . .
16 | RUN npm run build
17 |
18 | EXPOSE 3000
19 | CMD npm run serve
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Web Wallet
2 |
3 | [](https://circleci.com/gh/omgnetwork/web-wallet)
4 |
5 | This is an example client side wallet built with React.js which allows you to make interactions with the OMG network from the browser.
6 | To run this application locally, make sure you have a local instance of elixir-omg running or have access to an already deployed network.
7 |
8 | - This example application is using [`omg-js`](https://github.com/omgnetwork/omg-js)
9 | - Requires Node 12.16.1
10 |
11 | ## Initial Setup
12 |
13 | 1. Install dependencies by running `npm install` from the root
14 |
15 | 2. Create a `.env` file in the root and add your configuration. See `.env.template` for an example with fake variables.
16 |
17 | ```env
18 | REACT_APP_WATCHER_URL= the watcher url
19 | REACT_APP_PLASMA_ADDRESS= the plasma framework address
20 | REACT_APP_BLOCKEXPLORER_URL= the block explorer url
21 | REACT_APP_ETHERSCAN_URL= the etherscan url (https://etherscan.io, etc.)
22 | REACT_APP_SYNC_INTERVAL= max number of blocks that watcher has to sync to the child chain before allowing further transactions
23 | REACT_APP_POLL_INTERVAL= number of seconds to poll account data
24 | REACT_APP_NETWORK= the network your environment is on (ropsten, rinkeby, private, main, etc.)
25 | REACT_APP_ALTERNATE_WALLETS= *optional* other web wallets hosted on different envs, follow this format -> name,url|name,url|name,url
26 | REACT_APP_SENTRY_DSN= *optional* sentry dsn handler
27 | REACT_APP_GTM_ID= *optional* google tag manager id (GTM-XXXXXXX)
28 | REACT_APP_RPC_PROXY= *optional, required for WalletConnect support* rpc url for connection to a remote ethereum node
29 | ```
30 |
31 | 3. Make sure you are using the correct version of Node
32 |
33 | 4. Start the app by running `npm run start` from the root directory.
34 |
35 | ## Running the wallet locally
36 |
37 | Open up your browser and navigate to `http://localhost:3000`.
38 |
39 | From here, you can perform these actions:
40 |
41 | 1. Deposit into the OMG Network.
42 |
43 | 2. Transfer funds on the OMG Network.
44 |
45 | 3. Exit your funds back to the Rootchain.
46 |
47 | 4. Process exits to receive your funds back on the Rootchain.
48 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src"
4 | },
5 | "include": ["src"]
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web-wallet",
3 | "version": "1.0.0",
4 | "private": true,
5 | "engines": {
6 | "node": ">=12.16.1"
7 | },
8 | "dependencies": {
9 | "@ledgerhq/hw-app-eth": "^5.27.2",
10 | "@ledgerhq/hw-transport-webusb": "^5.23.0",
11 | "@material-ui/core": "^4.8.3",
12 | "@material-ui/icons": "^4.5.1",
13 | "@material-ui/lab": "^4.0.0-alpha.39",
14 | "@metamask/legacy-web3": "^2.0.0",
15 | "@omisego/omg-js": "^4.1.2-1.0.4",
16 | "@sentry/react": "^5.21.4",
17 | "@walletconnect/web3-provider": "^1.3.6",
18 | "axios": "^0.21.1",
19 | "bignumber.js": "^9.0.0",
20 | "bn.js": "^5.1.1",
21 | "buffer": "^5.6.0",
22 | "elliptic": "^6.5.3",
23 | "eth-sig-util": "^2.5.3",
24 | "ethereumjs-abi": "^0.6.8",
25 | "ethereumjs-util": "^7.0.5",
26 | "human-standard-token-abi": "^2.0.0",
27 | "json5": "^2.1.2",
28 | "lodash": "^4.17.20",
29 | "moment": "^2.24.0",
30 | "node-sass": "^4.13.0",
31 | "numbro": "^2.1.2",
32 | "omg-json-bigint": "^1.0.0",
33 | "react": "^16.12.0",
34 | "react-copy-to-clipboard": "^5.0.2",
35 | "react-dom": "^16.12.0",
36 | "react-gtm-module": "^2.0.8",
37 | "react-redux": "^7.1.3",
38 | "react-scripts": "^4.0.3",
39 | "redux": "^4.0.5",
40 | "redux-devtools-extension": "^2.13.8",
41 | "redux-mock-store": "^1.5.4",
42 | "redux-thunk": "^2.3.0",
43 | "serve": "^11.3.2",
44 | "truncate-middle": "^1.0.6",
45 | "walletlink": "^2.0.2",
46 | "web3": "1.3.4"
47 | },
48 | "scripts": {
49 | "preinstall": "npx npm-force-resolutions",
50 | "buildenv-dev": "react-env",
51 | "buildenv-prod": "NODE_ENV=production react-env --dest build",
52 | "serve": "npm run buildenv-prod && serve -s build -l 3000 -c public/serve.json",
53 | "start": "npm run buildenv-dev && react-scripts start",
54 | "build": "GENERATE_SOURCEMAP=false react-scripts build",
55 | "lint": "eslint . --ext .js,.jsx",
56 | "test": "react-scripts test --watchAll=false",
57 | "test:coverage": "npm run test --coverage",
58 | "audit-check": "audit-ci --moderate"
59 | },
60 | "eslintConfig": {
61 | "extends": "react-app"
62 | },
63 | "browserslist": {
64 | "production": [
65 | ">0.2%",
66 | "not dead",
67 | "not op_mini all"
68 | ],
69 | "development": [
70 | "last 1 chrome version",
71 | "last 1 firefox version",
72 | "last 1 safari version"
73 | ]
74 | },
75 | "devDependencies": {
76 | "@beam-australia/react-env": "2.1.2",
77 | "audit-ci": "^3.1.1"
78 | },
79 | "resolutions": {
80 | "http-proxy": "^1.18.1",
81 | "elliptic": "^6.5.3",
82 | "object-path": "^0.11.5",
83 | "node-forge": "^0.10.0"
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/public/ether.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/public/ether.png
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/public/favicon.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 | OMG Network | Web Wallet
16 |
17 |
18 |
19 | You need to enable JavaScript to run this app.
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "OMG Network | Web Wallet",
3 | "name": "OMG Network | Web Wallet",
4 | "icons": [
5 | {
6 | "src": "favicon.png",
7 | "type": "image/png",
8 | "sizes": "236x236"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/public/omg_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/public/serve.json:
--------------------------------------------------------------------------------
1 | {
2 | "headers": [
3 | {
4 | "source": "*",
5 | "headers": [
6 | {
7 | "key": "X-Frame-Options",
8 | "value": "SAMEORIGIN"
9 | },
10 | {
11 | "key": "Strict-Transport-Security",
12 | "value": "max-age=15552000; includeSubDomains"
13 | },
14 | {
15 | "key": "X-Content-Type-Options",
16 | "value": "nosniff"
17 | },
18 | {
19 | "key": "X-XSS-Protection",
20 | "value": "1; mode=block"
21 | },
22 | {
23 | "key": "Feature-Policy",
24 | "value": "geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; vibrate 'none'; fullscreen 'self'; payment 'none';"
25 | },
26 | {
27 | "key": "Referrer-Policy",
28 | "value": "no-referrer"
29 | }
30 | ]
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/src/actions/__tests__/createAction.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { createAction } from 'actions/createAction';
17 | import store from 'store';
18 |
19 | jest.mock('store');
20 | jest.mock('services/networkService');
21 |
22 | function fakeAsyncRequestSuccess () {
23 | return Promise.resolve('toto-success');
24 | }
25 |
26 | function fakeAsyncRequestFailure () {
27 | return Promise.reject(Error('toto-failed'));
28 | }
29 |
30 | describe('createAction', () => {
31 | beforeEach(() => {
32 | store.clearActions();
33 | jest.clearAllMocks();
34 | });
35 |
36 | it('should return false to caller on async failure', async () => {
37 | const res = await store.dispatch(
38 | createAction('TEST/GET', () => fakeAsyncRequestFailure())
39 | );
40 | expect(res).toBe(false);
41 | });
42 |
43 | it('should return true to caller on async success', async () => {
44 | const res = await store.dispatch(
45 | createAction('TEST/GET', () => fakeAsyncRequestSuccess())
46 | );
47 | expect(res).toBe(true);
48 | });
49 |
50 | it('should dispatch request/success on successful async call', async () => {
51 | const expectedActions = [
52 | { type: 'TEST/GET/REQUEST' },
53 | { type: 'TEST/GET/SUCCESS', payload: 'toto-success' }
54 | ];
55 | await store.dispatch(
56 | createAction('TEST/GET', () => fakeAsyncRequestSuccess())
57 | );
58 | expect(store.getActions()).toEqual(expectedActions);
59 | });
60 |
61 | it('should dispatch request/error/uiError on failure of async call', async () => {
62 | const expectedActions = [
63 | { type: 'TEST/GET/REQUEST' },
64 | { type: 'TEST/GET/ERROR' },
65 | { type: 'UI/ERROR/UPDATE', payload: 'Something went wrong' }
66 | ];
67 | await store.dispatch(
68 | createAction('TEST/GET', () => fakeAsyncRequestFailure())
69 | );
70 | expect(store.getActions()).toEqual(expectedActions);
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/src/actions/__tests__/setupAction.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import * as actions from 'actions/setupAction';
17 | import store from 'store';
18 |
19 | jest.mock('store');
20 |
21 | describe('setupActions', () => {
22 | beforeEach(() => {
23 | store.clearActions();
24 | jest.clearAllMocks();
25 | });
26 |
27 | it('should dispatch correct actions on setWalletMethod', async () => {
28 | const expectedActions = [ { type: 'SETUP/WALLET_METHOD/SET', payload: 'WalletLink' } ];
29 | await store.dispatch(actions.setWalletMethod('WalletLink'));
30 | expect(store.getActions()).toEqual(expectedActions);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/actions/__tests__/tokenAction.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { getToken } from 'actions/tokenAction';
17 | import networkService from 'services/networkService';
18 | import store from 'store';
19 |
20 | jest.mock('services/networkService');
21 | jest.mock('store');
22 |
23 | describe('tokenAction', () => {
24 | beforeEach(() => {
25 | store.clearActions();
26 | jest.clearAllMocks();
27 | });
28 |
29 | it('should return token information using getToken', async () => {
30 | const tokenInfo = await getToken('0x123');
31 | // expect(networkService.web3.eth.Contract).toHaveBeenCalled();
32 | expect(tokenInfo).toEqual({
33 | currency: '0x123',
34 | decimals: 18,
35 | name: 'OMG'
36 | });
37 | });
38 |
39 | it('should return early if token info already fetched', async () => {
40 | await getToken('0x0000000000000000000000000000000000000000');
41 | // expect(networkService.web3.eth.Contract).not.toHaveBeenCalled();
42 | expect(store.getActions()).toEqual([]);
43 | });
44 |
45 | it('should dispatch token success using getToken', async () => {
46 | await getToken('0x123');
47 | const expectedActions = [ {
48 | type: 'TOKEN/GET/SUCCESS',
49 | payload: {
50 | currency: '0x123',
51 | decimals: 18,
52 | name: 'OMG'
53 | }
54 | } ];
55 | expect(store.getActions()).toEqual(expectedActions);
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/src/actions/__tests__/uiAction.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import * as actions from 'actions/uiAction';
17 | import store from 'store';
18 |
19 | jest.mock('store');
20 |
21 | describe('uiActions', () => {
22 | beforeEach(() => {
23 | store.clearActions();
24 | jest.clearAllMocks();
25 | });
26 |
27 | it('should dispatch correct actions on openModal', async () => {
28 | const expectedActions = [ { type: 'UI/MODAL/OPEN', payload: 'toto' } ];
29 | await store.dispatch(actions.openModal('toto'));
30 | expect(store.getActions()).toEqual(expectedActions);
31 | });
32 |
33 | it('should dispatch correct actions on closeModal', async () => {
34 | const expectedActions = [ { type: 'UI/MODAL/CLOSE', payload: 'toto' } ];
35 | await store.dispatch(actions.closeModal('toto'));
36 | expect(store.getActions()).toEqual(expectedActions);
37 | });
38 |
39 | it('should dispatch correct actions on openAlert', async () => {
40 | const expectedActions = [ { type: 'UI/ALERT/UPDATE', payload: 'toto' } ];
41 | await store.dispatch(actions.openAlert('toto'));
42 | expect(store.getActions()).toEqual(expectedActions);
43 | });
44 |
45 | it('should dispatch correct actions on closeAlert', async () => {
46 | const expectedActions = [ { type: 'UI/ALERT/UPDATE', payload: null } ];
47 | await store.dispatch(actions.closeAlert());
48 | expect(store.getActions()).toEqual(expectedActions);
49 | });
50 |
51 | it('should dispatch correct actions on openError', async () => {
52 | const expectedActions = [ { type: 'UI/ERROR/UPDATE', payload: 'toto' } ];
53 | await store.dispatch(actions.openError('toto'));
54 | expect(store.getActions()).toEqual(expectedActions);
55 | });
56 |
57 | it('should dispatch correct actions on closeError', async () => {
58 | const expectedActions = [ { type: 'UI/ERROR/UPDATE', payload: null } ];
59 | await store.dispatch(actions.closeError());
60 | expect(store.getActions()).toEqual(expectedActions);
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/src/actions/createAction.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { WebWalletError } from 'services/errorService';
17 |
18 | export function createAction (key, asyncAction) {
19 | return async function (dispatch) {
20 | dispatch({ type: `${key}/REQUEST` });
21 | try {
22 | const response = await asyncAction();
23 | dispatch({ type: `${key}/SUCCESS`, payload: response });
24 | return true;
25 | } catch (error) {
26 | // cancel request loading state
27 | dispatch({ type: `${key}/ERROR` });
28 |
29 | const _error = error instanceof WebWalletError
30 | ? error
31 | : new WebWalletError({
32 | originalError: error,
33 | customErrorMessage: 'Something went wrong',
34 | reportToSentry: true,
35 | reportToUi: true
36 | });
37 |
38 | // perform necessary reports
39 | _error.report(dispatch);
40 | return false;
41 | }
42 | };
43 | }
44 |
--------------------------------------------------------------------------------
/src/actions/setupAction.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function setWalletMethod (methodName) {
17 | return function (dispatch) {
18 | return dispatch({ type: 'SETUP/WALLET_METHOD/SET', payload: methodName });
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/actions/tokenAction.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import erc20abi from 'human-standard-token-abi';
17 | import networkService from 'services/networkService';
18 | import truncate from 'truncate-middle';
19 | import store from 'store';
20 |
21 | export async function getToken (_currency) {
22 | const currency = _currency.toLowerCase();
23 |
24 | const state = store.getState();
25 | if (state.token[currency]) {
26 | return state.token[currency];
27 | }
28 |
29 | const tokenContract = new networkService.web3.eth.Contract(erc20abi, currency);
30 |
31 | //this breaks web3.js 1.3.4
32 | //const callOptions = { from: currency };
33 | //tokenContract.methods.symbol().call(callOptions) will fail
34 |
35 | const [ _name, _decimals ] = await Promise.all([
36 | tokenContract.methods.symbol().call(),
37 | tokenContract.methods.decimals().call()
38 | ]).catch(e => [ null, null ]);
39 |
40 | const decimals = _decimals ? Number(_decimals.toString()) : 0;
41 | const name = _name || truncate(currency, 6, 4, '...');
42 |
43 | const tokenInfo = {
44 | currency,
45 | decimals,
46 | name
47 | };
48 |
49 | store.dispatch({
50 | type: 'TOKEN/GET/SUCCESS',
51 | payload: tokenInfo
52 | });
53 | return tokenInfo;
54 | }
55 |
--------------------------------------------------------------------------------
/src/actions/uiAction.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function openModal (modal) {
17 | return function (dispatch) {
18 | return dispatch({ type: 'UI/MODAL/OPEN', payload: modal });
19 | };
20 | }
21 |
22 | export function closeModal (modal) {
23 | return function (dispatch) {
24 | return dispatch({ type: 'UI/MODAL/CLOSE', payload: modal });
25 | };
26 | }
27 |
28 | export function openAlert (message) {
29 | return function (dispatch) {
30 | return dispatch({ type: 'UI/ALERT/UPDATE', payload: message });
31 | };
32 | }
33 |
34 | export function closeAlert () {
35 | return function (dispatch) {
36 | return dispatch({ type: 'UI/ALERT/UPDATE', payload: null });
37 | };
38 | }
39 |
40 | export function openError (message) {
41 | return function (dispatch) {
42 | return dispatch({ type: 'UI/ERROR/UPDATE', payload: message });
43 | };
44 | }
45 |
46 | export function closeError () {
47 | return function (dispatch) {
48 | return dispatch({ type: 'UI/ERROR/UPDATE', payload: null });
49 | };
50 | }
51 |
52 | export function ledgerConnect (derivation) {
53 | return function (dispatch) {
54 | return dispatch({ type: 'UI/LEDGER/UPDATE', payload: derivation });
55 | };
56 | }
57 |
58 | export function setActiveHistoryTab (tab) {
59 | return function (dispatch) {
60 | return dispatch({ type: 'UI/HISTORYTAB/UPDATE', payload: tab });
61 | };
62 | }
63 |
--------------------------------------------------------------------------------
/src/components/alert/Alert.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { Snackbar } from '@material-ui/core';
18 | import MuiAlert from '@material-ui/lab/Alert';
19 |
20 | function _Alert ({ children, open, onClose, type = 'success', duration = 3000 }) {
21 | function Alert (props) {
22 | return ;
23 | }
24 |
25 | return (
26 |
35 |
36 | {children}
37 |
38 |
39 | );
40 | }
41 |
42 | export default _Alert;
43 |
--------------------------------------------------------------------------------
/src/components/alert/Alert.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 |
--------------------------------------------------------------------------------
/src/components/button/Button.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { CircularProgress } from '@material-ui/core';
18 |
19 | import Tooltip from 'components/tooltip/Tooltip';
20 |
21 | import * as styles from './Button.module.scss';
22 |
23 | function Button ({
24 | children,
25 | style,
26 | onClick,
27 | type,
28 | disabled,
29 | loading,
30 | tooltip = '',
31 | className
32 | }) {
33 | return (
34 |
47 | {children}
48 | {loading && (
49 |
50 |
51 |
52 |
53 |
54 | )}
55 |
56 | );
57 | }
58 |
59 | export default React.memo(Button);
60 |
--------------------------------------------------------------------------------
/src/components/button/Button.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Button {
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | color: $gray6;
8 | padding: 15px;
9 | flex: 1;
10 | cursor: pointer;
11 | transition: all 200ms ease-in-out;
12 | min-width: 150px;
13 | @include mobile {
14 | min-width: 100px;
15 | }
16 | }
17 |
18 | .primary {
19 | background-color: $blue;
20 | }
21 |
22 | .secondary {
23 | background-color: $gray4;
24 | }
25 |
26 | .outline {
27 | border: 2px solid $gray4;
28 | }
29 |
30 | .disabled {
31 | filter: brightness(50%);
32 | cursor: initial;
33 | }
34 |
35 | .loading {
36 | margin: 0 -20px 0 10px !important;
37 | }
--------------------------------------------------------------------------------
/src/components/copy/Copy.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState } from 'react';
17 | import { CopyToClipboard } from 'react-copy-to-clipboard';
18 | import { FileCopyOutlined } from '@material-ui/icons';
19 |
20 | import Alert from 'components/alert/Alert';
21 |
22 | import * as styles from './Copy.module.scss';
23 |
24 | function Copy ({ value, light }) {
25 | const [ open, setOpen ] = useState(false);
26 |
27 | return (
28 |
29 |
setOpen(true)}
32 | >
33 |
38 |
39 |
40 |
41 |
setOpen(false)}>
42 | Copied to clipboard!
43 |
44 |
45 | );
46 | }
47 |
48 | export default React.memo(Copy);
49 |
--------------------------------------------------------------------------------
/src/components/copy/Copy.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Copy {
4 | .icon {
5 | cursor: pointer;
6 | background-color: $gray3;
7 | border-radius: 100%;
8 | width: 25px;
9 | height: 25px;
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 |
14 | svg {
15 | width: 12px;
16 | height: 12px;
17 | }
18 | }
19 |
20 | .light {
21 | background-color: $gray3;
22 | color: $gray6;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/gaspicker/GasPicker.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useEffect } from 'react';
17 | import { useSelector } from 'react-redux';
18 |
19 | import { selectGas } from 'selectors/gasSelector';
20 |
21 | import * as styles from './GasPicker.module.scss';
22 |
23 | function GasPicker ({ selectedSpeed, setSelectedSpeed, setGasPrice }) {
24 | const gas = useSelector(selectGas);
25 |
26 | useEffect(() => {
27 | setGasPrice(gas[selectedSpeed]);
28 | }, [ selectedSpeed, gas, setGasPrice ]);
29 |
30 | return (
31 |
32 |
33 | Gas Fee
34 |
35 |
36 |
37 |
setSelectedSpeed('slow')}
39 | className={[
40 | styles.category,
41 | selectedSpeed === 'slow' ? styles.selected : ''
42 | ].join(' ')}
43 | >
44 |
Slow
45 |
{gas.slow / 1000000000} gwei
46 |
47 |
48 |
setSelectedSpeed('normal')}
50 | className={[
51 | styles.category,
52 | selectedSpeed === 'normal' ? styles.selected : ''
53 | ].join(' ')}
54 | >
55 |
Normal
56 |
{gas.normal / 1000000000} gwei
57 |
58 |
59 |
setSelectedSpeed('fast')}
61 | className={[
62 | styles.category,
63 | selectedSpeed === 'fast' ? styles.selected : ''
64 | ].join(' ')}
65 | >
66 |
Fast
67 |
{gas.fast / 1000000000} gwei
68 |
69 |
70 |
71 | );
72 | }
73 |
74 | export default React.memo(GasPicker);
75 |
--------------------------------------------------------------------------------
/src/components/gaspicker/GasPicker.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .GasPicker {
4 | display: flex;
5 | flex-direction: column;
6 |
7 | .label {
8 | margin-bottom: 10px;
9 | }
10 |
11 | .items {
12 | display: flex;
13 | flex-direction: row;
14 | justify-content: space-between;
15 |
16 | .category {
17 | display: flex;
18 | cursor: pointer;
19 | flex: 1;
20 | margin-right: 10px;
21 | flex-direction: column;
22 | justify-content: center;
23 | transition: all 100ms ease-in-out;
24 | padding: 10px;
25 | color: $gray5;
26 | border: 2px solid $gray4;
27 | .title {
28 | font-weight: bold;
29 | color: $gray6;
30 | padding-bottom: 5px;
31 | }
32 | &:last-child {
33 | margin-right: 0px;
34 | }
35 | }
36 |
37 | .selected {
38 | background-color: $gray3;
39 | border: 2px solid $blue;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/hamburger/Hamburger.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import * as styles from './Hamburger.module.scss';
4 |
5 | function Hamburger ({ hamburgerClick, isOpen, className }) {
6 | return (
7 | hamburgerClick()} className={className}>
8 |
15 |
22 |
29 |
30 | );
31 | }
32 |
33 | export default Hamburger;
34 |
--------------------------------------------------------------------------------
/src/components/hamburger/Hamburger.module.scss:
--------------------------------------------------------------------------------
1 | .xline {
2 | height: 2px;
3 | width: 20px;
4 | background-color: white;
5 | margin: 5px 0;
6 | transition: all 250ms ease-in-out;
7 | }
8 |
9 | .xline1 {
10 | transform-origin: top left;
11 | &.open {
12 | transform: rotate(45deg) translateY(0px);
13 | }
14 | &.closed {
15 | transform: initial;
16 | }
17 | }
18 |
19 | .xline2 {
20 | &.open {
21 | opacity: 0;
22 | }
23 | &.closed {
24 | opacity: 1;
25 | }
26 | }
27 |
28 | .xline3 {
29 | transform-origin: bottom left;
30 | &.open {
31 | transform: rotate(-45deg) translateY(0px);
32 | }
33 | &.closed {
34 | transform: initial;
35 | }
36 | }
--------------------------------------------------------------------------------
/src/components/info/Info.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 |
18 | import * as styles from './Info.module.scss';
19 |
20 | function Info ({ data }) {
21 | return (
22 |
23 | {data.map((i, index) => (
24 |
25 | {i.header && (
26 |
{i.header}
27 | )}
28 |
29 |
30 | {i.title}
31 |
32 | {i.value}
33 |
34 |
35 | ))}
36 |
37 | );
38 | }
39 |
40 | export default Info;
41 |
--------------------------------------------------------------------------------
/src/components/info/Info.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Info {
4 | display: flex;
5 | flex-direction: column;
6 |
7 | .header {
8 | padding-bottom: 10px;
9 | font-family: 'Messina';
10 | }
11 |
12 | .item {
13 | display: flex;
14 | flex-direction: row;
15 | align-items: center;
16 | word-break: break-word;
17 | justify-content: space-between;
18 | padding-bottom: 15px;
19 | margin-bottom: 15px;
20 | border-bottom: 1px solid $gray3;
21 | span:last-child {
22 | margin-left: 10px;
23 | }
24 | .headerFont {
25 | font-family: 'Messina';
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/components/input/Input.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { Search } from '@material-ui/icons';
18 | import BN from 'bignumber.js';
19 |
20 | import * as styles from './Input.module.scss';
21 |
22 | function Input ({
23 | placeholder,
24 | label,
25 | type = 'text',
26 | icon,
27 | unit,
28 | value,
29 | onChange,
30 | paste,
31 | className,
32 | maxValue
33 | }) {
34 | async function handlePaste () {
35 | try {
36 | const text = await navigator.clipboard.readText();
37 | if (text) {
38 | onChange({ target: { value: text } });
39 | }
40 | } catch (err) {
41 | // navigator clipboard api not supported in client browser
42 | }
43 | }
44 |
45 | function handleMaxClick () {
46 | onChange({ target: { value: maxValue } });
47 | }
48 |
49 | const overMax = new BN(value).gt(new BN(maxValue));
50 |
51 | return (
52 |
53 | {label &&
{label}
}
54 |
60 | {icon &&
}
61 |
68 | {unit && (
69 |
70 | {maxValue && (value !== maxValue) && (
71 |
75 | MAX
76 |
77 | )}
78 | {unit}
79 |
80 | )}
81 | {paste && (
82 |
83 | Paste
84 |
85 | )}
86 |
87 |
88 | );
89 | }
90 |
91 | export default React.memo(Input);
92 |
--------------------------------------------------------------------------------
/src/components/input/Input.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Input {
4 | display: flex;
5 | flex-direction: column;
6 | margin-bottom: 10px;
7 |
8 | .label {
9 | font-size: 1em;
10 | margin-bottom: 10px;
11 | }
12 |
13 | .field {
14 | position: relative;
15 | padding: 10px;
16 | border: 2px solid $gray4;
17 | transition: all 200ms ease-in-out;
18 | display: flex;
19 | flex-direction: row;
20 | align-items: center;
21 | &:focus-within {
22 | border: 2px solid $blue;
23 | }
24 | .icon {
25 | margin-right: 10px;
26 | }
27 | .input {
28 | flex: 1;
29 | background-color: $gray3;
30 | color: $gray6;
31 | }
32 | .unit {
33 | margin: 0 10px;
34 | position: absolute;
35 | right: 0;
36 | background-color: $gray3;
37 | display: flex;
38 | flex-direction: row;
39 | align-items: center;
40 | }
41 | .paste {
42 | color: $blue;
43 | margin-left: 10px;
44 | cursor: pointer;
45 | }
46 | &.error {
47 | border: 2px solid $red;
48 | color: $red;
49 | .input {
50 | color: $red;
51 | }
52 | }
53 | }
54 | }
55 |
56 | .maxValue {
57 | background-color: $blue;
58 | opacity: 0.8;
59 | color: white;
60 | padding: 3px 7px;
61 | font-size: 12px;
62 | border-radius: 4px;
63 | margin-right: 10px;
64 | z-index: 1;
65 | cursor: pointer;
66 | transition: all 150ms ease-in-out;
67 | &:active {
68 | opacity: 0.5;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/components/inputselect/InputSelect.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { KeyboardArrowDown } from '@material-ui/icons';
18 | import Input from 'components/input/Input';
19 |
20 | import * as styles from './InputSelect.module.scss';
21 |
22 | function InputSelect ({
23 | placeholder,
24 | label,
25 | value,
26 | onChange,
27 | selectOptions,
28 | onSelect,
29 | selectValue,
30 | maxValue
31 | }) {
32 | const selected = selectOptions.find(i => i.value === selectValue);
33 |
34 | const renderUnit = (
35 |
36 |
41 | {selectOptions.map((i, index) => (
42 |
46 | {i.title} - {i.subTitle}
47 |
48 | ))}
49 |
50 |
51 |
52 |
{selected ? selected.title : ''}
53 |
{selected ? selected.subTitle : ''}
54 |
55 |
56 |
57 |
58 | );
59 |
60 | return (
61 |
70 | );
71 | }
72 |
73 | export default React.memo(InputSelect);
74 |
--------------------------------------------------------------------------------
/src/components/inputselect/InputSelect.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .selectContainer {
4 | height: 46px;
5 | margin: -10px -10px -10px 0;
6 | position: relative;
7 |
8 | .select {
9 | border: none;
10 | outline: none;
11 | border-radius: 0;
12 | padding-right: 10px;
13 | -webkit-appearance: none;
14 | -webkit-border-radius: 0px;
15 | background-color: $gray3;
16 | color: $gray3;
17 | position: absolute;
18 | right: 0;
19 | top: 0;
20 | bottom: 0;
21 | opacity: 0;
22 | }
23 |
24 | .selected {
25 | flex: 1;
26 | display: flex;
27 | flex-direction: row;
28 | justify-content: flex-end;
29 | align-items: center;
30 | height: 46px;
31 | margin-right: 10px;
32 |
33 | .details {
34 | text-align: right;
35 | margin-right: 10px;
36 | font-size: 0.9em;
37 | .subTitle {
38 | font-size: 0.7em;
39 | white-space: nowrap;
40 | }
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/components/mobileheader/MobileHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import logo from 'images/omg_logo.svg';
4 |
5 | import Hamburger from 'components/hamburger/Hamburger';
6 | import * as styles from './MobileHeader.module.scss';
7 |
8 | function MobileHeader ({ mobileMenuOpen, onHamburgerClick }) {
9 | return (
10 |
11 |
12 |
16 |
17 | );
18 | }
19 |
20 | export default MobileHeader;
21 |
--------------------------------------------------------------------------------
/src/components/mobileheader/MobileHeader.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .MobileHeader {
4 | display: none;
5 | flex-direction: row;
6 | justify-content: space-between;
7 | background-color: $gray1;
8 | align-items: center;
9 | margin-bottom: 15px;
10 |
11 | @include mobile {
12 | display: flex;
13 | }
14 | .logo {
15 | height: 30px;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/mobilemenu/MobileMenu.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Status from 'containers/status/Status';
4 |
5 | import * as styles from './MobileMenu.module.scss';
6 |
7 | function MobileMenu ({ mobileMenuOpen }) {
8 | return (
9 |
15 | );
16 | }
17 |
18 | export default MobileMenu;
19 |
--------------------------------------------------------------------------------
/src/components/mobilemenu/MobileMenu.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .menu {
4 | background-color: $gray1;
5 | padding: 15px;
6 | position: fixed;
7 | top: 60px;
8 | bottom: 0;
9 | left: 0;
10 | right: 0;
11 | display: none;
12 | max-width: initial;
13 | z-index: 2;
14 | &.open {
15 | display: flex;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/modal/Modal.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { makeStyles } from '@material-ui/core/styles';
18 | import {
19 | Modal,
20 | Backdrop,
21 | Fade
22 | } from '@material-ui/core';
23 |
24 | // Renamed due to https://github.com/facebook/create-react-app/issues/10047
25 | import { gray6, gray3, gray1 } from 'index.module.scss';
26 |
27 | const useStyles = makeStyles({
28 | modal: {
29 | display: 'flex',
30 | alignItems: 'center',
31 | justifyContent: 'center',
32 | outline: 'none'
33 | },
34 | paper: {
35 | backgroundColor: gray3,
36 | padding: '20px',
37 | border: 'none',
38 | outline: 'none',
39 | width: '500px',
40 | boxSizing: 'border-box',
41 | maxWidth: '100%'
42 | },
43 | light: {
44 | backgroundColor: gray6,
45 | color: gray1,
46 | borderRadius: '4px'
47 | }
48 | });
49 |
50 | function _Modal ({
51 | children,
52 | open,
53 | onClose,
54 | light
55 | }) {
56 | const classes = useStyles();
57 |
58 | return (
59 |
71 |
72 |
78 | {children}
79 |
80 |
81 |
82 | );
83 | }
84 |
85 | export default _Modal;
86 |
--------------------------------------------------------------------------------
/src/components/pager/Pager.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { NavigateNext, NavigateBefore } from '@material-ui/icons';
18 |
19 | import * as styles from './Pager.module.scss';
20 |
21 | function Pager ({ currentPage, isLastPage, onClickNext, onClickBack }) {
22 | return (
23 |
24 |
{`Page ${currentPage}`}
25 |
32 |
33 |
34 |
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default Pager;
48 |
--------------------------------------------------------------------------------
/src/components/pager/Pager.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Pager {
4 | display: flex;
5 | flex-direction: row;
6 | justify-content: flex-end;
7 | align-items: center;
8 | margin-bottom: 20px;
9 |
10 | .number {
11 | font-size: 0.8em;
12 | margin-right: 10px;
13 | }
14 |
15 | .box {
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | height: 20px;
20 | margin-left: 3px;
21 | transition: all 200ms ease-in-out;
22 | cursor: pointer;
23 | }
24 |
25 | .disabled {
26 | pointer-events: none;
27 | cursor: initial;
28 | opacity: 0.5;
29 | }
30 | }
--------------------------------------------------------------------------------
/src/components/select/Select.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import * as styles from './Select.module.scss';
18 |
19 | function Select ({
20 | label,
21 | value,
22 | options,
23 | onSelect,
24 | loading,
25 | error = '',
26 | className
27 | }) {
28 | const selected = options.find(i => i.value === value);
29 |
30 | function renderOption (i) {
31 | if (i.title && i.subTitle) {
32 | return `${i.title} - ${i.subTitle}`;
33 | }
34 | if (i.title && !i.subTitle) {
35 | return i.title;
36 | }
37 | if (i.subTitle && !i.title) {
38 | return i.subTitle;
39 | }
40 | }
41 |
42 | const renderLoading = (
43 |
44 | Loading...
45 |
46 | );
47 |
48 | const renderSelect = (
49 | <>
50 |
55 | {options.map((i, index) => (
56 |
60 | {renderOption(i)}
61 |
62 | ))}
63 |
64 |
65 |
66 |
{selected ? selected.title : error}
67 |
{selected ? selected.subTitle : ''}
68 |
69 |
70 | >
71 | );
72 |
73 | return (
74 |
80 | {label &&
{label}
}
81 |
82 | {loading ? renderLoading : renderSelect}
83 |
84 |
85 | );
86 | }
87 |
88 | export default React.memo(Select);
89 |
--------------------------------------------------------------------------------
/src/components/select/Select.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Select {
4 | display: flex;
5 | flex-direction: column;
6 | margin-bottom: 10px;
7 |
8 | .label {
9 | margin-bottom: 10px;
10 | }
11 |
12 | .field {
13 | position: relative;
14 | border: 2px solid $gray4;
15 | transition: all 200ms ease-in-out;
16 | display: flex;
17 | flex-direction: row;
18 | align-items: center;
19 | }
20 |
21 | .select {
22 | border: none;
23 | outline: none;
24 | border-radius: 0;
25 | padding-right: 10px;
26 | -webkit-appearance: none;
27 | -webkit-border-radius: 0px;
28 | background-color: $gray3;
29 | color: $gray3;
30 | position: absolute;
31 | left: 0;
32 | top: 0;
33 | bottom: 0;
34 | opacity: 0;
35 | }
36 |
37 | .selected {
38 | flex: 1;
39 | display: flex;
40 | flex-direction: row;
41 | align-items: center;
42 | height: 50px;
43 | margin-left: 10px;
44 |
45 | .details {
46 | text-align: left;
47 | margin-right: 10px;
48 | font-size: 0.9em;
49 | .subTitle {
50 | font-size: 0.7em;
51 | white-space: nowrap;
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/src/components/tabs/Tabs.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 |
18 | import * as styles from './Tabs.module.scss';
19 |
20 | function Tabs ({ tabs, activeTab, onClick, className }) {
21 | return (
22 |
23 | {tabs.map((i, index) => {
24 | return (
25 |
onClick(i)}
28 | className={[
29 | styles.tab,
30 | activeTab === i ? styles.active : ''
31 | ].join(' ')}
32 | >
33 | {i}
34 |
35 | );
36 | })}
37 |
38 | );
39 | }
40 |
41 | export default React.memo(Tabs);
42 |
--------------------------------------------------------------------------------
/src/components/tabs/Tabs.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Tabs {
4 | display: flex;
5 | flex-direction: row;
6 | justify-content: flex-start;
7 | border-bottom: 2px solid $gray4;
8 | flex: 1;
9 | margin-bottom: 20px;
10 |
11 | .tab {
12 | color: $gray5;
13 | transition: color 200ms ease-in-out;
14 | cursor: pointer;
15 | margin-right: 20px;
16 | padding-bottom: 10px;
17 | }
18 |
19 | .active {
20 | color: $gray6;
21 | border-bottom: 2px solid $gray6;
22 | margin-bottom: -2px;
23 | z-index: 1;
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/components/tooltip/Tooltip.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Tooltip as MuiTooltip } from '@material-ui/core';
3 |
4 | import * as styles from './Tooltip.module.scss';
5 |
6 | function Tooltip ({
7 | title,
8 | arrow = true,
9 | children
10 | }) {
11 | return (
12 |
15 | {title}
16 |
17 | }
18 | arrow={arrow}
19 | >
20 | {children}
21 |
22 | );
23 | }
24 |
25 | export default React.memo(Tooltip);
26 |
--------------------------------------------------------------------------------
/src/components/tooltip/Tooltip.module.scss:
--------------------------------------------------------------------------------
1 | .title {
2 | font-size: 14px;
3 | padding: 10px;
4 | }
5 |
--------------------------------------------------------------------------------
/src/components/transaction/Transaction.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 |
18 | import Tooltip from 'components/tooltip/Tooltip';
19 |
20 | import * as styles from './Transaction.module.scss';
21 |
22 | function Transaction ({
23 | link,
24 | status,
25 | statusPercentage,
26 | subStatus,
27 | button,
28 | title,
29 | midTitle,
30 | subTitle,
31 | tooltip = ''
32 | }) {
33 | function renderValue () {
34 | if (button) {
35 | return (
36 |
37 |
41 | {button.text}
42 |
43 |
{subStatus}
44 |
45 | );
46 | }
47 | return (
48 |
49 |
50 |
58 |
{status}
59 | {status === 'Pending' && !!statusPercentage && (
60 |
61 |
62 | {`(${Math.max(statusPercentage, 0)}%)`}
63 |
64 |
65 | )}
66 |
67 |
{subStatus}
68 |
69 | );
70 | }
71 |
72 | const Resolved = link ? 'a' : 'div';
73 | return (
74 |
75 |
81 | {title}
82 | {midTitle && (
83 | {midTitle}
84 | )}
85 | {subTitle}
86 |
87 |
88 | {renderValue()}
89 |
90 |
91 | );
92 | }
93 |
94 | export default React.memo(Transaction);
95 |
--------------------------------------------------------------------------------
/src/components/transaction/Transaction.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Transaction {
4 | display: flex;
5 | flex-direction: row;
6 | padding: 20px;
7 | background-color: $gray3;
8 | margin-bottom: 5px;
9 | min-height: 101px;
10 | box-sizing: border-box;
11 | transition: all 200ms ease-in-out;
12 | &:hover {
13 | background-color: $gray2;
14 | }
15 | @include mobile {
16 | flex-direction: column;
17 | padding: 15px 10px;
18 | }
19 | }
20 |
21 | .left {
22 | display: flex;
23 | flex-direction: column;
24 | flex: 1;
25 | div:last-child {
26 | margin-top: 10px;
27 | font-size: 0.7em;
28 | }
29 | @include mobile {
30 | margin-bottom: 10px;
31 | }
32 | }
33 |
34 | .midTitle {
35 | margin-top: 10px;
36 | color: $gray6;
37 | font-size: 0.8em;
38 | }
39 |
40 | .statusContainer {
41 | display: flex;
42 | flex-direction: column;
43 | text-align: right;
44 | align-items: flex-end;
45 | font-size: 0.9em;
46 | @include mobile {
47 | text-align: left;
48 | align-items: flex-start;
49 | }
50 | div:last-child {
51 | margin-top: 10px;
52 | font-size: 0.8em;
53 | }
54 | }
55 |
56 | .status {
57 | display: flex;
58 | flex-direction: row;
59 | align-items: center;
60 | justify-content: flex-end;
61 | div:last-child {
62 | font-size: 0.8em;
63 | }
64 | @include mobile {
65 | flex-direction: row-reverse;
66 | justify-content: flex-end;
67 | }
68 | .indicator {
69 | margin: 0 10px 0 0;
70 | width: 8px;
71 | height: 8px;
72 | border-radius: 100%;
73 | @include mobile {
74 | margin-left: 10px;
75 | }
76 | }
77 | .pending {
78 | background-color: $yellow;
79 | }
80 | .exited {
81 | background-color: $green;
82 | }
83 | .failed {
84 | background-color: $red;
85 | }
86 | }
87 |
88 | .percentage {
89 | margin-left: 10px;
90 | @include mobile {
91 | margin-left: 0;
92 | margin-right: 10px;
93 | }
94 | }
95 |
96 | .button {
97 | color: $gray1;
98 | background-color: $blue;
99 | border-radius: 20px;
100 | padding: 5px 10px;
101 | cursor: pointer;
102 | }
103 |
--------------------------------------------------------------------------------
/src/components/walletpicker/WalletPicker.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .WalletPicker {
4 | display: flex;
5 | flex-direction: column;
6 | justify-content: center;
7 | align-items: flex-start;
8 | margin-left: auto;
9 | margin-right: auto;
10 | flex: 1;
11 | padding: 20px;
12 | font-family: 'Messina';
13 | @include mobile {
14 | font-size: 0.9em;
15 | }
16 |
17 | .title {
18 | display: flex;
19 | flex-direction: row;
20 | justify-content: space-between;
21 | align-items: flex-start;
22 | width: 100%;
23 | @include mobile {
24 | flex-direction: column;
25 | }
26 | img {
27 | margin-bottom: 20px;
28 | height: 60px;
29 | @include mobile {
30 | height: 50px;
31 | }
32 | }
33 | .menu {
34 | display: flex;
35 | flex-direction: row;
36 | align-items: center;
37 | z-index: 1;
38 | position: relative;
39 | @include mobile {
40 | width: 100%;
41 | justify-content: space-between;
42 | }
43 | a {
44 | cursor: pointer;
45 | }
46 | .chevron {
47 | transform: rotate(90deg);
48 | transition: all 200ms ease-in-out;
49 | height: 20px;
50 | margin-bottom: 0;
51 | &.open {
52 | transform: rotate(-90deg);
53 | }
54 | }
55 | .dropdown {
56 | display: flex;
57 | flex-direction: column;
58 | position: absolute;
59 | right: 0;
60 | top: 27px;
61 | a {
62 | background-color: $gray3;
63 | transition: all 200ms ease-in-out;
64 | padding: 10px 15px;
65 | cursor: pointer;
66 | &:hover {
67 | background-color: $gray2;
68 | }
69 | }
70 | }
71 | .network {
72 | margin-left: 20px;
73 | display: flex;
74 | flex-direction: row;
75 | align-items: center;
76 | cursor: pointer;
77 | .indicator {
78 | margin-right: 5px;
79 | width: 5px;
80 | height: 13px;
81 | background-color: $green;
82 | border-radius: 4px;
83 | }
84 | }
85 | }
86 | }
87 |
88 | .directive {
89 | margin: 20px 0;
90 | font-size: 1.2em;
91 | }
92 |
93 | .loader {
94 | display: flex;
95 | flex-direction: column;
96 | .button {
97 | margin-top: 20px;
98 | align-self: center;
99 | }
100 | }
101 |
102 | .wallets {
103 | display: flex;
104 | flex-direction: row;
105 | width: 800px;
106 | justify-content: space-around;
107 | margin-top: 20px;
108 | @include mobile {
109 | flex-direction: column;
110 | width: 100%;
111 | }
112 | .wallet {
113 | width: calc(25% - 10px);
114 | border: 2px solid transparent;
115 | border-radius: 4px;
116 | transition: all 200ms ease-in-out;
117 | display: flex;
118 | flex-direction: column;
119 | color: $gray1;
120 | background-color: $gray6;
121 | align-items: center;
122 | box-sizing: border-box;
123 | padding: 20px;
124 | text-align: center;
125 | &.disabled {
126 | pointer-events: none;
127 | opacity: 0.4;
128 | }
129 | @include mobile {
130 | width: 100%;
131 | margin-bottom: 10px;
132 | }
133 | h3 {
134 | font-size: 1em;
135 | margin-top: 10px;
136 | }
137 | img {
138 | height: 50px;
139 | width: 50px;
140 | border-radius: 8px;
141 | }
142 | .walletconnect {
143 | border: 1px solid #389BFC;
144 | border-radius: 8px;
145 | display: flex;
146 | justify-content: center;
147 | align-items: center;
148 | width: 50px;
149 | height: 50px;
150 | img {
151 | height: 23px;
152 | width: auto;
153 | margin-left: 2px;
154 | }
155 | }
156 | & > div {
157 | font-size: 0.8em;
158 | @include mobile {
159 | font-size: 1em;
160 | }
161 | }
162 | &:hover {
163 | cursor: pointer;
164 | border: 2px solid $blue;
165 | }
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/containers/account/Account.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useMemo, useCallback } from 'react';
17 | import { useDispatch, useSelector } from 'react-redux';
18 | import { isEqual } from 'lodash';
19 | import truncate from 'truncate-middle';
20 | import { Send, MergeType } from '@material-ui/icons';
21 |
22 | import { selectLoading } from 'selectors/loadingSelector';
23 | import { selectIsSynced } from 'selectors/statusSelector';
24 | import { selectChildchainBalance, selectRootchainBalance } from 'selectors/balanceSelector';
25 | import { selectPendingExits } from 'selectors/exitSelector';
26 | import { selectChildchainTransactions } from 'selectors/transactionSelector';
27 |
28 | import { openModal } from 'actions/uiAction';
29 |
30 | import Copy from 'components/copy/Copy';
31 | import Button from 'components/button/Button';
32 | import { logAmount } from 'util/amountConvert';
33 |
34 | import networkService from 'services/networkService';
35 |
36 | import * as styles from './Account.module.scss';
37 |
38 | function Account () {
39 | const dispatch = useDispatch();
40 | const isSynced = useSelector(selectIsSynced);
41 | const childBalance = useSelector(selectChildchainBalance, isEqual);
42 | const rootBalance = useSelector(selectRootchainBalance, isEqual);
43 | const pendingExits = useSelector(selectPendingExits, isEqual);
44 | const transactions = useSelector(selectChildchainTransactions, isEqual);
45 | const criticalTransactionLoading = useSelector(selectLoading([ 'EXIT/CREATE' ]));
46 |
47 | const exitPending = useMemo(() => pendingExits.some(i => i.status === 'Pending'), [ pendingExits ]);
48 | const transferPending = useMemo(() => transactions.some(i => i.status === 'Pending'), [ transactions ]);
49 | const disabled = !childBalance.length || !isSynced || exitPending || transferPending;
50 |
51 | const handleModalClick = useCallback(
52 | (name) => dispatch(openModal(name)),
53 | [ dispatch ]
54 | );
55 |
56 | return (
57 |
58 |
Account
59 |
60 | {`Wallet Address : ${networkService.account ? truncate(networkService.account, 6, 4, '...') : ''}`}
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Balance on Childchain
69 | OMG Network
70 |
71 |
72 |
handleModalClick('mergeModal')}
74 | className={[
75 | styles.transfer,
76 | (disabled || criticalTransactionLoading) ? styles.disabled : ''
77 | ].join(' ')}
78 | >
79 |
80 | Merge
81 |
82 |
handleModalClick('transferModal')}
84 | className={[
85 | styles.transfer,
86 | (disabled || criticalTransactionLoading) ? styles.disabled : ''
87 | ].join(' ')}
88 | >
89 |
90 | Transfer
91 |
92 |
93 |
94 | {childBalance.map((i, index) => {
95 | return (
96 |
97 |
98 | {i.name}
99 |
100 |
{logAmount(i.amount, i.decimals)}
101 |
102 | );
103 | })}
104 |
105 | handleModalClick('depositModal')}
107 | type='primary'
108 | disabled={!isSynced}
109 | >
110 | DEPOSIT
111 |
112 | handleModalClick('exitModal')}
114 | type='secondary'
115 | disabled={disabled}
116 | >
117 | EXIT
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Balance on Rootchain
126 | Ethereum Network
127 |
128 |
129 |
130 | {rootBalance.map((i, index) => {
131 | return (
132 |
133 |
134 | {i.name}
135 |
136 |
{logAmount(i.amount, i.decimals)}
137 |
138 | );
139 | })}
140 |
141 |
142 |
143 | );
144 | }
145 |
146 | export default React.memo(Account);
147 |
--------------------------------------------------------------------------------
/src/containers/account/Account.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Account {
4 | margin-bottom: 20px;
5 | }
6 |
7 | .wallet {
8 | display: flex;
9 | flex-direction: row;
10 | align-items: center;
11 | margin-bottom: 20px;
12 | @include mobile {
13 | justify-content: space-between;
14 | }
15 | .address {
16 | margin-right: 20px;
17 | @include mobile {
18 | font-size: 0.8em;
19 | }
20 | }
21 | }
22 |
23 | .balances {
24 | display: flex;
25 | flex-direction: row;
26 | @include mobile {
27 | flex-direction: column;
28 | }
29 |
30 | .box {
31 | background-color: $gray3;
32 | padding: 20px;
33 | display: flex;
34 | flex-direction: column;
35 | flex: 1;
36 | @include mobile {
37 | font-size: 0.8rem;
38 | padding: 15px;
39 | }
40 |
41 | &:first-child {
42 | margin-right: 20px;
43 | @include mobile {
44 | margin-right: 0;
45 | margin-bottom: 20px;
46 | }
47 | }
48 |
49 | .buttons {
50 | margin: 20px -20px -20px -20px;
51 | @include mobile {
52 | margin: 15px -15px -15px -15px;
53 | }
54 | display: flex;
55 | flex-direction: row;
56 | button {
57 | flex: 1;
58 | }
59 | }
60 |
61 | .header {
62 | display: flex;
63 | flex-direction: row;
64 | justify-content: space-between;
65 | align-items: center;
66 | margin-bottom: 20px;
67 | .actions {
68 | display: flex;
69 | flex-direction: row;
70 | align-items: center;
71 | @include mobile {
72 | flex-direction: column;
73 | align-items: flex-end;
74 | }
75 | }
76 | .title {
77 | display: flex;
78 | flex-direction: column;
79 | font-family: 'Messina';
80 | span:first-child {
81 | font-size: 0.8em;
82 | }
83 | }
84 | .transfer {
85 | font-family: 'Messina';
86 | cursor: pointer;
87 | border-radius: 20px;
88 | padding: 5px 10px;
89 | border: 2px solid $gray6;
90 | filter: brightness(100%);
91 | display: flex;
92 | flex-direction: row;
93 | align-items: center;
94 | color: $gray6;
95 | svg {
96 | margin-right: 10px;
97 | width: 15px;
98 | height: 15px;
99 | }
100 | &:first-child {
101 | margin-right: 10px;
102 | @include mobile {
103 | margin-right: 0px;
104 | margin-bottom: 5px;
105 | }
106 | }
107 | }
108 | .disabled {
109 | pointer-events: none;
110 | border: 2px solid $gray3;
111 | color: $gray3;
112 | filter: brightness(75%);
113 | }
114 | }
115 |
116 | .row {
117 | display: flex;
118 | flex-direction: row;
119 | align-items: center;
120 | justify-content: space-between;
121 | color: $gray6;
122 | margin-bottom: 5px;
123 |
124 | .token {
125 | display: flex;
126 | flex-direction: row;
127 | align-items: center;
128 | .symbol {
129 | margin-right: 10px;
130 | }
131 | }
132 | }
133 | }
134 | }
--------------------------------------------------------------------------------
/src/containers/app/App.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState } from 'react';
17 | import { useDispatch, useSelector } from 'react-redux';
18 |
19 | import { closeAlert, closeError } from 'actions/uiAction';
20 | import { selectAlert, selectError } from 'selectors/uiSelector';
21 |
22 | import Home from 'containers/home/Home';
23 | import WalletPicker from 'components/walletpicker/WalletPicker';
24 | import Alert from 'components/alert/Alert';
25 |
26 | import * as styles from './App.module.scss';
27 |
28 | function App () {
29 | const dispatch = useDispatch();
30 |
31 | const errorMessage = useSelector(selectError);
32 | const alertMessage = useSelector(selectAlert);
33 | const [ enabled, setEnabled ] = useState(false);
34 |
35 | const handleErrorClose = () => dispatch(closeError());
36 | const handleAlertClose = () => dispatch(closeAlert());
37 |
38 | return (
39 |
40 |
46 | {errorMessage}
47 |
48 |
49 |
55 | {alertMessage}
56 |
57 |
58 | {!enabled &&
}
59 | {enabled &&
}
60 |
61 | );
62 | }
63 |
64 | export default App;
65 |
--------------------------------------------------------------------------------
/src/containers/app/App.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .App {
4 | display: flex;
5 | flex-direction: column;
6 | min-height: 100vh;
7 | }
8 |
--------------------------------------------------------------------------------
/src/containers/home/Home.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Home {
4 | display: flex;
5 | flex-direction: row;
6 | flex: 1;
7 | max-height: 100vh;
8 |
9 | @include mobile {
10 | flex-direction: column;
11 | max-height: initial;
12 | }
13 |
14 | .sidebar {
15 | display: flex;
16 | flex-direction: column;
17 | background-color: $gray2;
18 | align-items: flex-start;
19 |
20 | .logo {
21 | width: 130px;
22 | padding: 50px 0px 10px 40px;
23 | }
24 |
25 | @include mobile {
26 | display: none;
27 | }
28 | }
29 |
30 | .main {
31 | padding: 40px;
32 | background-color: $gray1;
33 | flex: 1;
34 | overflow: auto;
35 | position: relative;
36 | @include mobile {
37 | padding: 15px;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/containers/modals/deposit/DepositModal.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState, useCallback, useEffect } from 'react';
17 | import { useDispatch } from 'react-redux';
18 |
19 | import { closeModal } from 'actions/uiAction';
20 | import { getToken } from 'actions/tokenAction';
21 | import networkService from 'services/networkService';
22 |
23 | import Modal from 'components/modal/Modal';
24 |
25 | import InputStep from './steps/InputStep';
26 | import ApproveStep from './steps/ApproveStep';
27 |
28 | const ETH = networkService.OmgUtil.transaction.ETH_CURRENCY;
29 |
30 | function DepositModal ({ open }) {
31 | const dispatch = useDispatch();
32 |
33 | const [ step, setStep ] = useState('INPUT_STEP');
34 | const [ currency, setCurrency ] = useState(ETH);
35 | const [ tokenInfo, setTokenInfo ] = useState({});
36 | const [ value, setValue ] = useState('');
37 |
38 | useEffect(() => {
39 | async function getTokenInfo () {
40 | if (currency && networkService.web3.utils.isAddress(currency)) {
41 | const tokenInfo = await getToken(currency);
42 | setTokenInfo(tokenInfo);
43 | } else {
44 | setTokenInfo({});
45 | }
46 | }
47 | getTokenInfo();
48 | }, [ currency ]);
49 |
50 | const handleClose = useCallback(() => {
51 | setCurrency(ETH);
52 | setValue('');
53 | setStep('INPUT_STEP');
54 | dispatch(closeModal('depositModal'));
55 | }, [ dispatch ]);
56 |
57 | return (
58 |
59 | {step === 'INPUT_STEP' && (
60 | setStep('APPROVE_STEP')}
63 | currency={currency}
64 | tokenInfo={tokenInfo}
65 | value={value}
66 | setCurrency={setCurrency}
67 | setTokenInfo={setTokenInfo}
68 | setValue={setValue}
69 | />
70 | )}
71 | {step === 'APPROVE_STEP' && (
72 |
78 | )}
79 |
80 | );
81 | }
82 |
83 | export default React.memo(DepositModal);
84 |
--------------------------------------------------------------------------------
/src/containers/modals/deposit/DepositModal.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .buttons {
4 | display: flex;
5 | flex-direction: row;
6 | margin-top: 30px;
7 | justify-content: flex-end;
8 |
9 | div:first-child {
10 | margin-right: 10px;
11 | }
12 | }
13 |
14 | .disclaimer {
15 | font-size: 0.8em;
16 | margin-top: 10px;
17 | }
18 |
19 | .tabs {
20 | margin-top: 20px;
21 | }
22 |
23 | .loader {
24 | height: 250px;
25 | display: flex;
26 | justify-items: center;
27 | align-items: center;
28 | }
--------------------------------------------------------------------------------
/src/containers/modals/deposit/steps/InputStep.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { useDispatch, useSelector } from 'react-redux';
3 |
4 | import GasPicker from 'components/gaspicker/GasPicker';
5 | import Button from 'components/button/Button';
6 | import Input from 'components/input/Input';
7 | import Tabs from 'components/tabs/Tabs';
8 |
9 | import { depositEth } from 'actions/networkAction';
10 | import { openAlert, setActiveHistoryTab } from 'actions/uiAction';
11 | import { powAmount } from 'util/amountConvert';
12 | import networkService from 'services/networkService';
13 | import { selectLoading } from 'selectors/loadingSelector';
14 |
15 | import * as styles from '../DepositModal.module.scss';
16 |
17 | const ETH = networkService.OmgUtil.transaction.ETH_CURRENCY;
18 |
19 | function InputStep ({
20 | onClose,
21 | onNext,
22 | currency,
23 | tokenInfo,
24 | value,
25 | setCurrency,
26 | setTokenInfo,
27 | setValue
28 | }) {
29 | const dispatch = useDispatch();
30 | const [ activeTab, setActiveTab ] = useState('ETH');
31 | const depositLoading = useSelector(selectLoading([ 'DEPOSIT/CREATE' ]));
32 | const [ selectedSpeed, setSelectedSpeed ] = useState('normal');
33 | const [ gasPrice, setGasPrice ] = useState();
34 |
35 | function handleClose () {
36 | setActiveTab('ETH');
37 | onClose();
38 | }
39 |
40 | async function depositETH () {
41 | if (value > 0 && tokenInfo) {
42 | const amount = powAmount(value, tokenInfo.decimals);
43 | const res = await dispatch(depositEth(amount, gasPrice));
44 | if (res) {
45 | dispatch(setActiveHistoryTab('Deposits'));
46 | dispatch(openAlert('ETH deposit submitted.'));
47 | handleClose();
48 | }
49 | }
50 | }
51 |
52 | const disabledSubmit = value <= 0 || !currency || !networkService.web3.utils.isAddress(currency);
53 |
54 | return (
55 | <>
56 | Deposit
57 |
58 | {
61 | i === 'ETH' ? setCurrency(ETH) : setCurrency('');
62 | setActiveTab(i);
63 | }}
64 | activeTab={activeTab}
65 | tabs={[ 'ETH', 'ERC20' ]}
66 | />
67 |
68 | {activeTab === 'ERC20' && (
69 | setCurrency(i.target.value)}
75 | />
76 | )}
77 |
78 | setValue(i.target.value)}
85 | />
86 |
87 | {activeTab === 'ETH' && (
88 |
93 | )}
94 |
95 |
96 |
101 | CANCEL
102 |
103 | {activeTab === 'ETH' && (
104 |
112 | DEPOSIT
113 |
114 | )}
115 | {activeTab === 'ERC20' && (
116 |
122 | NEXT
123 |
124 | )}
125 |
126 | >
127 | );
128 | }
129 |
130 | export default React.memo(InputStep);
131 |
--------------------------------------------------------------------------------
/src/containers/modals/exit/ExitModal.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState } from 'react';
17 | import { useDispatch } from 'react-redux';
18 |
19 | import { closeModal } from 'actions/uiAction';
20 |
21 | import Modal from 'components/modal/Modal';
22 |
23 | import SelectStep from './steps/SelectStep';
24 | import AddTokenStep from './steps/AddTokenStep';
25 | import DoExitStep from './steps/DoExitStep';
26 |
27 | function ExitModal ({ open }) {
28 | const dispatch = useDispatch();
29 |
30 | const [ gasPrice, setGasPrice ] = useState();
31 | const [ selectedSpeed, setSelectedSpeed ] = useState('normal');
32 | const [ selectedUTXO, setSelectedUTXO ] = useState();
33 | const [ step, setStep ] = useState(1);
34 |
35 | function handleClose () {
36 | setSelectedUTXO();
37 | setStep(1);
38 | dispatch(closeModal('exitModal'));
39 | }
40 |
41 | return (
42 |
43 | {step === 1 && (
44 |
54 | )}
55 | {step === 2 && (
56 |
62 | )}
63 | {step === 3 && (
64 |
69 | )}
70 |
71 | );
72 | }
73 |
74 | export default React.memo(ExitModal);
75 |
--------------------------------------------------------------------------------
/src/containers/modals/exit/ExitModal.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .buttons {
4 | display: flex;
5 | flex-direction: row;
6 | margin-top: 30px;
7 | justify-content: flex-end;
8 |
9 | div:first-child {
10 | margin-right: 10px;
11 | }
12 | }
13 |
14 | .disclaimer {
15 | margin-top: 20px;
16 | }
17 |
18 | .list {
19 | height: 160px;
20 | overflow-y: auto;
21 | margin-bottom: 10px;
22 | .utxo {
23 | font-size: 0.8em;
24 | display: flex;
25 | flex-direction: row;
26 | align-items: center;
27 | justify-content: space-between;
28 | padding: 10px;
29 | height: 25px;
30 | background-color: $gray3;
31 | border-bottom: 2px solid $gray4;
32 | transition: all 200ms ease-in-out;
33 | cursor: pointer;
34 | .title {
35 | flex: 1
36 | }
37 | .value {
38 | flex: 1;
39 | display: flex;
40 | flex-direction: row;
41 | align-items: center;
42 | justify-content: flex-end;
43 | text-align: right;
44 | .check {
45 | display: flex;
46 | justify-content: center;
47 | align-items: center;
48 | width: 50px;
49 | svg {
50 | width: 15px;
51 | height: 15px;
52 | }
53 | }
54 | }
55 | }
56 | .selected {
57 | background-color: $gray2;
58 | color: $gray6;
59 | }
60 | }
--------------------------------------------------------------------------------
/src/containers/modals/exit/steps/AddTokenStep.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { useDispatch, useSelector } from 'react-redux';
18 |
19 | import { selectLoading } from 'selectors/loadingSelector';
20 | import { addExitQueue } from 'actions/networkAction';
21 |
22 | import Button from 'components/button/Button';
23 |
24 | import * as styles from '../ExitModal.module.scss';
25 |
26 | function AddTokenStep ({
27 | selectedUTXO,
28 | setSelectedUTXO,
29 | setStep,
30 | gasPrice
31 | }) {
32 | const dispatch = useDispatch();
33 |
34 | const addExitQueueLoading = useSelector(selectLoading([ 'QUEUE/CREATE' ]));
35 |
36 | async function doAddExitQueue () {
37 | const res = await dispatch(addExitQueue(selectedUTXO.currency, gasPrice));
38 | if (res) {
39 | return setStep(3);
40 | }
41 | }
42 |
43 | function handleBackClick () {
44 | setSelectedUTXO();
45 | setStep(1);
46 | }
47 |
48 | return (
49 | <>
50 | Add Exit Queue
51 |
52 | {`The exit queue for ${selectedUTXO.tokenInfo.name} does not exist yet. Adding the exit queue is required before being able to start your exit.`}
53 |
54 |
55 |
60 | GO BACK
61 |
62 |
69 | ADD QUEUE
70 |
71 |
72 | >
73 | );
74 | }
75 |
76 | export default React.memo(AddTokenStep);
77 |
--------------------------------------------------------------------------------
/src/containers/modals/exit/steps/DoExitStep.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { useDispatch, useSelector } from 'react-redux';
18 |
19 | import { exitUtxo } from 'actions/networkAction';
20 | import { openAlert } from 'actions/uiAction';
21 | import { selectLoading } from 'selectors/loadingSelector';
22 |
23 | import Button from 'components/button/Button';
24 |
25 | import * as styles from '../ExitModal.module.scss';
26 |
27 | function DoExitStep ({
28 | selectedUTXO,
29 | handleClose,
30 | gasPrice
31 | }) {
32 | const dispatch = useDispatch();
33 |
34 | const submitLoading = useSelector(selectLoading([ 'EXIT/CREATE' ]));
35 |
36 | async function doExit () {
37 | const res = await dispatch(exitUtxo(selectedUTXO, gasPrice));
38 | if (res) {
39 | dispatch(openAlert('Exit submitted. You will be blocked from making further transactions until the exit is confirmed.'));
40 | handleClose();
41 | }
42 | }
43 |
44 | return (
45 | <>
46 | Start Standard Exit
47 |
48 | {'The exit queue has been added. You can now start your exit.'}
49 |
50 |
51 |
56 | CANCEL
57 |
58 |
66 | SUBMIT EXIT
67 |
68 |
69 | >
70 | );
71 | }
72 |
73 | export default React.memo(DoExitStep);
74 |
--------------------------------------------------------------------------------
/src/containers/modals/exit/steps/SelectStep.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState, useMemo, useEffect } from 'react';
17 | import { orderBy } from 'lodash';
18 | import { useDispatch, useSelector } from 'react-redux';
19 | import { Check } from '@material-ui/icons';
20 |
21 | import networkService from 'services/networkService';
22 | import { openAlert } from 'actions/uiAction';
23 | import { checkForExitQueue, exitUtxo } from 'actions/networkAction';
24 | import { selectLoading } from 'selectors/loadingSelector';
25 |
26 | import GasPicker from 'components/gaspicker/GasPicker';
27 | import Input from 'components/input/Input';
28 | import Button from 'components/button/Button';
29 |
30 | import { logAmount } from 'util/amountConvert';
31 |
32 | import * as styles from '../ExitModal.module.scss';
33 |
34 | function SelectStep ({
35 | setSelectedUTXO,
36 | selectedUTXO,
37 | handleClose,
38 | setStep,
39 | gasPrice,
40 | setGasPrice,
41 | selectedSpeed,
42 | setSelectedSpeed
43 | }) {
44 | const dispatch = useDispatch();
45 |
46 | const [ utxos, setUtxos ] = useState([]);
47 | const [ searchUTXO, setSearchUTXO ] = useState('');
48 |
49 | const submitLoading = useSelector(selectLoading([
50 | `QUEUE/GET_${selectedUTXO ? selectedUTXO.currency : ''}`,
51 | 'EXIT/CREATE'
52 | ]));
53 |
54 | useEffect(() => {
55 | async function fetchUTXOS () {
56 | const _utxos = await networkService.getUtxos();
57 | const utxos = orderBy(_utxos, i => i.currency, 'desc');
58 | setUtxos(utxos);
59 | }
60 | fetchUTXOS();
61 | }, []);
62 |
63 | async function doCheckExitQueue () {
64 | const res = await dispatch(checkForExitQueue(selectedUTXO.currency));
65 | if (!res) {
66 | return setStep(2);
67 | }
68 | return doExit();
69 | }
70 |
71 | async function doExit () {
72 | const res = await dispatch(exitUtxo(selectedUTXO, gasPrice));
73 | if (res) {
74 | dispatch(openAlert('Exit submitted. You will be blocked from making further transactions until the exit is confirmed.'));
75 | handleClose();
76 | }
77 | }
78 |
79 | const _utxos = useMemo(() => {
80 | return utxos.filter(i => {
81 | return i.currency.toLowerCase().includes(searchUTXO.toLowerCase()) ||
82 | i.tokenInfo.name.toLowerCase().includes(searchUTXO.toLowerCase());
83 | }).filter(i => !!i);
84 | }, [ utxos, searchUTXO ]);
85 |
86 | function closeModal () {
87 | setSearchUTXO('');
88 | setSelectedSpeed('normal');
89 | handleClose();
90 | }
91 |
92 | return (
93 | <>
94 | Start Standard Exit
95 |
96 | setSearchUTXO(i.target.value)}
102 | />
103 |
104 |
105 | {!utxos.length && (
106 |
You do not have any UTXOs on the OMG Network.
107 | )}
108 | {_utxos.map((i, index) => {
109 | return (
110 |
setSelectedUTXO(i)}
113 | className={[
114 | styles.utxo,
115 | selectedUTXO === i ? styles.selected : ''
116 | ].join(' ')}
117 | >
118 |
119 | {i.tokenInfo.name}
120 |
121 |
122 |
123 |
124 | {logAmount(i.amount.toString(), i.tokenInfo.decimals)}
125 |
126 |
127 |
128 | {selectedUTXO === i && }
129 |
130 |
131 |
132 | );
133 | })}
134 |
135 |
136 |
141 |
142 |
143 |
148 | CANCEL
149 |
150 |
158 | SUBMIT EXIT
159 |
160 |
161 | >
162 | );
163 | }
164 |
165 | export default React.memo(SelectStep);
166 |
--------------------------------------------------------------------------------
/src/containers/modals/ledger/LedgerConnect.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .buttons {
4 | display: flex;
5 | flex-direction: row;
6 | margin-top: 30px;
7 | justify-content: flex-end;
8 |
9 | div:first-child {
10 | margin-right: 10px;
11 | }
12 | }
13 |
14 | .header {
15 | display: flex;
16 | flex-direction: column;
17 | align-items: center;
18 | margin-top: 20px;
19 | }
20 |
21 | .logo {
22 | padding: 7px;
23 | height: 60px;
24 | border-radius: 20px;
25 | background-color: white;
26 | }
27 |
28 | .logoContainer {
29 | display: flex;
30 | margin-top: 30px;
31 | align-items: center;
32 | justify-content: center;
33 | position: relative;
34 | @include mobile {
35 | display: none;
36 | }
37 | .spinner {
38 | position: absolute;
39 | bottom: -10px;
40 | right: -10px;
41 | background-color: $blue;
42 | border-radius: 100%;
43 | width: 30px;
44 | height: 30px;
45 | display: flex;
46 | justify-content: center;
47 | align-items: center;
48 | }
49 | }
50 |
51 | .title {
52 | margin-top: 30px;
53 | font-size: 1.5em;
54 | font-family: 'Messina';
55 | font-weight: 400;
56 | color: white;
57 | text-align: center;
58 | }
59 |
60 | .description {
61 | font-family: 'Messina';
62 | margin-top: 20px;
63 | color: white;
64 | font-size: 1em;
65 | }
66 |
67 | .steps {
68 | margin: 20px 0;
69 | .step {
70 | min-height: 40px;
71 | margin-bottom: 10px;
72 | border-radius: 4px;
73 | background-color: $gray2;
74 | display: flex;
75 | flex-direction: row;
76 | font-family: 'Messina';
77 | @include mobile {
78 | font-size: 0.8em;
79 | }
80 | .text {
81 | padding: 10px 15px;
82 | display: flex;
83 | align-items: center;
84 | }
85 | .iconWrapper {
86 | border-radius: 4px 0px 0px 4px;
87 | min-width: 40px;
88 | background-color: white;
89 | display: flex;
90 | justify-content: center;
91 | align-items: center;
92 | img {
93 | height: 15px;
94 | }
95 | }
96 | }
97 | }
98 |
99 | .tabs {
100 | margin-top: 20px;
101 | }
102 |
103 | .selectAddressContainer {
104 | text-align: center;
105 | }
106 |
--------------------------------------------------------------------------------
/src/containers/modals/ledger/LedgerPrompt.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { CircularProgress } from '@material-ui/core';
18 |
19 | import { hashTypedDataMessage, hashTypedDataDomain } from '@omisego/omg-js-util';
20 |
21 | import Button from 'components/button/Button';
22 |
23 | import ledger from 'images/ledger_connect.png';
24 | import eth from 'images/eth.svg';
25 | import connect from 'images/connect.svg';
26 | import lock from 'images/lock.svg';
27 |
28 | import * as styles from './LedgerPrompt.module.scss';
29 |
30 | function LedgerPrompt ({
31 | loading,
32 | submit,
33 | handleClose,
34 | typedData
35 | }) {
36 | return (
37 | <>
38 | {!loading && (
39 | <>
40 |
41 |
42 |
43 |
44 |
Ledger Sign
45 |
46 | Please make sure your Ledger meets the following conditions:
47 |
48 |
49 |
50 |
51 |
52 |
Connected
53 |
54 |
55 |
56 |
57 |
58 |
Unlocked
59 |
60 |
61 |
62 |
63 |
64 |
The Ethereum application is open and running a version greater than 1.4.0
65 |
66 |
67 |
68 |
73 | CANCEL
74 |
75 | submit({ useLedgerSign: true })}
78 | type='primary'
79 | loading={loading}
80 | >
81 | SIGN
82 |
83 |
84 | >
85 | )}
86 |
87 | {loading && (
88 | <>
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
Processing...
97 |
98 |
99 | Please continue signing the transaction on your Ledger device.
100 | Check that the domain and message hash displayed on the device match the following:
101 |
102 | {typedData && (
103 |
104 |
105 | Domain Hash: {hashTypedDataDomain(typedData).toUpperCase()}
106 |
107 |
108 | Message Hash: {hashTypedDataMessage(typedData).toUpperCase()}
109 |
110 |
111 | )}
112 | >
113 | )}
114 | >
115 | );
116 | }
117 |
118 | export default React.memo(LedgerPrompt);
119 |
--------------------------------------------------------------------------------
/src/containers/modals/ledger/LedgerPrompt.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .buttons {
4 | display: flex;
5 | flex-direction: row;
6 | margin-top: 30px;
7 | justify-content: flex-end;
8 |
9 | .button {
10 | margin-right: 10px;
11 | min-width: 0;
12 | &:last-child {
13 | margin-right: 0px;
14 | }
15 | }
16 | }
17 |
18 | .header {
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | margin-top: 20px;
23 | }
24 |
25 | .logo {
26 | padding: 7px;
27 | height: 60px;
28 | border-radius: 20px;
29 | background-color: white;
30 | }
31 |
32 | .logoContainer {
33 | position: relative;
34 | display: flex;
35 | align-items: center;
36 | justify-content: center;
37 | @include mobile {
38 | display: none;
39 | }
40 | .spinner {
41 | position: absolute;
42 | bottom: -10px;
43 | right: -10px;
44 | background-color: $blue;
45 | border-radius: 100%;
46 | width: 30px;
47 | height: 30px;
48 | display: flex;
49 | justify-content: center;
50 | align-items: center;
51 | }
52 | }
53 |
54 | .title {
55 | margin-top: 20px;
56 | font-size: 1.5em;
57 | font-family: 'Messina';
58 | font-weight: 400;
59 | color: white;
60 | text-align: center;
61 | }
62 |
63 | .description {
64 | font-family: 'Messina';
65 | margin-top: 20px;
66 | color: white;
67 | font-size: 1em;
68 | }
69 |
70 | .steps {
71 | margin: 20px 0;
72 | .step {
73 | min-height: 50px;
74 | margin-bottom: 10px;
75 | border-radius: 4px;
76 | background-color: $gray2;
77 | display: flex;
78 | flex-direction: row;
79 | align-items: center;
80 | font-family: 'Messina';
81 | @include mobile {
82 | font-size: 0.8em;
83 | }
84 | .text {
85 | padding: 10px 15px;
86 | display: flex;
87 | align-items: center;
88 | }
89 | .iconWrapper {
90 | border-radius: 4px 0px 0px 4px;
91 | min-width: 40px;
92 | min-height: 50px;
93 | background-color: white;
94 | display: flex;
95 | justify-content: center;
96 | align-items: center;
97 | img {
98 | height: 15px;
99 | max-width: 15px;
100 | }
101 | }
102 | }
103 | .code {
104 | word-break: break-all;
105 | font-family: 'MessinaMono';
106 | padding: 10px 15px;
107 | }
108 | }
--------------------------------------------------------------------------------
/src/containers/modals/merge/MergeModal.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .buttons {
4 | display: flex;
5 | flex-direction: row;
6 | margin-top: 30px;
7 | justify-content: flex-end;
8 |
9 | .button {
10 | margin-right: 10px;
11 | min-width: 0;
12 | &:last-child {
13 | margin-right: 0px;
14 | }
15 | }
16 | }
17 |
18 | .disclaimer {
19 | font-family: 'Messina';
20 | margin: 20px 0;
21 | }
22 |
23 | .list {
24 | height: 250px;
25 | overflow-y: auto;
26 | .utxo {
27 | font-size: 0.9em;
28 | display: flex;
29 | flex-direction: row;
30 | align-items: center;
31 | justify-content: space-between;
32 | background-color: $gray3;
33 | border-bottom: 2px solid $gray4;
34 | padding: 10px;
35 | height: 25px;
36 | transition: all 200ms ease-in-out;
37 | cursor: pointer;
38 | .title {
39 | flex: 1
40 | }
41 | .value {
42 | flex: 1;
43 | display: flex;
44 | flex-direction: row;
45 | align-items: center;
46 | justify-content: flex-end;
47 | text-align: right;
48 | .check {
49 | display: flex;
50 | justify-content: center;
51 | align-items: center;
52 | width: 50px;
53 | svg {
54 | width: 15px;
55 | height: 15px;
56 | }
57 | }
58 | }
59 | }
60 | .selected {
61 | background-color: $gray2;
62 | color: $gray6;
63 | }
64 | }
--------------------------------------------------------------------------------
/src/containers/modals/processexit/ProcessExitsModal.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState } from 'react';
17 | import { useDispatch, useSelector } from 'react-redux';
18 | import numbro from 'numbro';
19 |
20 | import { selectByzantine } from 'selectors/statusSelector';
21 | import { processExits, fetchExits } from 'actions/networkAction';
22 |
23 | import GasPicker from 'components/gaspicker/GasPicker';
24 | import Button from 'components/button/Button';
25 | import Modal from 'components/modal/Modal';
26 |
27 | import * as styles from './ProcessExitsModal.module.scss';
28 |
29 | function ProcessExitsModal ({ exitData, open, toggle }) {
30 | const dispatch = useDispatch();
31 |
32 | const byzantineChain = useSelector(selectByzantine);
33 | const [ loading, setLoading ] = useState(false);
34 | const [ gasPrice, setGasPrice ] = useState();
35 | const [ selectedSpeed, setSelectedSpeed ] = useState('normal');
36 |
37 | async function submit () {
38 | setLoading(true);
39 | const res = await dispatch(processExits(exitData.queuePosition, exitData.currency, gasPrice));
40 | if (res) {
41 | await dispatch(fetchExits());
42 | setLoading(false);
43 | return handleClose();
44 | }
45 | return setLoading(false);
46 | }
47 |
48 | function handleClose () {
49 | setSelectedSpeed('normal');
50 | toggle();
51 | }
52 |
53 | return (
54 |
55 | Process Exit
56 |
57 |
58 | This exit is currently
59 | {exitData ? numbro(exitData.queuePosition).format({ output: 'ordinal' }) : ''}
60 | {`in the queue for this token. You will need to process ${exitData.queuePosition} ${exitData.queuePosition === 1 ? 'exit' : 'exits'} to release your funds.`}
61 |
62 |
63 |
68 |
69 |
70 |
75 | CANCEL
76 |
77 |
88 | PROCESS
89 |
90 |
91 |
92 | );
93 | }
94 |
95 | export default ProcessExitsModal;
96 |
--------------------------------------------------------------------------------
/src/containers/modals/processexit/ProcessExitsModal.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .buttons {
4 | display: flex;
5 | flex-direction: row;
6 | margin-top: 30px;
7 | justify-content: flex-end;
8 |
9 | div:first-child {
10 | margin-right: 10px;
11 | }
12 | }
13 |
14 | .disclaimer {
15 | padding: 10px;
16 | background-color: $blue;
17 | color: $gray6;
18 | margin-top: -12px;
19 | font-size: 0.9em;
20 | margin-bottom: 10px;
21 | }
22 |
23 | .note {
24 | margin: 10px 0;
25 | }
26 |
27 | .position {
28 | color: $gray6;
29 | font-weight: bold;
30 | margin: 0 7px;
31 | }
32 |
--------------------------------------------------------------------------------
/src/containers/modals/transfer/TransferModal.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .disclaimer {
4 | font-family: 'Messina';
5 | margin-top: 20px;
6 | }
7 |
8 | .buttons {
9 | display: flex;
10 | flex-direction: row;
11 | margin-top: 30px;
12 | justify-content: flex-end;
13 |
14 | .button {
15 | margin-right: 10px;
16 | min-width: 0;
17 | &:last-child {
18 | margin-right: 0px;
19 | }
20 | }
21 | }
22 |
23 | .address {
24 | font-size: 0.9em;
25 | margin-bottom: 20px;
26 | margin-top: 20px;
27 | word-break: break-all;
28 | }
29 |
30 | .utxoPickLink {
31 | cursor: pointer;
32 | color: $blue;
33 | font-size: 12px;
34 | text-align: right;
35 | }
36 |
37 | .description {
38 | font-family: 'Messina';
39 | margin-bottom: 20px;
40 | }
41 |
42 | .list {
43 | height: 250px;
44 | overflow-y: auto;
45 | .utxo {
46 | font-size: 0.9em;
47 | display: flex;
48 | flex-direction: row;
49 | align-items: center;
50 | justify-content: space-between;
51 | background-color: $gray3;
52 | border-bottom: 2px solid $gray4;
53 | padding: 10px;
54 | height: 25px;
55 | transition: all 200ms ease-in-out;
56 | cursor: pointer;
57 | .title {
58 | flex: 1
59 | }
60 | .value {
61 | flex: 1;
62 | display: flex;
63 | flex-direction: row;
64 | align-items: center;
65 | justify-content: flex-end;
66 | text-align: right;
67 | .check {
68 | display: flex;
69 | justify-content: center;
70 | align-items: center;
71 | width: 50px;
72 | svg {
73 | width: 15px;
74 | height: 15px;
75 | }
76 | }
77 | }
78 | }
79 | .selected {
80 | background-color: $gray2;
81 | color: $gray6;
82 | }
83 | }
84 |
85 | .doubleList {
86 | height: 150px;
87 | }
88 |
--------------------------------------------------------------------------------
/src/containers/modals/wrongnetwork/WrongNetworkModal.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import { useDispatch } from 'react-redux';
18 |
19 | import Modal from 'components/modal/Modal';
20 | import { closeModal } from 'actions/uiAction';
21 | import { getNetworkName, getOtherNetworks } from 'util/networkName';
22 | import close from 'images/close.png';
23 | import arrow from 'images/arrow.png';
24 |
25 | import * as styles from './WrongNetworkModal.module.scss';
26 |
27 | function WrongNetworkModal ({ open, onClose }) {
28 | const dispatch = useDispatch();
29 |
30 | function handleClose () {
31 | onClose();
32 | dispatch(closeModal('wrongNetworkModal'));
33 | }
34 |
35 | return (
36 |
41 |
42 |
48 |
Wrong Network
49 |
50 |
51 |
52 | Please switch your wallet to the {getNetworkName()} in order to continue.
53 |
54 |
55 |
56 |
62 |
{getNetworkName()}
63 |
64 |
65 |
70 |
71 |
72 | {getOtherNetworks().map((network, index) => {
73 | return (
74 |
78 | );
79 | })}
80 |
81 |
82 |
83 |
84 | );
85 | }
86 |
87 | export default React.memo(WrongNetworkModal);
88 |
--------------------------------------------------------------------------------
/src/containers/modals/wrongnetwork/WrongNetworkModal.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .WrongNetworkModal {
4 | display: flex;
5 | flex-direction: column;
6 | justify-content: center;
7 | align-items: center;
8 | font-family: 'Messina';
9 | text-align: center;
10 | position: relative;
11 | padding: 40px;
12 | @include mobile {
13 | padding: 20px;
14 | }
15 | .close {
16 | position: absolute;
17 | right: 0;
18 | top: 0;
19 | height: 15px;
20 | cursor: pointer;
21 | }
22 | h2 {
23 | color: $gray1;
24 | }
25 |
26 | .content {
27 | max-width: 220px;
28 | .description {
29 | margin: 20px 0;
30 | font-size: 0.9em;
31 | }
32 | .currentNetwork {
33 | background-color: $gray4;
34 | color: $gray6;
35 | border-radius: 6px;
36 | padding: 15px 20px;
37 | display: flex;
38 | flex-direction: row;
39 | align-items: center;
40 | margin-bottom: 10px;
41 | }
42 | .network {
43 | background-color: $gray6;
44 | padding: 10px;
45 | display: flex;
46 | flex-direction: row;
47 | align-items: center;
48 | color: $gray4;
49 | margin-bottom: 1px;
50 | &:first-child {
51 | border-top-left-radius: 6px;
52 | border-top-right-radius: 6px;
53 | }
54 | &:last-child {
55 | border-bottom-left-radius: 6px;
56 | border-bottom-right-radius: 6px;
57 | }
58 | }
59 | .indicator {
60 | background-color: $gray5;
61 | width: 7px;
62 | height: 7px;
63 | border-radius: 100%;
64 | margin-right: 10px;
65 | &.active {
66 | background-color: $green;
67 | }
68 | }
69 | .otherNetworks {
70 | background-color: $gray7;
71 | border-radius: 6px;
72 | padding: 10px;
73 | }
74 | .arrow {
75 | width: 20px;
76 | opacity: 0.2;
77 | transform: rotate((-90deg));
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/containers/status/Status.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .Status {
4 | display: flex;
5 | flex-direction: column;
6 | justify-content: space-between;
7 | padding: 40px;
8 | max-width: 300px;
9 | flex: 1;
10 |
11 | h1 {
12 | margin-bottom: 40px;
13 | }
14 |
15 | .statusCircle {
16 | border-radius: 100%;
17 | width: 8px;
18 | height: 8px;
19 | margin-left: 10px;
20 | }
21 | .healthy {
22 | background-color: $green;
23 | }
24 | .unhealthy {
25 | background-color: $red;
26 | }
27 | .healthyText {
28 | color: $green;
29 | }
30 | .unhealthyText {
31 | color: $red;
32 | }
33 |
34 | .indicator {
35 | display: flex;
36 | flex-direction: row;
37 | align-items: center;
38 | }
39 |
40 | .icon {
41 | cursor: pointer;
42 | background-color: $gray3;
43 | border-radius: 100%;
44 | width: 25px;
45 | height: 25px;
46 | display: flex;
47 | justify-content: center;
48 | align-items: center;
49 |
50 | svg {
51 | width: 12px;
52 | height: 12px;
53 | }
54 | }
55 |
56 | .github {
57 | cursor: pointer;
58 | color: $gray3;
59 | svg {
60 | width: 40px;
61 | height: 40px;
62 | }
63 | }
64 | }
65 |
66 | .logo {
67 | margin-bottom: 40px;
68 | height: 50px;
69 | }
70 |
--------------------------------------------------------------------------------
/src/containers/transactions/Deposits.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState, useEffect } from 'react';
17 | import { orderBy, isEqual } from 'lodash';
18 | import { useSelector } from 'react-redux';
19 | import truncate from 'truncate-middle';
20 |
21 | import { selectEthDeposits, selectErc20Deposits } from 'selectors/transactionSelector';
22 | import { selectLoading } from 'selectors/loadingSelector';
23 |
24 | import Transaction from 'components/transaction/Transaction';
25 | import Pager from 'components/pager/Pager';
26 |
27 | import config from 'util/config';
28 | import { logAmount } from 'util/amountConvert';
29 |
30 | import * as styles from './Transactions.module.scss';
31 |
32 | const PER_PAGE = 10;
33 |
34 | function Deposits ({ searchHistory }) {
35 | const [ page, setPage ] = useState(1);
36 |
37 | const ethDeposits = useSelector(selectEthDeposits, isEqual);
38 | const erc20Deposits = useSelector(selectErc20Deposits, isEqual);
39 | const loading = useSelector(selectLoading([ 'DEPOSIT/GETALL' ]));
40 |
41 | useEffect(() => {
42 | setPage(1);
43 | }, [ searchHistory ]);
44 |
45 | const deposits = orderBy(
46 | [ ...ethDeposits, ...erc20Deposits ],
47 | i => i.blockNumber, 'desc'
48 | );
49 | const _deposits = deposits.filter(i => {
50 | return i.transactionHash.includes(searchHistory) || i.returnValues.token.includes(searchHistory);
51 | });
52 |
53 | const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
54 | const endingIndex = page * PER_PAGE;
55 | const paginatedDeposits = _deposits.slice(startingIndex, endingIndex);
56 |
57 | return (
58 |
59 |
60 |
setPage(page + 1)}
64 | onClickBack={() => setPage(page - 1)}
65 | />
66 | {!paginatedDeposits.length && !loading && (
67 | No deposit history.
68 | )}
69 | {!paginatedDeposits.length && loading && (
70 | Loading...
71 | )}
72 | {paginatedDeposits.map((i, index) => {
73 | return (
74 |
85 | );
86 | })}
87 |
88 |
89 | );
90 | }
91 |
92 | export default React.memo(Deposits);
93 |
--------------------------------------------------------------------------------
/src/containers/transactions/Exits.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState } from 'react';
17 | import { orderBy, isEqual } from 'lodash';
18 | import moment from 'moment';
19 | import { useSelector } from 'react-redux';
20 | import truncate from 'truncate-middle';
21 |
22 | import config from 'util/config';
23 | import { selectPendingExits, selectExitedExits } from 'selectors/exitSelector';
24 | import { selectLoading } from 'selectors/loadingSelector';
25 |
26 | import ProcessExitsModal from 'containers/modals/processexit/ProcessExitsModal';
27 | import Transaction from 'components/transaction/Transaction';
28 | import Pager from 'components/pager/Pager';
29 |
30 | import * as styles from './Transactions.module.scss';
31 |
32 | const PER_PAGE = 10;
33 |
34 | function Exits ({ searchHistory }) {
35 | const [ page, setPage ] = useState(1);
36 | const [ processExitModal, setProcessExitModal ] = useState(false);
37 |
38 | const pendingExits = orderBy(useSelector(selectPendingExits, isEqual), i => i.blockNumber, 'desc');
39 | const exitedExits = orderBy(useSelector(selectExitedExits, isEqual), i => i.blockNumber, 'desc');
40 | const loading = useSelector(selectLoading([ 'EXIT/GETALL' ]));
41 |
42 | const _pendingExits = pendingExits.filter(i => {
43 | return i.transactionHash.includes(searchHistory);
44 | });
45 |
46 | const _exitedExits = exitedExits.filter(i => {
47 | return i.transactionHash.includes(searchHistory);
48 | });
49 |
50 | const renderPending = _pendingExits.map((i, index) => {
51 | const exitableMoment = moment.unix(i.exitableAt);
52 | const isExitable = moment().isAfter(exitableMoment);
53 |
54 | function getStatus () {
55 | if (i.status === 'Confirmed' && i.pendingPercentage >= 100) {
56 | return 'In Challenge Period';
57 | }
58 | return i.status;
59 | }
60 |
61 | return (
62 | setProcessExitModal(i),
68 | text: 'Process Exit'
69 | }
70 | : undefined
71 | }
72 | link={`${config.etherscanUrl}/tx/${i.transactionHash}`}
73 | status={getStatus()}
74 | subStatus={`Block ${i.blockNumber}`}
75 | statusPercentage={i.pendingPercentage <= 100 ? i.pendingPercentage : ''}
76 | title={truncate(i.transactionHash, 6, 4, '...')}
77 | midTitle={i.exitableAt ? `Exitable ${exitableMoment.format('lll')}` : ''}
78 | subTitle={i.currency ? truncate(i.currency, 6, 4, '...'): ''}
79 | />
80 | );
81 | });
82 |
83 | const renderExited = _exitedExits.map((i, index) => {
84 | return (
85 |
92 | );
93 | });
94 |
95 | const allExits = [ ...renderPending, ...renderExited ];
96 |
97 | const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
98 | const endingIndex = page * PER_PAGE;
99 | const paginatedExits = allExits.slice(startingIndex, endingIndex);
100 |
101 | return (
102 | <>
103 | setProcessExitModal(false)}
107 | />
108 |
109 |
Exits
110 |
111 |
112 |
setPage(page + 1)}
116 | onClickBack={() => setPage(page - 1)}
117 | />
118 | {!allExits.length && !loading && (
119 | No exit history.
120 | )}
121 | {!allExits.length && loading && (
122 | Loading...
123 | )}
124 | {React.Children.toArray(paginatedExits)}
125 |
126 |
127 |
128 | >
129 | );
130 | }
131 |
132 | export default React.memo(Exits);
133 |
--------------------------------------------------------------------------------
/src/containers/transactions/Transactions.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React, { useState } from 'react';
17 | import { useDispatch } from 'react-redux';
18 | import { orderBy, isEqual } from 'lodash';
19 | import { useSelector } from 'react-redux';
20 | import BN from 'bn.js';
21 | import moment from 'moment';
22 | import truncate from 'truncate-middle';
23 |
24 | import { setActiveHistoryTab } from 'actions/uiAction';
25 |
26 | import { selectActiveHistoryTab } from 'selectors/uiSelector';
27 | import { selectChildchainTransactions } from 'selectors/transactionSelector';
28 | import { selectLoading } from 'selectors/loadingSelector';
29 | import networkService from 'services/networkService';
30 | import config from 'util/config';
31 |
32 | import Tabs from 'components/tabs/Tabs';
33 | import Input from 'components/input/Input';
34 | import Transaction from 'components/transaction/Transaction';
35 | import Pager from 'components/pager/Pager';
36 |
37 | import Exits from './Exits';
38 | import Deposits from './Deposits';
39 |
40 | import * as styles from './Transactions.module.scss';
41 |
42 | const PER_PAGE = 10;
43 |
44 | function Transactions () {
45 | const dispatch = useDispatch();
46 | const [ page, setPage ] = useState(1);
47 | const [ searchHistory, setSearchHistory ] = useState('');
48 |
49 | const loading = useSelector(selectLoading([ 'TRANSACTION/GETALL' ]));
50 | const activeTab = useSelector(selectActiveHistoryTab, isEqual);
51 | const unorderedTransactions = useSelector(selectChildchainTransactions, isEqual);
52 | const transactions = orderBy(unorderedTransactions, i => i.block.timestamp, 'desc');
53 |
54 | function renderStatus (utxo) {
55 | if (utxo.status === 'Pending') {
56 | return 'Pending';
57 | }
58 | const total = utxo.outputs.reduce((prev, curr) => {
59 | if (curr.owner !== networkService.account) {
60 | return prev.add(new BN(curr.amount));
61 | }
62 | return prev;
63 | }, new BN(0));
64 | return `${total.toString()}`;
65 | }
66 |
67 | const _transactions = transactions.filter(i => {
68 | return i.txhash.includes(searchHistory) || i.metadata.toLowerCase().includes(searchHistory);
69 | });
70 |
71 | const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
72 | const endingIndex = page * PER_PAGE;
73 | const paginatedTransactions = _transactions.slice(startingIndex, endingIndex);
74 |
75 | return (
76 |
77 |
78 |
History
79 | {
84 | setPage(1);
85 | setSearchHistory(i.target.value.toLowerCase());
86 | }}
87 | className={styles.searchBar}
88 | />
89 |
90 |
91 |
92 |
93 |
{
95 | setPage(1);
96 | dispatch(setActiveHistoryTab(tab));
97 | }}
98 | activeTab={activeTab}
99 | tabs={[ 'Transactions', 'Deposits' ]}
100 | />
101 |
102 | {activeTab === 'Transactions' && (
103 |
104 |
setPage(page + 1)}
108 | onClickBack={() => setPage(page - 1)}
109 | />
110 | {!paginatedTransactions.length && !loading && (
111 | No transaction history.
112 | )}
113 | {!paginatedTransactions.length && loading && (
114 | Loading...
115 | )}
116 | {paginatedTransactions.map((i, index) => {
117 | return (
118 |
131 | );
132 | })}
133 |
134 | )}
135 |
136 | {activeTab === 'Deposits' && }
137 |
138 |
139 |
140 |
141 |
142 | );
143 | }
144 |
145 | export default React.memo(Transactions);
146 |
--------------------------------------------------------------------------------
/src/containers/transactions/Transactions.module.scss:
--------------------------------------------------------------------------------
1 | @import 'index.module.scss';
2 |
3 | .container {
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | .header {
9 | h2 {
10 | flex: 1;
11 | margin-bottom: 0;
12 | }
13 | display: flex;
14 | flex-direction: row;
15 | justify-content: space-between;
16 | align-items: center;
17 | margin-bottom: 20px;
18 | @include mobile {
19 | flex-direction: column;
20 | align-items: flex-start;
21 | }
22 | }
23 |
24 | .data {
25 | display: flex;
26 | flex-direction: row;
27 | @include mobile {
28 | flex-direction: column;
29 | }
30 | }
31 |
32 | .section {
33 | flex: 1;
34 | &:first-child {
35 | margin-right: 20px;
36 | @include mobile {
37 | margin-right: 0;
38 | margin-bottom: 20px;
39 | }
40 | }
41 | }
42 |
43 | .transactionSection {
44 | margin-bottom: 20px;
45 | }
46 |
47 | .disclaimer {
48 | color: $gray3;
49 | margin-bottom: 20px;
50 | }
51 |
52 | .searchBar {
53 | flex: 1;
54 | margin-bottom: 0;
55 | & > div {
56 | border: none !important;
57 | border-bottom: 2px solid $gray3 !important;
58 | }
59 | input {
60 | background-color: $gray1 !important;
61 | }
62 | }
63 |
64 | .transactions {
65 | height: 100%;
66 | overflow: auto;
67 |
68 | .transaction {
69 | border-bottom: 1px dashed $gray3;
70 | padding: 20px 0;
71 | &:last-child {
72 | border-bottom: none;
73 | }
74 | }
75 | }
76 |
77 | .subTitle {
78 | display: flex;
79 | flex-direction: row;
80 | align-items: center;
81 | justify-content: space-between;
82 |
83 | margin-bottom: 32px;
84 | span {
85 | margin-right: 20px;
86 | }
87 | }
88 |
89 | .processExitButton {
90 | color: $blue;
91 | cursor: pointer;
92 | }
--------------------------------------------------------------------------------
/src/fonts/MessinaSans-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/fonts/MessinaSans-Regular.otf
--------------------------------------------------------------------------------
/src/fonts/MessinaSansMono-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/fonts/MessinaSansMono-Regular.otf
--------------------------------------------------------------------------------
/src/images/arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/arrow.png
--------------------------------------------------------------------------------
/src/images/boxarrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/browserwallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/browserwallet.png
--------------------------------------------------------------------------------
/src/images/chevron.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/images/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/close.png
--------------------------------------------------------------------------------
/src/images/coinbase.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/coinbase.jpg
--------------------------------------------------------------------------------
/src/images/connect.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/eth.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/key.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/ledger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/ledger.png
--------------------------------------------------------------------------------
/src/images/ledger_connect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/ledger_connect.png
--------------------------------------------------------------------------------
/src/images/lock.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/omg_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/walletconnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omgnetwork/web-wallet/4a8386f7d1174cdacaf8f092c0f8e3c3ed4ae28d/src/images/walletconnect.png
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import React from 'react';
17 | import ReactDOM from 'react-dom';
18 | import { Provider } from 'react-redux';
19 | import TagManager from 'react-gtm-module';
20 |
21 | import config from 'util/config';
22 | import store from 'store';
23 |
24 | import App from 'containers/app/App';
25 |
26 | // Renamed due to https://github.com/facebook/create-react-app/issues/10047
27 | import './index.module.scss';
28 |
29 | if (config.gtmId) {
30 | TagManager.initialize({ gtmId: config.gtmId });
31 | }
32 |
33 | // https://docs.metamask.io/guide/ethereum-provider.html#ethereum-autorefreshonnetworkchange
34 | if (window.ethereum) {
35 | window.ethereum.autoRefreshOnNetworkChange = false;
36 | }
37 |
38 | ReactDOM.render(
39 |
40 |
41 | ,
42 | document.getElementById('root')
43 | );
44 |
--------------------------------------------------------------------------------
/src/index.module.scss:
--------------------------------------------------------------------------------
1 | $red: #ff6868;
2 | $yellow: #f0ba31;
3 | $green: #0ebf9a;
4 | $blue: #4967ff;
5 |
6 | $gray1: #101010;
7 | $gray2: #29292e;
8 | $gray3: #35353f;
9 | $gray4: #585868;
10 | $gray5: #b3b3bf;
11 | $gray6: #ffffff;
12 | $gray7: #F2F3F5;
13 |
14 | :export {
15 | red: $red;
16 | yellow: $yellow;
17 | green: $green;
18 | blue: $blue;
19 | gray1: $gray1;
20 | gray2: $gray2;
21 | gray3: $gray3;
22 | gray4: $gray4;
23 | gray5: $gray5;
24 | gray6: $gray6;
25 | }
26 |
27 | @mixin mobile {
28 | @media screen and (max-width: 1000px) {
29 | @content
30 | }
31 | }
32 |
33 | @mixin tablet {
34 | @media screen and (max-width: 1000px) {
35 | @content
36 | }
37 | }
38 |
39 | @font-face {
40 | font-family: 'Messina';
41 | src: url(./fonts/MessinaSans-Regular.otf) format('opentype');
42 | }
43 |
44 | @font-face {
45 | font-family: 'MessinaMono';
46 | src: url(./fonts/MessinaSansMono-Regular.otf) format('opentype');
47 | }
48 |
49 | a {
50 | color: inherit;
51 | text-decoration: none;
52 | }
53 |
54 | body {
55 | margin: 0;
56 | padding: 0;
57 | color: $gray5;
58 | background-color: $gray1;
59 | font-family: 'MessinaMono', monospace;
60 | font-size: 14px;
61 | }
62 |
63 | input {
64 | font-family: 'MessinaMono', monospace;
65 | font-size: 1em;
66 | border: none;
67 | outline: none;
68 | }
69 |
70 | input::-webkit-outer-spin-button,
71 | input::-webkit-inner-spin-button {
72 | -webkit-appearance: none;
73 | margin: 0;
74 | }
75 |
76 | h1 {
77 | margin: 0;
78 | white-space: pre;
79 | font-family: 'Messina';
80 | font-weight: 400;
81 | font-size: 2em;
82 | color: $blue;
83 | }
84 |
85 | h2 {
86 | color: $gray6;
87 | font-family: 'Messina';
88 | font-weight: 100;
89 | margin: 0 0 10px 0;
90 | font-size: 1.5em;
91 | @include mobile {
92 | font-size: 1.2em;
93 | }
94 | }
95 |
96 | // override globals and third party libs
97 | .walletconnect-modal__base {
98 | max-width: 225px !important;
99 | }
100 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/balanceReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import balanceReducer from '../balanceReducer';
17 |
18 | describe('balanceReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = balanceReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({ rootchain: [], childchain: [] });
22 | });
23 |
24 | it('should handle balance success', () => {
25 | const action = {
26 | type: 'BALANCE/GET/SUCCESS',
27 | payload: { rootchain: [ 'toto' ], childchain: [ 'toto' ] }
28 | };
29 | const newState = balanceReducer(undefined, action);
30 | expect(newState).toEqual(action.payload);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/depositReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import depositReducer from '../depositReducer';
17 |
18 | describe('depositReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = depositReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({ eth: {}, erc20: {} });
22 | });
23 |
24 | it('should handle deposit fetch success', () => {
25 | const action = {
26 | type: 'DEPOSIT/GETALL/SUCCESS',
27 | payload: {
28 | eth: [ {
29 | transactionHash: 'toto'
30 | } ],
31 | erc20: [ {
32 | transactionHash: 'toto'
33 | } ]
34 | }
35 | };
36 |
37 | const expected = {
38 | eth: { 'toto': { transactionHash: 'toto' } },
39 | erc20: { 'toto': { transactionHash: 'toto' } }
40 | };
41 |
42 | const newState = depositReducer(undefined, action);
43 | expect(newState).toEqual(expected);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/exitReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import exitReducer from '../exitReducer';
17 |
18 | describe('exitReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = exitReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({ pending: {}, exited: {} });
22 | });
23 |
24 | it('should handle exit fetch success', () => {
25 | const action = {
26 | type: 'EXIT/GETALL/SUCCESS',
27 | payload: { pending: [ 'toto' ], exited: [ 'toto' ] }
28 | };
29 | const newState = exitReducer(undefined, action);
30 | expect(newState).toEqual(action.payload);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/feeReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import feeReducer from '../feeReducer';
17 |
18 | describe('feeReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = feeReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({});
22 | });
23 |
24 | it('should handle fee fetch success', () => {
25 | const action = {
26 | type: 'FEE/GET/SUCCESS',
27 | payload: [
28 | { currency: 'ETH', amount: 1 },
29 | { currency: 'OMG', amount: 10 }
30 | ]
31 | };
32 | const newState = feeReducer(undefined, action);
33 | expect(newState).toEqual({
34 | ETH: { currency: 'ETH', amount: 1 },
35 | OMG: { currency: 'OMG', amount: 10 }
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/gasReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import gasReducer from '../gasReducer';
17 |
18 | describe('gasReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = gasReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({ slow: 0, normal: 0, fast: 0 });
22 | });
23 |
24 | it('should handle gas fetch success', () => {
25 | const action = {
26 | type: 'GAS/GET/SUCCESS',
27 | payload: { slow: 1, normal: 10, fast: 100 }
28 | };
29 | const newState = gasReducer(undefined, action);
30 | expect(newState).toEqual(action.payload);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/loadingReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import loadingReducer from '../loadingReducer';
17 |
18 | describe('loadingReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = loadingReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({});
22 | });
23 |
24 | it('should handle request correctly', () => {
25 | const action = { type: 'TEST/GET/REQUEST' };
26 | const newState = loadingReducer(undefined, action);
27 | expect(newState).toEqual({ 'TEST/GET': true });
28 | });
29 |
30 | it('should cancel loading state on non request correctly', () => {
31 | const action = { type: 'TEST/GET/SUCCESS' };
32 | const newState = loadingReducer(undefined, action);
33 | expect(newState).toEqual({ 'TEST/GET': false });
34 |
35 | const action2 = { type: 'TEST/GET/ERROR' };
36 | const newState2 = loadingReducer(undefined, action2);
37 | expect(newState2).toEqual({ 'TEST/GET': false });
38 | });
39 |
40 | it('should pass through other action types', () => {
41 | const action = { type: 'TEST/MODAL/OPEN' };
42 | const newState = loadingReducer(undefined, action);
43 | expect(newState).toEqual({});
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/queueReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import queueReducer from '../queueReducer';
17 |
18 | describe('queueReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = queueReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({});
22 | });
23 |
24 | it('should handle queue fetch success', () => {
25 | const action = {
26 | type: 'QUEUE/GET/SUCCESS',
27 | payload: { currency: 'ETH', queue: [ 1,2,3 ] }
28 | };
29 | const newState = queueReducer(undefined, action);
30 | expect(newState).toEqual({ ETH: [ 1,2,3 ] });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/setupReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import setupReducer from '../setupReducer';
17 |
18 | describe('setupReducer', () => {
19 | it('should return the initial state', () => {
20 | const initialState = { walletMethod: 'WalletConnect' };
21 | const newState = setupReducer(initialState, { type: 'ACTION/NOT/EXIST' });
22 | expect(newState).toEqual(initialState);
23 | });
24 |
25 | it('should handle setting the wallet method', () => {
26 | const initialState = { walletMethod: null };
27 | const action = {
28 | type: 'SETUP/WALLET_METHOD/SET',
29 | payload: 'WalletConnect'
30 | };
31 | const newState = setupReducer(initialState, action);
32 | expect(newState).toEqual({ ...initialState, walletMethod: 'WalletConnect' });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/statusReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import statusReducer from '../statusReducer';
17 |
18 | describe('statusReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = statusReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({ connection: false, byzantine: false });
22 | });
23 |
24 | it('should handle status fetch success', () => {
25 | const action = {
26 | type: 'STATUS/GET/SUCCESS',
27 | payload: { connection: true, byzantine: false }
28 | };
29 | const newState = statusReducer(undefined, action);
30 | expect(newState).toEqual(action.payload);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/tokenReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import tokenReducer from '../tokenReducer';
17 |
18 | describe('tokenReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = tokenReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({
22 | '0x0000000000000000000000000000000000000000': {
23 | currency: '0x0000000000000000000000000000000000000000',
24 | decimals: 18,
25 | name: 'ETH'
26 | }
27 | });
28 | });
29 |
30 | it('should handle token fetch success', () => {
31 | const action = {
32 | type: 'TOKEN/GET/SUCCESS',
33 | payload: { currency: '0xomg', decimals: 18, name: 'OMG' }
34 | };
35 | const newState = tokenReducer(undefined, action);
36 | expect(newState).toEqual({
37 | '0x0000000000000000000000000000000000000000': { currency: '0x0000000000000000000000000000000000000000', decimals: 18, name: 'ETH' },
38 | '0xomg': { currency: '0xomg', decimals: 18, name: 'OMG' }
39 | });
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/transactionReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import transactionReducer from '../transactionReducer';
17 |
18 | describe('transactionReducer', () => {
19 | it('should return the initial state', () => {
20 | const newState = transactionReducer(undefined, { type: '@@INIT' });
21 | expect(newState).toEqual({});
22 | });
23 |
24 | it('should handle transaction fetch success', () => {
25 | const action = {
26 | type: 'TRANSACTION/GETALL/SUCCESS',
27 | payload: [ { txhash: '0x1', metadata: 'toto' } ]
28 | };
29 | const newState = transactionReducer(undefined, action);
30 | expect(newState).toEqual({
31 | '0x1': { txhash: '0x1', metadata: 'toto' }
32 | });
33 | });
34 |
35 | it('should handle transfer create success', () => {
36 | const action = {
37 | type: 'TRANSFER/CREATE/SUCCESS',
38 | payload: { txhash: '0x1', metadata: 'toto' }
39 | };
40 | const newState = transactionReducer(undefined, action);
41 | expect(newState).toEqual({
42 | '0x1': { txhash: '0x1', metadata: 'toto' }
43 | });
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/src/reducers/__tests__/uiReducer.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import uiReducer from '../uiReducer';
17 |
18 | const initialState = {
19 | depositModal: false,
20 | transferModal: false,
21 | exitModal: false,
22 | mergeModal: false,
23 | wrongNetworkModal: false,
24 | ledger: false,
25 | ledgerConnectModal: true,
26 | activeHistoryTab: 'Transactions',
27 | alert: null,
28 | error: null
29 | };
30 |
31 | describe('uiReducer', () => {
32 | it('should return the initial state', () => {
33 | const newState = uiReducer(undefined, { type: '@@INIT' });
34 | expect(newState).toEqual(initialState);
35 | });
36 |
37 | it('should handle modal open', () => {
38 | const action = {
39 | type: 'UI/MODAL/OPEN',
40 | payload: 'depositModal'
41 | };
42 | const newState = uiReducer(undefined, action);
43 | expect(newState).toEqual({ ...initialState, depositModal: true });
44 | });
45 |
46 | it('should handle modal close', () => {
47 | const action = {
48 | type: 'UI/MODAL/CLOSE',
49 | payload: 'depositModal'
50 | };
51 | const newState = uiReducer(undefined, action);
52 | expect(newState).toEqual(initialState);
53 | });
54 |
55 | it('should handle new alert', () => {
56 | const action = {
57 | type: 'UI/ALERT/UPDATE',
58 | payload: 'oops'
59 | };
60 | const newState = uiReducer(undefined, action);
61 | expect(newState).toEqual({ ...initialState, alert: 'oops' });
62 | });
63 |
64 | it('should handle new error', () => {
65 | const action = {
66 | type: 'UI/ERROR/UPDATE',
67 | payload: 'oops'
68 | };
69 | const newState = uiReducer(undefined, action);
70 | expect(newState).toEqual({ ...initialState, error: 'oops' });
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/src/reducers/balanceReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialState = {
17 | rootchain: [],
18 | childchain: []
19 | };
20 |
21 | function balanceReducer (state = initialState, action) {
22 | switch (action.type) {
23 | case 'BALANCE/GET/SUCCESS':
24 | const { rootchain, childchain } = action.payload;
25 | return { ...state, rootchain, childchain };
26 | default:
27 | return state;
28 | }
29 | }
30 |
31 | export default balanceReducer;
32 |
--------------------------------------------------------------------------------
/src/reducers/depositReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { keyBy } from 'lodash';
17 |
18 | const initialState = {
19 | eth: {},
20 | erc20: {}
21 | };
22 |
23 | function depositReducer (state = initialState, action) {
24 | switch (action.type) {
25 | case 'DEPOSIT/CREATE/SUCCESS':
26 | const isEth = action.payload.isEth;
27 | if (isEth) {
28 | return {
29 | ...state,
30 | eth: {
31 | ...state.eth,
32 | [action.payload.transactionHash]: action.payload
33 | }
34 | };
35 | }
36 | return {
37 | ...state,
38 | erc20: {
39 | ...state.erc20,
40 | [action.payload.transactionHash]: action.payload
41 | }
42 | };
43 | case 'DEPOSIT/CHECKALL/SUCCESS':
44 | case 'DEPOSIT/GETALL/SUCCESS':
45 | const { eth, erc20 } = action.payload;
46 | return {
47 | ...state,
48 | eth: {
49 | ...state.eth,
50 | ...keyBy(eth, 'transactionHash')
51 | },
52 | erc20: {
53 | ...state.erc20,
54 | ...keyBy(erc20, 'transactionHash')
55 | }
56 | };
57 | default:
58 | return state;
59 | }
60 | }
61 |
62 | export default depositReducer;
63 |
--------------------------------------------------------------------------------
/src/reducers/exitReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { keyBy } from 'lodash';
17 |
18 | const initialState = {
19 | pending: {},
20 | exited: {}
21 | };
22 |
23 | function exitReducer (state = initialState, action) {
24 | switch (action.type) {
25 | case 'EXIT/GETALL/SUCCESS':
26 | // action.payload will be null on an event timeout, so return old state
27 | if (!action.payload) {
28 | return state;
29 | }
30 | return { ...state, ...action.payload };
31 | case 'EXIT/CREATE/SUCCESS':
32 | return {
33 | ...state,
34 | pending: {
35 | ...state.pending,
36 | [action.payload.transactionHash]: action.payload
37 | }
38 | };
39 | case 'EXIT/CHECKALL/SUCCESS':
40 | return {
41 | ...state,
42 | pending: {
43 | ...state.pending,
44 | ...keyBy(action.payload, 'transactionHash')
45 | }
46 | };
47 | default:
48 | return state;
49 | }
50 | }
51 |
52 | export default exitReducer;
53 |
--------------------------------------------------------------------------------
/src/reducers/feeReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { keyBy } from 'lodash';
17 | const initialState = {};
18 |
19 | function feeReducer (state = initialState, action) {
20 | switch (action.type) {
21 | case 'FEE/GET/SUCCESS':
22 | return { ...state, ...keyBy(action.payload, 'currency') };
23 | default:
24 | return state;
25 | }
26 | }
27 |
28 | export default feeReducer;
29 |
--------------------------------------------------------------------------------
/src/reducers/gasReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialState = {
17 | slow: 0,
18 | normal: 0,
19 | fast: 0
20 | };
21 |
22 | function gasReducer (state = initialState, action) {
23 | switch (action.type) {
24 | case 'GAS/GET/SUCCESS':
25 | return { ...state, ...action.payload };
26 | default:
27 | return state;
28 | }
29 | }
30 |
31 | export default gasReducer;
32 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { combineReducers } from 'redux';
17 |
18 | import loadingReducer from './loadingReducer';
19 | import depositReducer from './depositReducer';
20 | import transactionReducer from './transactionReducer';
21 | import statusReducer from './statusReducer';
22 | import balanceReducer from './balanceReducer';
23 | import exitReducer from './exitReducer';
24 | import queueReducer from './queueReducer';
25 | import tokenReducer from './tokenReducer';
26 | import feeReducer from './feeReducer';
27 | import gasReducer from './gasReducer';
28 | import uiReducer from './uiReducer';
29 | import setupReducer from './setupReducer';
30 |
31 | const rootReducer = combineReducers({
32 | loading: loadingReducer,
33 | deposit: depositReducer,
34 | transaction: transactionReducer,
35 | status: statusReducer,
36 | balance: balanceReducer,
37 | exit: exitReducer,
38 | queue: queueReducer,
39 | token: tokenReducer,
40 | fees: feeReducer,
41 | gas: gasReducer,
42 | ui: uiReducer,
43 | setup: setupReducer
44 | });
45 |
46 | export default rootReducer;
47 |
--------------------------------------------------------------------------------
/src/reducers/loadingReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialLoadingState = {};
17 |
18 | function loadingReducer (state = initialLoadingState, action) {
19 | const segments = action.type.split('/');
20 | const requestName = `${segments[0]}/${segments[1]}`;
21 | const requestState = segments[2];
22 |
23 | if (
24 | requestState !== 'REQUEST' &&
25 | requestState !== 'SUCCESS' &&
26 | requestState !== 'ERROR'
27 | ) {
28 | return state;
29 | }
30 |
31 | return {
32 | ...state,
33 | [requestName]: requestState === 'REQUEST'
34 | };
35 | }
36 |
37 | export default loadingReducer;
38 |
--------------------------------------------------------------------------------
/src/reducers/queueReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialState = {};
17 |
18 | function queueReducer (state = initialState, action) {
19 | switch (action.type) {
20 | case 'QUEUE/GET/SUCCESS':
21 | if (action.payload) {
22 | const { currency, queue } = action.payload;
23 | return { ...state, [currency]: queue };
24 | }
25 | return state;
26 | default:
27 | return state;
28 | }
29 | }
30 |
31 | export default queueReducer;
32 |
--------------------------------------------------------------------------------
/src/reducers/setupReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialState = {
17 | walletMethod: null
18 | };
19 |
20 | function setupReducer (state = initialState, action) {
21 | switch (action.type) {
22 | case 'SETUP/WALLET_METHOD/SET':
23 | return { ...state, walletMethod: action.payload };
24 | default:
25 | return state;
26 | }
27 | }
28 |
29 | export default setupReducer;
30 |
--------------------------------------------------------------------------------
/src/reducers/statusReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialState = {
17 | connection: false,
18 | byzantine: false
19 | };
20 |
21 | function statusReducer (state = initialState, action) {
22 | switch (action.type) {
23 | case 'STATUS/GET/SUCCESS':
24 | return { ...state, ...action.payload };
25 | case 'ETHSTATS/GET/SUCCESS':
26 | if (action.payload) {
27 | return { ...state, ...action.payload };
28 | }
29 | return state;
30 | default:
31 | return state;
32 | }
33 | }
34 |
35 | export default statusReducer;
36 |
--------------------------------------------------------------------------------
/src/reducers/tokenReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const eth = '0x0000000000000000000000000000000000000000';
17 | const initialState = {
18 | [eth]: {
19 | currency: eth,
20 | decimals: 18,
21 | name: 'ETH'
22 | }
23 | };
24 |
25 | function tokenReducer (state = initialState, action) {
26 | switch (action.type) {
27 | case 'TOKEN/GET/SUCCESS':
28 | return { ...state, [action.payload.currency]: action.payload };
29 | default:
30 | return state;
31 | }
32 | }
33 |
34 | export default tokenReducer;
35 |
--------------------------------------------------------------------------------
/src/reducers/transactionReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { keyBy } from 'lodash';
17 | const initialState = {};
18 |
19 | function transactionReducer (state = initialState, action) {
20 | switch (action.type) {
21 | case 'TRANSACTION/GETALL/SUCCESS':
22 | return { ...state, ...keyBy(action.payload, 'txhash') };
23 | case 'TRANSFER/CREATE/SUCCESS':
24 | return { ...state, [action.payload.txhash]: action.payload };
25 | default:
26 | return state;
27 | }
28 | }
29 |
30 | export default transactionReducer;
31 |
--------------------------------------------------------------------------------
/src/reducers/uiReducer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | const initialState = {
17 | depositModal: false,
18 | transferModal: false,
19 | exitModal: false,
20 | mergeModal: false,
21 | wrongNetworkModal: false,
22 | ledgerConnectModal: true,
23 | ledger: false,
24 | alert: null,
25 | error: null,
26 | activeHistoryTab: 'Transactions'
27 | };
28 |
29 | function uiReducer (state = initialState, action) {
30 | switch (action.type) {
31 | case 'UI/MODAL/OPEN':
32 | return { ...state, [action.payload]: true };
33 | case 'UI/MODAL/CLOSE':
34 | return { ...state, [action.payload]: false };
35 | case 'UI/ALERT/UPDATE':
36 | return { ...state, alert: action.payload };
37 | case 'UI/ERROR/UPDATE':
38 | return { ...state, error: action.payload };
39 | case 'UI/LEDGER/UPDATE':
40 | return { ...state, ledger: action.payload };
41 | case 'UI/HISTORYTAB/UPDATE':
42 | return { ...state, activeHistoryTab: action.payload };
43 | default:
44 | return state;
45 | }
46 | }
47 |
48 | export default uiReducer;
49 |
--------------------------------------------------------------------------------
/src/selectors/balanceSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectRootchainBalance (state) {
17 | return state.balance.rootchain;
18 | }
19 |
20 | export function selectChildchainBalance (state) {
21 | return state.balance.childchain;
22 | }
23 |
--------------------------------------------------------------------------------
/src/selectors/exitSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectPendingExits (state) {
17 | return Object.values(state.exit.pending);
18 | }
19 |
20 | export function selectExitedExits (state) {
21 | return Object.values(state.exit.exited);
22 | }
23 |
--------------------------------------------------------------------------------
/src/selectors/feeSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectFees (state) {
17 | return state.fees;
18 | }
19 |
--------------------------------------------------------------------------------
/src/selectors/gasSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectGas (state) {
17 | return state.gas;
18 | }
19 |
--------------------------------------------------------------------------------
/src/selectors/loadingSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectLoading (requestNames) {
17 | return function (state) {
18 | return requestNames.some(name => state.loading[name]);
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/selectors/queueSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { flatten } from 'lodash';
17 |
18 | export function selectQueue (currency) {
19 | return function (state) {
20 | return state.queue[currency];
21 | };
22 | }
23 |
24 | export function selectQueues (state) {
25 | return state.queue;
26 | }
27 |
28 | export function selectAllQueues (state) {
29 | const queues = Object.values(state.queue);
30 | return flatten(queues);
31 | }
32 |
33 | export function selectQueuedTokens (state) {
34 | return Object.keys(state.queue);
35 | }
36 |
--------------------------------------------------------------------------------
/src/selectors/setupSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectWalletMethod () {
17 | return function (state) {
18 | return state.setup['walletMethod'];
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/selectors/statusSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectConnection (state) {
17 | return state.status.connection;
18 | }
19 |
20 | export function selectByzantine (state) {
21 | return state.status.byzantine;
22 | }
23 |
24 | export function selectIsSynced (state) {
25 | return state.status.watcherSynced;
26 | }
27 |
28 | export function selectLastSeenBlock (state) {
29 | return state.status.lastSeenBlock;
30 | }
31 |
--------------------------------------------------------------------------------
/src/selectors/transactionSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectChildchainTransactions (state) {
17 | return Object.values(state.transaction);
18 | }
19 |
20 | export function selectErc20Deposits (state) {
21 | return Object.values(state.deposit.erc20);
22 | }
23 |
24 | export function selectEthDeposits (state) {
25 | return Object.values(state.deposit.eth);
26 | }
27 |
--------------------------------------------------------------------------------
/src/selectors/uiSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | export function selectModalState (modal) {
17 | return function (state) {
18 | return state.ui[modal];
19 | };
20 | }
21 |
22 | export function selectAlert (state) {
23 | return state.ui.alert;
24 | }
25 |
26 | export function selectError (state) {
27 | return state.ui.error;
28 | }
29 |
30 | export function selectLedger (state) {
31 | return state.ui.ledger;
32 | }
33 |
34 | export function selectActiveHistoryTab (state) {
35 | return state.ui.activeHistoryTab;
36 | }
37 |
--------------------------------------------------------------------------------
/src/services/__mocks__/networkService.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License. */
12 |
13 | const networkService = {
14 | OmgUtil: {
15 | ethErrorReason: jest.fn().mockImplementationOnce(() => Promise.resolve('toto'))
16 | },
17 | web3: {
18 | eth: {
19 | Contract: function () {
20 | return {
21 | methods: {
22 | symbol: () => ({
23 | call: jest.fn(() => Promise.resolve('OMG'))
24 | }),
25 | decimals: () => ({
26 | call: jest.fn(() => Promise.resolve(18))
27 | })
28 | }
29 | };
30 | }
31 | }
32 | },
33 | checkStatus: () => Promise.resolve('toto'),
34 | getBalances: () => Promise.resolve('toto'),
35 | getAllTransactions: () => Promise.resolve('toto'),
36 | getDeposits: () => Promise.resolve('toto'),
37 | getExits: () => Promise.resolve('toto'),
38 | checkForExitQueue: () => Promise.resolve(true),
39 | getExitQueue: () => Promise.resolve('toto'),
40 | addExitQueue: () => Promise.resolve('toto'),
41 | exitUtxo: () => Promise.resolve('toto'),
42 | depositEth: () => Promise.resolve('toto'),
43 | processExits: () => Promise.resolve('toto'),
44 | transfer: () => Promise.resolve('toto'),
45 | mergeUtxos: () => Promise.resolve('toto'),
46 | getGasPrice: () => Promise.resolve('toto'),
47 | fetchFees: () => Promise.resolve([ 1, 2, 3 ])
48 | };
49 |
50 | export default networkService;
51 |
--------------------------------------------------------------------------------
/src/services/errorService.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import * as Sentry from '@sentry/react';
17 | import config from 'util/config';
18 |
19 | import { openError } from 'actions/uiAction';
20 |
21 | if (config.sentry) {
22 | Sentry.init({ dsn: config.sentry });
23 | }
24 |
25 | const errorCache = [];
26 | const noLogErrors = [
27 | 'user denied',
28 | 'user rejected',
29 | 'user canceled',
30 | 'user cancelled'
31 | ];
32 |
33 | export class WebWalletError extends Error {
34 | constructor ({
35 | originalError,
36 | customErrorMessage,
37 | reportToSentry,
38 | reportToUi
39 | }) {
40 | super(originalError.message);
41 | this._originalError = originalError;
42 | this._customErrorMessage = customErrorMessage;
43 | this._reportToSentry = reportToSentry;
44 | this._reportToUi = reportToUi;
45 | }
46 |
47 | report (dispatchMethod) {
48 | const metamaskHeaderNotFoundCode = -3200;
49 | if (
50 | noLogErrors.find(i => this._originalError.message && this._originalError.message.toLowerCase().includes(i)) ||
51 | this._originalError.code === metamaskHeaderNotFoundCode
52 | ) {
53 | return;
54 | }
55 |
56 | if (this._reportToSentry && config.sentry) {
57 | if (!errorCache.includes(this._originalError.message)) {
58 | errorCache.push(this._originalError.message);
59 | try {
60 | Sentry.captureException(this._originalError);
61 | } catch (error) {
62 | //
63 | }
64 | }
65 | }
66 |
67 | if (this._reportToUi) {
68 | dispatchMethod(
69 | openError(this._customErrorMessage || this._originalError.message || 'Something went wrong.')
70 | );
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/store/__mocks__/index.js:
--------------------------------------------------------------------------------
1 | import configureMockStore from 'redux-mock-store';
2 | import thunk from 'redux-thunk';
3 |
4 | const middlewares = [ thunk ];
5 | const mockStore = configureMockStore(middlewares);
6 |
7 | const store = mockStore({
8 | fees: {},
9 | token: {
10 | '0x0000000000000000000000000000000000000000': {
11 | currency: '0x0000000000000000000000000000000000000000',
12 | decimals: 18,
13 | name: 'ETH'
14 | }
15 | }
16 | });
17 |
18 | export default store;
19 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import reduxThunk from 'redux-thunk';
17 | import * as Sentry from '@sentry/react';
18 | import { composeWithDevTools } from 'redux-devtools-extension';
19 | import { createStore, applyMiddleware } from 'redux';
20 | import reducers from 'reducers';
21 |
22 | const initialState = {};
23 |
24 | const sentryReduxEnhancer = Sentry.createReduxEnhancer({
25 | configureScopeWithState: (scope, state) => {
26 | scope.setTag('wallet-method', state.setup.walletMethod);
27 | },
28 | stateTransformer: state => {
29 | return {
30 | status: state.status,
31 | ui: state.ui,
32 | setup: state.setup
33 | };
34 | }
35 | });
36 |
37 | const store = createStore(
38 | reducers,
39 | initialState,
40 | composeWithDevTools (
41 | applyMiddleware(reduxThunk),
42 | sentryReduxEnhancer
43 | )
44 | );
45 |
46 | export default store;
47 |
--------------------------------------------------------------------------------
/src/util/__tests__/amountConvert.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { logAmount, powAmount } from 'util/amountConvert';
17 |
18 | describe('logAmount', () => {
19 | it('renders the highest denomination as a string', () => {
20 | const res = logAmount('1', 18);
21 | expect(res).toBe('0.000000000000000001');
22 | expect(typeof res).toBe('string');
23 | });
24 |
25 | it('can safely accept any amount or power type', () => {
26 | const res = logAmount(1, 18);
27 | expect(res).toBe('0.000000000000000001');
28 |
29 | const res2 = logAmount('1.0', '18');
30 | expect(res2).toBe('0.000000000000000001');
31 | });
32 |
33 | it('can handle unsafe numbers', () => {
34 | const res = logAmount('999999999999999999999999999999999', 18);
35 | expect(res).toBe('999999999999999.999999999999999999');
36 | });
37 | });
38 |
39 | describe('powAmount', () => {
40 | it('renders the lowest denomination as a string', () => {
41 | const res = powAmount('1', 18);
42 | expect(res).toBe('1000000000000000000');
43 | expect(typeof res).toBe('string');
44 | });
45 |
46 | it('can safely accept any amount or power type', () => {
47 | const res = powAmount(1, 18);
48 | expect(res).toBe('1000000000000000000');
49 |
50 | const res2 = powAmount('1.0', '18');
51 | expect(res2).toBe('1000000000000000000');
52 | });
53 |
54 | it('can handle unsafe numbers', () => {
55 | const res = powAmount('999999999999999999999999999999999', 18);
56 | expect(res).toBe('999999999999999999999999999999999000000000000000000');
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/src/util/amountConvert.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | // we use BigNumber here for decimal support
17 | import BigNumber from 'bignumber.js';
18 |
19 | export function logAmount (amount, power) {
20 | const x = new BigNumber(amount);
21 | const exp = new BigNumber(10).pow(power);
22 |
23 | const calculated = x.div(exp);
24 | return calculated.toFixed();
25 | }
26 |
27 | export function powAmount (amount, power) {
28 | const x = new BigNumber(amount);
29 | const exp = new BigNumber(10).pow(power);
30 |
31 | const calculated = x.multipliedBy(exp);
32 | return calculated.toFixed(0);
33 | }
34 |
--------------------------------------------------------------------------------
/src/util/config.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import env from '@beam-australia/react-env';
17 |
18 | export default {
19 | watcherUrl: env('WATCHER_URL'),
20 | plasmaAddress: env('PLASMA_ADDRESS'),
21 | blockExplorerUrl: env('BLOCKEXPLORER_URL'),
22 | etherscanUrl: env('ETHERSCAN_URL'),
23 | checkSyncInterval: env('SYNC_INTERVAL'),
24 | pollInterval: env('POLL_INTERVAL'),
25 | network: env('NETWORK'),
26 | alternateWallets: env('ALTERNATE_WALLETS'),
27 | sentry: env('SENTRY_DSN'),
28 | gtmId: env('GTM_ID'),
29 | rpcProxy: env('RPC_PROXY')
30 | };
31 |
--------------------------------------------------------------------------------
/src/util/networkName.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { omit } from 'lodash';
17 | import config from 'util/config';
18 |
19 | const networkMap = {
20 | 'ropsten': 'Ropsten Test Network',
21 | 'main': 'Main Ethereum Network',
22 | 'rinkeby': 'Rinkeby Test Network',
23 | 'kovan': 'Kovan Test Network',
24 | 'private': 'Private Network'
25 | };
26 |
27 | const shortNetworkMap = {
28 | 'ropsten': 'Ropsten',
29 | 'main': 'Mainnet',
30 | 'rinkeby': 'Rinkeby',
31 | 'kovan': 'Kovan',
32 | 'private': 'Private'
33 | };
34 |
35 | export function getNetworkName () {
36 | return networkMap[config.network];
37 | }
38 |
39 | export function getShortNetworkName () {
40 | return shortNetworkMap[config.network];
41 | }
42 |
43 | export function getOtherNetworks () {
44 | const otherNetworks = omit(networkMap, [ 'private', config.network ]);
45 | return Object.values(otherNetworks);
46 | }
47 |
48 | export function getAlternateNetworks () {
49 | const rawAlternates = config.alternateWallets;
50 | if (!rawAlternates) {
51 | return [];
52 | }
53 | const options = rawAlternates.split('|');
54 |
55 | const networks = [];
56 | options.forEach(option => {
57 | const [ networkName, networkUrl ] = option.split(',');
58 | networks.push({
59 | name: networkName.trim(),
60 | url: networkUrl.trim()
61 | });
62 | });
63 |
64 | return networks;
65 | }
66 |
--------------------------------------------------------------------------------
/src/util/useInterval.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-present OmiseGO Pte Ltd
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License. */
15 |
16 | import { useEffect, useRef } from 'react';
17 |
18 | export default function useInterval (callback, delay) {
19 | const savedCallback = useRef();
20 |
21 | useEffect(() => {
22 | savedCallback.current = callback;
23 | }, [ callback ]);
24 |
25 | useEffect(() => {
26 | function tick () {
27 | savedCallback.current();
28 | }
29 | if (delay !== null) {
30 | tick();
31 | let id = setInterval(tick, delay);
32 | return () => clearInterval(id);
33 | }
34 | }, [ delay ]);
35 | }
36 |
--------------------------------------------------------------------------------