├── .gitignore
├── CONTRIBUTING.md
├── Dockerfile-traefik
├── README.md
├── app
├── .dockerignore
├── .eslintrc
├── Dockerfile
├── nginx.conf
├── package.json
├── postinstall
│ ├── config
│ │ └── webpack.config.js
│ └── scripts
│ │ └── watch.js
└── sources
│ ├── extensionStoresMedia
│ ├── chromestore_icon_128.jpg
│ ├── chromestore_promo_1400x560.jpg
│ ├── chromestore_promo_1400x560.psd
│ ├── chromestore_promo_440x280.jpg
│ └── chromestore_promo_920x680.jpg
│ ├── public
│ ├── _locales
│ │ └── en
│ │ │ └── messages.json
│ ├── assets
│ │ ├── icon128.png
│ │ ├── icon16.png
│ │ ├── icon48.png
│ │ └── icons
│ │ │ └── vendors
│ │ │ ├── bear.svg
│ │ │ ├── bird.svg
│ │ │ ├── cat.svg
│ │ │ ├── chicken.svg
│ │ │ ├── dog.svg
│ │ │ ├── elephant.svg
│ │ │ ├── fish.svg
│ │ │ ├── frog.svg
│ │ │ ├── gorilla.svg
│ │ │ ├── horse.svg
│ │ │ ├── lion.svg
│ │ │ ├── penguin.svg
│ │ │ ├── shark.svg
│ │ │ └── squirrel.svg
│ ├── content.js
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
│ └── src
│ ├── assets
│ ├── fonts
│ │ ├── Montserrat-Bold.ttf
│ │ ├── Montserrat-Italic.ttf
│ │ ├── Montserrat-Light.ttf
│ │ ├── Montserrat-Medium.ttf
│ │ ├── Montserrat-Regular.ttf
│ │ └── Montserrat-Semibold.ttf
│ ├── icons
│ │ ├── android-alert.svg
│ │ ├── android.svg
│ │ ├── apple.svg
│ │ ├── arrow-left.svg
│ │ ├── arrow-right-c.svg
│ │ ├── arrow-right.svg
│ │ ├── arrow-swap.svg
│ │ ├── assets
│ │ │ ├── altcoins.svg
│ │ │ ├── bch.svg
│ │ │ ├── btc.svg
│ │ │ ├── dash.svg
│ │ │ ├── eth.svg
│ │ │ ├── lightning.svg
│ │ │ ├── lnbtc.svg
│ │ │ └── ltc.svg
│ │ ├── back.svg
│ │ ├── bookmark.svg
│ │ ├── check-circle.svg
│ │ ├── checkmark-circled.svg
│ │ ├── chevron-down.svg
│ │ ├── chevron-right.svg
│ │ ├── chevron-up.svg
│ │ ├── chevrons-down.svg
│ │ ├── chrome.svg
│ │ ├── clock.svg
│ │ ├── close-circled.svg
│ │ ├── close.svg
│ │ ├── copy.svg
│ │ ├── forward.svg
│ │ ├── hamburger.svg
│ │ ├── help-circled.svg
│ │ ├── info.svg
│ │ ├── information-circled.svg
│ │ ├── linux.svg
│ │ ├── log-in.svg
│ │ ├── log-out.svg
│ │ ├── loop.svg
│ │ ├── macos.svg
│ │ ├── message-square.svg
│ │ ├── paper.svg
│ │ ├── pause.svg
│ │ ├── play.svg
│ │ ├── plus-circle.svg
│ │ ├── receive.svg
│ │ ├── reply.svg
│ │ ├── send.svg
│ │ ├── settings.svg
│ │ ├── social
│ │ │ ├── github.svg
│ │ │ ├── medium.svg
│ │ │ ├── slack.svg
│ │ │ ├── twitter.svg
│ │ │ └── youtube.svg
│ │ ├── url.svg
│ │ ├── vendors
│ │ │ ├── bear.svg
│ │ │ ├── bird.svg
│ │ │ ├── cat.svg
│ │ │ ├── chicken.svg
│ │ │ ├── dog.svg
│ │ │ ├── elephant.svg
│ │ │ ├── fish.svg
│ │ │ ├── frog.svg
│ │ │ ├── gorilla.svg
│ │ │ ├── horse.svg
│ │ │ ├── lion.svg
│ │ │ ├── penguin.svg
│ │ │ ├── shark.svg
│ │ │ └── squirrel.svg
│ │ ├── windows.svg
│ │ └── x-circle.svg
│ └── img
│ │ └── logo
│ │ ├── compact.png
│ │ ├── full.png
│ │ ├── full_clean.png
│ │ └── textOnly.png
│ ├── background.js
│ ├── components
│ ├── AssetChip
│ │ ├── index.js
│ │ ├── index.module.css
│ │ └── view.js
│ ├── BalanceSummary
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── CheckDestination
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── LoginForm
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── PaymentConfirmation
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── PaymentDetails
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── PaymentsGroup
│ │ ├── PaymentItem
│ │ │ ├── index.js
│ │ │ ├── styles.js
│ │ │ └── view.js
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── ReceivePayment
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── RestoreForm
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── SelectReceiveAsset
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── SettingsForm
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── SignupForm
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ └── common
│ │ ├── BackButton.js
│ │ ├── Button.js
│ │ ├── CopyButton.js
│ │ ├── Form.js
│ │ ├── Header.js
│ │ ├── Icon.js
│ │ ├── Input.js
│ │ ├── Message.js
│ │ ├── Nav.js
│ │ ├── Select.js
│ │ ├── index.js
│ │ └── utils.js
│ ├── index.js
│ ├── locales
│ ├── en.js
│ └── index.js
│ ├── registerServiceWorker.js
│ ├── scenes
│ ├── Check
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Confirm
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Landing
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Login
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Payment
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Payments
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Receive
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Restore
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Select
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── Settings
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ └── Signup
│ │ ├── index.js
│ │ ├── styles.js
│ │ └── view.js
│ ├── setupProxy.js
│ ├── stores
│ ├── accounts.js
│ ├── dataGeneric.js
│ ├── denominations.js
│ ├── index.js
│ ├── info.js
│ ├── payments.js
│ ├── settings.js
│ ├── ui.js
│ ├── vendors.js
│ └── wallets.js
│ ├── styles.js
│ └── utils
│ ├── GA.js
│ ├── HA.js
│ ├── LiveChat.js
│ ├── cryptonetChecker.js
│ └── logging.js
├── docker-compose-build.yml
├── docker-compose-dev.yml
├── docker-compose.yml
├── package.json
└── traefik.toml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/node
2 |
3 | ### Node ###
4 | # Logs
5 | logs
6 | *.log
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 |
11 | # Runtime data
12 | pids
13 | *.pid
14 | *.seed
15 | *.pid.lock
16 |
17 | # Directory for instrumented libs generated by jscoverage/JSCover
18 | lib-cov
19 |
20 | # Coverage directory used by tools like istanbul
21 | coverage
22 |
23 | # nyc test coverage
24 | .nyc_output
25 |
26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27 | .grunt
28 |
29 | # Bower dependency directory (https://bower.io/)
30 | bower_components
31 |
32 | # node-waf configuration
33 | .lock-wscript
34 |
35 | # Compiled binary addons (https://nodejs.org/api/addons.html)
36 | build/Release
37 |
38 | # Dependency directories
39 | node_modules/
40 | jspm_packages/
41 |
42 | # TypeScript v1 declaration files
43 | typings/
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 |
63 | # parcel-bundler cache (https://parceljs.org/)
64 | .cache
65 |
66 | # next.js build output
67 | .next
68 |
69 | # nuxt.js build output
70 | .nuxt
71 |
72 | # vuepress build output
73 | .vuepress/dist
74 |
75 | # Serverless directories
76 | .serverless
77 |
78 |
79 | # End of https://www.gitignore.io/api/node
80 |
81 | # Misc
82 | .DS_Store
83 | .env.local
84 | .env.development.local
85 | .env.test.local
86 | .env.production.local
87 | .vscode
88 |
89 | build*
90 |
91 | *token.txt
92 |
--------------------------------------------------------------------------------
/Dockerfile-traefik:
--------------------------------------------------------------------------------
1 | FROM traefik:alpine
2 |
3 | # -----------------------------------------------------------------------------
4 | # Configure proxy
5 | # -----------------------------------------------------------------------------
6 |
7 | COPY ./traefik.toml /etc/traefik/traefik.toml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
", "tabs", "http://lvh.me/*"],
46 | "web_accessible_resources": ["inpage.js", "phishing.html", "index.html", "assets/*"],
47 | "externally_connectable": {
48 | "matches": ["*://*.bitlum.io/*"],
49 | "ids": ["*"]
50 | },
51 | "content_security_policy": "script-src 'self' https://*.intercomcdn.com https://*.intercom.io https://www.google-analytics.com https://*.heapanalytics.com; object-src 'self';img-src * 'self' data:; style-src * 'unsafe-inline';"
52 | }
53 |
--------------------------------------------------------------------------------
/app/sources/src/assets/fonts/Montserrat-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/fonts/Montserrat-Bold.ttf
--------------------------------------------------------------------------------
/app/sources/src/assets/fonts/Montserrat-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/fonts/Montserrat-Italic.ttf
--------------------------------------------------------------------------------
/app/sources/src/assets/fonts/Montserrat-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/fonts/Montserrat-Light.ttf
--------------------------------------------------------------------------------
/app/sources/src/assets/fonts/Montserrat-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/fonts/Montserrat-Medium.ttf
--------------------------------------------------------------------------------
/app/sources/src/assets/fonts/Montserrat-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/fonts/Montserrat-Regular.ttf
--------------------------------------------------------------------------------
/app/sources/src/assets/fonts/Montserrat-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/fonts/Montserrat-Semibold.ttf
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/android-alert.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/android.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/apple.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
11 |
12 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/arrow-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/arrow-right-c.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/arrow-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/arrow-swap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/altcoins.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/bch.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
11 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/btc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/dash.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
11 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/eth.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/lightning.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
11 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/lnbtc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/assets/ltc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
11 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/back.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/bookmark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/check-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/checkmark-circled.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/chevron-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/chevron-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/chevron-up.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/chevrons-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/chrome.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
11 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/clock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/close-circled.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/copy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/forward.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/hamburger.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/help-circled.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/info.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/information-circled.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/linux.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/log-in.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/log-out.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/loop.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
10 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/message-square.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/paper.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/plus-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/receive.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/reply.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/send.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/settings.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/social/github.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/social/medium.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Monogram
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/social/slack.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/social/twitter.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/social/youtube.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/url.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/vendors/bird.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
17 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/vendors/cat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
13 |
21 |
23 |
25 |
27 |
36 |
38 |
39 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/vendors/fish.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
16 |
24 |
26 |
27 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/vendors/frog.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
13 |
20 |
30 |
33 |
34 |
36 |
38 |
40 |
41 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/vendors/penguin.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
10 |
17 |
31 |
33 |
34 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/windows.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/sources/src/assets/icons/x-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/sources/src/assets/img/logo/compact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/img/logo/compact.png
--------------------------------------------------------------------------------
/app/sources/src/assets/img/logo/full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/img/logo/full.png
--------------------------------------------------------------------------------
/app/sources/src/assets/img/logo/full_clean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/img/logo/full_clean.png
--------------------------------------------------------------------------------
/app/sources/src/assets/img/logo/textOnly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlum/bitlum-front/9308a14c3dca01f8269ef6b617bac61485162c45/app/sources/src/assets/img/logo/textOnly.png
--------------------------------------------------------------------------------
/app/sources/src/components/AssetChip/index.js:
--------------------------------------------------------------------------------
1 | import view from './view';
2 |
3 | export default view;
4 |
--------------------------------------------------------------------------------
/app/sources/src/components/AssetChip/index.module.css:
--------------------------------------------------------------------------------
1 | .root {
2 | display: flex;
3 | align-items: center;
4 | font-weight: 600;
5 | font-size: 2em;
6 | }
7 |
8 | .icon {
9 | height: 1.4em;
10 | width: 1.4em;
11 | margin-right: 0.5em;
12 | }
13 |
14 | .name {
15 | opacity: 0.85;
16 | }
--------------------------------------------------------------------------------
/app/sources/src/components/AssetChip/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 |
13 | // More assets icons here
14 | // https://github.com/cjdowner/cryptocurrency-icons/tree/master/svg/color
15 | import { ReactComponent as BTC } from 'assets/icons/assets/btc.svg';
16 | import { ReactComponent as LNBTC } from 'assets/icons/assets/lightning.svg';
17 | import { ReactComponent as ETH } from 'assets/icons/assets/eth.svg';
18 | import { ReactComponent as DASH } from 'assets/icons/assets/dash.svg';
19 | import { ReactComponent as LTC } from 'assets/icons/assets/ltc.svg';
20 | import { ReactComponent as BCH } from 'assets/icons/assets/bch.svg';
21 |
22 | import styles from './index.module.css';
23 |
24 | // -----------------------------------------------------------------------------
25 | // Code
26 | // -----------------------------------------------------------------------------
27 |
28 | const icons = {
29 | BTC: {
30 | blockchain: ,
31 | lightning: ,
32 | },
33 | ETH: {
34 | blockchain: ,
35 | },
36 | DASH: {
37 | blockchain: ,
38 | },
39 | LTC: {
40 | blockchain: ,
41 | },
42 | BCH: {
43 | blockchain: ,
44 | },
45 | };
46 |
47 | const AssetChip = ({ asset, type, onlyIcon, option, onSelect, onFocus, isFocused, className }) => {
48 | const currentAsset = option ? JSON.parse(option.value).asset : asset;
49 | const currentType = option ? JSON.parse(option.value).type : type;
50 | return (
51 |
52 | {currentAsset && currentType && icons[currentAsset][currentType]}
53 | {onlyIcon ? null : {currentAsset} }
54 |
55 | );
56 | };
57 |
58 | AssetChip.propTypes = {
59 | asset: PropTypes.oneOf(Object.keys(icons)),
60 | type: PropTypes.string,
61 | option: PropTypes.shape({
62 | value: PropTypes.string,
63 | }),
64 | onSelect: PropTypes.func,
65 | onFocus: PropTypes.func,
66 | className: PropTypes.string,
67 | isFocused: PropTypes.bool,
68 | };
69 |
70 | AssetChip.defaultProps = {
71 | asset: 'BTC',
72 | type: 'lightning',
73 | option: null,
74 | onSelect: null,
75 | onFocus: null,
76 | className: '',
77 | isFocused: false,
78 | };
79 |
80 | export default AssetChip;
81 |
--------------------------------------------------------------------------------
/app/sources/src/components/BalanceSummary/index.js:
--------------------------------------------------------------------------------
1 | import { withNamespaces } from 'react-i18next';
2 |
3 | import view from './view';
4 |
5 | export default withNamespaces()(view);
6 |
--------------------------------------------------------------------------------
/app/sources/src/components/BalanceSummary/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import { NavLink } from 'react-router-dom';
13 |
14 | import { P, Img, Span } from 'components/common';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | export * from 'components/common';
21 |
22 | export const Main = styled(P)`
23 | opacity: 0.9;
24 | font-size: 2.3em;
25 | font-weight: 400;
26 | `;
27 |
28 | export const Additional = styled(P)`
29 | font-size: 1em;
30 | font-weight: 600;
31 | opacity: 0.5;
32 | position: absolute;
33 | bottom: 0.8em;
34 | left: 1em;
35 | `;
36 |
37 | export const Receive = styled(NavLink)`
38 | display: flex;
39 | justify-content: center;
40 | align-items: center;
41 | opacity: 0.75;
42 | position: absolute;
43 | top: 0.8em;
44 | right: 1em;
45 | font-weight: 500;
46 | font-size: 0.9em;
47 | &:hover {
48 | opacity: 1;
49 | }
50 | & ${Img} {
51 | filter: invert(100%);
52 | height: 1em;
53 | width: 1em;
54 | margin-left: 0.3em;
55 | margin-top: 0.1em;
56 | }
57 | `;
58 |
59 | export const Send = styled(NavLink)`
60 | font: var(--fonts__header_bold);
61 | margin-top: 1em;
62 | width: 100%;
63 | `;
64 |
65 | export const Root = styled.div`
66 | position: relative;
67 | display: flex;
68 | flex-direction: column;
69 | justify-content: center;
70 | align-items: center;
71 | text-align: center;
72 | font-weight: 200;
73 | & > ${Span} {
74 | padding-left: 1em;
75 | margin-top: 1em;
76 | }
77 | ${({ appearance }) =>
78 | appearance !== 'onlyBalance' &&
79 | ` &:before {
80 | content: 'BALANCE';
81 | position: absolute;
82 | top: 0.8em;
83 | left: 1em;
84 | opacity: 0.6;
85 | }
86 | & ${Main} {
87 | padding-left: 0.4em;
88 | }
89 | align-items: flex-start;
90 | // background: var(--colors__bg_dark);
91 | background: linear-gradient(45deg, #461a99 0%, #249ade 65%, #41d4cb 100%);
92 | filter: grayscale(1);
93 | opacity: 0.9;
94 | border-top-right-radius: 0.7em;
95 | border-top-left-radius: 0.7em;
96 | // box-shadow: 0 0.6em 0.7em 0.2em rgba(21, 24, 46, 0.16);
97 | color: var(--colors__text_accent);
98 | `}
99 | `;
100 |
101 | export default Root;
102 |
--------------------------------------------------------------------------------
/app/sources/src/components/BalanceSummary/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import receiveIcon from 'assets/icons/plus-circle.svg';
16 |
17 | import { Root, Main, Additional, Receive, Send, Img, Span } from './styles';
18 |
19 | const log = logger();
20 |
21 | // -----------------------------------------------------------------------------
22 | // Code
23 | // -----------------------------------------------------------------------------
24 |
25 | export const BalanceSummary = ({ accounts, className, appearance = 'normal', denomination, t }) => {
26 |
27 | if (!accounts.get.data && accounts.get.loading) {
28 | return (
29 |
30 | Loading balance info...
31 |
32 | );
33 | }
34 |
35 | if (
36 | (accounts.get.error && !accounts.get.data) ||
37 | (!accounts.get.error && (!accounts.get.data || !accounts.get.data.balances))
38 | ) {
39 | return (
40 |
41 | Unable to load balance info
42 |
43 | );
44 | }
45 |
46 | if (appearance === 'onlyBalance') {
47 | return (
48 |
49 | Available
50 | {Object.keys(accounts.get.data.balances).map(asset => [
51 |
52 | {accounts.get.data.balances[asset].denominationsAvailable[denomination].toString()}
53 | ,
54 | ])}
55 |
56 | );
57 | }
58 | return (
59 |
60 |
61 | Receive
62 |
63 |
64 | {Object.keys(accounts.get.data.balances).map(asset => [
65 |
66 | {accounts.get.data.balances[asset].denominationsAvailable.main.toString()}
67 | ,
68 |
69 | {accounts.get.data.balances[asset].denominationsAvailable.additional.toString()}
70 | ,
71 | ])}
72 | {/*
73 | {totalBalance === 0 ? 'Receive' : 'Pay'}
74 | */}
75 |
76 | );
77 | };
78 |
79 | BalanceSummary.propTypes = {};
80 |
81 | BalanceSummary.defaultProps = {};
82 |
83 | export default BalanceSummary;
84 |
--------------------------------------------------------------------------------
/app/sources/src/components/CheckDestination/index.js:
--------------------------------------------------------------------------------
1 | import { withNamespaces } from 'react-i18next';
2 | import { withRouter } from 'react-router';
3 | import { observer } from 'mobx-react';
4 |
5 | import view from './view';
6 |
7 | export default withNamespaces()(withRouter(observer(view)));
8 |
--------------------------------------------------------------------------------
/app/sources/src/components/CheckDestination/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 | import { withLoader, Form, Span, P, A, Input, Message as MessageRaw } from 'components/common';
12 |
13 | // -----------------------------------------------------------------------------
14 | // Code
15 | // -----------------------------------------------------------------------------
16 |
17 | export * from 'components/common';
18 |
19 | export const DestinationInfo = styled.div`
20 | display: flex;
21 | flex-direction: column;
22 | & ${P} {
23 | margin-bottom: 0.5em;
24 | }
25 | & ${Span} {
26 | font-weight: 600;
27 | }
28 | `;
29 |
30 | export const Message = styled(MessageRaw)`
31 | flex-direction: column;
32 | & ${Span} {
33 | font-weight: 600;
34 | margin-top: 0.5em;
35 | cursor: pointer;
36 | }
37 | `;
38 |
39 | export const Maintenance = styled(MessageRaw)`
40 | position: relative;
41 | display: flex;
42 | flex-direction: column;
43 | justify-content: center;
44 | align-items: center;
45 | white-space: pre-wrap;
46 | text-align: center;
47 | background: var(--colors__bg_warn);
48 | font-weight: 400;
49 | & * {
50 | word-break: break-word;
51 | }
52 | & > ${Span} {
53 | font-weight: 600;
54 | padding: 0!important;
55 | }
56 | `;
57 |
58 | export const Root = withLoader(styled(Form)`
59 | height: 100%;
60 |
61 | & > ${P} {
62 | display: flex;
63 | flex-direction: column;
64 | }
65 |
66 | & > ${P}:first-child {
67 | margin-bottom: 1em;
68 | margin-left: 1.2em;
69 | }
70 |
71 | & ${P}:last-of-type {
72 | margin-top: auto;
73 | margin-bottom: 1em;
74 | border-top: 0.05em solid var(--colors__bg_dark);
75 | font-size: 0.8em;
76 | padding: 0.5em 1.5em;
77 | }
78 |
79 | & ${P}:last-of-type * {
80 | margin-top: 1em;
81 | word-break: break-word;
82 | }
83 |
84 | & ${P}:last-of-type ${Span}:first-of-type {
85 | font-weight: 500;
86 | }
87 |
88 | & input::placeholder {
89 | font-size: 0.8em;
90 | }
91 | & > ${Span} {
92 | word-break: initial;
93 | opacity: 0.8;
94 | }
95 |
96 | & ${A} {
97 | font-weight: 700;
98 | color: var(--colors__bg_accent);
99 | cursor: pointer;
100 | }
101 |
102 | & > ${A} {
103 | font-size: 0.6em;
104 | font-weight: 500;
105 | text-decoration: underline;
106 | margin-left: 2em;
107 | margin-top: 1em;
108 | }
109 | `);
110 |
111 | export default Root;
112 |
--------------------------------------------------------------------------------
/app/sources/src/components/LoginForm/index.js:
--------------------------------------------------------------------------------
1 | import { observer, inject } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 |
4 | import view from './view';
5 |
6 | export default withNamespaces()(inject('accounts')(observer(view)));
7 |
--------------------------------------------------------------------------------
/app/sources/src/components/LoginForm/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 | import { withLoader, Form, Button, Message } from 'components/common';
12 |
13 | // -----------------------------------------------------------------------------
14 | // Code
15 | // -----------------------------------------------------------------------------
16 |
17 | export * from 'components/common';
18 |
19 | export const Root = withLoader(styled(Form)`
20 | & ${Button} {
21 | height: 2.7em;
22 | }
23 | & ${Message} {
24 | margin: 1em 0;
25 | }
26 | & input {
27 | font-size: 0.9em;
28 | }
29 | & label {
30 | left: 1.4em;
31 | }
32 | `);
33 |
34 | export default Root;
35 |
--------------------------------------------------------------------------------
/app/sources/src/components/LoginForm/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import { Root, Input, Button, Message } from './styles';
16 |
17 | const log = logger();
18 |
19 | // -----------------------------------------------------------------------------
20 | // Code
21 | // -----------------------------------------------------------------------------
22 |
23 | export const LoginForm = ({ accounts, className, t }) => (
24 | {
27 | e.preventDefault();
28 | const emailElement = e.target.querySelector('#authEmail');
29 | const email = emailElement && emailElement.value;
30 | const passwordElement = e.target.querySelector('#authPassword');
31 | const password = passwordElement && passwordElement.value;
32 | accounts.authenticate.run(email, password);
33 | }}
34 | loading={accounts.authenticate.loading}
35 | >
36 |
44 |
52 |
53 | {accounts.authenticate.error && (
54 |
55 | {t([`errors.${accounts.authenticate.error.code}`, 'errors.default'])}
56 |
57 | )}
58 | {accounts.authenticate.data && Object.keys(accounts.authenticate.data).length === 0 && (
59 | No account was found with such email
60 | )}
61 |
62 | Login
63 |
64 |
65 | );
66 |
67 | LoginForm.propTypes = {};
68 |
69 | LoginForm.defaultProps = {};
70 |
71 | export default LoginForm;
72 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentConfirmation/index.js:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 |
4 | import view from './view';
5 |
6 | export default withNamespaces()(observer(view));
7 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentDetails/index.js:
--------------------------------------------------------------------------------
1 | import { withNamespaces } from 'react-i18next';
2 |
3 | import view from './view';
4 |
5 | export default withNamespaces()(view);
6 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentsGroup/PaymentItem/index.js:
--------------------------------------------------------------------------------
1 | import { withNamespaces } from 'react-i18next';
2 | import { withRouter } from 'react-router';
3 |
4 | import view from './view';
5 |
6 | export default withNamespaces()(withRouter(view));
7 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentsGroup/PaymentItem/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import { P, Span, Img } from 'components/common';
13 |
14 | import goToDetailsIcon from 'assets/icons/chevron-right.svg';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | export * from 'components/common';
21 |
22 | export const AmountMain = styled.span`
23 | font-size: 1.12em;
24 | color: ${({ direction }) => direction === 'incoming' && 'var(--colors__text_ok)'};
25 | `;
26 |
27 | export const AmountAdditional = styled.span`
28 | font-size: 0.8em;
29 | color: var(--colors__text_bright);
30 | margin-top: 0.4em;
31 | `;
32 |
33 | export const Time = styled.span``;
34 | export const Description = styled.span`
35 | max-width: 15em;
36 | word-break: break-word;
37 | white-space: ${({ wrap }) => (wrap ? 'normal' : 'nowrap')};
38 | margin-top: 0.6em;
39 | font-size: 0.8em;
40 | overflow: hidden;
41 | text-overflow: ellipsis;
42 | color: var(--colors__text_bright);
43 | ${({ wrap }) =>
44 | wrap
45 | ? `display: -webkit-box;
46 | -webkit-line-clamp: 5;
47 | -webkit-box-orient: vertical;`
48 | : ''};
49 | `;
50 |
51 | export const Info = styled.div`
52 | display: flex;
53 | flex-direction: column;
54 | `;
55 |
56 | export const Amount = styled.div`
57 | display: flex;
58 | flex-direction: column;
59 | align-items: flex-end;
60 | margin-left: auto;
61 | `;
62 |
63 | export const Root = styled.div`
64 | display: flex;
65 | align-items: flex-start;
66 | font-size: 0.8em;
67 | margin-left: 1.7em;
68 | padding-right: 3.5em;
69 | position: relative;
70 | &:not(:last-child) {
71 | border-bottom: 0.1em solid var(--colors__bg_dark);
72 | }
73 | & ${Info}, & ${Amount} {
74 | margin-top: 1.6em;
75 | margin-bottom: 1.6em;
76 | }
77 | &:after {
78 | position: absolute;
79 | right: 1.4em;
80 | opacity: 0.4;
81 | /* background: no-repeat url(${goToDetailsIcon}) center; */
82 | background-color: var(--colors__bg_dark);
83 | height: 100%;
84 | width: 0.7em;
85 | background-size: contain;
86 | }
87 | &:hover:after {
88 | display: block;
89 | content: '';
90 | }
91 |
92 | background-color: var(--colors__bg);
93 | `;
94 |
95 | export default Root;
96 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentsGroup/PaymentItem/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React, { Component } from 'react';
11 | import PropTypes from 'prop-types';
12 | import formatDate from 'date-fns/format';
13 |
14 | import NavLink from 'react-router-dom';
15 |
16 | import logger from 'utils/logging';
17 |
18 | import { Root, P, AmountAdditional, AmountMain, Description, Amount, Time, Info } from './styles';
19 |
20 | const log = logger();
21 |
22 | // -----------------------------------------------------------------------------
23 | // Code
24 | // -----------------------------------------------------------------------------
25 |
26 | export const PaymentItem = ({
27 | className,
28 | history,
29 | puid,
30 | updatedAt,
31 | description,
32 | isDescriptionReadable,
33 | direction,
34 | mainDenominationString,
35 | additionalDenominationString,
36 | t,
37 | }) => {
38 | return (
39 | {
42 | history.push(`/payments/${puid}`);
43 | }}
44 | >
45 |
46 | {formatDate(new Date(updatedAt), 'HH:mm')}
47 | {description}
48 |
49 |
50 | {mainDenominationString}
51 | {additionalDenominationString}
52 |
53 |
54 | );
55 | };
56 |
57 | PaymentItem.propTypes = {};
58 |
59 | PaymentItem.defaultProps = {};
60 |
61 | export default PaymentItem;
62 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentsGroup/index.js:
--------------------------------------------------------------------------------
1 | import { withNamespaces } from 'react-i18next';
2 | import { withRouter } from 'react-router';
3 |
4 | import view from './view';
5 |
6 | export default withNamespaces()(withRouter(view));
7 |
--------------------------------------------------------------------------------
/app/sources/src/components/PaymentsGroup/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React, { Component, useState } from 'react';
11 | import PropTypes from 'prop-types';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import {
16 | Root,
17 | Span,
18 | P,
19 | AmountAdditional,
20 | AmountMain,
21 | Vendor,
22 | Amount,
23 | Status,
24 | Button,
25 | Img,
26 | VendorIcon,
27 | GroupInfo,
28 | GroupedItems,
29 | PaymentItem,
30 | } from './styles';
31 |
32 | const log = logger();
33 |
34 | // -----------------------------------------------------------------------------
35 | // Code
36 | // -----------------------------------------------------------------------------
37 |
38 | export const PaymentsGroup = ({
39 | className,
40 | history,
41 | payments,
42 | status,
43 | vendorName,
44 | vendorIcon,
45 | vendorColor,
46 | t,
47 | }) => {
48 | const [folded, toggleFold] = useState(true);
49 | const groupedAmountMain = payments.reduce((p, c) => p + c.denominations.main.totalRaw, 0);
50 |
51 | const groupedAmountAdditional = payments.reduce(
52 | (p, c) => p + c.denominations.additional.totalRaw,
53 | 0,
54 | );
55 | const positiveTotal = groupedAmountMain >= 0 && groupedAmountAdditional > 0;
56 | return (
57 |
58 | {
61 | toggleFold(!folded);
62 | }}
63 | >
64 |
65 |
66 |
67 |
68 |
69 | {vendorName}
70 | {payments[0].description || payments[0].receipt}
71 |
72 |
73 |
74 |
75 | {payments[0].denominations.main.stringify(groupedAmountMain)}
76 |
77 |
78 | {payments[0].denominations.additional.stringify(groupedAmountAdditional)}
79 |
80 |
81 |
82 |
83 | {folded ? null : (
84 |
85 | {payments.map(payment => (
86 |
96 | ))}
97 |
98 | )}
99 |
100 | );
101 | };
102 |
103 | PaymentsGroup.propTypes = {};
104 |
105 | PaymentsGroup.defaultProps = {};
106 |
107 | export default PaymentsGroup;
108 |
--------------------------------------------------------------------------------
/app/sources/src/components/ReceivePayment/index.js:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 | import { withRouter } from 'react-router';
4 |
5 | import view from './view';
6 |
7 | export default withNamespaces()(withRouter(observer(view)));
8 |
--------------------------------------------------------------------------------
/app/sources/src/components/RestoreForm/index.js:
--------------------------------------------------------------------------------
1 | import { observer, inject } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 |
4 | import view from './view';
5 |
6 | export default withNamespaces()(inject('accounts')(observer(view)));
7 |
--------------------------------------------------------------------------------
/app/sources/src/components/RestoreForm/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 | import { withLoader, Form, Button, Message, A, P } from 'components/common';
12 |
13 | // -----------------------------------------------------------------------------
14 | // Code
15 | // -----------------------------------------------------------------------------
16 |
17 | export * from 'components/common';
18 |
19 | export const Root = withLoader(styled(Form)`
20 | & ${A} {
21 | cursor: pointer;
22 | font-weight: 500;
23 | color: var(--colors__bg_accent);
24 | }
25 |
26 | & ${Button} {
27 | height: 2.7em;
28 | }
29 | & ${Message} {
30 | margin: 1em 0;
31 | }
32 | & > ${P} {
33 | margin-left: 0.3em;
34 | font-size: 0.7em;
35 | font-weight: 500;
36 | color: var(--colors__text_dark);
37 | margin-top: 1em;
38 | margin-bottom: 0.4em;
39 | white-space: pre-line;
40 | }
41 | & input {
42 | font-size: 0.9em;
43 | }
44 | & label {
45 | left: 1.4em;
46 | }
47 | `);
48 |
49 | export default Root;
50 |
--------------------------------------------------------------------------------
/app/sources/src/components/RestoreForm/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 | import { Trans } from 'react-i18next';
13 |
14 | import logger from 'utils/logging';
15 |
16 | import { Root, Input, Button, Message, A, P } from './styles';
17 |
18 | const log = logger();
19 |
20 | // -----------------------------------------------------------------------------
21 | // Code
22 | // -----------------------------------------------------------------------------
23 |
24 | export const RestoreForm = ({ accounts, className, history, t, exists }) => (
25 | {
28 | e.preventDefault();
29 | const emailElement = e.target.querySelector('#restoreEmail');
30 | const email = emailElement && emailElement.value;
31 | accounts.sendRestoreLink.run({ body: { email } });
32 | }}
33 | loading={accounts.sendRestoreLink.loading}
34 | >
35 |
43 | {accounts.sendRestoreLink.error && (
44 |
45 | {t([`errors.${accounts.sendRestoreLink.error.code}`, 'errors.default'])}
46 |
47 | )}
48 | {accounts.sendRestoreLink.data && (
49 |
50 | {t('account.restoreSent', {
51 | email:
52 | document.querySelector('#restoreEmail') &&
53 | document.querySelector('#restoreEmail').value,
54 | })}
55 |
56 | )}
57 |
58 | {t('nav.restore')}
59 |
60 |
61 | );
62 |
63 | RestoreForm.propTypes = {};
64 |
65 | RestoreForm.defaultProps = {};
66 |
67 | export default RestoreForm;
68 |
--------------------------------------------------------------------------------
/app/sources/src/components/SelectReceiveAsset/index.js:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 | import { withRouter } from 'react-router';
4 |
5 | import view from './view';
6 |
7 | export default withNamespaces()(withRouter(observer(view)));
8 |
--------------------------------------------------------------------------------
/app/sources/src/components/SelectReceiveAsset/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import { withLoader } from 'components/common';
13 |
14 | import { Img, Span, P } from 'components/common';
15 |
16 | import goToDetailsIcon from 'assets/icons/chevron-right.svg';
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | export * from 'components/common';
23 |
24 | export const AssetItem = styled.div`
25 | cursor: pointer;
26 | position: relative;
27 | display: flex;
28 | align-items: center;
29 | margin-left: 2rem;
30 | margin-right: 2rem;
31 | width: calc(100vw - 4rem);
32 | background-color: var(--colors__bg_bright);
33 | border-radius: 0.2em;
34 | overflow: hidden;
35 | margin-bottom: 0.3rem;
36 | padding: 1em 1em;
37 | padding-right: 2em;
38 | margin-bottom: 0.5em;
39 | & ${Img} {
40 | height: 2.7em;
41 | width: 2.7em;
42 | opacity: 0.7;
43 | margin-right: 1.6rem;
44 | border-radius: 0.3em;
45 | }
46 | & ${P} {
47 | display: flex;
48 | flex-direction: column;
49 | }
50 | & ${Span} {
51 | word-break: break-word;
52 | }
53 | & ${Span}:first-child {
54 | font: var(--fonts__text_bold);
55 | }
56 | & ${Span}:last-child {
57 | padding-top: 0.5em;
58 | font-size: 0.8em;
59 | color: var(--colors__text_dark);
60 | }
61 |
62 | &:after {
63 | position: absolute;
64 | right: 0;
65 | top: 0;
66 | opacity: 0.4;
67 | /* background: no-repeat url(${goToDetailsIcon}) center; */
68 | background-color: var(--colors__bg_dark);
69 | height: 100%;
70 | width: 0.6em;
71 | background-size: contain;
72 | }
73 | &:hover:after {
74 | display: block;
75 | content: '';
76 | }
77 | `;
78 |
79 | export const Root = styled.div`
80 | background-color: var(--colors__bg);
81 | justify-content: center;
82 | display: flex;
83 | flex-direction: column;
84 |
85 | & ${AssetItem}:last-of-type {
86 | /* background: transparent; */
87 | margin-top: 3em;
88 | }
89 | `;
90 |
91 | export default Root;
92 |
--------------------------------------------------------------------------------
/app/sources/src/components/SelectReceiveAsset/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import { Root, AssetItem, P, Img, Span } from './styles';
16 |
17 | import iconOnchain from 'assets/icons/assets/btc.svg';
18 | import iconOffchain from 'assets/icons/assets/lightning.svg';
19 | import iconAltcoins from 'assets/icons/assets/altcoins.svg';
20 |
21 | const log = logger();
22 |
23 | // -----------------------------------------------------------------------------
24 | // Code
25 | // -----------------------------------------------------------------------------
26 |
27 | export const SelectReceiveAsset = ({ className, history, t }) => {
28 | return (
29 |
30 | {
32 | history.push(
33 | `/payments/receive/confirm?receive=${JSON.stringify({
34 | type: 'lightning',
35 | asset: 'BTC',
36 | })}`,
37 | );
38 | }}
39 | >
40 |
41 |
42 | Lightning Network Bitcoin
43 | Receive with lightning faster than other methods and takes less fees
44 |
45 |
46 | {
48 | history.push(
49 | `/payments/receive/confirm?receive=${JSON.stringify({
50 | type: 'blockchain',
51 | asset: 'BTC',
52 | })}`,
53 | );
54 | }}
55 | >
56 |
57 |
58 | On-chain Bitcoin
59 |
60 | Receive with on-chain / regular Bitcoin payment will take about ~10 minutes to confirm
61 |
62 |
63 |
64 | {
66 | window.open(
67 | 'https://zigzag.io?utm_source=integration&utm_medium=bitlumwallet&utm_campaign=receiveLink',
68 | '_blank',
69 | );
70 | }}
71 | >
72 |
73 |
74 | Recieve with alt-coins
75 |
76 | Receive with alt-coin implies conversion of alt-coin to Bitcoin with fee using zigzag.io
77 | service
78 |
79 |
80 |
81 |
82 | );
83 | };
84 |
85 | SelectReceiveAsset.propTypes = {};
86 |
87 | SelectReceiveAsset.defaultProps = {};
88 |
89 | export default SelectReceiveAsset;
90 |
--------------------------------------------------------------------------------
/app/sources/src/components/SettingsForm/index.js:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 | import { withRouter } from 'react-router';
4 |
5 | import view from './view';
6 |
7 | export default withNamespaces()(withRouter(observer(view)));
8 |
--------------------------------------------------------------------------------
/app/sources/src/components/SettingsForm/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 | import SelectRaw from 'react-select';
12 |
13 | import { withLoader } from 'components/common';
14 |
15 | import { Img, Span, P, Button } from 'components/common';
16 |
17 | // -----------------------------------------------------------------------------
18 | // Code
19 | // -----------------------------------------------------------------------------
20 |
21 | export * from 'components/common';
22 |
23 | export const Select = styled(SelectRaw)`
24 | min-width: 7em;
25 | `;
26 |
27 | export const SettingsItem = styled.div`
28 | position: relative;
29 | display: flex;
30 | align-items: center;
31 | margin-left: 2rem;
32 | width: calc(100vw - 4rem);
33 | background-color: var(--colors__bg_bright);
34 | border-radius: 0.2em;
35 | margin-bottom: 0.3rem;
36 | padding: 1em 1em;
37 | padding-right: 2em;
38 | margin-bottom: 0.5em;
39 |
40 | & > *:first-child {
41 | font: var(--fonts__text_bold);
42 | }
43 | & > *:last-child:not(:first-child) {
44 | margin-left: auto;
45 | cursor: pointer;
46 | }
47 |
48 | & ${Span} {
49 | word-break: break-word;
50 | font-size: 0.8em;
51 | }
52 | `;
53 |
54 | export const Root = styled.div`
55 | height: 100%;
56 | top: 0;
57 | width: 100%;
58 | height: 100%;
59 | background-color: var(--colors__bg);
60 | z-index: 10;
61 | justify-content: center;
62 | display: flex;
63 | flex-direction: column;
64 | `;
65 |
66 | export default Root;
67 |
--------------------------------------------------------------------------------
/app/sources/src/components/SettingsForm/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import { Root, SettingsItem, P, Button, Span, Select } from './styles';
16 |
17 | const log = logger();
18 |
19 | // -----------------------------------------------------------------------------
20 | // Code
21 | // -----------------------------------------------------------------------------
22 |
23 | export const SettingsForm = ({ className, settings, accounts, denominations, t }) => {
24 | const denominationsAvailable = Object.keys(denominations.get.data.BTC)
25 | .map(
26 | denomination =>
27 | !denomination.match(/(main|additional)/) && {
28 | value: denomination,
29 | label: denominations.get.data.BTC[denomination].sign,
30 | },
31 | )
32 | .filter(denomination => denomination);
33 |
34 | return (
35 |
36 |
37 | Main currency
38 | denomination.value === settings.get.data.denominations_BTC_main,
45 | )}
46 | onChange={data => {
47 | settings.set.run({ denominations_BTC_main: data.value });
48 | }}
49 | />
50 |
51 |
52 | Alternative currency
53 | denomination.value === settings.get.data.denominations_BTC_additional,
60 | )}
61 | onChange={data => {
62 | settings.set.run({ denominations_BTC_additional: data.value });
63 | }}
64 | />
65 |
66 | {settings.get.data.content_script_permissions !== 'granted' && (
67 | {
69 | window.chrome.permissions.request(
70 | {
71 | permissions: ['tabs'],
72 | origins: [''],
73 | },
74 | granted => {
75 | settings.set.run({ content_script_permissions: granted ? 'granted' : 'denied' });
76 | },
77 | );
78 | }}
79 | >
80 | Automate copy-paste of invoices
81 |
82 | )}
83 | {
85 | accounts.authenticate.cleanup('all');
86 | }}
87 | >
88 | Log out
89 |
90 |
91 | );
92 | };
93 |
94 | SettingsForm.propTypes = {};
95 |
96 | SettingsForm.defaultProps = {};
97 |
98 | export default SettingsForm;
99 |
--------------------------------------------------------------------------------
/app/sources/src/components/SignupForm/index.js:
--------------------------------------------------------------------------------
1 | import { observer, inject } from 'mobx-react';
2 | import { withNamespaces } from 'react-i18next';
3 |
4 | import view from './view';
5 |
6 | export default withNamespaces()(inject('accounts')(observer(view)));
7 |
--------------------------------------------------------------------------------
/app/sources/src/components/SignupForm/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 | import { withLoader, Form, Button, Message, A, P } from 'components/common';
12 |
13 | // -----------------------------------------------------------------------------
14 | // Code
15 | // -----------------------------------------------------------------------------
16 |
17 | export * from 'components/common';
18 |
19 | export const Root = withLoader(styled(Form)`
20 | & ${A} {
21 | cursor: pointer;
22 | font-weight: 500;
23 | color: var(--colors__bg_accent);
24 | }
25 |
26 | & ${Button} {
27 | height: 2.7em;
28 | }
29 | & ${Message} {
30 | margin: 1em 0;
31 | }
32 | & > ${P} {
33 | margin-left: 0.3em;
34 | font-size: 0.7em;
35 | font-weight: 500;
36 | color: var(--colors__text_dark);
37 | margin-top: 1em;
38 | margin-bottom: 0.4em;
39 | white-space: pre-line;
40 | }
41 | & input {
42 | font-size: 0.9em;
43 | }
44 | & label {
45 | left: 1.4em;
46 | }
47 | `);
48 |
49 | export default Root;
50 |
--------------------------------------------------------------------------------
/app/sources/src/components/SignupForm/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display name and button for name generation
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import PropTypes from 'prop-types';
12 | import { Trans } from 'react-i18next';
13 |
14 | import logger from 'utils/logging';
15 |
16 | import { Root, Input, Button, Message, A, P } from './styles';
17 |
18 | const log = logger();
19 |
20 | // -----------------------------------------------------------------------------
21 | // Code
22 | // -----------------------------------------------------------------------------
23 |
24 | export const SignupForm = ({ accounts, className, history, t, exists }) => (
25 | {
28 | e.preventDefault();
29 | const emailElement = e.target.querySelector('#signupEmail');
30 | const email = emailElement && emailElement.value;
31 | const passwordElement = e.target.querySelector('#signupPassword');
32 | const password = passwordElement && passwordElement.value;
33 | const referralElement = e.target.querySelector('#signupReferral');
34 | const referral = referralElement && referralElement.value;
35 | accounts.signup.run(email, password, referral);
36 | }}
37 | loading={accounts.signup.loading}
38 | >
39 |
47 |
55 | {/* Have you been invited by someone?
56 | */}
63 |
64 | {accounts.signup.error && (
65 |
66 |
67 | {' '}
68 | {
70 | history.push('/login');
71 | }}
72 | >
73 | {' '}
74 |
75 |
76 |
77 | )}
78 |
79 | {t('nav.signup')}
80 |
81 |
82 | );
83 |
84 | SignupForm.propTypes = {};
85 |
86 | SignupForm.defaultProps = {};
87 |
88 | export default SignupForm;
89 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/BackButton.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for button
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import styled from 'styled-components';
12 |
13 | import backIcon from 'assets/icons/arrow-left.svg';
14 |
15 | // -----------------------------------------------------------------------------
16 | // Code
17 | // -----------------------------------------------------------------------------
18 |
19 | export const BackButton = styled(({ children, ...rest }) => (
20 | {
22 | window.history.back();
23 | }}
24 | {...rest}
25 | >
26 | {children}
27 |
28 | ))`
29 | font-size: 1em;
30 | cursor: pointer;
31 | background: no-repeat url(${backIcon});
32 | background-size: contain;
33 | width: 1em;
34 | height: 1em;
35 | margin-left: 0.9em;
36 | margin-right: 1.4em;
37 | visibility: ${({ hidden }) => hidden && 'hidden'};
38 | `;
39 |
40 | export default BackButton;
41 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Button.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for button
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export const Button = styled.button`
17 | word-break: break-word;
18 | font-size: 1em;
19 | padding: ${({ link }) => (link ? '0' : '0.45em 1.3em')};
20 | border-radius: 0.2em;
21 | color: ${({ primary }) => (primary ? 'var(--colors__text_accent)' : 'var(--colors__bg_accent)')};
22 | background-color: ${({ primary }) => (primary ? 'var(--colors__bg_accent)' : null)};
23 | border: ${({ link }) => (link ? 'none' : '0.1em solid var(--colors__bg_accent)')};
24 | font-weight: 600;
25 | text-align: center;
26 | ${({ external, children }) =>
27 | external &&
28 | children &&
29 | `:after {
30 | content: url('data:image/svg+xml;utf8, ');
31 | fill: red;
32 | margin: 0 0.3em;
33 | }`};
34 | ${({ disabled }) =>
35 | disabled &&
36 | `pointer-events: none;
37 | opacity: 0.5;
38 | background-color: var(--colors__bg_dark);
39 | border-color: var(--colors__bg_dark);`}
40 | `;
41 |
42 | export default Button;
43 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/CopyButton.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for button
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import styled from 'styled-components';
12 |
13 | import { Button as ButtonCommon } from './Button';
14 |
15 | // -----------------------------------------------------------------------------
16 | // Code
17 | // -----------------------------------------------------------------------------
18 |
19 | export const CopyButton = styled(
20 | ({ copyData, copyText = 'Copy', copiedText = 'Copied!', children, inline, ...rest }) => (
21 | {
23 | const copyContainer = document.createElement('input');
24 | copyContainer.value = copyData;
25 | document.body.appendChild(copyContainer);
26 | copyContainer.select();
27 | document.execCommand('Copy');
28 | copyContainer.remove();
29 | const button = e.currentTarget;
30 | button.setAttribute('data-afterText', copiedText);
31 | setTimeout(() => {
32 | button.setAttribute('data-afterText', copyText);
33 | }, 800);
34 | }}
35 | data-afterText={copyText}
36 | {...rest}
37 | >
38 | {children}
39 |
40 | ),
41 | )`
42 | position: relative;
43 | font-size: 1em;
44 | border-radius: 0.2em;
45 | font-weight: 600;
46 | text-align: center;
47 | display: flex;
48 | align-items: center;
49 | cursor: pointer;
50 | grid-template-columns: 1fr;
51 | &:after {
52 | content: attr(data-afterText);
53 | position: absolute;
54 | font-size: 0.8em;
55 | bottom: -1.5em;
56 | left: 50%;
57 | right: 50%;
58 | transform: translate(-50%);
59 | word-break: initial;
60 | width: max-content;
61 | transition: opacity 0.3s ease-in-out;
62 | }
63 | `;
64 |
65 | export default CopyButton;
66 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Form.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for Form
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export const Form = styled.form`
17 | display: flex;
18 | flex-direction: column;
19 | `;
20 |
21 | export default Form;
22 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Header.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for Header
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export const Header = styled.header`
17 | font-weight: 700;
18 | display: flex;
19 | align-items: center;
20 | width: 100%;
21 | max-width: 100vw;
22 | `;
23 |
24 | export default Header;
25 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Icon.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for Icon
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import styled from 'styled-components';
12 |
13 | import { ReactComponent as Info } from 'assets/icons/information-circled.svg';
14 | import { ReactComponent as Warn } from 'assets/icons/android-alert.svg';
15 | import { ReactComponent as Error } from 'assets/icons/close-circled.svg';
16 |
17 | // -----------------------------------------------------------------------------
18 | // Code
19 | // -----------------------------------------------------------------------------
20 |
21 | const icons = {
22 | info: ,
23 | warn: ,
24 | error: ,
25 | };
26 |
27 | const Container = styled.button`
28 | height: 1em;
29 | width: 1em;
30 | font-size: 1em;
31 | `;
32 |
33 | export const Icon = ({
34 | i,
35 | className,
36 | ...rest
37 | } = {}) => (
38 |
39 | {icons[i.toLowerCase()]}
40 |
41 | );
42 |
43 | export default Icon;
44 |
45 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Input.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for Input
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import styled from 'styled-components';
12 |
13 | // -----------------------------------------------------------------------------
14 | // Code
15 | // -----------------------------------------------------------------------------
16 |
17 | const StyledInput = styled.input`
18 | width: 100%;
19 | padding: 1.15em;
20 | font-size: 1em;
21 | background-color: #fff;
22 |
23 | :not(:placeholder-shown) {
24 | padding-top: 1.7em;
25 | padding-bottom: 0.6em;
26 | }
27 |
28 | :invalid:not(:placeholder-shown) {
29 | background-color: var(--colors__bg_error);
30 | }
31 | `;
32 |
33 | const StyledLabel = styled.label`
34 | opacity: 0.4;
35 | position: absolute;
36 | top: 0.9em;
37 | left: 1.6em;
38 | font-size: 0.7em;
39 | font-weight: 600;
40 |
41 | ${StyledInput}:placeholder-shown + & {
42 | opacity: 0;
43 | }
44 |
45 | :before {
46 | content: attr(data-label-valid);
47 | }
48 |
49 | ${StyledInput}:invalid:not(:placeholder-shown) + & {
50 | color: var(--colors__text_error);
51 | }
52 |
53 | ${StyledInput}:invalid:not(:placeholder-shown) + &:before {
54 | content: attr(data-label-invalid);
55 | }
56 | `;
57 |
58 | const Container = styled.div`
59 | font-size: 1em;
60 | position: relative;
61 | border: 0.2rem solid var(--colors__bg);
62 | border-radius: 0.2em;
63 | overflow: hidden;
64 | `;
65 |
66 | export const Input = ({
67 | className,
68 | id,
69 | labelValid,
70 | labelInvalid,
71 | ...rest
72 | } = {}) => (
73 |
74 |
75 |
76 |
77 | );
78 |
79 | export default Input;
80 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Message.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Component to display childs with custom color and background
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export const Message = styled.div`
17 | word-break: break-word;
18 | white-space: pre-wrap;
19 | display: flex;
20 | flex-direction: column;
21 | width: 100%;
22 | justify-content: center;
23 | align-items: center;
24 | text-align: center;
25 | padding: 0.85em 1.3em;
26 | font-size: 0.8em;
27 | color: ${({ type }) => `var(--colors__text_${type})`};
28 | background-color: ${({ type }) => `var(--colors__bg_${type})`};
29 | `;
30 |
31 | export default Message;
32 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Nav.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for Nav
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export const Nav = styled.div`
17 | display: flex;
18 | flex-direction: ${({ column }) => (column ? 'column' : 'row')};
19 |
20 | & > * {
21 | padding: 0.5em 1em;
22 | cursor: pointer;
23 | }
24 |
25 | & > *{
26 | text-decoration: none;
27 | }
28 |
29 | & > :hover,
30 | & > .active {
31 | color: var(--colors__text_accent);
32 | font-weight: 600;
33 | }
34 | `;
35 |
36 | export default Nav;
37 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/Select.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styled component for Input
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import styled from 'styled-components';
12 |
13 | // -----------------------------------------------------------------------------
14 | // Code
15 | // -----------------------------------------------------------------------------
16 |
17 | const StyledSelect = styled.select`
18 | width: 100%;
19 | padding: 1.15em;
20 | font-size: 1em;
21 | background-color: #fff;
22 | `;
23 |
24 | const Container = styled.div`
25 | font-size: 1em;
26 | position: relative;
27 | border: 0.2rem solid var(--colors__bg);
28 | border-radius: 0.2em;
29 | overflow: hidden;
30 | position: relative;
31 |
32 | &:after {
33 | content: '';
34 | position: absolute;
35 | top: calc(50% - 0.125em);
36 | right: 1em;
37 | width: 0;
38 | height: 0;
39 | border-left: 0.5em solid transparent;
40 | border-right: 0.5em solid transparent;
41 | border-top: 0.5em solid var(--colors__bg_dark);
42 | clear: both;
43 | }
44 | `;
45 |
46 | export const Select = ({ className, ...rest } = {}) => (
47 |
48 |
49 |
50 | );
51 |
52 | export default Select;
53 |
--------------------------------------------------------------------------------
/app/sources/src/components/common/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Various utils for easier styling and reducing boilerplate
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled, { css } from 'styled-components';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export const withLoader = styledComponent => styled(styledComponent)`
17 | /* opacity: ${({ loading }) => (loading ? '0.3' : '1')}; */
18 | filter: ${({ loading }) => loading && 'blur(2px)'};
19 | pointer-events: ${({ loading }) => (loading ? 'none' : 'initial')};
20 | :after {
21 | position:absolute;
22 | content: '';
23 | z-index: 1000;
24 | background-color: rgba(255,255,255,0.8);
25 | width: 100%;
26 | height: 100%;
27 | top: 0;
28 | display: ${({ loading }) => (loading ? 'block' : 'none')};
29 | }
30 | :before {
31 | z-index: 2000;
32 | content: '';
33 | position: absolute;
34 | width: 2em;
35 | height: 2em;
36 | left: calc(50% - 1em);
37 | bottom: calc(50% - 1em);
38 | background-color: #333;
39 | border-radius: 100%;
40 | animation: sk-scaleout 1s infinite ease-in-out;
41 | display: ${({ loading }) => (loading ? 'block' : 'none')};
42 | }
43 |
44 | @keyframes sk-scaleout {
45 | 0% {
46 | transform: scale(0);
47 | }
48 | 100% {
49 | transform: scale(1);
50 | opacity: 0;
51 | }
52 | }
53 | `;
54 |
55 | const mediaBreakpoints = {
56 | desktopXL: 1200,
57 | desktop: 992,
58 | tablet: 768,
59 | mobile: 576,
60 | };
61 |
62 | // Iterate through the sizes and create a media template
63 | export const media = Object.keys(mediaBreakpoints).reduce((acc, label) => {
64 | acc[label] = (...args) => css`
65 | @media (max-width: ${mediaBreakpoints[label] / 16}em) {
66 | ${css(...args)};
67 | }
68 | `;
69 | return acc;
70 | }, {});
71 |
--------------------------------------------------------------------------------
/app/sources/src/locales/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Entrypoint for all internationalization stuff
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import i18n from 'i18next';
11 |
12 | import en from './en';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | i18n.init({
19 | fallbackLng: 'en',
20 | debug: process.env.NODE_ENV === 'development',
21 |
22 | interpolation: {
23 | escapeValue: false, // not needed for react!!
24 | },
25 |
26 | // react i18next special options (optional)
27 | react: {
28 | wait: false,
29 | bindI18n: 'languageChanged loaded',
30 | nsMode: 'default',
31 | },
32 | resources: {
33 | en: {
34 | translation: en,
35 | },
36 | },
37 | });
38 |
39 | export default i18n;
40 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Check/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import { observer, inject } from 'mobx-react';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import GA from 'utils/GA';
16 |
17 | import view from './view';
18 |
19 | const log = logger();
20 |
21 | // -----------------------------------------------------------------------------
22 | // Code
23 | // -----------------------------------------------------------------------------
24 |
25 | class Wrapper extends React.Component {
26 | async componentDidMount() {
27 | const { wallets, info } = this.props;
28 | const query = window.location.hash.match(/\?(.*)/);
29 |
30 | info.get.run();
31 |
32 | let wallet;
33 | if (query) {
34 | wallet = new URLSearchParams(query[0]).get('wallet');
35 | try {
36 | wallet = JSON.parse(wallet);
37 | } catch (error) {
38 | log.error(error);
39 | wallet = undefined;
40 | }
41 | }
42 | if (wallet) {
43 | GA({
44 | type: 'event',
45 | category: 'lnDomains',
46 | action: 'clickOnButton',
47 | label: wallet.origin || 'manual',
48 | });
49 | wallets.getDetails.run(wallet.wuid, wallet.asset);
50 | }
51 | }
52 |
53 | componentWillUnmount() {
54 | const { wallets } = this.props;
55 | wallets.getDetails.cleanup('all');
56 | clearInterval(this.polling);
57 | }
58 |
59 | render() {
60 | const query = window.location.hash.match(/\?(.*)/);
61 | let wallet;
62 | if (query) {
63 | wallet = new URLSearchParams(query[0]).get('wallet');
64 | try {
65 | wallet = JSON.parse(wallet);
66 | } catch (error) {
67 | log.error(error);
68 | wallet = undefined;
69 | }
70 | }
71 | return React.createElement(observer(view), { ...this.props, wallet });
72 | }
73 | }
74 |
75 | Wrapper.propTypes = {};
76 |
77 | export default inject('payments', 'wallets', 'accounts', 'info')(observer(Wrapper));
78 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Check/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Send scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import CheckDestinationRaw from 'components/CheckDestination';
13 |
14 | import { Header as HeaderRaw } from 'components/common';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | export * from 'components/common';
21 |
22 | export const Header = styled(HeaderRaw)`
23 | background: var(--colors__bg);
24 | font: var(--fonts__header_thin);
25 | min-height: var(--sizing__header_heigh);
26 | border-bottom: 0.05em solid var(--colors__bg_dark);
27 | `;
28 |
29 | export const CheckDestination = styled(CheckDestinationRaw)`
30 | padding-top: 2em;
31 | `;
32 |
33 | export const Root = styled.div`
34 | height: 100%;
35 | display: flex;
36 | flex-direction: column;
37 | justify-content: center;
38 | `;
39 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Check/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Send scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import logger from 'utils/logging';
13 |
14 | import { Root, Header, BackButton, P, CheckDestination, Support } from './styles';
15 |
16 | const log = logger();
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | const Send = ({ wallets, wallet, accounts, info }) => {
23 | return (
24 |
25 |
30 |
31 |
32 | );
33 | };
34 |
35 | export default Send;
36 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Confirm/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import { observer, inject } from 'mobx-react';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import GA from 'utils/GA';
16 |
17 | import view from './view';
18 |
19 | const log = logger();
20 |
21 | // -----------------------------------------------------------------------------
22 | // Code
23 | // -----------------------------------------------------------------------------
24 |
25 | class Wrapper extends React.Component {
26 | async componentDidMount() {
27 | const { vendors, accounts, info } = this.props;
28 | const query = window.location.hash.match(/\?(.*)/);
29 |
30 | let payment;
31 | if (query) {
32 | payment = new URLSearchParams(query[0]).get('payment');
33 | try {
34 | payment = JSON.parse(payment);
35 | } catch (error) {
36 | log.error(error);
37 | payment = undefined;
38 | }
39 | }
40 | if (!payment.origin) {
41 | try {
42 | const clipboardPayment = JSON.parse(localStorage.getItem('latestCopiedWuid'));
43 | if (clipboardPayment.wuid === payment.wuid) {
44 | payment.origin = clipboardPayment.origin;
45 | }
46 | } catch (e) {
47 | console.log(e);
48 | }
49 | GA({
50 | type: 'event',
51 | category: 'payment',
52 | action: 'insertedManually',
53 | label: payment.origin || 'unknown',
54 | });
55 | } else {
56 | GA({
57 | type: 'event',
58 | category: 'payment',
59 | action: 'insertedAutomatically_button',
60 | label: payment.origin,
61 | });
62 | }
63 |
64 | GA({
65 | type: 'event',
66 | category: 'vuidDomainPair',
67 | action: `${payment.origin || 'unknown'}_${payment.vuid}`,
68 | });
69 |
70 | vendors.get.run(payment.vuid, { origin: payment.origin });
71 | accounts.get.run();
72 | info.get.run();
73 |
74 | this.polling = setInterval(() => {
75 | accounts.get.run();
76 | info.get.run();
77 | }, 5000);
78 | }
79 |
80 | componentWillUnmount() {
81 | const { vendors } = this.props;
82 | vendors.get.cleanup('all');
83 | clearInterval(this.polling);
84 | }
85 |
86 | render() {
87 | const query = window.location.hash.match(/\?(.*)/);
88 | let payment;
89 | if (query) {
90 | payment = new URLSearchParams(query[0]).get('payment');
91 | try {
92 | payment = JSON.parse(payment);
93 | } catch (error) {
94 | log.error(error);
95 | payment = undefined;
96 | }
97 | }
98 | if (!payment.origin) {
99 | try {
100 | const clipboardPayment = JSON.parse(localStorage.getItem('latestCopiedWuid'));
101 | if (clipboardPayment.wuid === payment.wuid) {
102 | payment.origin = clipboardPayment.origin;
103 | }
104 | } catch (e) {
105 | console.log(e);
106 | }
107 | }
108 | return React.createElement(observer(view), { ...this.props, payment });
109 | }
110 | }
111 |
112 | Wrapper.propTypes = {};
113 |
114 | export default inject('payments', 'vendors', 'accounts', 'info')(observer(Wrapper));
115 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Confirm/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Send scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import PaymentConfirmationRaw from 'components/PaymentConfirmation';
13 |
14 | import { Header as HeaderRaw } from 'components/common';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | export * from 'components/common';
21 |
22 | export const Header = styled(HeaderRaw)`
23 | background: var(--colors__bg);
24 | font: var(--fonts__header_thin);
25 | min-height: var(--sizing__header_heigh);
26 | border-bottom: 0.05em solid var(--colors__bg_dark);
27 | `;
28 |
29 | export const PaymentConfirmation = styled(PaymentConfirmationRaw)``;
30 |
31 | export const Root = styled.div`
32 | display: flex;
33 | flex-direction: column;
34 | justify-content: flex-start;
35 | height: 100%;
36 | background: var(--colors__bg_bright);
37 | `;
38 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Confirm/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Send scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import logger from 'utils/logging';
13 |
14 | import { Root, Header, BackButton, P, PaymentConfirmation, Support } from './styles';
15 |
16 | const log = logger();
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | const Confirm = ({ payments, vendors, payment, accounts, info }) => {
23 | return (
24 |
25 |
30 | {payment ? (
31 |
38 | ) : (
39 | No payment provided to confirm
40 | )}
41 |
42 | );
43 | };
44 |
45 | export default Confirm;
46 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Landing/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import view from './view';
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | export default view;
17 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Landing/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Landing scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import SignupFormCommon from 'components/SignupForm';
13 |
14 | import { Div, media, Span } from 'components/common';
15 |
16 | import LogoFull from 'assets/img/logo/full.png';
17 | import LogoTextOnly from 'assets/img/logo/textOnly.png';
18 |
19 | // -----------------------------------------------------------------------------
20 | // Code
21 | // -----------------------------------------------------------------------------
22 |
23 | export * from 'components/common';
24 |
25 | export const Logo = styled.img.attrs({
26 | src: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
27 | })`
28 | position: relative;
29 | content: url(${LogoFull});
30 | height: 7.5em;
31 | ${media.desktop`
32 | content: url(${LogoTextOnly});
33 | `};
34 | `;
35 |
36 | export const Uvp = styled.div`
37 | padding-left: 1em;
38 | grid-area: left;
39 | align-items: flex-end;
40 | font-family: 'Open Sans', sans-serif;
41 | text-align: right;
42 | `;
43 |
44 | export const UvpTitle = styled.div`
45 | margin-top: -0.5em;
46 | display: flex;
47 | flex-direction: column;
48 | & > ${Span} {
49 | word-break: initial;
50 | }
51 | font-size: 2.7em;
52 | `;
53 |
54 | export const UvpDesc = styled.div`
55 | display: flex;
56 | flex-direction: column;
57 | margin-top: 1em;
58 | font-size: 1em;
59 | font-weight: 500;
60 | word-break: initial;
61 | `;
62 |
63 | export const SignupForm = styled(SignupFormCommon)``;
64 |
65 | export const Disclaimer = styled.div`
66 | position: relative;
67 | font-size: 0.8em;
68 | display: flex;
69 | flex-direction: column;
70 | font-weight: 600;
71 | color: var(--colors__text_error);
72 | & ${Span} {
73 | margin-bottom: 0.3em;
74 | }
75 | /* :before {
76 | content: '*';
77 | position: absolute;
78 | } */
79 | `;
80 |
81 | export const Root = styled.div`
82 | background-color: var(--colors__bg);
83 | display: grid;
84 | grid-template-areas:
85 | 'left right'
86 | 'left right';
87 | grid-template-rows: 1fr 1fr;
88 | grid-template-columns: 1fr 1fr;
89 | gap: 0 4em;
90 | height: 100%;
91 |
92 | & > ${Div}, & > ${Uvp} {
93 | display: flex;
94 | width: 100%;
95 | flex-direction: column;
96 | justify-content: center;
97 | }
98 |
99 | & > ${Div}:last-child {
100 | grid-area: right;
101 | align-items: flex-start;
102 | }
103 |
104 | & ${SignupForm} {
105 | width: 90%;
106 | max-width: 400px;
107 | min-width: 400px;
108 | }
109 |
110 | ${media.desktop`
111 | & > ${Uvp},
112 | & > ${Div}:last-child {
113 | align-items: center;
114 | }
115 | grid-template-areas: "left left"
116 | "right right";
117 | grid-template-rows: 1fr 1fr;
118 | grid-template-columns: 1fr 1fr;
119 | `};
120 | `;
121 |
122 | export default Root;
123 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Landing/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Public landing scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import { Root, Div, Uvp, SignupForm, Logo, Span, UvpDesc, UvpTitle, Disclaimer } from './styles';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | const Landing = () => (
19 |
20 |
21 |
22 |
23 | Lightning Network
24 | web wallet
25 |
26 |
27 | Fast, easy, no node install and synchronisation,
28 | no need to lock funds in channels and rebalance
29 |
30 |
31 |
32 |
33 |
34 | This is beta product, do not put a lot of money in it yet ;)
35 | If you will be too #reckless you can loose your funds
36 |
37 |
38 |
39 | );
40 |
41 | export default Landing;
42 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Login/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import { withRouter } from 'react-router';
11 |
12 | import view from './view';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | export default withRouter(view);
19 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Login/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Login scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import LoginFormCommon from 'components/LoginForm';
13 |
14 | import LogoFull from 'assets/img/logo/full.png';
15 |
16 | import { A, Span } from 'components/common';
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | export * from 'components/common';
23 |
24 | export const Root = styled.div`
25 | background-color: var(--colors__bg);
26 | display: flex;
27 | flex-direction: column;
28 | justify-content: center;
29 | align-items: center;
30 | height: 100%;
31 | & ${A} ${Span}:last-child {
32 | font: var(--fonts__text_bold);
33 | }
34 | & > ${A} {
35 | margin-top: 3.5em;
36 | display: flex;
37 | flex-direction: column;
38 | justify-content: center;
39 | align-items: center;
40 | color: var(--colors__bg_accent);
41 | font-size: 0.8em;
42 | }
43 | & > ${Span} {
44 | margin-top: 1.5em;
45 | font-size: 0.8em;
46 | color: var(--colors__bg_accent);
47 | cursor: pointer;
48 | }
49 | `;
50 |
51 | export const Logo = styled.img.attrs({
52 | src: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
53 | })`
54 | position: relative;
55 | content: url(${LogoFull});
56 | height: 3.5em;
57 | margin-bottom: 2em;
58 | `;
59 |
60 | export const LoginForm = styled(LoginFormCommon)`
61 | width: 100%;
62 | width: calc(100% - 2em);
63 | margin: 0 1em;
64 | & > div:last-of-type input {
65 | margin-bottom: 1.5em;
66 | }
67 | `;
68 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Login/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Authentication scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import { Root, LoginForm, Logo, A, Span, Button } from './styles';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | const Login = ({ history }) => (
19 |
20 |
21 |
22 | {process.env.NODE_ENV === 'development' ? (
23 | {
26 | window.chrome.permissions.request(
27 | {
28 | origins: ['http://lvh.me/*'],
29 | },
30 | () => {},
31 | );
32 | }}
33 | >
34 | Enable access to lvh.me
35 |
36 | ) : null}
37 | {
39 | history.push(`/signup`);
40 | }}
41 | >
42 | Do not have an account yet?
43 | Register here!
44 |
45 | {
47 | history.push(`/restore`);
48 | }}
49 | >
50 | Forgot your password?
51 |
52 | Have any other problems? Contact us!
53 |
54 | );
55 |
56 | export default Login;
57 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Payment/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import { observer, inject, PropTypes } from 'mobx-react';
12 | import { withNamespaces } from 'react-i18next';
13 | import { withRouter } from 'react-router';
14 |
15 | import view from './view';
16 |
17 | // -----------------------------------------------------------------------------
18 | // Code
19 | // -----------------------------------------------------------------------------
20 |
21 | class Wrapper extends React.Component {
22 | componentDidMount() {
23 | const {
24 | payments,
25 | match: {
26 | params: { puid },
27 | },
28 | } = this.props;
29 |
30 | payments.getById.run({ puid });
31 | }
32 |
33 | componentWillUnmount() {
34 | const { payments } = this.props;
35 | payments.getById.cleanup('all');
36 | }
37 |
38 | render() {
39 | return React.createElement(observer(view), this.props);
40 | }
41 | }
42 |
43 | Wrapper.propTypes = {};
44 |
45 | export default withNamespaces()(inject('payments')(withRouter(Wrapper)));
46 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Payment/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Payments scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import { P, Header as HeaderRaw } from 'components/common';
13 |
14 | import { ReactComponent as ErrorIconRaw } from 'assets/icons/x-circle.svg';
15 | import { ReactComponent as EmptyIconRaw } from 'assets/icons/paper.svg';
16 |
17 | import PaymentDetailsRaw from 'components/PaymentDetails';
18 |
19 | // -----------------------------------------------------------------------------
20 | // Code
21 | // -----------------------------------------------------------------------------
22 |
23 | export * from 'components/common';
24 |
25 | export const Header = styled(HeaderRaw)`
26 | min-height: var(--sizing__header_heigh);
27 | font: var(--fonts__header_thin);
28 | position: fixed;
29 | top: 0;
30 | z-index: 1;
31 | background-color: var(--colors__bg);
32 | `;
33 |
34 | export const PaymentDetails = styled(PaymentDetailsRaw)`
35 | margin-top: var(--sizing__header_heigh);
36 | `;
37 |
38 | export const EmptyIcon = styled(EmptyIconRaw)`
39 | margin-bottom: 3rem;
40 | height: 15rem;
41 | width: 15rem;
42 | opacity: 0.3;
43 | `;
44 | export const ErrorIcon = styled(ErrorIconRaw)`
45 | margin-bottom: 3rem;
46 | height: 15rem;
47 | width: 15rem;
48 | opacity: 0.3;
49 | `;
50 |
51 | export const EmptyWrapper = styled.div`
52 | display: flex;
53 | flex-direction: column;
54 | align-items: center;
55 | justify-content: center;
56 | opacity: 0.6;
57 | font-size: 2em;
58 | text-align: center;
59 | margin-top: 2em;
60 | margin-top: var(--sizing__header_heigh);
61 | & svg {
62 | stroke: #000;
63 | }
64 | `;
65 |
66 | export const Root = styled.div`
67 | display: flex;
68 | flex-direction: column;
69 | justify-content: center;
70 | `;
71 |
72 | export default Root;
73 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Payment/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Payments scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import formatDate from 'date-fns/format';
12 | import isSameDay from 'date-fns/is_same_day';
13 | import isToday from 'date-fns/is_today';
14 | import isYesteray from 'date-fns/is_yesterday';
15 |
16 | import {
17 | Root,
18 | EmptyIcon,
19 | ErrorIcon,
20 | EmptyWrapper,
21 | P,
22 | Header,
23 | Button,
24 | BalanceSummary,
25 | PaymentsGroup,
26 | Separator,
27 | BackButton,
28 | Support,
29 | PaymentDetails,
30 | } from './styles';
31 |
32 | // -----------------------------------------------------------------------------
33 | // Code
34 | // -----------------------------------------------------------------------------
35 |
36 | const getSeparatorText = date => {
37 | let distance;
38 | distance = formatDate(new Date(date), 'Do MMMM');
39 | if (isToday(date)) {
40 | distance = 'Today';
41 | }
42 | if (isYesteray(date)) {
43 | distance = 'Yesterday';
44 | }
45 | return distance;
46 | };
47 |
48 | // eslint-disable-next-line
49 | const Payment = ({ history, payments, location: { search }, t }) => {
50 | const backButtonHidden = new URLSearchParams(search).get('nopopup') === 'true';
51 |
52 | if (payments.getById.error || (!payments.getById.data && !payments.getById.loading)) {
53 | return (
54 |
55 |
56 |
57 | Payment details
58 |
59 |
60 |
61 |
62 | Unable to load details :(
63 | Try again later
64 |
65 |
66 | );
67 | }
68 |
69 | if (payments.getById.loading && !payments.getById.data) {
70 | return (
71 |
72 |
73 |
74 | Payment details
75 |
76 |
77 |
78 |
79 | Loading details
80 |
81 |
82 | );
83 | }
84 |
85 | if (!payments.getById.data[0]) {
86 | return (
87 |
88 |
89 |
90 | Payment details
91 |
92 |
93 |
94 |
95 | Payment not found
96 |
97 |
98 | );
99 | }
100 |
101 | return (
102 |
103 |
104 |
105 | Payment details
106 |
107 |
108 |
109 |
110 | );
111 | };
112 |
113 | export default Payment;
114 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Payments/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React, { useEffect } from 'react';
11 | import { observer, inject, PropTypes } from 'mobx-react';
12 | import { withNamespaces } from 'react-i18next';
13 |
14 | import view from './view';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | const Wrapper = props => {
21 | const { payments, accounts, ui, info } = props;
22 |
23 | useEffect(() => {
24 | accounts.get.run();
25 | payments.get.run();
26 | ui.getLiveChat.run();
27 | info.get.run();
28 | info.getSkippedAnnouncements.run();
29 |
30 | const polling = setInterval(() => {
31 | payments.get.run();
32 | accounts.get.run();
33 | info.get.run();
34 | }, 3000);
35 |
36 | return () => {
37 | clearInterval(polling);
38 | };
39 | });
40 |
41 | return React.createElement(observer(view), props);
42 | };
43 |
44 | Wrapper.propTypes = {
45 | // payments: PropTypes.observableObject.isRequired,
46 | };
47 |
48 | export default withNamespaces()(inject('payments', 'accounts', 'settings', 'info', 'ui')(Wrapper));
49 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Receive/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React, { useEffect } from 'react';
11 | import { observer, inject } from 'mobx-react';
12 |
13 | import logger from 'utils/logging';
14 |
15 | import view from './view';
16 |
17 | const log = logger();
18 |
19 | // -----------------------------------------------------------------------------
20 | // Code
21 | // -----------------------------------------------------------------------------
22 |
23 | const Wrapper = props => {
24 | const { payments, denominations } = props;
25 |
26 | useEffect(() => {
27 | const query = window.location.hash.match(/\?(.*)/);
28 |
29 | let receive;
30 | if (query) {
31 | receive = new URLSearchParams(query[0]).get('receive');
32 | try {
33 | receive = JSON.parse(receive);
34 | } catch (error) {
35 | log.error(error);
36 | receive = undefined;
37 | }
38 | }
39 | if (receive.type.match('blockchain')) {
40 | payments.receive.run(receive.type, null, receive.asset);
41 | }
42 |
43 | denominations.get.run();
44 |
45 | const polling = setInterval(() => {
46 | payments.get.run();
47 | }, 3000);
48 |
49 | return () => {
50 | clearInterval(polling);
51 | payments.receive.cleanup('all');
52 | };
53 | });
54 |
55 | const query = window.location.hash.match(/\?(.*)/);
56 |
57 | let receive;
58 | if (query) {
59 | receive = new URLSearchParams(query[0]).get('receive');
60 | try {
61 | receive = JSON.parse(receive);
62 | } catch (error) {
63 | log.error(error);
64 | receive = undefined;
65 | }
66 | }
67 |
68 | return React.createElement(observer(view), { ...props, receive, nopopup: new URLSearchParams(query[0]).get('nopopup') });
69 | };
70 |
71 | Wrapper.propTypes = {};
72 |
73 | export default inject('payments', 'denominations')(Wrapper);
74 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Receive/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Receive scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import ReceivePaymentCommon from 'components/ReceivePayment';
13 |
14 | import { Header as HeaderRaw } from 'components/common';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | export * from 'components/common';
21 |
22 | export const ReceivePayment = styled(ReceivePaymentCommon)``;
23 |
24 | export const Header = styled(HeaderRaw)`
25 | background: var(--colors__bg);
26 | font: var(--fonts__header_thin);
27 | min-height: var(--sizing__header_heigh);
28 | border-bottom: 0.05em solid var(--colors__bg_dark);
29 | `;
30 |
31 | export const Root = styled.div`
32 | display: flex;
33 | height: 100%;
34 | flex-direction: column;
35 | justify-content: center;
36 | `;
37 |
38 | export default Root;
39 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Receive/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Receive scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import { Root, Header, ReceivePayment, P, BackButton, Support } from './styles';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | const Receive = ({ payments, receive, denominations, nopopup }) => (
19 |
20 |
25 |
31 |
32 | );
33 |
34 | export default Receive;
35 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Restore/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import { observer, inject, PropTypes } from 'mobx-react';
12 | import { withNamespaces } from 'react-i18next';
13 | import { withRouter } from 'react-router';
14 |
15 | import view from './view';
16 |
17 | // -----------------------------------------------------------------------------
18 | // Code
19 | // -----------------------------------------------------------------------------
20 |
21 | class Wrapper extends React.Component {
22 | componentWillUnmount() {
23 | const { accounts } = this.props;
24 | accounts.sendRestoreLink.cleanup('all');
25 | }
26 |
27 | render() {
28 | return React.createElement(observer(view), this.props);
29 | }
30 | }
31 |
32 | Wrapper.propTypes = {};
33 |
34 | export default withNamespaces()(inject('accounts')(withRouter(Wrapper)));
35 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Restore/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Auth scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import RestoreFormCommon from 'components/RestoreForm';
13 |
14 | import LogoFull from 'assets/img/logo/full.png';
15 |
16 | import { A, Span, Header as HeaderRaw } from 'components/common';
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | export * from 'components/common';
23 |
24 | export const Header = styled(HeaderRaw)`
25 | background: var(--colors__bg);
26 | font: var(--fonts__header_thin);
27 | min-height: var(--sizing__header_heigh);
28 | border-bottom: 0.05em solid var(--colors__bg_dark);
29 | `;
30 |
31 | export const Root = styled.div`
32 | background-color: var(--colors__bg);
33 | display: flex;
34 | flex-direction: column;
35 | justify-content: center;
36 | align-items: center;
37 | height: 100%;
38 | & ${A} ${Span}:last-child {
39 | font: var(--fonts__text_bold);
40 | }
41 | & > ${A} {
42 | margin-top: 3.5em;
43 | display: flex;
44 | flex-direction: column;
45 | justify-content: center;
46 | align-items: center;
47 | color: var(--colors__bg_accent);
48 | font-size: 0.8em;
49 | }
50 | & > ${Span} {
51 | margin-top: 1.5em;
52 | font-size: 0.8em;
53 | color: var(--colors__bg_accent);
54 | cursor: pointer;
55 | margin-bottom: auto;
56 | }
57 | `;
58 |
59 | export const Logo = styled.img.attrs({
60 | src: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
61 | })`
62 | position: relative;
63 | content: url(${LogoFull});
64 | height: 3.5em;
65 | margin-bottom: 2em;
66 | `;
67 |
68 | export const RestoreForm = styled(RestoreFormCommon)`
69 | width: calc(100% - 2em);
70 | margin: 0 1em;
71 | margin-top: 1em;
72 | & > div:last-of-type input {
73 | margin-bottom: 1.5em;
74 | }
75 | `;
76 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Restore/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Authentication scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import { Root, Logo, RestoreForm, A, Span, Header, P, BackButton } from './styles';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | const Restore = ({ history }) => (
19 |
20 |
21 |
22 | Reset password
23 |
24 |
25 | Have any problems? Contact us!
26 |
27 | );
28 |
29 | export default Restore;
30 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Select/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import { observer, inject } from 'mobx-react';
12 | import { withNamespaces } from 'react-i18next';
13 |
14 | import view from './view';
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | class Wrapper extends React.Component {
21 | async componentDidMount() {
22 | const { payments, info } = this.props;
23 | info.get.run();
24 | payments.receive.run('blockchain', null, 'BTC');
25 | }
26 |
27 | componentWillUnmount() {
28 | const { payments } = this.props;
29 | payments.receive.cleanup('all');
30 | }
31 |
32 | render() {
33 | return React.createElement(observer(view), { ...this.props });
34 | }
35 | }
36 |
37 | Wrapper.propTypes = {};
38 |
39 | export default withNamespaces()(inject('payments', 'info')(observer(Wrapper)));
40 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Select/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Receive scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import SelectReceiveAssetRaw from 'components/SelectReceiveAsset';
13 |
14 | import {
15 | Header as HeaderRaw,
16 | Message as MessageRaw,
17 | withLoader,
18 | Span,
19 | Tip,
20 | } from 'components/common';
21 |
22 | // -----------------------------------------------------------------------------
23 | // Code
24 | // -----------------------------------------------------------------------------
25 |
26 | export * from 'components/common';
27 |
28 | export const SelectReceiveAsset = styled(SelectReceiveAssetRaw)`
29 | height: 100%;
30 | ${({ disabled }) =>
31 | disabled &&
32 | `
33 | opacity: 0.5;
34 | pointer-events: none;
35 | `}
36 | `;
37 |
38 | export const Header = styled(HeaderRaw)`
39 | background: var(--colors__bg);
40 | font: var(--fonts__header_thin);
41 | min-height: var(--sizing__header_heigh);
42 | border-bottom: 0.05em solid var(--colors__bg_dark);
43 | `;
44 |
45 | export const Maintenance = styled(MessageRaw)`
46 | position: relative;
47 | display: flex;
48 | flex-direction: column;
49 | justify-content: center;
50 | align-items: center;
51 | white-space: pre-wrap;
52 | text-align: center;
53 | margin-bottom: -3.5em;
54 | background: var(--colors__bg_warn);
55 | font-weight: 400;
56 | z-index: 11;
57 | & * {
58 | word-break: break-word;
59 | }
60 | & > ${Span} {
61 | font-weight: 600;
62 | font-size: 1.1em;
63 | padding: 0 !important;
64 | }
65 | & > ${Tip} {
66 | margin-left: 0.5em;
67 | }
68 | & > ${Tip}:before {
69 | background: none;
70 | border: 0.1em solid black;
71 | }
72 | `;
73 |
74 | export const Root = styled.div`
75 | display: flex;
76 | height: 100%;
77 | flex-direction: column;
78 | justify-content: center;
79 | `;
80 |
81 | export default withLoader(Root);
82 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Select/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Receive scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import { Root, Header, SelectReceiveAsset, P, BackButton, Support, Message, Span, Maintenance } from './styles';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | const Select = ({ payments, info, t }) => (
19 |
20 |
21 |
22 | Receive
23 |
24 |
25 | {payments.receive.error && !(info.get.data && info.get.data.status && info.get.data.status.type === 'maintenance' && info.get.data.status.message) ? (
26 |
27 | {t([`errors.${payments.receive.error.code}`, 'errors.default'], {
28 | ...payments.receive.error,
29 | })}
30 |
31 | ) : null}
32 | {info.get.data && info.get.data.status && info.get.data.status.type === 'maintenance' && info.get.data.status.message ? (
33 |
34 | {info.get.data.status.message.split('\n')[0]}
35 | {info.get.data.status.message
36 | .split('\n')
37 | .slice(1)
38 | .join('\n')}
39 |
40 | ) : null}
41 |
44 |
45 | );
46 |
47 | export default Select;
48 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Settings/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import { observer, inject, PropTypes } from 'mobx-react';
12 | import { withNamespaces } from 'react-i18next';
13 | import { withRouter } from 'react-router';
14 |
15 | import view from './view';
16 |
17 | // -----------------------------------------------------------------------------
18 | // Code
19 | // -----------------------------------------------------------------------------
20 |
21 | class Wrapper extends React.Component {
22 | componentDidMount() {
23 | const { settings, denominations } = this.props;
24 | if (settings.get.data) {
25 | settings.get.run();
26 | }
27 | if (denominations.get.data) {
28 | denominations.get.run();
29 | }
30 | }
31 |
32 | render() {
33 | return React.createElement(observer(view), this.props);
34 | }
35 | }
36 |
37 | Wrapper.propTypes = {};
38 |
39 | export default withNamespaces()(inject('settings', 'denominations', 'accounts')(withRouter(Wrapper)));
40 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Settings/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Payments scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import { P, Header as HeaderRaw } from 'components/common';
13 |
14 | import { ReactComponent as ErrorIconRaw } from 'assets/icons/x-circle.svg';
15 | import { ReactComponent as EmptyIconRaw } from 'assets/icons/paper.svg';
16 |
17 | import SettingsFormRaw from 'components/SettingsForm';
18 |
19 | // -----------------------------------------------------------------------------
20 | // Code
21 | // -----------------------------------------------------------------------------
22 |
23 | export * from 'components/common';
24 |
25 | export const Header = styled(HeaderRaw)`
26 | min-height: var(--sizing__header_heigh);
27 | font: var(--fonts__header_thin);
28 | position: fixed;
29 | top: 0;
30 | z-index: 1;
31 | background-color: var(--colors__bg);
32 | `;
33 |
34 | export const SettingsForm = styled(SettingsFormRaw)`
35 | margin-top: var(--sizing__header_heigh);
36 | `;
37 |
38 | export const EmptyIcon = styled(EmptyIconRaw)`
39 | margin-bottom: 3rem;
40 | height: 15rem;
41 | width: 15rem;
42 | opacity: 0.3;
43 | `;
44 | export const ErrorIcon = styled(ErrorIconRaw)`
45 | margin-bottom: 3rem;
46 | height: 15rem;
47 | width: 15rem;
48 | opacity: 0.3;
49 | `;
50 |
51 | export const EmptyWrapper = styled.div`
52 | display: flex;
53 | flex-direction: column;
54 | align-items: center;
55 | justify-content: center;
56 | opacity: 0.6;
57 | font-size: 2em;
58 | text-align: center;
59 | margin-top: 2em;
60 | margin-top: var(--sizing__header_heigh);
61 | & svg {
62 | stroke: #000;
63 | }
64 | `;
65 |
66 | export const Root = styled.div`
67 | display: flex;
68 | flex-direction: column;
69 | justify-content: center;
70 | `;
71 |
72 | export default Root;
73 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Settings/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Payments scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 | import formatDate from 'date-fns/format';
12 | import isSameDay from 'date-fns/is_same_day';
13 | import isToday from 'date-fns/is_today';
14 | import isYesteray from 'date-fns/is_yesterday';
15 |
16 | import {
17 | Root,
18 | EmptyIcon,
19 | ErrorIcon,
20 | EmptyWrapper,
21 | P,
22 | Header,
23 | SettingsForm,
24 | BackButton,
25 | Support,
26 | } from './styles';
27 |
28 | // -----------------------------------------------------------------------------
29 | // Code
30 | // -----------------------------------------------------------------------------
31 |
32 | // eslint-disable-next-line
33 | const SettingsScene = ({ history, settings, accounts, denominations, t }) => {
34 | if (settings.get.error || (!settings.get.data && !settings.get.loading)) {
35 | return (
36 |
37 |
38 |
39 | Settings
40 |
41 |
42 |
43 |
44 | Unable to load settings :(
45 | Try again later
46 |
47 |
48 | );
49 | }
50 |
51 | if (settings.get.loading && !settings.get.data) {
52 | return (
53 |
54 |
55 |
56 | Settings
57 |
58 |
59 |
60 |
61 | Loading settings
62 |
63 |
64 | );
65 | }
66 |
67 | return (
68 |
69 |
70 |
71 | Settings
72 |
73 |
74 |
75 |
76 | );
77 | };
78 |
79 | export default SettingsScene;
80 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Signup/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Data fetching and final component export
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import { withRouter } from 'react-router';
11 |
12 | import view from './view';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | export default withRouter(view);
19 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Signup/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Auth scene styles
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import styled from 'styled-components';
11 |
12 | import SignupFormCommon from 'components/SignupForm';
13 |
14 | import LogoFull from 'assets/img/logo/full.png';
15 |
16 | import { A, Span, Header as HeaderRaw } from 'components/common';
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | export * from 'components/common';
23 |
24 | export const Header = styled(HeaderRaw)`
25 | background: var(--colors__bg);
26 | font: var(--fonts__header_thin);
27 | min-height: var(--sizing__header_heigh);
28 | border-bottom: 0.05em solid var(--colors__bg_dark);
29 | `;
30 |
31 | export const Root = styled.div`
32 | background-color: var(--colors__bg);
33 | display: flex;
34 | flex-direction: column;
35 | justify-content: center;
36 | align-items: center;
37 | height: 100%;
38 | & ${A} ${Span}:last-child {
39 | font: var(--fonts__text_bold);
40 | }
41 | & > ${A} {
42 | margin-top: 3.5em;
43 | display: flex;
44 | flex-direction: column;
45 | justify-content: center;
46 | align-items: center;
47 | color: var(--colors__bg_accent);
48 | font-size: 0.8em;
49 | }
50 | & > ${Span} {
51 | margin-top: 1.5em;
52 | font-size: 0.8em;
53 | color: var(--colors__bg_accent);
54 | cursor: pointer;
55 | margin-bottom: auto;
56 | }
57 | `;
58 |
59 | export const Logo = styled.img.attrs({
60 | src: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
61 | })`
62 | position: relative;
63 | content: url(${LogoFull});
64 | height: 3.5em;
65 | margin-bottom: 2em;
66 | `;
67 |
68 | export const SignupForm = styled(SignupFormCommon)`
69 | width: calc(100% - 2em);
70 | margin: 0 1em;
71 | margin-top: 1em;
72 | & > div:last-of-type input {
73 | margin-bottom: 1.5em;
74 | }
75 | `;
76 |
--------------------------------------------------------------------------------
/app/sources/src/scenes/Signup/view.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Authentication scene
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import React from 'react';
11 |
12 | import { Root, Logo, SignupForm, A, Span, Header, P, BackButton } from './styles';
13 |
14 | // -----------------------------------------------------------------------------
15 | // Code
16 | // -----------------------------------------------------------------------------
17 |
18 | const Signup = ({ history }) => (
19 |
20 |
24 |
25 | {
27 | history.push(`/login`);
28 | }}
29 | >
30 | Already have account?
31 | Login instead
32 |
33 | Have any problems? Contact us!
34 |
35 | );
36 |
37 | export default Signup;
38 |
--------------------------------------------------------------------------------
/app/sources/src/setupProxy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Proxy setup for creat ereact app webpack dev server
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | const proxy = require('http-proxy-middleware');
11 |
12 | // -----------------------------------------------------------------------------
13 | // Code
14 | // -----------------------------------------------------------------------------
15 |
16 | module.exports = app => {
17 | app.use(
18 | proxy('/api', {
19 | target: 'http://host.docker.internal:3004',
20 | pathRewrite: {
21 | '^/api': '',
22 | },
23 | }),
24 | );
25 | };
26 |
--------------------------------------------------------------------------------
/app/sources/src/stores/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Entrypoint of all app stores
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import accounts from './accounts';
11 | import payments from './payments';
12 | import wallets from './wallets';
13 | import vendors from './vendors';
14 | import info from './info';
15 | import settings from './settings';
16 | import denominations from './denominations';
17 | import ui from './ui';
18 | import * as dataGeneric from './dataGeneric';
19 |
20 | // -----------------------------------------------------------------------------
21 | // Code
22 | // -----------------------------------------------------------------------------
23 |
24 | const init = async () => {
25 | await settings.get.init();
26 | await accounts.authenticate.run();
27 | if (accounts.authenticate.error) {
28 | await accounts.authenticate.cleanup('all');
29 | }
30 | };
31 |
32 | export { accounts, payments, wallets, settings, vendors, info, denominations, ui, init };
33 |
34 | export default {
35 | accounts,
36 | payments,
37 | wallets,
38 | settings,
39 | vendors,
40 | info,
41 | denominations,
42 | init,
43 | ui,
44 | ...dataGeneric,
45 | };
46 |
--------------------------------------------------------------------------------
/app/sources/src/stores/info.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Entrypoint of info store
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import logger from 'utils/logging';
11 | import GA from 'utils/GA';
12 |
13 | import { createDataFetcher } from './dataGeneric';
14 |
15 | const log = logger();
16 |
17 | // -----------------------------------------------------------------------------
18 | // Code
19 | // -----------------------------------------------------------------------------
20 |
21 | const info = {
22 | get: createDataFetcher({
23 | name: 'InfoGet',
24 | fetchOptions: {
25 | url: '/info',
26 | localFirst: true,
27 | },
28 | }),
29 | };
30 |
31 | info.skipAnnouncement = createDataFetcher({
32 | name: 'skipAnnouncement',
33 | fetchOptions: {
34 | method: 'POST',
35 | localName: 'skippedAnnouncements',
36 | localOnly: true,
37 | },
38 | async run(anuid) {
39 | const alreadySkipped = info.getSkippedAnnouncements.data || [];
40 | await info.getEngagedAnnouncements.run();
41 | GA({
42 | type: 'event',
43 | category: 'announcement',
44 | action:
45 | info.getEngagedAnnouncements.data && info.getEngagedAnnouncements.data.includes(anuid)
46 | ? 'skippedAndEngaged'
47 | : 'skipped',
48 | label: anuid,
49 | });
50 | return this.startFetching({ body: { data: [...alreadySkipped, anuid] } });
51 | },
52 | onData() {
53 | info.getSkippedAnnouncements.run();
54 | },
55 | });
56 |
57 | info.getSkippedAnnouncements = createDataFetcher({
58 | name: 'getSkippedAnnouncements',
59 | fetchOptions: {
60 | localName: 'skippedAnnouncements',
61 | localOnly: true,
62 | defaultValue: { data: [] },
63 | },
64 | });
65 |
66 | info.engageInAnnouncement = createDataFetcher({
67 | name: 'engageInAnnouncement',
68 | fetchOptions: {
69 | method: 'POST',
70 | localName: 'engagedAnnouncements',
71 | localOnly: true,
72 | },
73 | async run(anuid) {
74 | const alreadyEngaged = info.getEngagedAnnouncements.data || [];
75 | GA({
76 | type: 'event',
77 | category: 'announcement',
78 | action: 'engaged',
79 | label: anuid,
80 | });
81 | return this.startFetching({ body: { data: [...alreadyEngaged, anuid] } });
82 | },
83 | onData() {
84 | info.getEngagedAnnouncements.run();
85 | },
86 | });
87 |
88 | info.getEngagedAnnouncements = createDataFetcher({
89 | name: 'getEngagedAnnouncements',
90 | fetchOptions: {
91 | localName: 'engagedAnnouncements',
92 | localOnly: true,
93 | defaultValue: { data: [] },
94 | },
95 | });
96 |
97 | export default info;
98 |
--------------------------------------------------------------------------------
/app/sources/src/stores/settings.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Entrypoint of settings store
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import logger from 'utils/logging';
11 |
12 | import { denominations } from 'stores';
13 |
14 | import { createDataFetcher, round } from './dataGeneric';
15 |
16 | const log = logger();
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | const settings = {
23 | default: {
24 | content_script_permissions: undefined,
25 | denominations_BTC_main: 'USD',
26 | denominations_BTC_additional: 'SAT',
27 | },
28 | };
29 |
30 | settings.get = createDataFetcher({
31 | name: 'SettingsGet',
32 | fetchOptions: {
33 | localName: 'settings',
34 | localOnly: true,
35 | defaultValue: { data: settings.default },
36 | },
37 | init() {
38 | return new Promise(resolve => {
39 | window.chrome.permissions.contains(
40 | {
41 | permissions: ['tabs'],
42 | origins: [''],
43 | },
44 | async granted => {
45 | await settings.get.run();
46 | if (!settings.get.data) {
47 | await settings.set.run(settings.default);
48 | } else if (!settings.get.data.content_script_permissions && granted) {
49 | await settings.set.run({ content_script_permissions: 'granted' });
50 | }
51 | resolve();
52 | },
53 | );
54 | });
55 | },
56 | parseData(localSettings) {
57 | return {
58 | ...settings.default,
59 | ...localSettings,
60 | };
61 | },
62 | onData() {
63 | denominations.get.run();
64 | },
65 | });
66 |
67 | settings.set = createDataFetcher({
68 | name: 'SettingsSet',
69 | fetchOptions: {
70 | method: 'POST',
71 | localName: 'settings',
72 | localOnly: true,
73 | },
74 | async run(newSettings) {
75 | const currentSettings = settings.get.data || settings.default;
76 | return this.startFetching({ body: { data: { ...currentSettings, ...newSettings } } });
77 | },
78 | onData() {
79 | settings.get.run();
80 | },
81 | });
82 |
83 | export default settings;
84 |
--------------------------------------------------------------------------------
/app/sources/src/stores/ui.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Entrypoint of UI store
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import logger from 'utils/logging';
11 |
12 | import { createDataFetcher } from './dataGeneric';
13 |
14 | const log = logger();
15 |
16 | // -----------------------------------------------------------------------------
17 | // Code
18 | // -----------------------------------------------------------------------------
19 |
20 | const ui = {
21 | getLiveChat: createDataFetcher({
22 | name: 'GetLiveChat',
23 | data: { unread: 0 },
24 | async run() {
25 | return this.data || { unread: 0 };
26 | },
27 | }),
28 | };
29 |
30 | ui.setLiveChat = createDataFetcher({
31 | name: 'SetLiveChat',
32 | async run(data) {
33 | return ui.getLiveChat.onDataDefault(data, undefined, {});
34 | },
35 | });
36 |
37 | export default ui;
38 |
--------------------------------------------------------------------------------
/app/sources/src/stores/wallets.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Entrypoint of all wallets store
3 | *
4 | */
5 |
6 | // -----------------------------------------------------------------------------
7 | // Dependencies
8 | // -----------------------------------------------------------------------------
9 |
10 | import logger from 'utils/logging';
11 |
12 | import { accounts } from 'stores';
13 |
14 | import { createDataFetcher } from './dataGeneric';
15 |
16 | const log = logger();
17 |
18 | // -----------------------------------------------------------------------------
19 | // Code
20 | // -----------------------------------------------------------------------------
21 |
22 | const wallets = {
23 | getDetails: createDataFetcher({
24 | name: 'WalletsGetDetails',
25 | async fetchOptions({ wuid, asset } = {}) {
26 | return {
27 | url: `/wallets/details?asset=${asset}&wuid=${wuid}`,
28 | wuid,
29 | headers: {
30 | Authorization: `Bearer ${accounts.authenticate.data && accounts.authenticate.data.token}`,
31 | },
32 | };
33 | },
34 | parseData(data) {
35 | return {
36 | ...data,
37 | memo: data.memo && data.memo.replace(/&/g, '%26'),
38 | description: data.description && data.description.replace(/&/g, '%26'),
39 | };
40 | },
41 | async run(wuid, asset) {
42 | return this.startFetching({
43 | asset,
44 | wuid,
45 | headers: {
46 | Authorization: `Bearer ${accounts.authenticate.data && accounts.authenticate.data.token}`,
47 | },
48 | });
49 | },
50 | }),
51 | };
52 |
53 | export default wallets;
54 |
--------------------------------------------------------------------------------
/app/sources/src/utils/HA.js:
--------------------------------------------------------------------------------
1 |
2 | const trackingId =
3 | process.env.NODE_ENV !== 'production'
4 | ? '3256711276'
5 | : '664479579';
6 |
7 | (function HAinitializer() {
8 | window.heap = window.heap || [];
9 | window.heap.load = function(e, t) {
10 | window.heap.appid = e;
11 | window.heap.config = t = t || {};
12 | var r = t.forceSSL || 'https:' === document.location.protocol;
13 | const a = document.createElement('script');
14 | a.type = 'text/javascript';
15 | a.async = !0;
16 | a.src = (r ? 'https:' : 'https:') + '//cdn.heapanalytics.com/js/heap-' + e + '.js';
17 | var n = document.getElementsByTagName('script')[0];
18 | n.parentNode.insertBefore(a, n);
19 | for (
20 | var o = function(e) {
21 | return function() {
22 | window.heap.push([e].concat(Array.prototype.slice.call(arguments, 0)));
23 | };
24 | },
25 | p = [
26 | 'addEventProperties',
27 | 'addUserProperties',
28 | 'clearEventProperties',
29 | 'identify',
30 | 'resetIdentity',
31 | 'removeEventProperty',
32 | 'setEventProperties',
33 | 'track',
34 | 'unsetEventProperty',
35 | ],
36 | c = 0;
37 | c < p.length;
38 | c++
39 | )
40 | window.heap[p[c]] = o(p[c]);
41 | };
42 | window.heap.load(trackingId);
43 | })();
44 | export default '';
45 |
--------------------------------------------------------------------------------
/app/sources/src/utils/cryptonetChecker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Toolkit for checking current net (simnet/testnet/mainnet)
3 | * where app operates
4 | *
5 | */
6 |
7 | // -----------------------------------------------------------------------------
8 | // Dependencies
9 | // -----------------------------------------------------------------------------
10 |
11 | // -----------------------------------------------------------------------------
12 | // Code
13 | // -----------------------------------------------------------------------------
14 |
15 | const getCurrentNet = () =>
16 | (window.location.href.includes('simnet')
17 | ? 'simnet'
18 | : window.location.href.includes('testnet') ? 'testnet' : 'mainnet');
19 |
20 | export default getCurrentNet;
21 |
--------------------------------------------------------------------------------
/docker-compose-build.yml:
--------------------------------------------------------------------------------
1 | # Here changes of docker-compose for build prod app
2 | version: '3.4'
3 |
4 | services:
5 | ui:
6 | build:
7 | context: ./app
8 | target: builder
9 | volumes:
10 | - ./build:/opt/app/build-prod
11 | environment:
12 | - NODE_ENV=production
13 |
--------------------------------------------------------------------------------
/docker-compose-dev.yml:
--------------------------------------------------------------------------------
1 | # Here changes of docker-compose for development
2 | version: '3.4'
3 |
4 | services:
5 | ui:
6 | build:
7 | context: ./app
8 | target: development
9 | volumes:
10 | - ./build-watch:/opt/app/dist
11 | - ./app/sources/src:/opt/app/src
12 | - ./app/sources/public:/opt/app/public
13 | ports:
14 | - "3005:3000"
15 | environment:
16 | - NODE_ENV=development
17 | # Allows you to use any host like lvh.me and others
18 | - DANGEROUSLY_DISABLE_HOST_CHECK=true
19 | # Enables live reload inside VM or Docker
20 | - CHOKIDAR_USEPOLLING=true
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 | # ----------------------------------------------------------------------------
3 | # Setup default logging for all services
4 | # ----------------------------------------------------------------------------
5 | x-logging:
6 | &default-logging
7 | driver: json-file
8 | options:
9 | max-size: '10m'
10 | max-file: '10'
11 |
12 | services:
13 | # ----------------------------------------------------------------------------
14 | # Reverse proxy and SSL provider for all services
15 | # ----------------------------------------------------------------------------
16 | traefik:
17 | build:
18 | context: ./
19 | dockerfile: Dockerfile-traefik
20 | ports:
21 | - "80:80"
22 | - "443:443"
23 | - "10.135.15.180:8080:8080"
24 | restart: on-failure:3
25 | logging: *default-logging
26 | volumes:
27 | - /var/run/docker.sock:/var/run/docker.sock
28 | - ssl:/etc/traefik/acme
29 |
30 | # ----------------------------------------------------------------------------
31 | # Static file server with UI inside
32 | # ----------------------------------------------------------------------------
33 | ui:
34 | build: ./app
35 | restart: on-failure:3
36 | logging: *default-logging
37 | expose:
38 | - "80"
39 | environment:
40 | - INTERCOM_TOKEN=replace
41 | - NODE_ENV=production
42 | labels:
43 | - "traefik.enable=true"
44 | - "traefik.backend=ui"
45 | - "traefik.frontend.priority=10"
46 | - "traefik.port=80"
47 | - "traefik.frontend.rule=Host:testnet.bitlum.io,mainnet.bitlum.io"
48 |
49 | volumes:
50 | ssl:
51 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bitlum-ui",
3 | "version": "0.0.1",
4 | "description": "Bitlum wallet frontend services",
5 | "author": "Denis Khvostov",
6 | "private": true,
7 | "//": [
8 | "Comments section:",
9 | "root: is base docker-compose command with base Dockerfiles",
10 | "deploy: command that must be used for deployment to server through compose",
11 | "up: command to run app on development machine"
12 | ],
13 | "scripts": {
14 | "root": "docker-compose --project-name %npm_package_name% -f ./docker-compose.yml",
15 | "deploy": "npm run root -- up --build -d",
16 | "build": "npm run root -- -f ./docker-compose-build.yml up --build",
17 | "up": "npm run root -- -f ./docker-compose-dev.yml up --build"
18 | }
19 | }
--------------------------------------------------------------------------------
/traefik.toml:
--------------------------------------------------------------------------------
1 | debug = false
2 |
3 | logLevel = "INFO"
4 | defaultEntryPoints = ["https","http"]
5 |
6 | [entryPoints]
7 | [entryPoints.http]
8 | address = ":80"
9 | [entryPoints.http.redirect]
10 | entryPoint = "https"
11 | [entryPoints.https]
12 | address = ":443"
13 | [entryPoints.https.tls]
14 |
15 | [api]
16 |
17 | [docker]
18 | watch = true
19 | exposedByDefault = false
20 |
21 | [acme]
22 | email = "talionarwork@gmail.com"
23 | storage = "/etc/traefik/acme/acme.json"
24 | OnHostRule=true
25 | acmeLogging = true
26 | entryPoint = "https"
27 | [acme.httpChallenge]
28 | entryPoint = "http"
29 |
30 | [file]
31 | [backends.testnet_api]
32 | [backends.testnet_api.servers.server]
33 | url = "https://testnet.api.bitlum.io"
34 |
35 | [backends.mainnet_api]
36 | [backends.mainnet_api.servers.server]
37 | url = "https://api.bitlum.io"
38 |
39 | [frontends.testnet_api_passthrough]
40 | backend = "testnet_api"
41 | priority = 11
42 | [frontends.testnet_api_passthrough.routes.main]
43 | rule = "Host:testnet.bitlum.io;PathPrefixStrip:/api/"
44 |
45 | [frontends.mainnet_api_passthrough]
46 | backend = "mainnet_api"
47 | priority = 11
48 | [frontends.mainnet_api_passthrough.routes.main]
49 | rule = "Host:mainnet.bitlum.io;PathPrefixStrip:/api/"
--------------------------------------------------------------------------------