From 538d0fcb1a27aded4d881263679c55c9a6682465 Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 22 Oct 2019 15:41:47 +0300 Subject: [PATCH 001/144] DEXW-2225: Add simple http server to the desktop app --- electron/SimpleConnect.ts | 47 +++++++++++++++++++++++++++++++++++++++ electron/preload.ts | 5 ++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 electron/SimpleConnect.ts diff --git a/electron/SimpleConnect.ts b/electron/SimpleConnect.ts new file mode 100644 index 000000000..b58ffc8ce --- /dev/null +++ b/electron/SimpleConnect.ts @@ -0,0 +1,47 @@ +import { createServer, IncomingHttpHeaders, Server, STATUS_CODES } from 'http'; +import { URL } from 'url'; + +type Callback = (data: any, url: URL, headers: IncomingHttpHeaders) => Promise; + +export class SimpleConnect { + public static listen(port: number, cb: Callback): Server { + const server = createServer((req, res) => { + let dataString = ''; + + req.on('data', (chunk: string) => { + dataString += chunk; + }); + + req.on('end', () => { + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Access-Control-Allow-Origin', '*'); + + try { + const data = JSON.parse(dataString || 'null'); + const base = 'http://' + req.headers['host'].toString(); + const url = new URL(req.url, base); + + cb(data, url, req.headers).then((result: string) => { + res.writeHead(200); + res.end(result); + }).catch((error: string) => { + res.writeHead(400); + res.end(String(error) || STATUS_CODES[400]); + }); + } catch (e) { + res.writeHead(500); + res.end(String(e) || STATUS_CODES[500]); + } + }); + + req.on('error', (e) => { + res.writeHead(500); + res.end(String(e) || STATUS_CODES[500]); + }); + }); + + server.listen(port); + + return server; + } +} diff --git a/electron/preload.ts b/electron/preload.ts index ab58d40f8..675aafba9 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -1,5 +1,6 @@ import { Storage } from './Storage'; import { shell, remote } from 'electron'; +import { SimpleConnect } from './SimpleConnect'; process.once('loaded', () => { const g: any = global; @@ -8,10 +9,12 @@ process.once('loaded', () => { shell.openExternal(url); }; g.isDesktop = true; + g.SimpleConnect = SimpleConnect; + try { g.TransportNodeHid = require('@ledgerhq/hw-transport-node-hid'); } catch (e) { - + } const transferModule = remote.require('./transfer'); From c549486e7f6244e098e0c3e60da09d14a3069a5f Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 22 Oct 2019 15:44:54 +0300 Subject: [PATCH 002/144] DEXW-2225: Add connect providers --- data-service/connect/ConnectProvider.ts | 5 ++ data-service/connect/HttpConnectProvider.ts | 72 ++++++++++++++++ .../connect/PostMessageConnectProvider.ts | 86 +++++++++++++++++++ data-service/index.ts | 6 ++ data-service/utils/utils.ts | 2 + package-lock.json | 86 ++++++++++++++----- package.json | 2 +- 7 files changed, 235 insertions(+), 24 deletions(-) create mode 100644 data-service/connect/ConnectProvider.ts create mode 100644 data-service/connect/HttpConnectProvider.ts create mode 100644 data-service/connect/PostMessageConnectProvider.ts diff --git a/data-service/connect/ConnectProvider.ts b/data-service/connect/ConnectProvider.ts new file mode 100644 index 000000000..f161babf9 --- /dev/null +++ b/data-service/connect/ConnectProvider.ts @@ -0,0 +1,5 @@ +export interface ConnectProvider { + send(data: string, options: Record): Promise; + listen(cb: Function): Promise; + destroy(): void +} diff --git a/data-service/connect/HttpConnectProvider.ts b/data-service/connect/HttpConnectProvider.ts new file mode 100644 index 000000000..ebe94fa16 --- /dev/null +++ b/data-service/connect/HttpConnectProvider.ts @@ -0,0 +1,72 @@ +import { IncomingHttpHeaders, Server } from 'http'; +import { request } from '../utils/request'; +import { delay } from '../utils/utils'; +import { ConnectProvider } from './ConnectProvider'; + +interface HttpConnectProviderOptioins { + port: number; + url: string; + ttl?: number; +} + +interface SendOptions { + timeout?: number; + attempts?: number; +} + +type SimpleConnectCallback = (url: URL, data: any, headers: IncomingHttpHeaders) => Promise; + +export class HttpConnectProvider implements ConnectProvider { + private active = true; + private server: Server; + + constructor(private options: HttpConnectProviderOptioins) {} + + public async send(data: string, options: SendOptions = {}): Promise { + this.checkActive(); + + const { timeout = 1000, attempts = 1 } = options; + + for (let i = attempts; i > 0; i--) { + try { + const res = await request({ + url: this.options.url, + fetchOptions: { + method: 'POST', + body: data + } + }); + + return res; + } catch (e) { + await delay(timeout); + } + } + + throw new Error('Could not connect'); + } + + public async listen(cb: SimpleConnectCallback): Promise { + this.checkActive(); + this.server = (window as any).SimpleConnect.listen(this.options.port, cb); + + if (this.options.ttl) { + await delay(this.options.ttl); + this.server.close(); + } + } + + public destroy(): void { + this.active = false; + + if (this.server) { + this.server.close(); + } + } + + private checkActive(): void { + if (!this.active) { + throw new Error('Provider was destroyed'); + } + } +} diff --git a/data-service/connect/PostMessageConnectProvider.ts b/data-service/connect/PostMessageConnectProvider.ts new file mode 100644 index 000000000..1a787e42e --- /dev/null +++ b/data-service/connect/PostMessageConnectProvider.ts @@ -0,0 +1,86 @@ +import { Bus, WindowAdapter, WindowProtocol, IOneArgFunction } from '@waves/waves-browser-bus'; +import { delay } from '../utils/utils'; +import { ConnectProvider } from './ConnectProvider'; + +interface PostMessageConnectProviderOptioins { + mode?: 'export' | 'import'; + origins?: string[]; +} + +interface SendOptions { + event?: string; + timeout?: number; + attempts?: number; + mode?: 'listen' | 'dispatch' +} + +export class PostMessageConnectProvider implements ConnectProvider { + private adapter: WindowAdapter; + private bus: Bus; + private active: boolean; + + constructor(options: PostMessageConnectProviderOptioins = {}) { + this.adapter = new WindowAdapter( + [new WindowProtocol( + options.mode === 'import' ? + (window.opener || window.parent) : + window, + 'listen' + )], + [new WindowProtocol( + options.mode === 'import' ? + (window.opener || window.parent) : + window, + 'dispatch' + )], + { + origins: options.origins, + chanelId: `postMessageConnectProvider${options.mode === 'export' ? 'Client' : 'Server'}`, + availableChanelId: `postMessageConnectProvider${options.mode !== 'export' ? 'Client' : 'Server'}`, + } + ); + this.bus = new Bus(this.adapter); + this.active = true; + } + + public async send(data: string, options: SendOptions = {}): Promise { + this.checkActive(); + + const { timeout = 5000, attempts = 1 } = options; + + for (let i = attempts; i > 0; i--) { + try { + const res = await this.bus.request( + options.event, + data, + options.timeout + ); + + return JSON.parse(res) as T; + } catch (e) { + await delay(timeout); + } + } + + throw new Error('Could not connect'); + } + + public async listen(cb: IOneArgFunction): Promise { + this.checkActive(); + + this.bus.registerRequestHandler('data', (data) => { + return cb(JSON.parse(data)); + }); + } + + public destroy(): void { + this.bus.destroy(); + this.active = false; + } + + private checkActive(): void { + if (!this.active) { + throw new Error('Provider was destroyed'); + } + } +} diff --git a/data-service/index.ts b/data-service/index.ts index 9b8ce19f3..9c09b5f65 100644 --- a/data-service/index.ts +++ b/data-service/index.ts @@ -17,6 +17,8 @@ import * as signatureAdapters from '@waves/signature-adapter'; import { SIGN_TYPE, isValidAddress as utilsIsValidAddress } from '@waves/signature-adapter'; import { TTimeType } from './utils/utils'; import { IUserData } from './sign'; +import { HttpConnectProvider } from './connect/HttpConnectProvider'; +import { PostMessageConnectProvider } from './connect/PostMessageConnectProvider'; export { getAdapterByType, getAvailableList } from '@waves/signature-adapter'; export { Seed } from './classes/Seed'; @@ -33,6 +35,10 @@ export const utils = { ...utilsModule }; export const signature = { ...sign }; +export const connect = { + HttpConnectProvider, + PostMessageConnectProvider +}; export const signAdapters = signatureAdapters; export const isValidAddress = utilsIsValidAddress; diff --git a/data-service/utils/utils.ts b/data-service/utils/utils.ts index ceb84eec6..89a0ddcc3 100644 --- a/data-service/utils/utils.ts +++ b/data-service/utils/utils.ts @@ -183,3 +183,5 @@ export function getTransferFeeList() { .filter(item => item.balance.getTokens().gt(1.005) || item.isMy) .map(item => item.fee); } + +export const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)); diff --git a/package-lock.json b/package-lock.json index 7560bd56f..dbaa9b85a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -795,6 +795,22 @@ "integrity": "sha512-/ZHa5hNs6UP5F8h5FrxY3mjmYmmv9uodU0eBddwUvp0L4hsJD16dP+bY6xcc8lBMj7ghmm7Or63dG7VrhkcsnA==", "requires": { "@waves/waves-browser-bus": "^0.1.5" + }, + "dependencies": { + "@types/node": { + "version": "11.13.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.22.tgz", + "integrity": "sha512-rOsaPRUGTOXbRBOKToy4cgZXY4Y+QSVhxcLwdEveozbk7yuudhWMpxxcaXqYizLMP3VY7OcWCFtx9lGFh5j5kg==" + }, + "@waves/waves-browser-bus": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@waves/waves-browser-bus/-/waves-browser-bus-0.1.6.tgz", + "integrity": "sha512-oBXnMrxnZarsPeFjngGegBzmbIemZhhv7QXM1fCLTd0sjYA45MnGAZugi97dMggg/qjIAZ8NNkq/ozEIG27i0A==", + "requires": { + "@types/node": "^11.9.4", + "typed-ts-events": "^1.0.5" + } + } } }, "@waves/ledger": { @@ -902,18 +918,18 @@ "integrity": "sha512-jXbEnZ8dwy4bOZgumFv/9BTjpcCRP/oGAWcOh5pFMoeA/LShDGm2NwIds+4tDf3sEJu+nLD8UjK6aueM0s87RA==" }, "@waves/waves-browser-bus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@waves/waves-browser-bus/-/waves-browser-bus-0.1.5.tgz", - "integrity": "sha512-K7iAF2jqSxkEW1DdCAa4Qda21LDuN1MPP5zV/aHJjsO40MvFgMiLcpYSV9xw8OqXzYdZyk1omb9bBOA7r69aIQ==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@waves/waves-browser-bus/-/waves-browser-bus-0.2.2.tgz", + "integrity": "sha512-hbvtLsxaGGeNfQ2g4R4B3hQkTgFEiVoMzg3kzoLSpMegKqLQwOTLzaTdQbo+lI63GpAlq2BCojzqX/bGmWkw9Q==", "requires": { "@types/node": "^11.9.4", "typed-ts-events": "^1.0.5" }, "dependencies": { "@types/node": { - "version": "11.13.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.13.tgz", - "integrity": "sha512-GFWH7e4Q/OGLAO545bupVju+nE1YtLSwYAdLfSzAXnTPqoqKoXCOEtB7Cluvg9B/h2nGLhyzCDyCInYvrOE2nw==" + "version": "11.13.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.22.tgz", + "integrity": "sha512-rOsaPRUGTOXbRBOKToy4cgZXY4Y+QSVhxcLwdEveozbk7yuudhWMpxxcaXqYizLMP3VY7OcWCFtx9lGFh5j5kg==" } } }, @@ -1987,13 +2003,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, + "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -7027,7 +7045,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -7048,12 +7067,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7068,17 +7089,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -7195,7 +7219,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -7207,6 +7232,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7221,6 +7247,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7228,12 +7255,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7252,6 +7281,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -7339,7 +7369,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -7351,6 +7382,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -7436,7 +7468,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7472,6 +7505,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7491,6 +7525,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7534,12 +7569,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7665,13 +7702,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, + "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -12649,7 +12688,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "2.0.1", @@ -17449,9 +17489,9 @@ "dev": true }, "typed-ts-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-ts-events/-/typed-ts-events-1.0.5.tgz", - "integrity": "sha512-0a76E5Nc0t1L5YeOqYTLztuMrIT5FCGxzKVzowad0BR0ubS4BC+N2oisp3GI6ARnzwvvTyviYrwD+u6wmdNLTQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/typed-ts-events/-/typed-ts-events-1.1.1.tgz", + "integrity": "sha512-sYjxQrhBTg3HGzNBOXSURlIfmUGXS//dVGY08ofz9dbusX/IdcN8LD9SsFNbk4UgHy8reQPgSZw+ADpkLcPtDA==" }, "typedarray": { "version": "0.0.6", diff --git a/package.json b/package.json index 4a830c0d3..b738c0b42 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "@waves/parse-json-bignumber": "^1.0.1", "@waves/signature-adapter": "^5.6.1", "@waves/ts-types": "0.0.2", - "@waves/waves-browser-bus": "^0.1.5", + "@waves/waves-browser-bus": "0.2.2", "@waves/waves-transactions": "^3.18.1", "angular": "1.6.6", "angular-animate": "1.6.6", From fdae522f7a3a62b95c7921aeb115e99a9282d425 Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 22 Oct 2019 15:53:28 +0300 Subject: [PATCH 003/144] DEXW-2225: Add export/import with minimal UI --- src/modules/app/services/MultiAccount.js | 24 ++- src/modules/app/services/StorageImporter.js | 203 ++++++++++++++++++ src/modules/utils/modals/ModalManager.js | 8 + .../modals/migrateModal/migrateModal.html | 5 + .../utils/modals/migrateModal/migrateModal.js | 164 ++++++++++++++ 5 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 src/modules/app/services/StorageImporter.js create mode 100644 src/modules/utils/modals/migrateModal/migrateModal.html create mode 100644 src/modules/utils/modals/migrateModal/migrateModal.js diff --git a/src/modules/app/services/MultiAccount.js b/src/modules/app/services/MultiAccount.js index 1353b94ab..a55f0760a 100644 --- a/src/modules/app/services/MultiAccount.js +++ b/src/modules/app/services/MultiAccount.js @@ -8,10 +8,13 @@ decryptSeed, base58Encode, base58Decode, + base64Encode, blake2b, stringToBytes, address: buildAddress, - publicKey: buildPublicKey + publicKey: buildPublicKey, + sharedKey, + messageEncrypt } = libs.crypto; let _password; @@ -146,11 +149,30 @@ /** * @param {string} str + * @returns {string} */ hash(str) { return base58Encode(blake2b(base58Decode(str))); } + /** + * @param {string} privateKeyFrom + * @param {string} publicKeyTo + * @param {Object} storageData + * @returns {string} + */ + export(privateKeyFrom, publicKeyTo, storageData) { + return base64Encode( + messageEncrypt( + sharedKey(privateKeyFrom, publicKeyTo, 'waves_migration_token'), + JSON.stringify({ + password: _password, + storageData + }) + ) + ); + } + } angular.module('app').service('multiAccount', MultiAccount); diff --git a/src/modules/app/services/StorageImporter.js b/src/modules/app/services/StorageImporter.js new file mode 100644 index 000000000..e7bc9df34 --- /dev/null +++ b/src/modules/app/services/StorageImporter.js @@ -0,0 +1,203 @@ +// @ts-check + +(function () { + 'use strict'; + + const { libs } = require('@waves/waves-transactions'); + const { decryptSeed } = libs.crypto; + + class StorageImporter { + + static $inject = [ + '$log', + '$state', + 'storage', + 'user', + 'multiAccount' + ]; + + /** + * @param {ng.ILogService} $log + * @param {*} $state + * @param {app.utils.Storage} storage + * @param {app.User} user + * @param {app.MultiAccount} multiAccount + */ + constructor($log, $state, storage, user, multiAccount) { + this.$log = $log; + this.$state = $state; + this.storage = storage; + this.user = user; + this.multiAccount = multiAccount; + } + + /** + * @public + * @param {string} publicKeyTo + * @param {string} privateKeyFrom + * @returns {Promise<{password: string, storageData: Object}>} + */ + async export(privateKeyFrom, publicKeyTo) { + const keys = [ + 'multiAccountData', + 'multiAccountUsers', + 'multiAccountSettings', + 'multiAccountHash', + 'userList', + 'openClientMode' + ]; + + const storageData = {}; + + for (const key of keys) { + try { + // eslint-disable-next-line no-await-in-loop + const value = await this.storage.load(key); + + storageData[key] = value; + } catch (e) { + this.$log.error(`Could not read key "${key}" from storage. Error:`, e); + } + } + + return this.multiAccount.export(privateKeyFrom, publicKeyTo, storageData); + } + + /** + * @public + * @param {Object} data + * @param {string} data.password + * @param {Object} data.storageData + * @returns {Promise} + */ + async import(data) { + const multiAccountData = await this.storage.load('multiAccountData'); + + if (!multiAccountData) { + const signUpResult = await this.multiAccount.signUp( + data.password, + this.user.getSetting('encryptionRounds') + ); + + await this.user.saveMultiAccount(signUpResult); + } + + if (this.multiAccount.isSignedIn) { + await this._importData(data); + this._loginToFirstUser(data.password); + } else { + this.user.loginSignal.once(async () => { + await this._importData(data); + this._loginToFirstUser(data.password); + }); + } + } + + /** + * @private + * @param {Object} data + * @param {string} data.password + * @param {Object} data.storageData + * @returns {Promise} + */ + async _importData(data) { + const { multiAccountData, multiAccountUsers, ...rest } = data.storageData; + + await this._importMultiAccountUsers(multiAccountData, multiAccountUsers, data.password); + + for (const [key, value] of Object.entries(rest)) { + try { + // eslint-disable-next-line no-await-in-loop + await this._importDataItem(key, value); + } catch (e) { + this.$log.error(e); + } + } + + const multiAccountSettings = await this.user.getMultiAccountSettings(); + + this.user.setMultiAccountSettings(multiAccountSettings); + } + + /** + * @private + * @param {string} key + * @param {any} value + * @returns {Promise} + */ + async _importDataItem(key, value) { + const valueFromStorage = await this.storage.load(key); + + return !valueFromStorage ? + this.storage.save(key, value) : + Promise.resolve(); + } + + /** + * @private + * @param {string} multiAccountData + * @param {Object} multiAccountUsers + * @param {string} password + */ + async _importMultiAccountUsers(multiAccountData, multiAccountUsers, password) { + let currentMultiAccountUsers = await this.storage.load('multiAccountUsers'); + + if (!currentMultiAccountUsers) { + currentMultiAccountUsers = Object.create(null); + } + + try { + const users = JSON.parse(decryptSeed( + multiAccountData, + password, + this.user.getSetting('encryptionRounds') + )); + + for (const [hash, user] of Object.entries(users)) { + if (!currentMultiAccountUsers[hash]) { + currentMultiAccountUsers[hash] = multiAccountUsers[hash]; + // eslint-disable-next-line no-await-in-loop + const { multiAccountData, multiAccountHash } = await this.multiAccount.addUser(user); + // eslint-disable-next-line no-await-in-loop + await this.user.saveMultiAccount({ multiAccountData, multiAccountHash }); + } + } + + await this.storage.save('multiAccountUsers', currentMultiAccountUsers); + } catch (e) { + this.$log.error(e); + + return Promise.resolve(); + } + } + + /** + * @private + * @param {string} password + */ + async _loginToFirstUser(password) { + const multiAccountData = await this.user.getMultiAccountData(); + const multiAccountHash = await this.user.getMultiAccountHash(); + + await this.multiAccount.signIn( + multiAccountData, + password, + this.user.getSetting('encryptionRounds'), + multiAccountHash + ); + + const [firstUser] = await this.user.getMultiAccountUsers(); + + if (firstUser) { + this.user.logout('switch', true); + await this.user.login(firstUser); + this.user.goToActiveState(); + } else { + this.$state.go('create'); + } + } + + } + + angular.module('app').service('storageImporter', StorageImporter); +})(); diff --git a/src/modules/utils/modals/ModalManager.js b/src/modules/utils/modals/ModalManager.js index 68840c0e6..e5a447b63 100644 --- a/src/modules/utils/modals/ModalManager.js +++ b/src/modules/utils/modals/ModalManager.js @@ -708,6 +708,14 @@ }); } + showMigrateModal() { + return this._getModal({ + id: 'migrate-modal', + controller: 'MigrateModalCtrl', + contentUrl: 'modules/utils/modals/migrateModal/migrateModal.html' + }); + } + /** * @param {IDialogOptions} options * @return {Promise} diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html new file mode 100644 index 000000000..760c29e41 --- /dev/null +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -0,0 +1,5 @@ +
+ + Export + +
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js new file mode 100644 index 000000000..180684191 --- /dev/null +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -0,0 +1,164 @@ +// @ts-check + +(function () { + 'use strict'; + + const ds = require('data-service'); + const { libs, seedUtils } = require('@waves/waves-transactions'); + const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; + + /** + * @param {typeof Base} Base + * @param {ng.ILogService} $log + * @param {$mdDialog} $mdDialog + * @param {StorageImporter} storageImporter + * @returns {ExportModalCtrl} + */ + const controller = function (Base, $log, $mdDialog, storageImporter) { + const SEED_LENGTH = 20; + + class MigrateModalCtrl extends Base { + + /** + * @todo separate it for new and old client + */ + mode = window.opener ? 'import' : 'export'; + + constructor() { + super(); + + if (WavesApp.isDesktop()) { + this.connectProvider = new ds.connect.HttpConnectProvider({ + port: 8888, + url: 'http://localhost:8888/connect' + }); + } else { + this.connectProvider = new ds.connect.PostMessageConnectProvider({ + mode: this.mode + }); + } + + if (this.mode === 'import') { + this._listen(); + } + } + + export() { + const message = JSON.stringify({ event: 'connect' }); + + this.connectProvider.send(message, { + event: 'data', + attempts: 3 + }).then((result) => { + if (!result || result.event !== 'connect') { + throw new Error(`Message event is not valid: ${result.event}`); + } + + const publicKeyTo = result.payload; + const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); + + return storageImporter.export( + privateKey, + publicKeyTo + ).then((data) => { + return this.connectProvider.send(JSON.stringify({ + event: 'data', + payload: { + publicKey, + data + } + }), { event: 'data' }); + }); + }).then((result) => { + if (result.payload === 'ok') { + $log.log('done'); + this.connectProvider.destroy(); + } else { + $log.log('fail', result); + } + }).catch((e) => { + $log.error(e); + }); + } + + _listen() { + let privateKeyTo = null; + + this.connectProvider.listen((message) => { + return new Promise((resolve, reject) => { + if (!message) { + return reject(); + } + + switch (message.event) { + case 'connect': { + const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); + + privateKeyTo = privateKey; + + return resolve(JSON.stringify({ + event: 'connect', + payload: publicKey + })); + } + case 'data': { + const encryptedData = base64Decode(message.payload.data); + const publicKeyFrom = message.payload.publicKey; + + if (!privateKeyTo) { + return reject('Key pair does not exist'); + } + + try { + const data = JSON.parse( + messageDecrypt( + sharedKey( + privateKeyTo, + publicKeyFrom, + 'waves_migration_token' + ), + encryptedData + ) + ); + + return storageImporter.import(data).then(() => { + return resolve(JSON.stringify({ + event: 'data', + payload: 'ok' + })); + }).catch((e) => { + return reject(String(e)); + }).then(() => { + this.connectProvider.destroy(); + }); + } catch (e) { + return reject(String(e)); + } finally { + privateKeyTo = null; + } + } + default: return reject('Invalid message'); + } + }); + }); + } + + /** + * @param {number} seedLength + * @returns {TKeyPair} + */ + _generateSharedKeyPair(seedLength) { + const seed = seedUtils.generateNewSeed(seedLength); + + return keyPair(seed); + } + + } + + return new MigrateModalCtrl(); + }; + + controller.$inject = ['Base', '$log', '$mdDialog', 'storageImporter']; + + angular.module('app.utils').controller('MigrateModalCtrl', controller); +})(); From 8372ab548dc5abe1882177ae74d12ced25f83871 Mon Sep 17 00:00:00 2001 From: finico Date: Thu, 24 Oct 2019 19:08:36 +0300 Subject: [PATCH 004/144] DEXW-2225: Add import account page --- data-service/connect/HttpConnectProvider.ts | 2 +- src/index.hbs | 8 + src/modules/app/app.js | 1 + src/modules/app/services/StorageImporter.js | 59 ++---- .../controllers/ImportAccountCtrl.js | 182 ++++++++++++++++++ src/modules/importAccount/importAccount.js | 5 + .../templates/importAccount.html | 48 +++++ .../components/signInForm/signInForm.html | 35 ++++ .../components/signInForm/signInForm.js | 109 +++++++++++ src/modules/signIn/controllers/SignInCtrl.js | 79 ++------ src/modules/signIn/templates/signIn.html | 39 +--- .../signIn/templates/signInHasUsers.html | 74 ------- .../signIn/templates/signInNoUsers.html | 18 -- .../utils/modals/migrateModal/migrateModal.js | 89 +-------- .../welcome/controllers/WelcomeCtrl.js | 1 + 15 files changed, 434 insertions(+), 315 deletions(-) create mode 100644 src/modules/importAccount/controllers/ImportAccountCtrl.js create mode 100644 src/modules/importAccount/importAccount.js create mode 100644 src/modules/importAccount/templates/importAccount.html create mode 100644 src/modules/signIn/components/signInForm/signInForm.html create mode 100644 src/modules/signIn/components/signInForm/signInForm.js delete mode 100644 src/modules/signIn/templates/signInHasUsers.html delete mode 100644 src/modules/signIn/templates/signInNoUsers.html diff --git a/data-service/connect/HttpConnectProvider.ts b/data-service/connect/HttpConnectProvider.ts index ebe94fa16..c20849b1b 100644 --- a/data-service/connect/HttpConnectProvider.ts +++ b/data-service/connect/HttpConnectProvider.ts @@ -14,7 +14,7 @@ interface SendOptions { attempts?: number; } -type SimpleConnectCallback = (url: URL, data: any, headers: IncomingHttpHeaders) => Promise; +type SimpleConnectCallback = (data: any, url: URL, headers: IncomingHttpHeaders) => Promise; export class HttpConnectProvider implements ConnectProvider { private active = true; diff --git a/src/index.hbs b/src/index.hbs index 9e54b7ab6..4ca2f3b89 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -710,6 +710,14 @@ views: [{ name: 'main' }] } }, + { + id: 'importAccount', + data: { + url: '/import-account', + views: [{ name: 'main' }], + noLogin: true + } + }, { id: 'stand', data: { diff --git a/src/modules/app/app.js b/src/modules/app/app.js index 9d0ca7292..e80fb9944 100644 --- a/src/modules/app/app.js +++ b/src/modules/app/app.js @@ -114,6 +114,7 @@ 'app.keeper', 'app.fromBackup', 'app.import', + 'app.importAccount', 'app.wallet', 'app.dex', 'app.tokens', diff --git a/src/modules/app/services/StorageImporter.js b/src/modules/app/services/StorageImporter.js index e7bc9df34..4e4489ba4 100644 --- a/src/modules/app/services/StorageImporter.js +++ b/src/modules/app/services/StorageImporter.js @@ -71,7 +71,7 @@ * @returns {Promise} */ async import(data) { - const multiAccountData = await this.storage.load('multiAccountData'); + const multiAccountData = await this.user.getMultiAccountData(); if (!multiAccountData) { const signUpResult = await this.multiAccount.signUp( @@ -82,15 +82,7 @@ await this.user.saveMultiAccount(signUpResult); } - if (this.multiAccount.isSignedIn) { - await this._importData(data); - this._loginToFirstUser(data.password); - } else { - this.user.loginSignal.once(async () => { - await this._importData(data); - this._loginToFirstUser(data.password); - }); - } + await this._importData(data); } /** @@ -98,12 +90,13 @@ * @param {Object} data * @param {string} data.password * @param {Object} data.storageData - * @returns {Promise} + * @returns {Promise} */ async _importData(data) { - const { multiAccountData, multiAccountUsers, ...rest } = data.storageData; + const { multiAccountData, multiAccountUsers, multiAccountSettings, ...rest } = data.storageData; await this._importMultiAccountUsers(multiAccountData, multiAccountUsers, data.password); + await this._importMultiAccountSettings(multiAccountSettings); for (const [key, value] of Object.entries(rest)) { try { @@ -113,10 +106,6 @@ this.$log.error(e); } } - - const multiAccountSettings = await this.user.getMultiAccountSettings(); - - this.user.setMultiAccountSettings(multiAccountSettings); } /** @@ -163,7 +152,7 @@ } } - await this.storage.save('multiAccountUsers', currentMultiAccountUsers); + await this.user.saveMultiAccountUsers(currentMultiAccountUsers); } catch (e) { this.$log.error(e); @@ -173,28 +162,22 @@ /** * @private - * @param {string} password + * @param {Object} multiAccountSettings + * @returns {Promise} */ - async _loginToFirstUser(password) { - const multiAccountData = await this.user.getMultiAccountData(); - const multiAccountHash = await this.user.getMultiAccountHash(); - - await this.multiAccount.signIn( - multiAccountData, - password, - this.user.getSetting('encryptionRounds'), - multiAccountHash - ); - - const [firstUser] = await this.user.getMultiAccountUsers(); - - if (firstUser) { - this.user.logout('switch', true); - await this.user.login(firstUser); - this.user.goToActiveState(); - } else { - this.$state.go('create'); - } + async _importMultiAccountSettings(multiAccountSettings) { + delete multiAccountSettings.lastOpenVersion; + delete multiAccountSettings.termsAccepted; + + const currentMultiAccountSettings = await this.user.getMultiAccountSettings(); + const mergedSettings = { + ...multiAccountSettings, + ...currentMultiAccountSettings + }; + + await this.user.saveMultiAccountSettings(mergedSettings); + + this.user.setMultiAccountSettings(mergedSettings); } } diff --git a/src/modules/importAccount/controllers/ImportAccountCtrl.js b/src/modules/importAccount/controllers/ImportAccountCtrl.js new file mode 100644 index 000000000..5d9dadf1e --- /dev/null +++ b/src/modules/importAccount/controllers/ImportAccountCtrl.js @@ -0,0 +1,182 @@ +// @ts-check + +(() => { + 'use strict'; + + const ds = require('data-service'); + const { libs, seedUtils } = require('@waves/waves-transactions'); + const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; + + /** + * @param {*} Base + * @param {ng.IScope} $scope + * @param {*} user + * @param {*} multiAccount + * @param {*} storageImporter + */ + const controller = function (Base, $scope, user, multiAccount, storageImporter) { + const SEED_LENGTH = 20; + + class ImportAccountCtrl extends Base { + + /** + * @type {'idle' | 'progress' | 'ready' | 'success' | 'error'} + */ + status = 'idle'; + + /** + * @type {boolean} + */ + hasAccount = false; + + /** + * @type {Object} + */ + data = null; + + constructor() { + super($scope); + + if (WavesApp.isDesktop()) { + this.connectProvider = new ds.connect.HttpConnectProvider({ + port: 8888, + url: 'http://localhost:8888/connect' + }); + } else { + this.connectProvider = new ds.connect.PostMessageConnectProvider({ + mode: 'import' + }); + } + + user.getMultiAccountData().then((multiAccountData) => { + if (multiAccountData) { + this.hasAccount = true; + } else { + this._listen(); + } + }); + } + + importAccount() { + storageImporter.import(this.data).then(() => { + this.status = 'success'; + $scope.$digest(); + }).catch(() => { + this.status = 'error'; + $scope.$digest(); + }); + } + + async login() { + if (!multiAccount.isSignedIn) { + const multiAccountData = await user.getMultiAccountData(); + const multiAccountHash = await user.getMultiAccountHash(); + + await multiAccount.signIn( + multiAccountData, + this.data.password, + user.getSetting('encryptionRounds'), + multiAccountHash + ); + } + + const [firstUser] = await user.getMultiAccountUsers(); + + if (firstUser) { + user.logout('switch', true); + await user.login(firstUser); + user.goToActiveState(); + } else { + this.$state.go('create'); + } + } + + onSignIn() { + this._listen(); + } + + onResetPassword() { + throw new Error('ImportAccountCtrl.onResetPassword() not implemented'); + } + + /** + * @private + */ + _listen() { + let privateKeyTo = null; + this.status = 'progress'; + + this.connectProvider.listen((message) => { + return new Promise((resolve, reject) => { + if (!message) { + return reject(); + } + + switch (message.event) { + case 'connect': { + const { publicKey, privateKey } = keyPair( + seedUtils.generateNewSeed(SEED_LENGTH) + ); + + privateKeyTo = privateKey; + + return resolve(JSON.stringify({ + event: 'connect', + payload: publicKey + })); + } + case 'data': { + const encryptedData = base64Decode(message.payload.data); + const publicKeyFrom = message.payload.publicKey; + + if (!privateKeyTo) { + return reject('Key pair does not exist'); + } + + try { + this.data = JSON.parse( + messageDecrypt( + sharedKey( + privateKeyTo, + publicKeyFrom, + 'waves_migration_token' + ), + encryptedData + ) + ); + + this.status = 'ready'; + + return resolve(JSON.stringify({ + event: 'data', + payload: 'ok' + })); + } catch (e) { + this.status = 'error'; + + return reject(String(e)); + } finally { + privateKeyTo = null; + } + } + default: return reject('Invalid message'); + } + }); + }); + } + + } + + return new ImportAccountCtrl(); + }; + + controller.$inject = [ + 'Base', + '$scope', + 'user', + 'multiAccount', + 'storageImporter' + ]; + + angular.module('app.importAccount').controller('ImportAccountCtrl', controller); +})(); diff --git a/src/modules/importAccount/importAccount.js b/src/modules/importAccount/importAccount.js new file mode 100644 index 000000000..3559b6cfe --- /dev/null +++ b/src/modules/importAccount/importAccount.js @@ -0,0 +1,5 @@ +(() => { + 'use strict'; + + angular.module('app.importAccount', []); +})(); diff --git a/src/modules/importAccount/templates/importAccount.html b/src/modules/importAccount/templates/importAccount.html new file mode 100644 index 000000000..b5a5febc5 --- /dev/null +++ b/src/modules/importAccount/templates/importAccount.html @@ -0,0 +1,48 @@ + + +
+
+
+
+

Import account

+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ +
+ + Import + +
+ +
+ Success + + Go to account + +
+ +
+ Error + + Retry + +
+
+
+
diff --git a/src/modules/signIn/components/signInForm/signInForm.html b/src/modules/signIn/components/signInForm/signInForm.html new file mode 100644 index 000000000..47705ad2e --- /dev/null +++ b/src/modules/signIn/components/signInForm/signInForm.html @@ -0,0 +1,35 @@ +
+ +
+ +
+ + + + + + + +
+ + +
+
+ +
+ + + +
+
diff --git a/src/modules/signIn/components/signInForm/signInForm.js b/src/modules/signIn/components/signInForm/signInForm.js new file mode 100644 index 000000000..f65a81f69 --- /dev/null +++ b/src/modules/signIn/components/signInForm/signInForm.js @@ -0,0 +1,109 @@ +(() => { + 'use strict'; + + /** + * @param {typeof Base} Base + * @param {ng.IScope} $scope + * @param {*} $state + * @param {User} user + * @param {MultiAccount} multiAccount + * @param {ModalManager} modalManager + * @returns {SignInFormCtrl} + */ + const controller = function (Base, $scope, $state, user, multiAccount, modalManager) { + + class SignInFormCtrl extends Base { + + /** + * @type {string} + */ + password = ''; + /** + * @type {ng.IFormController|null} + */ + form = null; + /** + * @type {string} + */ + multiAccountData = ''; + /** + * @type {string} + */ + multiAccountHash = ''; + /** + * @type {Array|null} + */ + legacyUserList = null; + + constructor() { + super($scope); + + this.observe('password', this._updatePassword); + + Promise.all([ + user.getMultiAccountData(), + user.getMultiAccountHash(), + user.getFilteredUserList() + ]).then(([multiAccountData, multiAccountHash, userList]) => { + if (!multiAccountData) { + $state.go('signUp'); + } else { + this.multiAccountData = multiAccountData; + this.multiAccountHash = multiAccountHash; + this.legacyUserList = userList; + } + }); + } + + onSubmit() { + if (this.form.$invalid) { + return; + } + + this.showPasswordError = false; + + multiAccount.signIn( + this.multiAccountData, + this.password, + undefined, + this.multiAccountHash + ).then(() => { + this.onSuccess(); + }).catch(() => { + this._showPasswordError(); + }); + } + + showForgotPasswordModal() { + modalManager.showForgotPasswordModal().then(() => { + this.onResetPassword(); + }); + } + + _showPasswordError() { + this.password = ''; + this.showPasswordError = true; + } + + _updatePassword() { + if (this.password) { + this.showPasswordError = false; + } + } + + } + + return new SignInFormCtrl(); + }; + + controller.$inject = ['Base', '$scope', '$state', 'user', 'multiAccount', 'modalManager']; + + angular.module('app.signIn').component('wSignInForm', { + templateUrl: 'modules/signIn/components/signInForm/signInForm.html', + controller, + bindings: { + onSuccess: '&', + onResetPassword: '&' + } + }); +})(); diff --git a/src/modules/signIn/controllers/SignInCtrl.js b/src/modules/signIn/controllers/SignInCtrl.js index 3156db33d..f98366ac4 100644 --- a/src/modules/signIn/controllers/SignInCtrl.js +++ b/src/modules/signIn/controllers/SignInCtrl.js @@ -1,4 +1,4 @@ -(function () { +(() => { 'use strict'; const analytics = require('@waves/event-sender'); @@ -8,30 +8,12 @@ * @param {ng.IScope} $scope * @param {*} $state * @param {User} user - * @param {MultiAccount} multiAccount - * @param {ModalManager} modalManager * @returns {SignInCtrl} */ - const controller = function (Base, $scope, $state, user, multiAccount, modalManager) { + const controller = function (Base, $scope, $state, user) { class SignInCtrl extends Base { - /** - * @type {string} - */ - password = ''; - /** - * @type {ng.IFormController|null} - */ - loginForm = null; - /** - * @type {string} - */ - multiAccountData = ''; - /** - * @type {string} - */ - multiAccountHash = ''; /** * @type {Array|null} */ @@ -40,49 +22,33 @@ constructor() { super($scope); - this.observe('password', this._updatePassword); - analytics.send({ name: 'Onboarding Sign In Show', target: 'ui', params: { from: 'sign-in' } }); Promise.all([ user.getMultiAccountData(), - user.getMultiAccountHash(), user.getFilteredUserList() - ]).then(([multiAccountData, multiAccountHash, userList]) => { + ]).then(([multiAccountData, userList]) => { if (!multiAccountData) { $state.go('signUp'); } else { - this.multiAccountData = multiAccountData; - this.multiAccountHash = multiAccountHash; this.legacyUserList = userList; } }); } - onSubmit() { - this.showPasswordError = false; - - multiAccount.signIn( - this.multiAccountData, - this.password, - undefined, - this.multiAccountHash - ).then( - () => Promise.all([ - user.getMultiAccountUsers(), - user.getMultiAccountSettings() - ]), - () => { - this._showPasswordError(); - return Promise.reject(); - } - ).then(([multiAccountUsers, commonSettings]) => { + onLogin() { + Promise.all([ + user.getMultiAccountUsers(), + user.getMultiAccountSettings() + ]).then(([multiAccountUsers, commonSettings]) => { const [firstUser] = multiAccountUsers; user.setMultiAccountSettings(commonSettings); if (firstUser) { - this._login(firstUser); + user.login(firstUser).then(() => { + user.goToActiveState(); + }); } else if (this.legacyUserList && this.legacyUserList.length) { $state.go('migrate'); } else { @@ -93,27 +59,8 @@ }); } - showForgotPasswordModal() { - modalManager.showForgotPasswordModal().then(() => { - $state.go('signUp'); - }); - } - - _login(userData) { - user.login(userData).then(() => { - user.goToActiveState(); - }); - } - - _showPasswordError() { - this.password = ''; - this.showPasswordError = true; - } - - _updatePassword() { - if (this.password) { - this.showPasswordError = false; - } + onResetPassword() { + $state.go('signUp'); } } diff --git a/src/modules/signIn/templates/signIn.html b/src/modules/signIn/templates/signIn.html index c78816b91..9564755fa 100644 --- a/src/modules/signIn/templates/signIn.html +++ b/src/modules/signIn/templates/signIn.html @@ -13,41 +13,10 @@ -
- -
- -
- - - - - - - -
- - -
-
- -
- - - -
-
+ diff --git a/src/modules/signIn/templates/signInHasUsers.html b/src/modules/signIn/templates/signInHasUsers.html deleted file mode 100644 index 8c3e158f0..000000000 --- a/src/modules/signIn/templates/signInHasUsers.html +++ /dev/null @@ -1,74 +0,0 @@ -
- -
-
-
- -
-
- -
- - - - -
-
- -
-
{{::user.name}}
-
{{::user.address}}
-
-
-
-
- -
-
-
-
- - - - - - - - - - - - - - - -
- - - -
diff --git a/src/modules/signIn/templates/signInNoUsers.html b/src/modules/signIn/templates/signInNoUsers.html deleted file mode 100644 index 719fba892..000000000 --- a/src/modules/signIn/templates/signInNoUsers.html +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 180684191..292ea56b4 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -1,18 +1,17 @@ // @ts-check -(function () { +(() => { 'use strict'; const ds = require('data-service'); const { libs, seedUtils } = require('@waves/waves-transactions'); - const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; + const { keyPair } = libs.crypto; /** - * @param {typeof Base} Base + * @param {*} Base * @param {ng.ILogService} $log - * @param {$mdDialog} $mdDialog - * @param {StorageImporter} storageImporter - * @returns {ExportModalCtrl} + * @param {*} $mdDialog + * @param {*} storageImporter */ const controller = function (Base, $log, $mdDialog, storageImporter) { const SEED_LENGTH = 20; @@ -37,10 +36,6 @@ mode: this.mode }); } - - if (this.mode === 'import') { - this._listen(); - } } export() { @@ -55,7 +50,7 @@ } const publicKeyTo = result.payload; - const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); + const { publicKey, privateKey } = keyPair(seedUtils.generateNewSeed(SEED_LENGTH)); return storageImporter.export( privateKey, @@ -81,78 +76,6 @@ }); } - _listen() { - let privateKeyTo = null; - - this.connectProvider.listen((message) => { - return new Promise((resolve, reject) => { - if (!message) { - return reject(); - } - - switch (message.event) { - case 'connect': { - const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); - - privateKeyTo = privateKey; - - return resolve(JSON.stringify({ - event: 'connect', - payload: publicKey - })); - } - case 'data': { - const encryptedData = base64Decode(message.payload.data); - const publicKeyFrom = message.payload.publicKey; - - if (!privateKeyTo) { - return reject('Key pair does not exist'); - } - - try { - const data = JSON.parse( - messageDecrypt( - sharedKey( - privateKeyTo, - publicKeyFrom, - 'waves_migration_token' - ), - encryptedData - ) - ); - - return storageImporter.import(data).then(() => { - return resolve(JSON.stringify({ - event: 'data', - payload: 'ok' - })); - }).catch((e) => { - return reject(String(e)); - }).then(() => { - this.connectProvider.destroy(); - }); - } catch (e) { - return reject(String(e)); - } finally { - privateKeyTo = null; - } - } - default: return reject('Invalid message'); - } - }); - }); - } - - /** - * @param {number} seedLength - * @returns {TKeyPair} - */ - _generateSharedKeyPair(seedLength) { - const seed = seedUtils.generateNewSeed(seedLength); - - return keyPair(seed); - } - } return new MigrateModalCtrl(); diff --git a/src/modules/welcome/controllers/WelcomeCtrl.js b/src/modules/welcome/controllers/WelcomeCtrl.js index 88c50243e..e1d3da628 100644 --- a/src/modules/welcome/controllers/WelcomeCtrl.js +++ b/src/modules/welcome/controllers/WelcomeCtrl.js @@ -273,6 +273,7 @@ }); }) .catch(() => { + this.pendingRestore = false; storage.save('accountImportComplete', true); }); } From 0a1e3bf6e049338a4a46bcfe8434d86b50ebec9c Mon Sep 17 00:00:00 2001 From: finico Date: Fri, 25 Oct 2019 16:47:32 +0300 Subject: [PATCH 005/144] DEXW-2225: Refactor SignInForm --- .../components/signInForm/signInForm.html | 1 + .../components/signInForm/signInForm.js | 167 +++++++++--------- 2 files changed, 82 insertions(+), 86 deletions(-) diff --git a/src/modules/signIn/components/signInForm/signInForm.html b/src/modules/signIn/components/signInForm/signInForm.html index 47705ad2e..86f043517 100644 --- a/src/modules/signIn/components/signInForm/signInForm.html +++ b/src/modules/signIn/components/signInForm/signInForm.html @@ -10,6 +10,7 @@ type="password" class="big no-validate no-icon" ng-model="$ctrl.password" + ng-change="$ctrl.onPasswordChange()" required w-autofocus> diff --git a/src/modules/signIn/components/signInForm/signInForm.js b/src/modules/signIn/components/signInForm/signInForm.js index f65a81f69..26da7e7c8 100644 --- a/src/modules/signIn/components/signInForm/signInForm.js +++ b/src/modules/signIn/components/signInForm/signInForm.js @@ -1,106 +1,101 @@ (() => { 'use strict'; - /** - * @param {typeof Base} Base - * @param {ng.IScope} $scope - * @param {*} $state - * @param {User} user - * @param {MultiAccount} multiAccount - * @param {ModalManager} modalManager - * @returns {SignInFormCtrl} - */ - const controller = function (Base, $scope, $state, user, multiAccount, modalManager) { - - class SignInFormCtrl extends Base { - - /** - * @type {string} - */ - password = ''; - /** - * @type {ng.IFormController|null} - */ - form = null; - /** - * @type {string} - */ - multiAccountData = ''; - /** - * @type {string} - */ - multiAccountHash = ''; - /** - * @type {Array|null} - */ - legacyUserList = null; - - constructor() { - super($scope); - - this.observe('password', this._updatePassword); - - Promise.all([ - user.getMultiAccountData(), - user.getMultiAccountHash(), - user.getFilteredUserList() - ]).then(([multiAccountData, multiAccountHash, userList]) => { - if (!multiAccountData) { - $state.go('signUp'); - } else { - this.multiAccountData = multiAccountData; - this.multiAccountHash = multiAccountHash; - this.legacyUserList = userList; - } - }); - } + class SignInFormCtrl { + + static $inject = ['$state', 'user', 'multiAccount', 'modalManager']; + + /** + * @type {string} + */ + password = ''; + /** + * @type {ng.IFormController|null} + */ + form = null; + /** + * @type {string} + */ + multiAccountData = ''; + /** + * @type {string} + */ + multiAccountHash = ''; + /** + * @type {Array|null} + */ + legacyUserList = null; + + /** + * @param {*} $state + * @param {User} user + * @param {MultiAccount} multiAccount + * @param {ModalManager} modalManager + */ + constructor($state, user, multiAccount, modalManager) { + this.$state = $state; + this.user = user; + this.multiAccount = multiAccount; + this.modalManager = modalManager; + } - onSubmit() { - if (this.form.$invalid) { - return; + $onInit() { + Promise.all([ + this.user.getMultiAccountData(), + this.user.getMultiAccountHash(), + this.user.getFilteredUserList() + ]).then(([multiAccountData, multiAccountHash, userList]) => { + if (!multiAccountData) { + this.$state.go('signUp'); + } else { + this.multiAccountData = multiAccountData; + this.multiAccountHash = multiAccountHash; + this.legacyUserList = userList; } + }); + } - this.showPasswordError = false; - - multiAccount.signIn( - this.multiAccountData, - this.password, - undefined, - this.multiAccountHash - ).then(() => { - this.onSuccess(); - }).catch(() => { - this._showPasswordError(); - }); + onSubmit() { + if (this.form.$invalid) { + return; } - showForgotPasswordModal() { - modalManager.showForgotPasswordModal().then(() => { - this.onResetPassword(); - }); - } + this.showPasswordError = false; + + this.multiAccount.signIn( + this.multiAccountData, + this.password, + undefined, + this.multiAccountHash + ).then(() => { + this.onSuccess(); + }).catch(() => { + this._showPasswordError(); + }); + } - _showPasswordError() { - this.password = ''; - this.showPasswordError = true; - } + showForgotPasswordModal() { + this.modalManager.showForgotPasswordModal().then(() => { + this.onResetPassword(); + }); + } - _updatePassword() { - if (this.password) { - this.showPasswordError = false; - } + onPasswordChange() { + if (this.password) { + this.showPasswordError = false; } - } - return new SignInFormCtrl(); - }; + _showPasswordError() { + this.password = ''; + this.showPasswordError = true; + } - controller.$inject = ['Base', '$scope', '$state', 'user', 'multiAccount', 'modalManager']; + } angular.module('app.signIn').component('wSignInForm', { templateUrl: 'modules/signIn/components/signInForm/signInForm.html', - controller, + controller: SignInFormCtrl, bindings: { onSuccess: '&', onResetPassword: '&' From 4f78c42e19db6b0692223ffdea88aa6795d49967 Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 29 Oct 2019 12:31:34 +0300 Subject: [PATCH 006/144] DEXW-2225: Clean up --- src/index.hbs | 8 - src/modules/app/app.js | 1 - src/modules/app/services/StorageExporter.js | 58 ++++++ src/modules/app/services/StorageImporter.js | 186 ------------------ .../controllers/ImportAccountCtrl.js | 182 ----------------- src/modules/importAccount/importAccount.js | 5 - .../templates/importAccount.html | 48 ----- .../utils/modals/migrateModal/migrateModal.js | 17 +- 8 files changed, 63 insertions(+), 442 deletions(-) create mode 100644 src/modules/app/services/StorageExporter.js delete mode 100644 src/modules/app/services/StorageImporter.js delete mode 100644 src/modules/importAccount/controllers/ImportAccountCtrl.js delete mode 100644 src/modules/importAccount/importAccount.js delete mode 100644 src/modules/importAccount/templates/importAccount.html diff --git a/src/index.hbs b/src/index.hbs index 4ca2f3b89..9e54b7ab6 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -710,14 +710,6 @@ views: [{ name: 'main' }] } }, - { - id: 'importAccount', - data: { - url: '/import-account', - views: [{ name: 'main' }], - noLogin: true - } - }, { id: 'stand', data: { diff --git a/src/modules/app/app.js b/src/modules/app/app.js index e80fb9944..9d0ca7292 100644 --- a/src/modules/app/app.js +++ b/src/modules/app/app.js @@ -114,7 +114,6 @@ 'app.keeper', 'app.fromBackup', 'app.import', - 'app.importAccount', 'app.wallet', 'app.dex', 'app.tokens', diff --git a/src/modules/app/services/StorageExporter.js b/src/modules/app/services/StorageExporter.js new file mode 100644 index 000000000..47d78d004 --- /dev/null +++ b/src/modules/app/services/StorageExporter.js @@ -0,0 +1,58 @@ +(function () { + 'use strict'; + + class StorageExporter { + + static $inject = [ + '$log', + 'storage', + 'multiAccount' + ]; + + /** + * @param {ng.ILogService} $log + * @param {app.utils.Storage} storage + * @param {app.MultiAccount} multiAccount + */ + constructor($log, storage, multiAccount) { + this.$log = $log; + this.storage = storage; + this.multiAccount = multiAccount; + } + + /** + * @public + * @param {string} publicKeyTo + * @param {string} privateKeyFrom + * @returns {Promise<{password: string, storageData: Object}>} + */ + async export(privateKeyFrom, publicKeyTo) { + const keys = [ + 'multiAccountData', + 'multiAccountUsers', + 'multiAccountSettings', + 'multiAccountHash', + 'userList', + 'openClientMode' + ]; + + const storageData = {}; + + for (const key of keys) { + try { + // eslint-disable-next-line no-await-in-loop + const value = await this.storage.load(key); + + storageData[key] = value; + } catch (e) { + this.$log.error(`Could not read key "${key}" from storage. Error:`, e); + } + } + + return this.multiAccount.export(privateKeyFrom, publicKeyTo, storageData); + } + + } + + angular.module('app').service('storageExporter', StorageExporter); +})(); diff --git a/src/modules/app/services/StorageImporter.js b/src/modules/app/services/StorageImporter.js deleted file mode 100644 index 4e4489ba4..000000000 --- a/src/modules/app/services/StorageImporter.js +++ /dev/null @@ -1,186 +0,0 @@ -// @ts-check - -(function () { - 'use strict'; - - const { libs } = require('@waves/waves-transactions'); - const { decryptSeed } = libs.crypto; - - class StorageImporter { - - static $inject = [ - '$log', - '$state', - 'storage', - 'user', - 'multiAccount' - ]; - - /** - * @param {ng.ILogService} $log - * @param {*} $state - * @param {app.utils.Storage} storage - * @param {app.User} user - * @param {app.MultiAccount} multiAccount - */ - constructor($log, $state, storage, user, multiAccount) { - this.$log = $log; - this.$state = $state; - this.storage = storage; - this.user = user; - this.multiAccount = multiAccount; - } - - /** - * @public - * @param {string} publicKeyTo - * @param {string} privateKeyFrom - * @returns {Promise<{password: string, storageData: Object}>} - */ - async export(privateKeyFrom, publicKeyTo) { - const keys = [ - 'multiAccountData', - 'multiAccountUsers', - 'multiAccountSettings', - 'multiAccountHash', - 'userList', - 'openClientMode' - ]; - - const storageData = {}; - - for (const key of keys) { - try { - // eslint-disable-next-line no-await-in-loop - const value = await this.storage.load(key); - - storageData[key] = value; - } catch (e) { - this.$log.error(`Could not read key "${key}" from storage. Error:`, e); - } - } - - return this.multiAccount.export(privateKeyFrom, publicKeyTo, storageData); - } - - /** - * @public - * @param {Object} data - * @param {string} data.password - * @param {Object} data.storageData - * @returns {Promise} - */ - async import(data) { - const multiAccountData = await this.user.getMultiAccountData(); - - if (!multiAccountData) { - const signUpResult = await this.multiAccount.signUp( - data.password, - this.user.getSetting('encryptionRounds') - ); - - await this.user.saveMultiAccount(signUpResult); - } - - await this._importData(data); - } - - /** - * @private - * @param {Object} data - * @param {string} data.password - * @param {Object} data.storageData - * @returns {Promise} - */ - async _importData(data) { - const { multiAccountData, multiAccountUsers, multiAccountSettings, ...rest } = data.storageData; - - await this._importMultiAccountUsers(multiAccountData, multiAccountUsers, data.password); - await this._importMultiAccountSettings(multiAccountSettings); - - for (const [key, value] of Object.entries(rest)) { - try { - // eslint-disable-next-line no-await-in-loop - await this._importDataItem(key, value); - } catch (e) { - this.$log.error(e); - } - } - } - - /** - * @private - * @param {string} key - * @param {any} value - * @returns {Promise} - */ - async _importDataItem(key, value) { - const valueFromStorage = await this.storage.load(key); - - return !valueFromStorage ? - this.storage.save(key, value) : - Promise.resolve(); - } - - /** - * @private - * @param {string} multiAccountData - * @param {Object} multiAccountUsers - * @param {string} password - */ - async _importMultiAccountUsers(multiAccountData, multiAccountUsers, password) { - let currentMultiAccountUsers = await this.storage.load('multiAccountUsers'); - - if (!currentMultiAccountUsers) { - currentMultiAccountUsers = Object.create(null); - } - - try { - const users = JSON.parse(decryptSeed( - multiAccountData, - password, - this.user.getSetting('encryptionRounds') - )); - - for (const [hash, user] of Object.entries(users)) { - if (!currentMultiAccountUsers[hash]) { - currentMultiAccountUsers[hash] = multiAccountUsers[hash]; - // eslint-disable-next-line no-await-in-loop - const { multiAccountData, multiAccountHash } = await this.multiAccount.addUser(user); - // eslint-disable-next-line no-await-in-loop - await this.user.saveMultiAccount({ multiAccountData, multiAccountHash }); - } - } - - await this.user.saveMultiAccountUsers(currentMultiAccountUsers); - } catch (e) { - this.$log.error(e); - - return Promise.resolve(); - } - } - - /** - * @private - * @param {Object} multiAccountSettings - * @returns {Promise} - */ - async _importMultiAccountSettings(multiAccountSettings) { - delete multiAccountSettings.lastOpenVersion; - delete multiAccountSettings.termsAccepted; - - const currentMultiAccountSettings = await this.user.getMultiAccountSettings(); - const mergedSettings = { - ...multiAccountSettings, - ...currentMultiAccountSettings - }; - - await this.user.saveMultiAccountSettings(mergedSettings); - - this.user.setMultiAccountSettings(mergedSettings); - } - - } - - angular.module('app').service('storageImporter', StorageImporter); -})(); diff --git a/src/modules/importAccount/controllers/ImportAccountCtrl.js b/src/modules/importAccount/controllers/ImportAccountCtrl.js deleted file mode 100644 index 5d9dadf1e..000000000 --- a/src/modules/importAccount/controllers/ImportAccountCtrl.js +++ /dev/null @@ -1,182 +0,0 @@ -// @ts-check - -(() => { - 'use strict'; - - const ds = require('data-service'); - const { libs, seedUtils } = require('@waves/waves-transactions'); - const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; - - /** - * @param {*} Base - * @param {ng.IScope} $scope - * @param {*} user - * @param {*} multiAccount - * @param {*} storageImporter - */ - const controller = function (Base, $scope, user, multiAccount, storageImporter) { - const SEED_LENGTH = 20; - - class ImportAccountCtrl extends Base { - - /** - * @type {'idle' | 'progress' | 'ready' | 'success' | 'error'} - */ - status = 'idle'; - - /** - * @type {boolean} - */ - hasAccount = false; - - /** - * @type {Object} - */ - data = null; - - constructor() { - super($scope); - - if (WavesApp.isDesktop()) { - this.connectProvider = new ds.connect.HttpConnectProvider({ - port: 8888, - url: 'http://localhost:8888/connect' - }); - } else { - this.connectProvider = new ds.connect.PostMessageConnectProvider({ - mode: 'import' - }); - } - - user.getMultiAccountData().then((multiAccountData) => { - if (multiAccountData) { - this.hasAccount = true; - } else { - this._listen(); - } - }); - } - - importAccount() { - storageImporter.import(this.data).then(() => { - this.status = 'success'; - $scope.$digest(); - }).catch(() => { - this.status = 'error'; - $scope.$digest(); - }); - } - - async login() { - if (!multiAccount.isSignedIn) { - const multiAccountData = await user.getMultiAccountData(); - const multiAccountHash = await user.getMultiAccountHash(); - - await multiAccount.signIn( - multiAccountData, - this.data.password, - user.getSetting('encryptionRounds'), - multiAccountHash - ); - } - - const [firstUser] = await user.getMultiAccountUsers(); - - if (firstUser) { - user.logout('switch', true); - await user.login(firstUser); - user.goToActiveState(); - } else { - this.$state.go('create'); - } - } - - onSignIn() { - this._listen(); - } - - onResetPassword() { - throw new Error('ImportAccountCtrl.onResetPassword() not implemented'); - } - - /** - * @private - */ - _listen() { - let privateKeyTo = null; - this.status = 'progress'; - - this.connectProvider.listen((message) => { - return new Promise((resolve, reject) => { - if (!message) { - return reject(); - } - - switch (message.event) { - case 'connect': { - const { publicKey, privateKey } = keyPair( - seedUtils.generateNewSeed(SEED_LENGTH) - ); - - privateKeyTo = privateKey; - - return resolve(JSON.stringify({ - event: 'connect', - payload: publicKey - })); - } - case 'data': { - const encryptedData = base64Decode(message.payload.data); - const publicKeyFrom = message.payload.publicKey; - - if (!privateKeyTo) { - return reject('Key pair does not exist'); - } - - try { - this.data = JSON.parse( - messageDecrypt( - sharedKey( - privateKeyTo, - publicKeyFrom, - 'waves_migration_token' - ), - encryptedData - ) - ); - - this.status = 'ready'; - - return resolve(JSON.stringify({ - event: 'data', - payload: 'ok' - })); - } catch (e) { - this.status = 'error'; - - return reject(String(e)); - } finally { - privateKeyTo = null; - } - } - default: return reject('Invalid message'); - } - }); - }); - } - - } - - return new ImportAccountCtrl(); - }; - - controller.$inject = [ - 'Base', - '$scope', - 'user', - 'multiAccount', - 'storageImporter' - ]; - - angular.module('app.importAccount').controller('ImportAccountCtrl', controller); -})(); diff --git a/src/modules/importAccount/importAccount.js b/src/modules/importAccount/importAccount.js deleted file mode 100644 index 3559b6cfe..000000000 --- a/src/modules/importAccount/importAccount.js +++ /dev/null @@ -1,5 +0,0 @@ -(() => { - 'use strict'; - - angular.module('app.importAccount', []); -})(); diff --git a/src/modules/importAccount/templates/importAccount.html b/src/modules/importAccount/templates/importAccount.html deleted file mode 100644 index b5a5febc5..000000000 --- a/src/modules/importAccount/templates/importAccount.html +++ /dev/null @@ -1,48 +0,0 @@ - - -
-
-
-
-

Import account

-
- -
-
-
- -
- - -
-
- -
- -
- -
- - Import - -
- -
- Success - - Go to account - -
- -
- Error - - Retry - -
-
-
-
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 292ea56b4..48205c6a1 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -1,5 +1,3 @@ -// @ts-check - (() => { 'use strict'; @@ -11,18 +9,13 @@ * @param {*} Base * @param {ng.ILogService} $log * @param {*} $mdDialog - * @param {*} storageImporter + * @param {*} storageExporter */ - const controller = function (Base, $log, $mdDialog, storageImporter) { + const controller = function (Base, $log, $mdDialog, storageExporter) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { - /** - * @todo separate it for new and old client - */ - mode = window.opener ? 'import' : 'export'; - constructor() { super(); @@ -33,7 +26,7 @@ }); } else { this.connectProvider = new ds.connect.PostMessageConnectProvider({ - mode: this.mode + mode: 'export' }); } } @@ -52,7 +45,7 @@ const publicKeyTo = result.payload; const { publicKey, privateKey } = keyPair(seedUtils.generateNewSeed(SEED_LENGTH)); - return storageImporter.export( + return storageExporter.export( privateKey, publicKeyTo ).then((data) => { @@ -81,7 +74,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageImporter']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 4fb7fbe54d365f4b60733db9b300091f59c3d61e Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Thu, 31 Oct 2019 10:36:40 +0300 Subject: [PATCH 007/144] DEXW-2274: waves issuability hack --- src/modules/utils/modals/assetInfo/assetInfo.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/utils/modals/assetInfo/assetInfo.html b/src/modules/utils/modals/assetInfo/assetInfo.html index d35f018df..c11e1eb52 100644 --- a/src/modules/utils/modals/assetInfo/assetInfo.html +++ b/src/modules/utils/modals/assetInfo/assetInfo.html @@ -30,7 +30,7 @@
{{::$ctrl.asset.precision}}
-
+
From d4eefb9637f369127899750efbbb2cf03fd0dba7 Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 22 Oct 2019 15:41:47 +0300 Subject: [PATCH 008/144] DEXW-2225: Add simple http server to the desktop app --- electron/SimpleConnect.ts | 47 +++++++++++++++++++++++++++++++++++++++ electron/preload.ts | 5 ++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 electron/SimpleConnect.ts diff --git a/electron/SimpleConnect.ts b/electron/SimpleConnect.ts new file mode 100644 index 000000000..b58ffc8ce --- /dev/null +++ b/electron/SimpleConnect.ts @@ -0,0 +1,47 @@ +import { createServer, IncomingHttpHeaders, Server, STATUS_CODES } from 'http'; +import { URL } from 'url'; + +type Callback = (data: any, url: URL, headers: IncomingHttpHeaders) => Promise; + +export class SimpleConnect { + public static listen(port: number, cb: Callback): Server { + const server = createServer((req, res) => { + let dataString = ''; + + req.on('data', (chunk: string) => { + dataString += chunk; + }); + + req.on('end', () => { + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Access-Control-Allow-Origin', '*'); + + try { + const data = JSON.parse(dataString || 'null'); + const base = 'http://' + req.headers['host'].toString(); + const url = new URL(req.url, base); + + cb(data, url, req.headers).then((result: string) => { + res.writeHead(200); + res.end(result); + }).catch((error: string) => { + res.writeHead(400); + res.end(String(error) || STATUS_CODES[400]); + }); + } catch (e) { + res.writeHead(500); + res.end(String(e) || STATUS_CODES[500]); + } + }); + + req.on('error', (e) => { + res.writeHead(500); + res.end(String(e) || STATUS_CODES[500]); + }); + }); + + server.listen(port); + + return server; + } +} diff --git a/electron/preload.ts b/electron/preload.ts index ab58d40f8..675aafba9 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -1,5 +1,6 @@ import { Storage } from './Storage'; import { shell, remote } from 'electron'; +import { SimpleConnect } from './SimpleConnect'; process.once('loaded', () => { const g: any = global; @@ -8,10 +9,12 @@ process.once('loaded', () => { shell.openExternal(url); }; g.isDesktop = true; + g.SimpleConnect = SimpleConnect; + try { g.TransportNodeHid = require('@ledgerhq/hw-transport-node-hid'); } catch (e) { - + } const transferModule = remote.require('./transfer'); From b2fefa35174f3e90611e30ec712f02c15701af7c Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 22 Oct 2019 15:44:54 +0300 Subject: [PATCH 009/144] DEXW-2225: Add connect providers --- data-service/connect/ConnectProvider.ts | 5 ++ data-service/connect/HttpConnectProvider.ts | 72 ++++++++++++++++ .../connect/PostMessageConnectProvider.ts | 86 +++++++++++++++++++ data-service/index.ts | 6 ++ data-service/utils/utils.ts | 2 + package-lock.json | 86 ++++++++++++++----- package.json | 2 +- 7 files changed, 235 insertions(+), 24 deletions(-) create mode 100644 data-service/connect/ConnectProvider.ts create mode 100644 data-service/connect/HttpConnectProvider.ts create mode 100644 data-service/connect/PostMessageConnectProvider.ts diff --git a/data-service/connect/ConnectProvider.ts b/data-service/connect/ConnectProvider.ts new file mode 100644 index 000000000..f161babf9 --- /dev/null +++ b/data-service/connect/ConnectProvider.ts @@ -0,0 +1,5 @@ +export interface ConnectProvider { + send(data: string, options: Record): Promise; + listen(cb: Function): Promise; + destroy(): void +} diff --git a/data-service/connect/HttpConnectProvider.ts b/data-service/connect/HttpConnectProvider.ts new file mode 100644 index 000000000..ebe94fa16 --- /dev/null +++ b/data-service/connect/HttpConnectProvider.ts @@ -0,0 +1,72 @@ +import { IncomingHttpHeaders, Server } from 'http'; +import { request } from '../utils/request'; +import { delay } from '../utils/utils'; +import { ConnectProvider } from './ConnectProvider'; + +interface HttpConnectProviderOptioins { + port: number; + url: string; + ttl?: number; +} + +interface SendOptions { + timeout?: number; + attempts?: number; +} + +type SimpleConnectCallback = (url: URL, data: any, headers: IncomingHttpHeaders) => Promise; + +export class HttpConnectProvider implements ConnectProvider { + private active = true; + private server: Server; + + constructor(private options: HttpConnectProviderOptioins) {} + + public async send(data: string, options: SendOptions = {}): Promise { + this.checkActive(); + + const { timeout = 1000, attempts = 1 } = options; + + for (let i = attempts; i > 0; i--) { + try { + const res = await request({ + url: this.options.url, + fetchOptions: { + method: 'POST', + body: data + } + }); + + return res; + } catch (e) { + await delay(timeout); + } + } + + throw new Error('Could not connect'); + } + + public async listen(cb: SimpleConnectCallback): Promise { + this.checkActive(); + this.server = (window as any).SimpleConnect.listen(this.options.port, cb); + + if (this.options.ttl) { + await delay(this.options.ttl); + this.server.close(); + } + } + + public destroy(): void { + this.active = false; + + if (this.server) { + this.server.close(); + } + } + + private checkActive(): void { + if (!this.active) { + throw new Error('Provider was destroyed'); + } + } +} diff --git a/data-service/connect/PostMessageConnectProvider.ts b/data-service/connect/PostMessageConnectProvider.ts new file mode 100644 index 000000000..1a787e42e --- /dev/null +++ b/data-service/connect/PostMessageConnectProvider.ts @@ -0,0 +1,86 @@ +import { Bus, WindowAdapter, WindowProtocol, IOneArgFunction } from '@waves/waves-browser-bus'; +import { delay } from '../utils/utils'; +import { ConnectProvider } from './ConnectProvider'; + +interface PostMessageConnectProviderOptioins { + mode?: 'export' | 'import'; + origins?: string[]; +} + +interface SendOptions { + event?: string; + timeout?: number; + attempts?: number; + mode?: 'listen' | 'dispatch' +} + +export class PostMessageConnectProvider implements ConnectProvider { + private adapter: WindowAdapter; + private bus: Bus; + private active: boolean; + + constructor(options: PostMessageConnectProviderOptioins = {}) { + this.adapter = new WindowAdapter( + [new WindowProtocol( + options.mode === 'import' ? + (window.opener || window.parent) : + window, + 'listen' + )], + [new WindowProtocol( + options.mode === 'import' ? + (window.opener || window.parent) : + window, + 'dispatch' + )], + { + origins: options.origins, + chanelId: `postMessageConnectProvider${options.mode === 'export' ? 'Client' : 'Server'}`, + availableChanelId: `postMessageConnectProvider${options.mode !== 'export' ? 'Client' : 'Server'}`, + } + ); + this.bus = new Bus(this.adapter); + this.active = true; + } + + public async send(data: string, options: SendOptions = {}): Promise { + this.checkActive(); + + const { timeout = 5000, attempts = 1 } = options; + + for (let i = attempts; i > 0; i--) { + try { + const res = await this.bus.request( + options.event, + data, + options.timeout + ); + + return JSON.parse(res) as T; + } catch (e) { + await delay(timeout); + } + } + + throw new Error('Could not connect'); + } + + public async listen(cb: IOneArgFunction): Promise { + this.checkActive(); + + this.bus.registerRequestHandler('data', (data) => { + return cb(JSON.parse(data)); + }); + } + + public destroy(): void { + this.bus.destroy(); + this.active = false; + } + + private checkActive(): void { + if (!this.active) { + throw new Error('Provider was destroyed'); + } + } +} diff --git a/data-service/index.ts b/data-service/index.ts index 9b8ce19f3..9c09b5f65 100644 --- a/data-service/index.ts +++ b/data-service/index.ts @@ -17,6 +17,8 @@ import * as signatureAdapters from '@waves/signature-adapter'; import { SIGN_TYPE, isValidAddress as utilsIsValidAddress } from '@waves/signature-adapter'; import { TTimeType } from './utils/utils'; import { IUserData } from './sign'; +import { HttpConnectProvider } from './connect/HttpConnectProvider'; +import { PostMessageConnectProvider } from './connect/PostMessageConnectProvider'; export { getAdapterByType, getAvailableList } from '@waves/signature-adapter'; export { Seed } from './classes/Seed'; @@ -33,6 +35,10 @@ export const utils = { ...utilsModule }; export const signature = { ...sign }; +export const connect = { + HttpConnectProvider, + PostMessageConnectProvider +}; export const signAdapters = signatureAdapters; export const isValidAddress = utilsIsValidAddress; diff --git a/data-service/utils/utils.ts b/data-service/utils/utils.ts index ceb84eec6..89a0ddcc3 100644 --- a/data-service/utils/utils.ts +++ b/data-service/utils/utils.ts @@ -183,3 +183,5 @@ export function getTransferFeeList() { .filter(item => item.balance.getTokens().gt(1.005) || item.isMy) .map(item => item.fee); } + +export const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)); diff --git a/package-lock.json b/package-lock.json index 834e9b59a..d717e80c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -805,6 +805,22 @@ "integrity": "sha512-Ymrn5oqk6wbyvBRlVPph3v3qwkJrn2lLL0uKmSqkcTBCTbJPasYcwllKXCA1e0XV5NrgQ+3zy7KiPCeeKksVsg==", "requires": { "@waves/waves-browser-bus": "^0.1.5" + }, + "dependencies": { + "@types/node": { + "version": "11.13.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.22.tgz", + "integrity": "sha512-rOsaPRUGTOXbRBOKToy4cgZXY4Y+QSVhxcLwdEveozbk7yuudhWMpxxcaXqYizLMP3VY7OcWCFtx9lGFh5j5kg==" + }, + "@waves/waves-browser-bus": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@waves/waves-browser-bus/-/waves-browser-bus-0.1.6.tgz", + "integrity": "sha512-oBXnMrxnZarsPeFjngGegBzmbIemZhhv7QXM1fCLTd0sjYA45MnGAZugi97dMggg/qjIAZ8NNkq/ozEIG27i0A==", + "requires": { + "@types/node": "^11.9.4", + "typed-ts-events": "^1.0.5" + } + } } }, "@waves/ledger": { @@ -912,18 +928,18 @@ "integrity": "sha512-jXbEnZ8dwy4bOZgumFv/9BTjpcCRP/oGAWcOh5pFMoeA/LShDGm2NwIds+4tDf3sEJu+nLD8UjK6aueM0s87RA==" }, "@waves/waves-browser-bus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@waves/waves-browser-bus/-/waves-browser-bus-0.1.5.tgz", - "integrity": "sha512-K7iAF2jqSxkEW1DdCAa4Qda21LDuN1MPP5zV/aHJjsO40MvFgMiLcpYSV9xw8OqXzYdZyk1omb9bBOA7r69aIQ==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@waves/waves-browser-bus/-/waves-browser-bus-0.2.2.tgz", + "integrity": "sha512-hbvtLsxaGGeNfQ2g4R4B3hQkTgFEiVoMzg3kzoLSpMegKqLQwOTLzaTdQbo+lI63GpAlq2BCojzqX/bGmWkw9Q==", "requires": { "@types/node": "^11.9.4", "typed-ts-events": "^1.0.5" }, "dependencies": { "@types/node": { - "version": "11.13.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.13.tgz", - "integrity": "sha512-GFWH7e4Q/OGLAO545bupVju+nE1YtLSwYAdLfSzAXnTPqoqKoXCOEtB7Cluvg9B/h2nGLhyzCDyCInYvrOE2nw==" + "version": "11.13.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.22.tgz", + "integrity": "sha512-rOsaPRUGTOXbRBOKToy4cgZXY4Y+QSVhxcLwdEveozbk7yuudhWMpxxcaXqYizLMP3VY7OcWCFtx9lGFh5j5kg==" } } }, @@ -1967,13 +1983,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, + "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -6997,7 +7015,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -7018,12 +7037,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7038,17 +7059,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -7165,7 +7189,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -7177,6 +7202,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7191,6 +7217,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7198,12 +7225,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7222,6 +7251,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -7309,7 +7339,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -7321,6 +7352,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -7406,7 +7438,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7442,6 +7475,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7461,6 +7495,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7504,12 +7539,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7635,13 +7672,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, + "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -12595,7 +12634,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "2.0.1", @@ -17370,9 +17410,9 @@ "dev": true }, "typed-ts-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-ts-events/-/typed-ts-events-1.0.5.tgz", - "integrity": "sha512-0a76E5Nc0t1L5YeOqYTLztuMrIT5FCGxzKVzowad0BR0ubS4BC+N2oisp3GI6ARnzwvvTyviYrwD+u6wmdNLTQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/typed-ts-events/-/typed-ts-events-1.1.1.tgz", + "integrity": "sha512-sYjxQrhBTg3HGzNBOXSURlIfmUGXS//dVGY08ofz9dbusX/IdcN8LD9SsFNbk4UgHy8reQPgSZw+ADpkLcPtDA==" }, "typedarray": { "version": "0.0.6", diff --git a/package.json b/package.json index 8ef99e5de..226f18747 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "@waves/parse-json-bignumber": "^1.0.1", "@waves/signature-adapter": "^5.6.1", "@waves/ts-types": "0.0.2", - "@waves/waves-browser-bus": "^0.1.5", + "@waves/waves-browser-bus": "0.2.2", "@waves/waves-transactions": "^3.18.1", "angular": "1.6.6", "angular-animate": "1.6.6", From 0158fb0a167d02750f19b3ee526b3db20ea72388 Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 22 Oct 2019 15:53:28 +0300 Subject: [PATCH 010/144] DEXW-2225: Add export/import with minimal UI --- src/modules/app/services/MultiAccount.js | 24 ++- src/modules/app/services/StorageImporter.js | 203 ++++++++++++++++++ src/modules/utils/modals/ModalManager.js | 8 + .../modals/migrateModal/migrateModal.html | 5 + .../utils/modals/migrateModal/migrateModal.js | 164 ++++++++++++++ 5 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 src/modules/app/services/StorageImporter.js create mode 100644 src/modules/utils/modals/migrateModal/migrateModal.html create mode 100644 src/modules/utils/modals/migrateModal/migrateModal.js diff --git a/src/modules/app/services/MultiAccount.js b/src/modules/app/services/MultiAccount.js index 1353b94ab..a55f0760a 100644 --- a/src/modules/app/services/MultiAccount.js +++ b/src/modules/app/services/MultiAccount.js @@ -8,10 +8,13 @@ decryptSeed, base58Encode, base58Decode, + base64Encode, blake2b, stringToBytes, address: buildAddress, - publicKey: buildPublicKey + publicKey: buildPublicKey, + sharedKey, + messageEncrypt } = libs.crypto; let _password; @@ -146,11 +149,30 @@ /** * @param {string} str + * @returns {string} */ hash(str) { return base58Encode(blake2b(base58Decode(str))); } + /** + * @param {string} privateKeyFrom + * @param {string} publicKeyTo + * @param {Object} storageData + * @returns {string} + */ + export(privateKeyFrom, publicKeyTo, storageData) { + return base64Encode( + messageEncrypt( + sharedKey(privateKeyFrom, publicKeyTo, 'waves_migration_token'), + JSON.stringify({ + password: _password, + storageData + }) + ) + ); + } + } angular.module('app').service('multiAccount', MultiAccount); diff --git a/src/modules/app/services/StorageImporter.js b/src/modules/app/services/StorageImporter.js new file mode 100644 index 000000000..e7bc9df34 --- /dev/null +++ b/src/modules/app/services/StorageImporter.js @@ -0,0 +1,203 @@ +// @ts-check + +(function () { + 'use strict'; + + const { libs } = require('@waves/waves-transactions'); + const { decryptSeed } = libs.crypto; + + class StorageImporter { + + static $inject = [ + '$log', + '$state', + 'storage', + 'user', + 'multiAccount' + ]; + + /** + * @param {ng.ILogService} $log + * @param {*} $state + * @param {app.utils.Storage} storage + * @param {app.User} user + * @param {app.MultiAccount} multiAccount + */ + constructor($log, $state, storage, user, multiAccount) { + this.$log = $log; + this.$state = $state; + this.storage = storage; + this.user = user; + this.multiAccount = multiAccount; + } + + /** + * @public + * @param {string} publicKeyTo + * @param {string} privateKeyFrom + * @returns {Promise<{password: string, storageData: Object}>} + */ + async export(privateKeyFrom, publicKeyTo) { + const keys = [ + 'multiAccountData', + 'multiAccountUsers', + 'multiAccountSettings', + 'multiAccountHash', + 'userList', + 'openClientMode' + ]; + + const storageData = {}; + + for (const key of keys) { + try { + // eslint-disable-next-line no-await-in-loop + const value = await this.storage.load(key); + + storageData[key] = value; + } catch (e) { + this.$log.error(`Could not read key "${key}" from storage. Error:`, e); + } + } + + return this.multiAccount.export(privateKeyFrom, publicKeyTo, storageData); + } + + /** + * @public + * @param {Object} data + * @param {string} data.password + * @param {Object} data.storageData + * @returns {Promise} + */ + async import(data) { + const multiAccountData = await this.storage.load('multiAccountData'); + + if (!multiAccountData) { + const signUpResult = await this.multiAccount.signUp( + data.password, + this.user.getSetting('encryptionRounds') + ); + + await this.user.saveMultiAccount(signUpResult); + } + + if (this.multiAccount.isSignedIn) { + await this._importData(data); + this._loginToFirstUser(data.password); + } else { + this.user.loginSignal.once(async () => { + await this._importData(data); + this._loginToFirstUser(data.password); + }); + } + } + + /** + * @private + * @param {Object} data + * @param {string} data.password + * @param {Object} data.storageData + * @returns {Promise} + */ + async _importData(data) { + const { multiAccountData, multiAccountUsers, ...rest } = data.storageData; + + await this._importMultiAccountUsers(multiAccountData, multiAccountUsers, data.password); + + for (const [key, value] of Object.entries(rest)) { + try { + // eslint-disable-next-line no-await-in-loop + await this._importDataItem(key, value); + } catch (e) { + this.$log.error(e); + } + } + + const multiAccountSettings = await this.user.getMultiAccountSettings(); + + this.user.setMultiAccountSettings(multiAccountSettings); + } + + /** + * @private + * @param {string} key + * @param {any} value + * @returns {Promise} + */ + async _importDataItem(key, value) { + const valueFromStorage = await this.storage.load(key); + + return !valueFromStorage ? + this.storage.save(key, value) : + Promise.resolve(); + } + + /** + * @private + * @param {string} multiAccountData + * @param {Object} multiAccountUsers + * @param {string} password + */ + async _importMultiAccountUsers(multiAccountData, multiAccountUsers, password) { + let currentMultiAccountUsers = await this.storage.load('multiAccountUsers'); + + if (!currentMultiAccountUsers) { + currentMultiAccountUsers = Object.create(null); + } + + try { + const users = JSON.parse(decryptSeed( + multiAccountData, + password, + this.user.getSetting('encryptionRounds') + )); + + for (const [hash, user] of Object.entries(users)) { + if (!currentMultiAccountUsers[hash]) { + currentMultiAccountUsers[hash] = multiAccountUsers[hash]; + // eslint-disable-next-line no-await-in-loop + const { multiAccountData, multiAccountHash } = await this.multiAccount.addUser(user); + // eslint-disable-next-line no-await-in-loop + await this.user.saveMultiAccount({ multiAccountData, multiAccountHash }); + } + } + + await this.storage.save('multiAccountUsers', currentMultiAccountUsers); + } catch (e) { + this.$log.error(e); + + return Promise.resolve(); + } + } + + /** + * @private + * @param {string} password + */ + async _loginToFirstUser(password) { + const multiAccountData = await this.user.getMultiAccountData(); + const multiAccountHash = await this.user.getMultiAccountHash(); + + await this.multiAccount.signIn( + multiAccountData, + password, + this.user.getSetting('encryptionRounds'), + multiAccountHash + ); + + const [firstUser] = await this.user.getMultiAccountUsers(); + + if (firstUser) { + this.user.logout('switch', true); + await this.user.login(firstUser); + this.user.goToActiveState(); + } else { + this.$state.go('create'); + } + } + + } + + angular.module('app').service('storageImporter', StorageImporter); +})(); diff --git a/src/modules/utils/modals/ModalManager.js b/src/modules/utils/modals/ModalManager.js index 68840c0e6..e5a447b63 100644 --- a/src/modules/utils/modals/ModalManager.js +++ b/src/modules/utils/modals/ModalManager.js @@ -708,6 +708,14 @@ }); } + showMigrateModal() { + return this._getModal({ + id: 'migrate-modal', + controller: 'MigrateModalCtrl', + contentUrl: 'modules/utils/modals/migrateModal/migrateModal.html' + }); + } + /** * @param {IDialogOptions} options * @return {Promise} diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html new file mode 100644 index 000000000..760c29e41 --- /dev/null +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -0,0 +1,5 @@ +
+ + Export + +
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js new file mode 100644 index 000000000..180684191 --- /dev/null +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -0,0 +1,164 @@ +// @ts-check + +(function () { + 'use strict'; + + const ds = require('data-service'); + const { libs, seedUtils } = require('@waves/waves-transactions'); + const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; + + /** + * @param {typeof Base} Base + * @param {ng.ILogService} $log + * @param {$mdDialog} $mdDialog + * @param {StorageImporter} storageImporter + * @returns {ExportModalCtrl} + */ + const controller = function (Base, $log, $mdDialog, storageImporter) { + const SEED_LENGTH = 20; + + class MigrateModalCtrl extends Base { + + /** + * @todo separate it for new and old client + */ + mode = window.opener ? 'import' : 'export'; + + constructor() { + super(); + + if (WavesApp.isDesktop()) { + this.connectProvider = new ds.connect.HttpConnectProvider({ + port: 8888, + url: 'http://localhost:8888/connect' + }); + } else { + this.connectProvider = new ds.connect.PostMessageConnectProvider({ + mode: this.mode + }); + } + + if (this.mode === 'import') { + this._listen(); + } + } + + export() { + const message = JSON.stringify({ event: 'connect' }); + + this.connectProvider.send(message, { + event: 'data', + attempts: 3 + }).then((result) => { + if (!result || result.event !== 'connect') { + throw new Error(`Message event is not valid: ${result.event}`); + } + + const publicKeyTo = result.payload; + const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); + + return storageImporter.export( + privateKey, + publicKeyTo + ).then((data) => { + return this.connectProvider.send(JSON.stringify({ + event: 'data', + payload: { + publicKey, + data + } + }), { event: 'data' }); + }); + }).then((result) => { + if (result.payload === 'ok') { + $log.log('done'); + this.connectProvider.destroy(); + } else { + $log.log('fail', result); + } + }).catch((e) => { + $log.error(e); + }); + } + + _listen() { + let privateKeyTo = null; + + this.connectProvider.listen((message) => { + return new Promise((resolve, reject) => { + if (!message) { + return reject(); + } + + switch (message.event) { + case 'connect': { + const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); + + privateKeyTo = privateKey; + + return resolve(JSON.stringify({ + event: 'connect', + payload: publicKey + })); + } + case 'data': { + const encryptedData = base64Decode(message.payload.data); + const publicKeyFrom = message.payload.publicKey; + + if (!privateKeyTo) { + return reject('Key pair does not exist'); + } + + try { + const data = JSON.parse( + messageDecrypt( + sharedKey( + privateKeyTo, + publicKeyFrom, + 'waves_migration_token' + ), + encryptedData + ) + ); + + return storageImporter.import(data).then(() => { + return resolve(JSON.stringify({ + event: 'data', + payload: 'ok' + })); + }).catch((e) => { + return reject(String(e)); + }).then(() => { + this.connectProvider.destroy(); + }); + } catch (e) { + return reject(String(e)); + } finally { + privateKeyTo = null; + } + } + default: return reject('Invalid message'); + } + }); + }); + } + + /** + * @param {number} seedLength + * @returns {TKeyPair} + */ + _generateSharedKeyPair(seedLength) { + const seed = seedUtils.generateNewSeed(seedLength); + + return keyPair(seed); + } + + } + + return new MigrateModalCtrl(); + }; + + controller.$inject = ['Base', '$log', '$mdDialog', 'storageImporter']; + + angular.module('app.utils').controller('MigrateModalCtrl', controller); +})(); From a1eea3d8525738a19c4aecb9726d36f19daaa056 Mon Sep 17 00:00:00 2001 From: finico Date: Thu, 24 Oct 2019 19:08:36 +0300 Subject: [PATCH 011/144] DEXW-2225: Add import account page --- data-service/connect/HttpConnectProvider.ts | 2 +- src/index.hbs | 8 + src/modules/app/app.js | 1 + src/modules/app/services/StorageImporter.js | 59 ++---- .../controllers/ImportAccountCtrl.js | 182 ++++++++++++++++++ src/modules/importAccount/importAccount.js | 5 + .../templates/importAccount.html | 48 +++++ .../components/signInForm/signInForm.html | 35 ++++ .../components/signInForm/signInForm.js | 109 +++++++++++ src/modules/signIn/controllers/SignInCtrl.js | 79 ++------ src/modules/signIn/templates/signIn.html | 39 +--- .../signIn/templates/signInHasUsers.html | 74 ------- .../signIn/templates/signInNoUsers.html | 18 -- .../utils/modals/migrateModal/migrateModal.js | 89 +-------- .../welcome/controllers/WelcomeCtrl.js | 1 + 15 files changed, 434 insertions(+), 315 deletions(-) create mode 100644 src/modules/importAccount/controllers/ImportAccountCtrl.js create mode 100644 src/modules/importAccount/importAccount.js create mode 100644 src/modules/importAccount/templates/importAccount.html create mode 100644 src/modules/signIn/components/signInForm/signInForm.html create mode 100644 src/modules/signIn/components/signInForm/signInForm.js delete mode 100644 src/modules/signIn/templates/signInHasUsers.html delete mode 100644 src/modules/signIn/templates/signInNoUsers.html diff --git a/data-service/connect/HttpConnectProvider.ts b/data-service/connect/HttpConnectProvider.ts index ebe94fa16..c20849b1b 100644 --- a/data-service/connect/HttpConnectProvider.ts +++ b/data-service/connect/HttpConnectProvider.ts @@ -14,7 +14,7 @@ interface SendOptions { attempts?: number; } -type SimpleConnectCallback = (url: URL, data: any, headers: IncomingHttpHeaders) => Promise; +type SimpleConnectCallback = (data: any, url: URL, headers: IncomingHttpHeaders) => Promise; export class HttpConnectProvider implements ConnectProvider { private active = true; diff --git a/src/index.hbs b/src/index.hbs index a7d8a4a75..4200e73c7 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -710,6 +710,14 @@ views: [{ name: 'main' }] } }, + { + id: 'importAccount', + data: { + url: '/import-account', + views: [{ name: 'main' }], + noLogin: true + } + }, { id: 'stand', data: { diff --git a/src/modules/app/app.js b/src/modules/app/app.js index 9d0ca7292..e80fb9944 100644 --- a/src/modules/app/app.js +++ b/src/modules/app/app.js @@ -114,6 +114,7 @@ 'app.keeper', 'app.fromBackup', 'app.import', + 'app.importAccount', 'app.wallet', 'app.dex', 'app.tokens', diff --git a/src/modules/app/services/StorageImporter.js b/src/modules/app/services/StorageImporter.js index e7bc9df34..4e4489ba4 100644 --- a/src/modules/app/services/StorageImporter.js +++ b/src/modules/app/services/StorageImporter.js @@ -71,7 +71,7 @@ * @returns {Promise} */ async import(data) { - const multiAccountData = await this.storage.load('multiAccountData'); + const multiAccountData = await this.user.getMultiAccountData(); if (!multiAccountData) { const signUpResult = await this.multiAccount.signUp( @@ -82,15 +82,7 @@ await this.user.saveMultiAccount(signUpResult); } - if (this.multiAccount.isSignedIn) { - await this._importData(data); - this._loginToFirstUser(data.password); - } else { - this.user.loginSignal.once(async () => { - await this._importData(data); - this._loginToFirstUser(data.password); - }); - } + await this._importData(data); } /** @@ -98,12 +90,13 @@ * @param {Object} data * @param {string} data.password * @param {Object} data.storageData - * @returns {Promise} + * @returns {Promise} */ async _importData(data) { - const { multiAccountData, multiAccountUsers, ...rest } = data.storageData; + const { multiAccountData, multiAccountUsers, multiAccountSettings, ...rest } = data.storageData; await this._importMultiAccountUsers(multiAccountData, multiAccountUsers, data.password); + await this._importMultiAccountSettings(multiAccountSettings); for (const [key, value] of Object.entries(rest)) { try { @@ -113,10 +106,6 @@ this.$log.error(e); } } - - const multiAccountSettings = await this.user.getMultiAccountSettings(); - - this.user.setMultiAccountSettings(multiAccountSettings); } /** @@ -163,7 +152,7 @@ } } - await this.storage.save('multiAccountUsers', currentMultiAccountUsers); + await this.user.saveMultiAccountUsers(currentMultiAccountUsers); } catch (e) { this.$log.error(e); @@ -173,28 +162,22 @@ /** * @private - * @param {string} password + * @param {Object} multiAccountSettings + * @returns {Promise} */ - async _loginToFirstUser(password) { - const multiAccountData = await this.user.getMultiAccountData(); - const multiAccountHash = await this.user.getMultiAccountHash(); - - await this.multiAccount.signIn( - multiAccountData, - password, - this.user.getSetting('encryptionRounds'), - multiAccountHash - ); - - const [firstUser] = await this.user.getMultiAccountUsers(); - - if (firstUser) { - this.user.logout('switch', true); - await this.user.login(firstUser); - this.user.goToActiveState(); - } else { - this.$state.go('create'); - } + async _importMultiAccountSettings(multiAccountSettings) { + delete multiAccountSettings.lastOpenVersion; + delete multiAccountSettings.termsAccepted; + + const currentMultiAccountSettings = await this.user.getMultiAccountSettings(); + const mergedSettings = { + ...multiAccountSettings, + ...currentMultiAccountSettings + }; + + await this.user.saveMultiAccountSettings(mergedSettings); + + this.user.setMultiAccountSettings(mergedSettings); } } diff --git a/src/modules/importAccount/controllers/ImportAccountCtrl.js b/src/modules/importAccount/controllers/ImportAccountCtrl.js new file mode 100644 index 000000000..5d9dadf1e --- /dev/null +++ b/src/modules/importAccount/controllers/ImportAccountCtrl.js @@ -0,0 +1,182 @@ +// @ts-check + +(() => { + 'use strict'; + + const ds = require('data-service'); + const { libs, seedUtils } = require('@waves/waves-transactions'); + const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; + + /** + * @param {*} Base + * @param {ng.IScope} $scope + * @param {*} user + * @param {*} multiAccount + * @param {*} storageImporter + */ + const controller = function (Base, $scope, user, multiAccount, storageImporter) { + const SEED_LENGTH = 20; + + class ImportAccountCtrl extends Base { + + /** + * @type {'idle' | 'progress' | 'ready' | 'success' | 'error'} + */ + status = 'idle'; + + /** + * @type {boolean} + */ + hasAccount = false; + + /** + * @type {Object} + */ + data = null; + + constructor() { + super($scope); + + if (WavesApp.isDesktop()) { + this.connectProvider = new ds.connect.HttpConnectProvider({ + port: 8888, + url: 'http://localhost:8888/connect' + }); + } else { + this.connectProvider = new ds.connect.PostMessageConnectProvider({ + mode: 'import' + }); + } + + user.getMultiAccountData().then((multiAccountData) => { + if (multiAccountData) { + this.hasAccount = true; + } else { + this._listen(); + } + }); + } + + importAccount() { + storageImporter.import(this.data).then(() => { + this.status = 'success'; + $scope.$digest(); + }).catch(() => { + this.status = 'error'; + $scope.$digest(); + }); + } + + async login() { + if (!multiAccount.isSignedIn) { + const multiAccountData = await user.getMultiAccountData(); + const multiAccountHash = await user.getMultiAccountHash(); + + await multiAccount.signIn( + multiAccountData, + this.data.password, + user.getSetting('encryptionRounds'), + multiAccountHash + ); + } + + const [firstUser] = await user.getMultiAccountUsers(); + + if (firstUser) { + user.logout('switch', true); + await user.login(firstUser); + user.goToActiveState(); + } else { + this.$state.go('create'); + } + } + + onSignIn() { + this._listen(); + } + + onResetPassword() { + throw new Error('ImportAccountCtrl.onResetPassword() not implemented'); + } + + /** + * @private + */ + _listen() { + let privateKeyTo = null; + this.status = 'progress'; + + this.connectProvider.listen((message) => { + return new Promise((resolve, reject) => { + if (!message) { + return reject(); + } + + switch (message.event) { + case 'connect': { + const { publicKey, privateKey } = keyPair( + seedUtils.generateNewSeed(SEED_LENGTH) + ); + + privateKeyTo = privateKey; + + return resolve(JSON.stringify({ + event: 'connect', + payload: publicKey + })); + } + case 'data': { + const encryptedData = base64Decode(message.payload.data); + const publicKeyFrom = message.payload.publicKey; + + if (!privateKeyTo) { + return reject('Key pair does not exist'); + } + + try { + this.data = JSON.parse( + messageDecrypt( + sharedKey( + privateKeyTo, + publicKeyFrom, + 'waves_migration_token' + ), + encryptedData + ) + ); + + this.status = 'ready'; + + return resolve(JSON.stringify({ + event: 'data', + payload: 'ok' + })); + } catch (e) { + this.status = 'error'; + + return reject(String(e)); + } finally { + privateKeyTo = null; + } + } + default: return reject('Invalid message'); + } + }); + }); + } + + } + + return new ImportAccountCtrl(); + }; + + controller.$inject = [ + 'Base', + '$scope', + 'user', + 'multiAccount', + 'storageImporter' + ]; + + angular.module('app.importAccount').controller('ImportAccountCtrl', controller); +})(); diff --git a/src/modules/importAccount/importAccount.js b/src/modules/importAccount/importAccount.js new file mode 100644 index 000000000..3559b6cfe --- /dev/null +++ b/src/modules/importAccount/importAccount.js @@ -0,0 +1,5 @@ +(() => { + 'use strict'; + + angular.module('app.importAccount', []); +})(); diff --git a/src/modules/importAccount/templates/importAccount.html b/src/modules/importAccount/templates/importAccount.html new file mode 100644 index 000000000..b5a5febc5 --- /dev/null +++ b/src/modules/importAccount/templates/importAccount.html @@ -0,0 +1,48 @@ + + +
+
+
+
+

Import account

+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ +
+ + Import + +
+ +
+ Success + + Go to account + +
+ +
+ Error + + Retry + +
+
+
+
diff --git a/src/modules/signIn/components/signInForm/signInForm.html b/src/modules/signIn/components/signInForm/signInForm.html new file mode 100644 index 000000000..47705ad2e --- /dev/null +++ b/src/modules/signIn/components/signInForm/signInForm.html @@ -0,0 +1,35 @@ +
+ +
+ +
+ + + + + + + +
+ + +
+
+ +
+ + + +
+
diff --git a/src/modules/signIn/components/signInForm/signInForm.js b/src/modules/signIn/components/signInForm/signInForm.js new file mode 100644 index 000000000..f65a81f69 --- /dev/null +++ b/src/modules/signIn/components/signInForm/signInForm.js @@ -0,0 +1,109 @@ +(() => { + 'use strict'; + + /** + * @param {typeof Base} Base + * @param {ng.IScope} $scope + * @param {*} $state + * @param {User} user + * @param {MultiAccount} multiAccount + * @param {ModalManager} modalManager + * @returns {SignInFormCtrl} + */ + const controller = function (Base, $scope, $state, user, multiAccount, modalManager) { + + class SignInFormCtrl extends Base { + + /** + * @type {string} + */ + password = ''; + /** + * @type {ng.IFormController|null} + */ + form = null; + /** + * @type {string} + */ + multiAccountData = ''; + /** + * @type {string} + */ + multiAccountHash = ''; + /** + * @type {Array|null} + */ + legacyUserList = null; + + constructor() { + super($scope); + + this.observe('password', this._updatePassword); + + Promise.all([ + user.getMultiAccountData(), + user.getMultiAccountHash(), + user.getFilteredUserList() + ]).then(([multiAccountData, multiAccountHash, userList]) => { + if (!multiAccountData) { + $state.go('signUp'); + } else { + this.multiAccountData = multiAccountData; + this.multiAccountHash = multiAccountHash; + this.legacyUserList = userList; + } + }); + } + + onSubmit() { + if (this.form.$invalid) { + return; + } + + this.showPasswordError = false; + + multiAccount.signIn( + this.multiAccountData, + this.password, + undefined, + this.multiAccountHash + ).then(() => { + this.onSuccess(); + }).catch(() => { + this._showPasswordError(); + }); + } + + showForgotPasswordModal() { + modalManager.showForgotPasswordModal().then(() => { + this.onResetPassword(); + }); + } + + _showPasswordError() { + this.password = ''; + this.showPasswordError = true; + } + + _updatePassword() { + if (this.password) { + this.showPasswordError = false; + } + } + + } + + return new SignInFormCtrl(); + }; + + controller.$inject = ['Base', '$scope', '$state', 'user', 'multiAccount', 'modalManager']; + + angular.module('app.signIn').component('wSignInForm', { + templateUrl: 'modules/signIn/components/signInForm/signInForm.html', + controller, + bindings: { + onSuccess: '&', + onResetPassword: '&' + } + }); +})(); diff --git a/src/modules/signIn/controllers/SignInCtrl.js b/src/modules/signIn/controllers/SignInCtrl.js index 3156db33d..f98366ac4 100644 --- a/src/modules/signIn/controllers/SignInCtrl.js +++ b/src/modules/signIn/controllers/SignInCtrl.js @@ -1,4 +1,4 @@ -(function () { +(() => { 'use strict'; const analytics = require('@waves/event-sender'); @@ -8,30 +8,12 @@ * @param {ng.IScope} $scope * @param {*} $state * @param {User} user - * @param {MultiAccount} multiAccount - * @param {ModalManager} modalManager * @returns {SignInCtrl} */ - const controller = function (Base, $scope, $state, user, multiAccount, modalManager) { + const controller = function (Base, $scope, $state, user) { class SignInCtrl extends Base { - /** - * @type {string} - */ - password = ''; - /** - * @type {ng.IFormController|null} - */ - loginForm = null; - /** - * @type {string} - */ - multiAccountData = ''; - /** - * @type {string} - */ - multiAccountHash = ''; /** * @type {Array|null} */ @@ -40,49 +22,33 @@ constructor() { super($scope); - this.observe('password', this._updatePassword); - analytics.send({ name: 'Onboarding Sign In Show', target: 'ui', params: { from: 'sign-in' } }); Promise.all([ user.getMultiAccountData(), - user.getMultiAccountHash(), user.getFilteredUserList() - ]).then(([multiAccountData, multiAccountHash, userList]) => { + ]).then(([multiAccountData, userList]) => { if (!multiAccountData) { $state.go('signUp'); } else { - this.multiAccountData = multiAccountData; - this.multiAccountHash = multiAccountHash; this.legacyUserList = userList; } }); } - onSubmit() { - this.showPasswordError = false; - - multiAccount.signIn( - this.multiAccountData, - this.password, - undefined, - this.multiAccountHash - ).then( - () => Promise.all([ - user.getMultiAccountUsers(), - user.getMultiAccountSettings() - ]), - () => { - this._showPasswordError(); - return Promise.reject(); - } - ).then(([multiAccountUsers, commonSettings]) => { + onLogin() { + Promise.all([ + user.getMultiAccountUsers(), + user.getMultiAccountSettings() + ]).then(([multiAccountUsers, commonSettings]) => { const [firstUser] = multiAccountUsers; user.setMultiAccountSettings(commonSettings); if (firstUser) { - this._login(firstUser); + user.login(firstUser).then(() => { + user.goToActiveState(); + }); } else if (this.legacyUserList && this.legacyUserList.length) { $state.go('migrate'); } else { @@ -93,27 +59,8 @@ }); } - showForgotPasswordModal() { - modalManager.showForgotPasswordModal().then(() => { - $state.go('signUp'); - }); - } - - _login(userData) { - user.login(userData).then(() => { - user.goToActiveState(); - }); - } - - _showPasswordError() { - this.password = ''; - this.showPasswordError = true; - } - - _updatePassword() { - if (this.password) { - this.showPasswordError = false; - } + onResetPassword() { + $state.go('signUp'); } } diff --git a/src/modules/signIn/templates/signIn.html b/src/modules/signIn/templates/signIn.html index c78816b91..9564755fa 100644 --- a/src/modules/signIn/templates/signIn.html +++ b/src/modules/signIn/templates/signIn.html @@ -13,41 +13,10 @@
-
- -
- -
- - - - - - - -
- - -
-
- -
- - - -
-
+
diff --git a/src/modules/signIn/templates/signInHasUsers.html b/src/modules/signIn/templates/signInHasUsers.html deleted file mode 100644 index 8c3e158f0..000000000 --- a/src/modules/signIn/templates/signInHasUsers.html +++ /dev/null @@ -1,74 +0,0 @@ -
- -
-
-
- -
-
- -
- - - - -
-
- -
-
{{::user.name}}
-
{{::user.address}}
-
-
-
-
- -
-
-
-
- - - - - - - - - - - - - - - -
- - - -
diff --git a/src/modules/signIn/templates/signInNoUsers.html b/src/modules/signIn/templates/signInNoUsers.html deleted file mode 100644 index 719fba892..000000000 --- a/src/modules/signIn/templates/signInNoUsers.html +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 180684191..292ea56b4 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -1,18 +1,17 @@ // @ts-check -(function () { +(() => { 'use strict'; const ds = require('data-service'); const { libs, seedUtils } = require('@waves/waves-transactions'); - const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; + const { keyPair } = libs.crypto; /** - * @param {typeof Base} Base + * @param {*} Base * @param {ng.ILogService} $log - * @param {$mdDialog} $mdDialog - * @param {StorageImporter} storageImporter - * @returns {ExportModalCtrl} + * @param {*} $mdDialog + * @param {*} storageImporter */ const controller = function (Base, $log, $mdDialog, storageImporter) { const SEED_LENGTH = 20; @@ -37,10 +36,6 @@ mode: this.mode }); } - - if (this.mode === 'import') { - this._listen(); - } } export() { @@ -55,7 +50,7 @@ } const publicKeyTo = result.payload; - const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); + const { publicKey, privateKey } = keyPair(seedUtils.generateNewSeed(SEED_LENGTH)); return storageImporter.export( privateKey, @@ -81,78 +76,6 @@ }); } - _listen() { - let privateKeyTo = null; - - this.connectProvider.listen((message) => { - return new Promise((resolve, reject) => { - if (!message) { - return reject(); - } - - switch (message.event) { - case 'connect': { - const { publicKey, privateKey } = this._generateSharedKeyPair(SEED_LENGTH); - - privateKeyTo = privateKey; - - return resolve(JSON.stringify({ - event: 'connect', - payload: publicKey - })); - } - case 'data': { - const encryptedData = base64Decode(message.payload.data); - const publicKeyFrom = message.payload.publicKey; - - if (!privateKeyTo) { - return reject('Key pair does not exist'); - } - - try { - const data = JSON.parse( - messageDecrypt( - sharedKey( - privateKeyTo, - publicKeyFrom, - 'waves_migration_token' - ), - encryptedData - ) - ); - - return storageImporter.import(data).then(() => { - return resolve(JSON.stringify({ - event: 'data', - payload: 'ok' - })); - }).catch((e) => { - return reject(String(e)); - }).then(() => { - this.connectProvider.destroy(); - }); - } catch (e) { - return reject(String(e)); - } finally { - privateKeyTo = null; - } - } - default: return reject('Invalid message'); - } - }); - }); - } - - /** - * @param {number} seedLength - * @returns {TKeyPair} - */ - _generateSharedKeyPair(seedLength) { - const seed = seedUtils.generateNewSeed(seedLength); - - return keyPair(seed); - } - } return new MigrateModalCtrl(); diff --git a/src/modules/welcome/controllers/WelcomeCtrl.js b/src/modules/welcome/controllers/WelcomeCtrl.js index 1ecb961ab..5a88de7ff 100644 --- a/src/modules/welcome/controllers/WelcomeCtrl.js +++ b/src/modules/welcome/controllers/WelcomeCtrl.js @@ -273,6 +273,7 @@ }); }) .catch(() => { + this.pendingRestore = false; storage.save('accountImportComplete', true); }); } From 7e55bb634a2d9e09222f625df39d0aa6e4d98a0b Mon Sep 17 00:00:00 2001 From: finico Date: Fri, 25 Oct 2019 16:47:32 +0300 Subject: [PATCH 012/144] DEXW-2225: Refactor SignInForm --- .../components/signInForm/signInForm.html | 1 + .../components/signInForm/signInForm.js | 167 +++++++++--------- 2 files changed, 82 insertions(+), 86 deletions(-) diff --git a/src/modules/signIn/components/signInForm/signInForm.html b/src/modules/signIn/components/signInForm/signInForm.html index 47705ad2e..86f043517 100644 --- a/src/modules/signIn/components/signInForm/signInForm.html +++ b/src/modules/signIn/components/signInForm/signInForm.html @@ -10,6 +10,7 @@ type="password" class="big no-validate no-icon" ng-model="$ctrl.password" + ng-change="$ctrl.onPasswordChange()" required w-autofocus> diff --git a/src/modules/signIn/components/signInForm/signInForm.js b/src/modules/signIn/components/signInForm/signInForm.js index f65a81f69..26da7e7c8 100644 --- a/src/modules/signIn/components/signInForm/signInForm.js +++ b/src/modules/signIn/components/signInForm/signInForm.js @@ -1,106 +1,101 @@ (() => { 'use strict'; - /** - * @param {typeof Base} Base - * @param {ng.IScope} $scope - * @param {*} $state - * @param {User} user - * @param {MultiAccount} multiAccount - * @param {ModalManager} modalManager - * @returns {SignInFormCtrl} - */ - const controller = function (Base, $scope, $state, user, multiAccount, modalManager) { - - class SignInFormCtrl extends Base { - - /** - * @type {string} - */ - password = ''; - /** - * @type {ng.IFormController|null} - */ - form = null; - /** - * @type {string} - */ - multiAccountData = ''; - /** - * @type {string} - */ - multiAccountHash = ''; - /** - * @type {Array|null} - */ - legacyUserList = null; - - constructor() { - super($scope); - - this.observe('password', this._updatePassword); - - Promise.all([ - user.getMultiAccountData(), - user.getMultiAccountHash(), - user.getFilteredUserList() - ]).then(([multiAccountData, multiAccountHash, userList]) => { - if (!multiAccountData) { - $state.go('signUp'); - } else { - this.multiAccountData = multiAccountData; - this.multiAccountHash = multiAccountHash; - this.legacyUserList = userList; - } - }); - } + class SignInFormCtrl { + + static $inject = ['$state', 'user', 'multiAccount', 'modalManager']; + + /** + * @type {string} + */ + password = ''; + /** + * @type {ng.IFormController|null} + */ + form = null; + /** + * @type {string} + */ + multiAccountData = ''; + /** + * @type {string} + */ + multiAccountHash = ''; + /** + * @type {Array|null} + */ + legacyUserList = null; + + /** + * @param {*} $state + * @param {User} user + * @param {MultiAccount} multiAccount + * @param {ModalManager} modalManager + */ + constructor($state, user, multiAccount, modalManager) { + this.$state = $state; + this.user = user; + this.multiAccount = multiAccount; + this.modalManager = modalManager; + } - onSubmit() { - if (this.form.$invalid) { - return; + $onInit() { + Promise.all([ + this.user.getMultiAccountData(), + this.user.getMultiAccountHash(), + this.user.getFilteredUserList() + ]).then(([multiAccountData, multiAccountHash, userList]) => { + if (!multiAccountData) { + this.$state.go('signUp'); + } else { + this.multiAccountData = multiAccountData; + this.multiAccountHash = multiAccountHash; + this.legacyUserList = userList; } + }); + } - this.showPasswordError = false; - - multiAccount.signIn( - this.multiAccountData, - this.password, - undefined, - this.multiAccountHash - ).then(() => { - this.onSuccess(); - }).catch(() => { - this._showPasswordError(); - }); + onSubmit() { + if (this.form.$invalid) { + return; } - showForgotPasswordModal() { - modalManager.showForgotPasswordModal().then(() => { - this.onResetPassword(); - }); - } + this.showPasswordError = false; + + this.multiAccount.signIn( + this.multiAccountData, + this.password, + undefined, + this.multiAccountHash + ).then(() => { + this.onSuccess(); + }).catch(() => { + this._showPasswordError(); + }); + } - _showPasswordError() { - this.password = ''; - this.showPasswordError = true; - } + showForgotPasswordModal() { + this.modalManager.showForgotPasswordModal().then(() => { + this.onResetPassword(); + }); + } - _updatePassword() { - if (this.password) { - this.showPasswordError = false; - } + onPasswordChange() { + if (this.password) { + this.showPasswordError = false; } - } - return new SignInFormCtrl(); - }; + _showPasswordError() { + this.password = ''; + this.showPasswordError = true; + } - controller.$inject = ['Base', '$scope', '$state', 'user', 'multiAccount', 'modalManager']; + } angular.module('app.signIn').component('wSignInForm', { templateUrl: 'modules/signIn/components/signInForm/signInForm.html', - controller, + controller: SignInFormCtrl, bindings: { onSuccess: '&', onResetPassword: '&' From f44c47f397dd60d43673e615f6d76b1786636e64 Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 29 Oct 2019 12:31:34 +0300 Subject: [PATCH 013/144] DEXW-2225: Clean up --- src/index.hbs | 8 - src/modules/app/app.js | 1 - src/modules/app/services/StorageExporter.js | 58 ++++++ src/modules/app/services/StorageImporter.js | 186 ------------------ .../controllers/ImportAccountCtrl.js | 182 ----------------- src/modules/importAccount/importAccount.js | 5 - .../templates/importAccount.html | 48 ----- .../utils/modals/migrateModal/migrateModal.js | 17 +- 8 files changed, 63 insertions(+), 442 deletions(-) create mode 100644 src/modules/app/services/StorageExporter.js delete mode 100644 src/modules/app/services/StorageImporter.js delete mode 100644 src/modules/importAccount/controllers/ImportAccountCtrl.js delete mode 100644 src/modules/importAccount/importAccount.js delete mode 100644 src/modules/importAccount/templates/importAccount.html diff --git a/src/index.hbs b/src/index.hbs index 4200e73c7..a7d8a4a75 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -710,14 +710,6 @@ views: [{ name: 'main' }] } }, - { - id: 'importAccount', - data: { - url: '/import-account', - views: [{ name: 'main' }], - noLogin: true - } - }, { id: 'stand', data: { diff --git a/src/modules/app/app.js b/src/modules/app/app.js index e80fb9944..9d0ca7292 100644 --- a/src/modules/app/app.js +++ b/src/modules/app/app.js @@ -114,7 +114,6 @@ 'app.keeper', 'app.fromBackup', 'app.import', - 'app.importAccount', 'app.wallet', 'app.dex', 'app.tokens', diff --git a/src/modules/app/services/StorageExporter.js b/src/modules/app/services/StorageExporter.js new file mode 100644 index 000000000..47d78d004 --- /dev/null +++ b/src/modules/app/services/StorageExporter.js @@ -0,0 +1,58 @@ +(function () { + 'use strict'; + + class StorageExporter { + + static $inject = [ + '$log', + 'storage', + 'multiAccount' + ]; + + /** + * @param {ng.ILogService} $log + * @param {app.utils.Storage} storage + * @param {app.MultiAccount} multiAccount + */ + constructor($log, storage, multiAccount) { + this.$log = $log; + this.storage = storage; + this.multiAccount = multiAccount; + } + + /** + * @public + * @param {string} publicKeyTo + * @param {string} privateKeyFrom + * @returns {Promise<{password: string, storageData: Object}>} + */ + async export(privateKeyFrom, publicKeyTo) { + const keys = [ + 'multiAccountData', + 'multiAccountUsers', + 'multiAccountSettings', + 'multiAccountHash', + 'userList', + 'openClientMode' + ]; + + const storageData = {}; + + for (const key of keys) { + try { + // eslint-disable-next-line no-await-in-loop + const value = await this.storage.load(key); + + storageData[key] = value; + } catch (e) { + this.$log.error(`Could not read key "${key}" from storage. Error:`, e); + } + } + + return this.multiAccount.export(privateKeyFrom, publicKeyTo, storageData); + } + + } + + angular.module('app').service('storageExporter', StorageExporter); +})(); diff --git a/src/modules/app/services/StorageImporter.js b/src/modules/app/services/StorageImporter.js deleted file mode 100644 index 4e4489ba4..000000000 --- a/src/modules/app/services/StorageImporter.js +++ /dev/null @@ -1,186 +0,0 @@ -// @ts-check - -(function () { - 'use strict'; - - const { libs } = require('@waves/waves-transactions'); - const { decryptSeed } = libs.crypto; - - class StorageImporter { - - static $inject = [ - '$log', - '$state', - 'storage', - 'user', - 'multiAccount' - ]; - - /** - * @param {ng.ILogService} $log - * @param {*} $state - * @param {app.utils.Storage} storage - * @param {app.User} user - * @param {app.MultiAccount} multiAccount - */ - constructor($log, $state, storage, user, multiAccount) { - this.$log = $log; - this.$state = $state; - this.storage = storage; - this.user = user; - this.multiAccount = multiAccount; - } - - /** - * @public - * @param {string} publicKeyTo - * @param {string} privateKeyFrom - * @returns {Promise<{password: string, storageData: Object}>} - */ - async export(privateKeyFrom, publicKeyTo) { - const keys = [ - 'multiAccountData', - 'multiAccountUsers', - 'multiAccountSettings', - 'multiAccountHash', - 'userList', - 'openClientMode' - ]; - - const storageData = {}; - - for (const key of keys) { - try { - // eslint-disable-next-line no-await-in-loop - const value = await this.storage.load(key); - - storageData[key] = value; - } catch (e) { - this.$log.error(`Could not read key "${key}" from storage. Error:`, e); - } - } - - return this.multiAccount.export(privateKeyFrom, publicKeyTo, storageData); - } - - /** - * @public - * @param {Object} data - * @param {string} data.password - * @param {Object} data.storageData - * @returns {Promise} - */ - async import(data) { - const multiAccountData = await this.user.getMultiAccountData(); - - if (!multiAccountData) { - const signUpResult = await this.multiAccount.signUp( - data.password, - this.user.getSetting('encryptionRounds') - ); - - await this.user.saveMultiAccount(signUpResult); - } - - await this._importData(data); - } - - /** - * @private - * @param {Object} data - * @param {string} data.password - * @param {Object} data.storageData - * @returns {Promise} - */ - async _importData(data) { - const { multiAccountData, multiAccountUsers, multiAccountSettings, ...rest } = data.storageData; - - await this._importMultiAccountUsers(multiAccountData, multiAccountUsers, data.password); - await this._importMultiAccountSettings(multiAccountSettings); - - for (const [key, value] of Object.entries(rest)) { - try { - // eslint-disable-next-line no-await-in-loop - await this._importDataItem(key, value); - } catch (e) { - this.$log.error(e); - } - } - } - - /** - * @private - * @param {string} key - * @param {any} value - * @returns {Promise} - */ - async _importDataItem(key, value) { - const valueFromStorage = await this.storage.load(key); - - return !valueFromStorage ? - this.storage.save(key, value) : - Promise.resolve(); - } - - /** - * @private - * @param {string} multiAccountData - * @param {Object} multiAccountUsers - * @param {string} password - */ - async _importMultiAccountUsers(multiAccountData, multiAccountUsers, password) { - let currentMultiAccountUsers = await this.storage.load('multiAccountUsers'); - - if (!currentMultiAccountUsers) { - currentMultiAccountUsers = Object.create(null); - } - - try { - const users = JSON.parse(decryptSeed( - multiAccountData, - password, - this.user.getSetting('encryptionRounds') - )); - - for (const [hash, user] of Object.entries(users)) { - if (!currentMultiAccountUsers[hash]) { - currentMultiAccountUsers[hash] = multiAccountUsers[hash]; - // eslint-disable-next-line no-await-in-loop - const { multiAccountData, multiAccountHash } = await this.multiAccount.addUser(user); - // eslint-disable-next-line no-await-in-loop - await this.user.saveMultiAccount({ multiAccountData, multiAccountHash }); - } - } - - await this.user.saveMultiAccountUsers(currentMultiAccountUsers); - } catch (e) { - this.$log.error(e); - - return Promise.resolve(); - } - } - - /** - * @private - * @param {Object} multiAccountSettings - * @returns {Promise} - */ - async _importMultiAccountSettings(multiAccountSettings) { - delete multiAccountSettings.lastOpenVersion; - delete multiAccountSettings.termsAccepted; - - const currentMultiAccountSettings = await this.user.getMultiAccountSettings(); - const mergedSettings = { - ...multiAccountSettings, - ...currentMultiAccountSettings - }; - - await this.user.saveMultiAccountSettings(mergedSettings); - - this.user.setMultiAccountSettings(mergedSettings); - } - - } - - angular.module('app').service('storageImporter', StorageImporter); -})(); diff --git a/src/modules/importAccount/controllers/ImportAccountCtrl.js b/src/modules/importAccount/controllers/ImportAccountCtrl.js deleted file mode 100644 index 5d9dadf1e..000000000 --- a/src/modules/importAccount/controllers/ImportAccountCtrl.js +++ /dev/null @@ -1,182 +0,0 @@ -// @ts-check - -(() => { - 'use strict'; - - const ds = require('data-service'); - const { libs, seedUtils } = require('@waves/waves-transactions'); - const { keyPair, sharedKey, messageDecrypt, base64Decode } = libs.crypto; - - /** - * @param {*} Base - * @param {ng.IScope} $scope - * @param {*} user - * @param {*} multiAccount - * @param {*} storageImporter - */ - const controller = function (Base, $scope, user, multiAccount, storageImporter) { - const SEED_LENGTH = 20; - - class ImportAccountCtrl extends Base { - - /** - * @type {'idle' | 'progress' | 'ready' | 'success' | 'error'} - */ - status = 'idle'; - - /** - * @type {boolean} - */ - hasAccount = false; - - /** - * @type {Object} - */ - data = null; - - constructor() { - super($scope); - - if (WavesApp.isDesktop()) { - this.connectProvider = new ds.connect.HttpConnectProvider({ - port: 8888, - url: 'http://localhost:8888/connect' - }); - } else { - this.connectProvider = new ds.connect.PostMessageConnectProvider({ - mode: 'import' - }); - } - - user.getMultiAccountData().then((multiAccountData) => { - if (multiAccountData) { - this.hasAccount = true; - } else { - this._listen(); - } - }); - } - - importAccount() { - storageImporter.import(this.data).then(() => { - this.status = 'success'; - $scope.$digest(); - }).catch(() => { - this.status = 'error'; - $scope.$digest(); - }); - } - - async login() { - if (!multiAccount.isSignedIn) { - const multiAccountData = await user.getMultiAccountData(); - const multiAccountHash = await user.getMultiAccountHash(); - - await multiAccount.signIn( - multiAccountData, - this.data.password, - user.getSetting('encryptionRounds'), - multiAccountHash - ); - } - - const [firstUser] = await user.getMultiAccountUsers(); - - if (firstUser) { - user.logout('switch', true); - await user.login(firstUser); - user.goToActiveState(); - } else { - this.$state.go('create'); - } - } - - onSignIn() { - this._listen(); - } - - onResetPassword() { - throw new Error('ImportAccountCtrl.onResetPassword() not implemented'); - } - - /** - * @private - */ - _listen() { - let privateKeyTo = null; - this.status = 'progress'; - - this.connectProvider.listen((message) => { - return new Promise((resolve, reject) => { - if (!message) { - return reject(); - } - - switch (message.event) { - case 'connect': { - const { publicKey, privateKey } = keyPair( - seedUtils.generateNewSeed(SEED_LENGTH) - ); - - privateKeyTo = privateKey; - - return resolve(JSON.stringify({ - event: 'connect', - payload: publicKey - })); - } - case 'data': { - const encryptedData = base64Decode(message.payload.data); - const publicKeyFrom = message.payload.publicKey; - - if (!privateKeyTo) { - return reject('Key pair does not exist'); - } - - try { - this.data = JSON.parse( - messageDecrypt( - sharedKey( - privateKeyTo, - publicKeyFrom, - 'waves_migration_token' - ), - encryptedData - ) - ); - - this.status = 'ready'; - - return resolve(JSON.stringify({ - event: 'data', - payload: 'ok' - })); - } catch (e) { - this.status = 'error'; - - return reject(String(e)); - } finally { - privateKeyTo = null; - } - } - default: return reject('Invalid message'); - } - }); - }); - } - - } - - return new ImportAccountCtrl(); - }; - - controller.$inject = [ - 'Base', - '$scope', - 'user', - 'multiAccount', - 'storageImporter' - ]; - - angular.module('app.importAccount').controller('ImportAccountCtrl', controller); -})(); diff --git a/src/modules/importAccount/importAccount.js b/src/modules/importAccount/importAccount.js deleted file mode 100644 index 3559b6cfe..000000000 --- a/src/modules/importAccount/importAccount.js +++ /dev/null @@ -1,5 +0,0 @@ -(() => { - 'use strict'; - - angular.module('app.importAccount', []); -})(); diff --git a/src/modules/importAccount/templates/importAccount.html b/src/modules/importAccount/templates/importAccount.html deleted file mode 100644 index b5a5febc5..000000000 --- a/src/modules/importAccount/templates/importAccount.html +++ /dev/null @@ -1,48 +0,0 @@ - - -
-
-
-
-

Import account

-
- -
-
-
- -
- - -
-
- -
- -
- -
- - Import - -
- -
- Success - - Go to account - -
- -
- Error - - Retry - -
-
-
-
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 292ea56b4..48205c6a1 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -1,5 +1,3 @@ -// @ts-check - (() => { 'use strict'; @@ -11,18 +9,13 @@ * @param {*} Base * @param {ng.ILogService} $log * @param {*} $mdDialog - * @param {*} storageImporter + * @param {*} storageExporter */ - const controller = function (Base, $log, $mdDialog, storageImporter) { + const controller = function (Base, $log, $mdDialog, storageExporter) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { - /** - * @todo separate it for new and old client - */ - mode = window.opener ? 'import' : 'export'; - constructor() { super(); @@ -33,7 +26,7 @@ }); } else { this.connectProvider = new ds.connect.PostMessageConnectProvider({ - mode: this.mode + mode: 'export' }); } } @@ -52,7 +45,7 @@ const publicKeyTo = result.payload; const { publicKey, privateKey } = keyPair(seedUtils.generateNewSeed(SEED_LENGTH)); - return storageImporter.export( + return storageExporter.export( privateKey, publicKeyTo ).then((data) => { @@ -81,7 +74,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageImporter']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 88be8069dd3498b7de81c4259d1ab21e9a462565 Mon Sep 17 00:00:00 2001 From: finico Date: Wed, 6 Nov 2019 11:22:35 +0300 Subject: [PATCH 014/144] DEXW-2225: Fix bus creation --- .../connect/PostMessageConnectProvider.ts | 21 ++------ server.ts | 2 +- .../utils/modals/migrateModal/migrateModal.js | 49 ++++++++++++------- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/data-service/connect/PostMessageConnectProvider.ts b/data-service/connect/PostMessageConnectProvider.ts index 1a787e42e..09215d3e8 100644 --- a/data-service/connect/PostMessageConnectProvider.ts +++ b/data-service/connect/PostMessageConnectProvider.ts @@ -3,6 +3,7 @@ import { delay } from '../utils/utils'; import { ConnectProvider } from './ConnectProvider'; interface PostMessageConnectProviderOptioins { + win?: Window; mode?: 'export' | 'import'; origins?: string[]; } @@ -21,23 +22,9 @@ export class PostMessageConnectProvider implements ConnectProvider { constructor(options: PostMessageConnectProviderOptioins = {}) { this.adapter = new WindowAdapter( - [new WindowProtocol( - options.mode === 'import' ? - (window.opener || window.parent) : - window, - 'listen' - )], - [new WindowProtocol( - options.mode === 'import' ? - (window.opener || window.parent) : - window, - 'dispatch' - )], - { - origins: options.origins, - chanelId: `postMessageConnectProvider${options.mode === 'export' ? 'Client' : 'Server'}`, - availableChanelId: `postMessageConnectProvider${options.mode !== 'export' ? 'Client' : 'Server'}`, - } + [new WindowProtocol(window, WindowProtocol.PROTOCOL_TYPES.LISTEN)], + [new WindowProtocol(options.win, WindowProtocol.PROTOCOL_TYPES.DISPATCH)], + { origins: options.origins } ); this.bus = new Bus(this.adapter); this.active = true; diff --git a/server.ts b/server.ts index 82c731a7e..25ceecc3d 100644 --- a/server.ts +++ b/server.ts @@ -86,7 +86,7 @@ function createSimpleServer({ port = 8000 }) { console.log(`https://${ip}:${port}`); } -createMyServer(8080); +createMyServer(args.port || 8080); if (args.startSimple) { createSimpleServer(args); diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 48205c6a1..2023d60d1 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -16,27 +16,14 @@ class MigrateModalCtrl extends Base { - constructor() { - super(); - - if (WavesApp.isDesktop()) { - this.connectProvider = new ds.connect.HttpConnectProvider({ - port: 8888, - url: 'http://localhost:8888/connect' - }); - } else { - this.connectProvider = new ds.connect.PostMessageConnectProvider({ - mode: 'export' - }); - } - } - export() { + const connectProvider = this._getConnectProvider(); const message = JSON.stringify({ event: 'connect' }); - this.connectProvider.send(message, { + connectProvider.send(message, { event: 'data', - attempts: 3 + attempts: 3, + timeout: 10000 }).then((result) => { if (!result || result.event !== 'connect') { throw new Error(`Message event is not valid: ${result.event}`); @@ -49,7 +36,7 @@ privateKey, publicKeyTo ).then((data) => { - return this.connectProvider.send(JSON.stringify({ + return connectProvider.send(JSON.stringify({ event: 'data', payload: { publicKey, @@ -60,7 +47,6 @@ }).then((result) => { if (result.payload === 'ok') { $log.log('done'); - this.connectProvider.destroy(); } else { $log.log('fail', result); } @@ -69,6 +55,31 @@ }); } + /** + * @returns {ConnectProvider} + */ + _getConnectProvider() { + const origins = WavesApp.isProduction() ? + WavesApp.network.migrationOrigins : + '*'; + + if (WavesApp.isDesktop()) { + return new ds.connect.HttpConnectProvider({ + port: 8888, + url: 'http://localhost:8888/connect', + origins + }); + } else { + const childWindow = window.open('https://localhost:8080/migration'); + + return new ds.connect.PostMessageConnectProvider({ + win: childWindow, + mode: 'export', + origins + }); + } + } + } return new MigrateModalCtrl(); From 2b2d123736008ccf5fa772113660f013a58cfd3d Mon Sep 17 00:00:00 2001 From: finico Date: Thu, 31 Oct 2019 14:08:16 +0300 Subject: [PATCH 015/144] DEXW-2281: Update desktop wizard --- src/index.hbs | 8 ++ src/modules/app/app.js | 1 + .../controllers/DesktopUpdateCtrl.js | 75 +++++++++++++++++++ src/modules/desktopUpdate/desktopUpdate.js | 5 ++ .../templates/desktopUpdate.html | 35 +++++++++ 5 files changed, 124 insertions(+) create mode 100644 src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js create mode 100644 src/modules/desktopUpdate/desktopUpdate.js create mode 100644 src/modules/desktopUpdate/templates/desktopUpdate.html diff --git a/src/index.hbs b/src/index.hbs index a7d8a4a75..f24521b8d 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -724,6 +724,14 @@ views: [{ name: 'main' }] } }, + { + id: 'desktopUpdate', + data: { + url: '/desktop-update', + noLogin: true, + views: [{ name: 'main' }] + } + }, { id: 'main', data: { diff --git a/src/modules/app/app.js b/src/modules/app/app.js index 9d0ca7292..f169ce500 100644 --- a/src/modules/app/app.js +++ b/src/modules/app/app.js @@ -110,6 +110,7 @@ 'app.restore', 'app.saveSeed', 'app.desktop', + 'app.desktopUpdate', 'app.ledger', 'app.keeper', 'app.fromBackup', diff --git a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js new file mode 100644 index 000000000..1114958e8 --- /dev/null +++ b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js @@ -0,0 +1,75 @@ +(() => { + 'use strict'; + + const ds = require('data-service'); + + /** + * @param {ng.IScope} $scope + * @param {*} $state + * @param {*} configService + */ + const controller = ($scope, $state, configService) => { + class DesktopUpdateCtrl { + + step = 0; + progress = 0; + error = null; + + constructor() { + if (!WavesApp.isDesktop()) { + $state.go('/'); + } + } + + download() { + const url = this._getDistUrl(); + const [fileName] = url.pathname.split('/').slice(-1); + + ds.utils.downloadFile(url, (progress) => { + this.progress = Math.ceil(progress); + $scope.$digest(); + }).then((content) => { + transfer('download', { + fileName, + fileContent: content + }).then(() => { + this._nextStep(); + $scope.$digest(); + }).catch((e) => { + if (e.message === 'Cancel') { + this._resetProgress(); + } else { + this.error = String(e); + } + + $scope.$digest(); + }); + }).catch((e) => { + this.error = String(e); + $scope.$digest(); + }); + } + + _getDistUrl() { + const urls = configService.get('DESKTOP_URLS'); + + return new URL(urls[WavesApp.platform]); + } + + _nextStep() { + this.step = this.step + 1; + } + + _resetProgress() { + this.progress = 0; + } + + } + + return new DesktopUpdateCtrl(); + }; + + controller.$inject = ['$scope', '$state', 'configService']; + + angular.module('app.desktopUpdate').controller('DesktopUpdateCtrl', controller); +})(); diff --git a/src/modules/desktopUpdate/desktopUpdate.js b/src/modules/desktopUpdate/desktopUpdate.js new file mode 100644 index 000000000..c23ab3324 --- /dev/null +++ b/src/modules/desktopUpdate/desktopUpdate.js @@ -0,0 +1,5 @@ +(() => { + 'use strict'; + + angular.module('app.desktopUpdate', []); +})(); diff --git a/src/modules/desktopUpdate/templates/desktopUpdate.html b/src/modules/desktopUpdate/templates/desktopUpdate.html new file mode 100644 index 000000000..beb3942e0 --- /dev/null +++ b/src/modules/desktopUpdate/templates/desktopUpdate.html @@ -0,0 +1,35 @@ + + +
+
+
+ + +
+

Update App

+ +
{{$ctrl.progress}} %
+
{{$ctrl.error}}
+ + + + +
+
+ + +
+

Install App

+ +
Then we'll continue
+
+
+
+
+
+
+ + From 6ed2d92e633b8129161c232fd31981056892e28a Mon Sep 17 00:00:00 2001 From: finico Date: Fri, 1 Nov 2019 11:51:38 +0300 Subject: [PATCH 016/144] DEXW-2281: Indicate pending while downloading --- src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js | 5 +++++ src/modules/desktopUpdate/templates/desktopUpdate.html | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js index 1114958e8..0ca2f8ae8 100644 --- a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js +++ b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js @@ -14,6 +14,7 @@ step = 0; progress = 0; error = null; + isDownloading = false; constructor() { if (!WavesApp.isDesktop()) { @@ -25,6 +26,8 @@ const url = this._getDistUrl(); const [fileName] = url.pathname.split('/').slice(-1); + this.isDownloading = true; + ds.utils.downloadFile(url, (progress) => { this.progress = Math.ceil(progress); $scope.$digest(); @@ -34,6 +37,7 @@ fileContent: content }).then(() => { this._nextStep(); + this.isDownloading = false; $scope.$digest(); }).catch((e) => { if (e.message === 'Cancel') { @@ -42,6 +46,7 @@ this.error = String(e); } + this.isDownloading = false; $scope.$digest(); }); }).catch((e) => { diff --git a/src/modules/desktopUpdate/templates/desktopUpdate.html b/src/modules/desktopUpdate/templates/desktopUpdate.html index beb3942e0..d66e43a8b 100644 --- a/src/modules/desktopUpdate/templates/desktopUpdate.html +++ b/src/modules/desktopUpdate/templates/desktopUpdate.html @@ -13,6 +13,8 @@

Update App

From d652a2e7e95ec694dbaa703fb0b702aee819471a Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Thu, 31 Oct 2019 13:39:20 +0300 Subject: [PATCH 017/144] DEXW-2282: migration page --- locale/en/app.migration.json | 3 ++ locale/ru/app.migration.json | 3 ++ mocks/waves-client-config/master/config.json | 3 +- .../master/testnet.config.json | 3 +- src/index.hbs | 7 ++++ src/modules/app/app.js | 3 +- src/modules/app/initialize/AppConfig.js | 2 +- src/modules/app/initialize/AppRun.js | 21 ++++++++++-- src/modules/app/services/User.js | 14 ++++++-- .../migration/controllers/MigrationCtrl.js | 33 +++++++++++++++++++ src/modules/migration/migration.js | 5 +++ .../migration/templates/migration.html | 7 ++++ 12 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 locale/en/app.migration.json create mode 100644 locale/ru/app.migration.json create mode 100644 src/modules/migration/controllers/MigrationCtrl.js create mode 100644 src/modules/migration/migration.js create mode 100644 src/modules/migration/templates/migration.html diff --git a/locale/en/app.migration.json b/locale/en/app.migration.json new file mode 100644 index 000000000..0db3279e4 --- /dev/null +++ b/locale/en/app.migration.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/locale/ru/app.migration.json b/locale/ru/app.migration.json new file mode 100644 index 000000000..0db3279e4 --- /dev/null +++ b/locale/ru/app.migration.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/mocks/waves-client-config/master/config.json b/mocks/waves-client-config/master/config.json index b4a365190..a3e753fbd 100644 --- a/mocks/waves-client-config/master/config.json +++ b/mocks/waves-client-config/master/config.json @@ -79,5 +79,6 @@ "SERVICE_TEMPORARILY_UNAVAILABLE": false, "GATEWAYS_SOON": [ "5dJj4Hn9t2Ve3tRpNGirUHy4yBK6qdJRAJYV21yPPuGz" - ] + ], + "DEXW_LOCKED": false } diff --git a/mocks/waves-client-config/master/testnet.config.json b/mocks/waves-client-config/master/testnet.config.json index b1b6290e7..31f273d8c 100644 --- a/mocks/waves-client-config/master/testnet.config.json +++ b/mocks/waves-client-config/master/testnet.config.json @@ -55,5 +55,6 @@ "GATEWAYS_SOON": [ "GVWSgVsmEx4KTAZPm31JZDmdehxFTFZBuy7V8gzb8JxE", "E9KLFjmbD4psBWyHs8Wq3Uux9U45AeFxXb9eCask43YZ" - ] + ], + "DEXW_LOCKED": false } diff --git a/src/index.hbs b/src/index.hbs index f24521b8d..e7925dffe 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -732,6 +732,13 @@ views: [{ name: 'main' }] } }, + { + id: 'migration', + data: { + url: '/migration', + views: [{ name: 'main' }] + } + }, { id: 'main', data: { diff --git a/src/modules/app/app.js b/src/modules/app/app.js index f169ce500..18b4154a2 100644 --- a/src/modules/app/app.js +++ b/src/modules/app/app.js @@ -119,7 +119,8 @@ 'app.dex', 'app.tokens', 'app.unavailable', - 'app.stand' + 'app.stand', + 'app.migration' ]); })(); diff --git a/src/modules/app/initialize/AppConfig.js b/src/modules/app/initialize/AppConfig.js index e4a76a6fa..bbe4dfa92 100644 --- a/src/modules/app/initialize/AppConfig.js +++ b/src/modules/app/initialize/AppConfig.js @@ -214,8 +214,8 @@ * @private */ _initStates() { - const defaultUrl = AppConfig.getUrlFromState(WavesApp.stateTree.find('welcome')); + $urlRouterProvider.when('', defaultUrl); WavesApp.stateTree.toArray() diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 0e1217410..94c94cacc 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -368,12 +368,24 @@ const START_STATES = WavesApp.stateTree.where({ noLogin: true }) .map((item) => WavesApp.stateTree.getPath(item.id).join('.')); + const DEXW_LOCKED_STATES = WavesApp.stateTree.toArray() + .filter((state) => + state.id === 'migration' || state.id === 'signIn' + ) + .map((state) => state.id); + const offInitialTransitions = $transitions.onStart({}, transition => { + const DEXW_LOCKED = configService.get('DEXW_LOCKED'); + const toState = transition.to(); const fromState = transition.from(); const params = transition.params(); let tryDesktop; + if (DEXW_LOCKED && DEXW_LOCKED_STATES.indexOf(toState.name) === -1) { + return $state.target(DEXW_LOCKED_STATES[0]); + } + if (START_STATES.indexOf(toState.name) === -1) { if (fromState.name === 'unavailable') { return $state.target(START_STATES[0]); @@ -425,7 +437,7 @@ this._modalRouter.initialize(); }); - const offInnerTransitions = this._onInnerTransitions(START_STATES); + const offInnerTransitions = this._onInnerTransitions(START_STATES, DEXW_LOCKED_STATES); user.logoutSignal.once(() => { offInnerTransitions(); @@ -435,10 +447,15 @@ }); } - _onInnerTransitions(START_STATES) { + _onInnerTransitions(START_STATES, DEXW_LOCKED_STATES) { return $transitions.onStart({}, transition => { const toState = transition.to(); const { custom } = transition.options(); + const DEXW_LOCKED = configService.get('DEXW_LOCKED'); + + if (DEXW_LOCKED && DEXW_LOCKED_STATES.indexOf(toState.name) === -1) { + return $state.target(DEXW_LOCKED_STATES[1]); + } if (START_STATES.indexOf(toState.name) !== -1 && !custom.logout) { return false; diff --git a/src/modules/app/services/User.js b/src/modules/app/services/User.js index 7c9762dee..8f27167da 100644 --- a/src/modules/app/services/User.js +++ b/src/modules/app/services/User.js @@ -28,7 +28,8 @@ timeLine, utils, themes, - multiAccount + multiAccount, + $injector ) { const tsUtils = require('ts-utils'); @@ -426,8 +427,14 @@ } goToActiveState() { + const configService = $injector.get('configService'); + const DEXW_LOCKED = configService.get('DEXW_LOCKED'); if (!this.initRouteState) { - $state.go(this.getActiveState('wallet')); + if (DEXW_LOCKED) { + $state.go(this.getActiveState('migration')); + } else { + $state.go(this.getActiveState('wallet')); + } } } @@ -921,7 +928,8 @@ 'timeLine', 'utils', 'themes', - 'multiAccount' + 'multiAccount', + '$injector' ]; angular.module('app').factory('user', factory); diff --git a/src/modules/migration/controllers/MigrationCtrl.js b/src/modules/migration/controllers/MigrationCtrl.js new file mode 100644 index 000000000..d322ccddb --- /dev/null +++ b/src/modules/migration/controllers/MigrationCtrl.js @@ -0,0 +1,33 @@ +(function () { + 'use strict'; + + /** + * @param {Base} Base + * {$rootScope.Scope} $scope + * @return {MigrationCtrl} + */ + const controller = function ( + Base, + $scope + ) { + + class MigrationCtrl extends Base { + + constructor() { + super($scope); + } + + } + + return new MigrationCtrl(); + }; + + + controller.$inject = [ + 'Base', + '$scope' + ]; + + angular.module('app.migration') + .controller('MigrationCtrl', controller); +})(); diff --git a/src/modules/migration/migration.js b/src/modules/migration/migration.js new file mode 100644 index 000000000..e65b3481a --- /dev/null +++ b/src/modules/migration/migration.js @@ -0,0 +1,5 @@ +(function () { + 'use strict'; + + angular.module('app.migration', []); +})(); diff --git a/src/modules/migration/templates/migration.html b/src/modules/migration/templates/migration.html new file mode 100644 index 000000000..eaa2e2d1a --- /dev/null +++ b/src/modules/migration/templates/migration.html @@ -0,0 +1,7 @@ + + +
+ Migration Page +
+ + From 893c25aa21136c8727661421e9be7b35fe5fc3a7 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 1 Nov 2019 18:25:08 +0300 Subject: [PATCH 018/144] DEXW-2282: change routing logic --- src/index.hbs | 1 + src/modules/app/initialize/AppRun.js | 114 +++++++++--------- src/modules/app/services/ConfigService.js | 8 ++ src/modules/app/services/User.js | 21 ++-- .../migration/controllers/MigrationCtrl.js | 39 +++++- .../migration/templates/dexMoving.html | 3 + src/modules/migration/templates/migrate.html | 5 + .../migration/templates/migration.html | 8 +- src/modules/signIn/controllers/SignInCtrl.js | 35 +++++- 9 files changed, 157 insertions(+), 77 deletions(-) create mode 100644 src/modules/migration/templates/dexMoving.html create mode 100644 src/modules/migration/templates/migrate.html diff --git a/src/index.hbs b/src/index.hbs index e7925dffe..8985c4b27 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -735,6 +735,7 @@ { id: 'migration', data: { + noLogin: true, url: '/migration', views: [{ name: 'main' }] } diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 94c94cacc..0274145b2 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -127,56 +127,64 @@ _unavailable = false; constructor() { - const identityImg = require('identity-img'); - - LOADER.addProgress(PROGRESS_MAP.APP_RUN); - - /** - * List of css class on body (from current state) - * @type {Array} - */ - this.activeClasses = []; - /** - * @type {ModalRouter} - * @private - */ - this._modalRouter = new ModalRouter(); - - /** - * Configure library generation avatar by address - */ - identityImg.config({ rows: 8, cells: 8 }); - - this._setHandlers(); - this._stopLoader(); - this._initializeLogin(); - this._initializeOutLinks(); + configService.configReadyPromise.then(() => { + const identityImg = require('identity-img'); - if (WavesApp.isDesktop()) { - window.listenMainProcessEvent((type, url) => { - const parts = utils.parseElectronUrl(url); - const path = parts.path.replace(/\/$/, '') || parts.path; - - if (path) { - const noLogin = path === '/' || WavesApp.stateTree.where({ noLogin: true }) - .some(item => { - const url = item.get('url') || item.id; - return path === url; - }); - - if (noLogin) { - location.hash = `#!${path}${parts.search}`; - } else { - user.onLogin().then(() => { - setTimeout(() => { - location.hash = `#!${path}${parts.search}`; - }, 1000); - }); + LOADER.addProgress(PROGRESS_MAP.APP_RUN); + + /** + * List of css class on body (from current state) + * @type {Array} + */ + this.activeClasses = []; + /** + * @type {ModalRouter} + * @private + */ + this._modalRouter = new ModalRouter(); + + /** + * Configure library generation avatar by address + */ + identityImg.config({ rows: 8, cells: 8 }); + + this._setHandlers(); + this._stopLoader(); + this._initializeLogin(); + this._initializeOutLinks(); + + if (WavesApp.isDesktop()) { + window.listenMainProcessEvent((type, url) => { + const parts = utils.parseElectronUrl(url); + const path = parts.path.replace(/\/$/, '') || parts.path; + + if (path) { + const noLogin = path === '/' || WavesApp.stateTree.where({ noLogin: true }) + .some(item => { + const url = item.get('url') || item.id; + return path === url; + }); + + if (noLogin) { + location.hash = `#!${path}${parts.search}`; + } else { + user.onLogin().then(() => { + setTimeout(() => { + location.hash = `#!${path}${parts.search}`; + }, 1000); + }); + } } - } - }); - } + }); + } + if (configService.get('DEXW_LOCKED') && $state.current.name !== 'migration') { + $state.go('migration'); + } else { + $state.go('signIn'); + } + + }); $rootScope.WavesApp = WavesApp; } @@ -368,11 +376,7 @@ const START_STATES = WavesApp.stateTree.where({ noLogin: true }) .map((item) => WavesApp.stateTree.getPath(item.id).join('.')); - const DEXW_LOCKED_STATES = WavesApp.stateTree.toArray() - .filter((state) => - state.id === 'migration' || state.id === 'signIn' - ) - .map((state) => state.id); + const DEXW_LOCKED_STATES = ['migration', 'signIn']; const offInitialTransitions = $transitions.onStart({}, transition => { const DEXW_LOCKED = configService.get('DEXW_LOCKED'); @@ -383,7 +387,7 @@ let tryDesktop; if (DEXW_LOCKED && DEXW_LOCKED_STATES.indexOf(toState.name) === -1) { - return $state.target(DEXW_LOCKED_STATES[0]); + return $state.target('migration'); } if (START_STATES.indexOf(toState.name) === -1) { @@ -454,10 +458,10 @@ const DEXW_LOCKED = configService.get('DEXW_LOCKED'); if (DEXW_LOCKED && DEXW_LOCKED_STATES.indexOf(toState.name) === -1) { - return $state.target(DEXW_LOCKED_STATES[1]); + return $state.target('migration'); } - if (START_STATES.indexOf(toState.name) !== -1 && !custom.logout) { + if (START_STATES.indexOf(toState.name) !== -1 && !custom.logout && !DEXW_LOCKED) { return false; } else { state.signals.changeRouterStateStart.dispatch(transition); diff --git a/src/modules/app/services/ConfigService.js b/src/modules/app/services/ConfigService.js index 34e633a00..8087d6b3c 100644 --- a/src/modules/app/services/ConfigService.js +++ b/src/modules/app/services/ConfigService.js @@ -29,10 +29,17 @@ * @type Promise */ configReady; + /** + * @type Promise + */ + configReadyPromise; constructor() { super(); + this.configReadyPromise = new Promise((resolve) => { + this._resolve = resolve; + }); this.configReady = createPoll(this, this._getConfig, this._setConfig, 30000); createPoll(this, this._getFeeConfig, this._setFeeConfig, 30000); } @@ -90,6 +97,7 @@ * @private */ _setConfig(config) { + this._resolve(); const myConfig = this._config; this._config = config; diff --git a/src/modules/app/services/User.js b/src/modules/app/services/User.js index 8f27167da..09393291d 100644 --- a/src/modules/app/services/User.js +++ b/src/modules/app/services/User.js @@ -29,7 +29,6 @@ utils, themes, multiAccount, - $injector ) { const tsUtils = require('ts-utils'); @@ -309,6 +308,15 @@ }); } + /** + * @return {Promise} + */ + getMultiAccountUsersCount() { + return storage.load('multiAccountUsers').then(users => { + return Object.keys(users).length; + }); + } + /** * @return {Promise} */ @@ -427,14 +435,8 @@ } goToActiveState() { - const configService = $injector.get('configService'); - const DEXW_LOCKED = configService.get('DEXW_LOCKED'); if (!this.initRouteState) { - if (DEXW_LOCKED) { - $state.go(this.getActiveState('migration')); - } else { - $state.go(this.getActiveState('wallet')); - } + $state.go(this.getActiveState('wallet')); } } @@ -928,8 +930,7 @@ 'timeLine', 'utils', 'themes', - 'multiAccount', - '$injector' + 'multiAccount' ]; angular.module('app').factory('user', factory); diff --git a/src/modules/migration/controllers/MigrationCtrl.js b/src/modules/migration/controllers/MigrationCtrl.js index d322ccddb..ab05eea06 100644 --- a/src/modules/migration/controllers/MigrationCtrl.js +++ b/src/modules/migration/controllers/MigrationCtrl.js @@ -3,18 +3,48 @@ /** * @param {Base} Base - * {$rootScope.Scope} $scope + * @param {$rootScope.Scope} $scope + * @param {ConfigService} configService + * @param {User} user + * @param $state * @return {MigrationCtrl} */ const controller = function ( Base, - $scope + $scope, + configService, + user, + $state ) { + const PATH = 'modules/migration/templates'; + class MigrationCtrl extends Base { + /** + * @type {string} + */ + template = `${PATH}/migrate.html`; + constructor() { super($scope); + + Promise.all([ + user.getMultiAccountUsersCount(), + user.getFilteredUserList() + ]) + .then(([multiAccountUsersCount, legacyUsers]) => { + const hasUsersInLocalStorage = multiAccountUsersCount || + (legacyUsers && legacyUsers.length); + + if ((!user.isAuthorised && hasUsersInLocalStorage)) { + $state.go('signIn'); + } + + if (!hasUsersInLocalStorage && configService.get('DEXW_LOCKED')) { + this.template = `${PATH}/dexMoving.html`; + } + }); } } @@ -25,7 +55,10 @@ controller.$inject = [ 'Base', - '$scope' + '$scope', + 'configService', + 'user', + '$state' ]; angular.module('app.migration') diff --git a/src/modules/migration/templates/dexMoving.html b/src/modules/migration/templates/dexMoving.html new file mode 100644 index 000000000..a894cbd11 --- /dev/null +++ b/src/modules/migration/templates/dexMoving.html @@ -0,0 +1,3 @@ +
+ Dex Moving 🤷‍ +
diff --git a/src/modules/migration/templates/migrate.html b/src/modules/migration/templates/migrate.html new file mode 100644 index 000000000..84ef8c6f9 --- /dev/null +++ b/src/modules/migration/templates/migrate.html @@ -0,0 +1,5 @@ + + +
+ Migration Page +
diff --git a/src/modules/migration/templates/migration.html b/src/modules/migration/templates/migration.html index eaa2e2d1a..2a80b115f 100644 --- a/src/modules/migration/templates/migration.html +++ b/src/modules/migration/templates/migration.html @@ -1,7 +1 @@ - - -
- Migration Page -
- - + diff --git a/src/modules/signIn/controllers/SignInCtrl.js b/src/modules/signIn/controllers/SignInCtrl.js index f98366ac4..22a8e4eb3 100644 --- a/src/modules/signIn/controllers/SignInCtrl.js +++ b/src/modules/signIn/controllers/SignInCtrl.js @@ -8,9 +8,11 @@ * @param {ng.IScope} $scope * @param {*} $state * @param {User} user + * @param {ModalManager} modalManager + * @param {ConfigService} configService * @returns {SignInCtrl} */ - const controller = function (Base, $scope, $state, user) { + const controller = function (Base, $scope, $state, user, modalManager, configService) { class SignInCtrl extends Base { @@ -63,12 +65,41 @@ $state.go('signUp'); } + showForgotPasswordModal() { + modalManager.showForgotPasswordModal().then(() => { + $state.go('signUp'); + }); + } + + _login(userData) { + user.login(userData).then(() => { + const DEXW_LOCKED = configService.get('DEXW_LOCKED'); + + if (DEXW_LOCKED) { + $state.go('migration'); + } else { + user.goToActiveState(); + } + }); + } + + _showPasswordError() { + this.password = ''; + this.showPasswordError = true; + } + + _updatePassword() { + if (this.password) { + this.showPasswordError = false; + } + } + } return new SignInCtrl(); }; - controller.$inject = ['Base', '$scope', '$state', 'user', 'multiAccount', 'modalManager']; + controller.$inject = ['Base', '$scope', '$state', 'user', 'modalManager', 'configService']; angular.module('app.signIn').controller('SignInCtrl', controller); })(); From 07f72e42bd1c50bc70761a489e3b1b3edbb7fbde Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 1 Nov 2019 18:27:27 +0300 Subject: [PATCH 019/144] DEXW-2282: refactor --- src/modules/app/services/User.js | 2 +- src/modules/migration/templates/dexMoving.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/app/services/User.js b/src/modules/app/services/User.js index 09393291d..b26e9c447 100644 --- a/src/modules/app/services/User.js +++ b/src/modules/app/services/User.js @@ -28,7 +28,7 @@ timeLine, utils, themes, - multiAccount, + multiAccount ) { const tsUtils = require('ts-utils'); diff --git a/src/modules/migration/templates/dexMoving.html b/src/modules/migration/templates/dexMoving.html index a894cbd11..fc88b2694 100644 --- a/src/modules/migration/templates/dexMoving.html +++ b/src/modules/migration/templates/dexMoving.html @@ -1,3 +1,3 @@
- Dex Moving 🤷‍ + Dex Moving
From a64957d05242fe3f9e3131b9fd0d96feb1e06e8a Mon Sep 17 00:00:00 2001 From: vba2000 Date: Wed, 6 Nov 2019 11:57:04 +0300 Subject: [PATCH 020/144] DEXW-2225: add is Native function --- data-service/utils/utils.ts | 55 +++++++++++++++++++++++++++++++++++++ package-lock.json | 52 ++++++++++------------------------- 2 files changed, 69 insertions(+), 38 deletions(-) diff --git a/data-service/utils/utils.ts b/data-service/utils/utils.ts index 89a0ddcc3..e79546cbf 100644 --- a/data-service/utils/utils.ts +++ b/data-service/utils/utils.ts @@ -185,3 +185,58 @@ export function getTransferFeeList() { } export const delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout)); + +export const isNativeFunction = (function () { + const toString = Object.prototype.toString; + + // Используется для разложения на составляющие декомпилированного + // исходного кода функции + const fnToString = Function.prototype.toString; + + // Используется для определения конструкторов среды (Safari > 4; + // по сути, предназначено специально для типизированных массивов) + const reHostCtor = /^\[object .+?Constructor\]$/; + + // Составление регулярного выражения на основе часто употребляемого + // нативного метода в качестве шаблона. + // Выбираем `Object#toString`, так как вполне вероятно, что он ещё не задействован. + const reNative = RegExp('^' + + // Применяем `Object#toString` к строке + String(toString) + // Избавляемся от любых специальных символов регулярных выражений + .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&') + // Заменяем упоминания `toString` на `.*?`, чтобы сохранить обобщённый вид шаблона. + // Заменяем `for ...` и тому подобное для поддержки окружений вроде Rhino, + // которые добавляют дополнительную информацию, такую как арность метода. + .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + function isNative(value: any) { + const type = typeof value; + return type == 'function' + // Используем `Function#toString`, чтобы обойти собственный метод + // `toString` самого значения и избежать ложного результата. + ? reNative.test(fnToString.call(value)) + // На всякий случай выполняем проверку на наличие объектов среды, так + // как некоторые окружения могут представлять компоненты вроде + // типизированных массивов как методы DOM, что может не соответствовать + // нормальному нативному паттерну. + : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; + } + + return isNative; +})(); + + +export const isNativeNotBound = (value: any) => { + + if (!value || typeof value.name !== 'string') { + return false; + } + + if (!isNativeFunction(value)) { + return false; + } + + return value.name.indexOf('bound') === -1; +}; diff --git a/package-lock.json b/package-lock.json index dbaa9b85a..bbaf3aa9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2003,15 +2003,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, - "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -7045,8 +7043,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -7067,14 +7064,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7089,20 +7084,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -7219,8 +7211,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -7232,7 +7223,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7247,7 +7237,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7255,14 +7244,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7281,7 +7268,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7369,8 +7355,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7382,7 +7367,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7468,8 +7452,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7505,7 +7488,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7525,7 +7507,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7569,14 +7550,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -7702,15 +7681,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, - "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -12688,8 +12665,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-glob": { "version": "2.0.1", From a81c89aa1a91cddc4304445732ae83a05b8952e7 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Wed, 6 Nov 2019 13:45:01 +0300 Subject: [PATCH 021/144] DEXW-2282: add warning plate --- src/index.hbs | 4 ++ .../ComponentWarningPlate.js | 57 +++++++++++++++ .../componentWarningPlate.html | 21 ++++++ .../componentWarningPlate.less | 21 ++++++ src/modules/utils/services/utils.js | 72 +++++++++++++++++++ 5 files changed, 175 insertions(+) create mode 100644 src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js create mode 100644 src/modules/app/directives/componentWarningPlate/componentWarningPlate.html create mode 100644 src/modules/app/directives/componentWarningPlate/componentWarningPlate.less diff --git a/src/index.hbs b/src/index.hbs index 8985c4b27..9cee5a8bd 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -522,6 +522,10 @@ +
+ +
+
diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js new file mode 100644 index 000000000..bb6166921 --- /dev/null +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -0,0 +1,57 @@ +(function () { + 'use strict'; + + /** + * @param {ModalManager} modalManager + * @param {app.utils} utils + * @return {ComponentWarningPlate} + */ + const controller = function (modalManager, utils) { + + class ComponentWarningPlate { + + /** + * @type {number} + */ + days = 0; + /** + * @type {number} + */ + hours = 0; + /** + * @type {number} + */ + minutes = 0; + + constructor() { + utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this)); + } + + showMovingModal() { + modalManager.showExportAccount(); + } + + _setTime(last) { + this.days = this._to2Digest(last.days); + this.hours = this._to2Digest(last.hours); + this.minutes = this._to2Digest(last.minutes); + } + + _to2Digest(num) { + return num < 10 ? `0${num}` : String(num); + } + + } + + return new ComponentWarningPlate(); + + }; + + controller.$inject = ['modalManager', 'utils']; + + angular.module('app').component('wWarningPlate', { + templateUrl: 'modules/app/directives/componentWarningPlate/componentWarningPlate.html', + transclude: false, + controller + }); +})(); diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html new file mode 100644 index 000000000..b050b6a8e --- /dev/null +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -0,0 +1,21 @@ +
+
+
+ {{$ctrl.days}} + d: +
+
+ {{$ctrl.hours}} + h: +
+
+ {{$ctrl.minutes}} + m +
+
+ +
+ +
+
+ diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less new file mode 100644 index 000000000..8e3db5837 --- /dev/null +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less @@ -0,0 +1,21 @@ +w-warning-plate { + .warning-plate { + + &-content { + display: flex; + flex-direction: row; + } + + &-button { + cursor: pointer; + border-radius: 4px; + background-color: #fff; + color: #f89300; + } + + &-timer { + display: flex; + flex-direction: row; + } + } +} diff --git a/src/modules/utils/services/utils.js b/src/modules/utils/services/utils.js index b80759096..78d841cc0 100644 --- a/src/modules/utils/services/utils.js +++ b/src/modules/utils/services/utils.js @@ -183,6 +183,14 @@ ledger: 2 }; + const MS_IN_SEC = 1000; + const SEC_IN_MINUTE = 60; + const MINUTES_IN_HOUR = 60; + const HOURS_IN_DAY = 24; + const MS_IN_MINUTE = MS_IN_SEC * SEC_IN_MINUTE; + const MS_IN_HOUR = MS_IN_MINUTE * MINUTES_IN_HOUR; + const MS_IN_DAY = MS_IN_HOUR * HOURS_IN_DAY; + class BigNumberPart extends tsApiValidator.BasePart { getValue(data) { @@ -1971,6 +1979,29 @@ } else { pom.click(); } + }, + + /** + * @param {TTimerOptions} options + * @param cb + */ + startTimer(options, cb) { + const getLastTime = _time.bind(null, options); + let lastTime = {}; + + function loop() { + const currentTime = getLastTime(); + if (lastTime.minutes !== currentTime.minutes || lastTime.seconds !== currentTime.seconds) { + cb(currentTime); + lastTime = currentTime; + } + + if ((currentTime.seconds + currentTime.hours + currentTime.minutes + currentTime.days) > 0) { + requestAnimationFrame(loop); + } + } + + loop(); } }; @@ -2170,6 +2201,38 @@ return _getSignal(observer, keys); } + /** + * @param {TTimerOptions} date + * @return {{hours: number, seconds: number, minutes: number, days: number}} + * @private + */ + function _time(date) { + const year = date.year; + const day = date.day; + const month = date.month - 1; + const hours = date.hours || 0; + const minutes = date.minutes || 0; + const seconds = date.seconds || 0; + + const UTC3 = 10800000; + const offset = (new Date()).getTimezoneOffset() * 60000; + const msToday = Date.now(); + const msDate = (new Date(year, month, day, hours, minutes, seconds)).getTime() - offset - UTC3; + const delta = (msDate - msToday) < 0 ? 0 : (msDate - msToday); + + const daysLast = Math.floor(delta / MS_IN_DAY); + const hoursLast = Math.floor(delta / MS_IN_HOUR) % HOURS_IN_DAY; + const minuteslast = Math.floor(delta / MS_IN_MINUTE) % MINUTES_IN_HOUR; + const secondslast = Math.floor(delta / MS_IN_SEC) % SEC_IN_MINUTE; + + return { + days: daysLast, + hours: hoursLast, + minutes: minuteslast, + seconds: secondslast + }; + } + return utils; }; @@ -2189,3 +2252,12 @@ * @property {number} expiration */ +/** + * @typedef {object} TTimerOptions + * @property {number} year + * @property {number} month + * @property {number} day + * @property {number} hours + * @property {number} seconds? + */ + From 74176eaf40d6b468e42acb2ce7565182cbf01e89 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Thu, 7 Nov 2019 11:00:58 +0300 Subject: [PATCH 022/144] DEXW-2282: fix export modal --- .../directives/componentWarningPlate/ComponentWarningPlate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index bb6166921..2bc1a616d 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -28,7 +28,7 @@ } showMovingModal() { - modalManager.showExportAccount(); + modalManager.showMigrateModal(); } _setTime(last) { From 6965a5903cd3d4894bb28e10b813b925e6fa333a Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Thu, 7 Nov 2019 11:20:20 +0300 Subject: [PATCH 023/144] DEXW-2282: finish without text --- locale/de/app.dex.json | 1 + locale/de/app.utils.json | 9 ++ locale/en/app.dex.json | 1 + locale/en/app.utils.json | 9 ++ locale/es/app.dex.json | 1 + locale/es/app.utils.json | 9 ++ locale/et_EE/app.dex.json | 1 + locale/et_EE/app.utils.json | 9 ++ locale/fr/app.dex.json | 1 + locale/fr/app.utils.json | 9 ++ locale/hi_IN/app.dex.json | 1 + locale/hi_IN/app.utils.json | 9 ++ locale/id/app.dex.json | 1 + locale/id/app.utils.json | 9 ++ locale/it/app.dex.json | 1 + locale/it/app.utils.json | 9 ++ locale/ja/app.dex.json | 1 + locale/ja/app.utils.json | 9 ++ locale/ko/app.dex.json | 1 + locale/ko/app.utils.json | 9 ++ locale/nl_NL/app.dex.json | 1 + locale/nl_NL/app.utils.json | 9 ++ locale/pl/app.dex.json | 1 + locale/pl/app.utils.json | 9 ++ locale/pt_BR/app.dex.json | 1 + locale/pt_BR/app.utils.json | 9 ++ locale/pt_PT/app.dex.json | 1 + locale/pt_PT/app.utils.json | 9 ++ locale/ru/app.dex.json | 1 + locale/ru/app.utils.json | 9 ++ locale/tr/app.dex.json | 1 + locale/tr/app.utils.json | 9 ++ locale/zh_CN/app.dex.json | 5 +- locale/zh_CN/app.utils.json | 15 ++- src/img/icons/time-filled.svg | 3 + src/index.hbs | 2 +- .../componentWarningPlate.html | 6 +- .../componentWarningPlate.less | 82 +++++++++++++++- .../less/dex-layout__column_createorder.less | 2 +- src/modules/dex/less/dex.less | 94 +------------------ .../less/largeHeader/largeHeader.less | 4 +- src/themeConfig/black/icons.less | 1 + src/themeConfig/default/icons.less | 3 +- 43 files changed, 271 insertions(+), 106 deletions(-) create mode 100644 src/img/icons/time-filled.svg diff --git a/locale/de/app.dex.json b/locale/de/app.dex.json index 14b69846b..52811f4b1 100644 --- a/locale/de/app.dex.json +++ b/locale/de/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Keine Märkte, die ihren Filtern entsprechen" }, "price": "Preis", + "vol": "Vol", "volume": "Volumen" } }, diff --git a/locale/de/app.utils.json b/locale/de/app.utils.json index 25b393b3e..706f0de62 100644 --- a/locale/de/app.utils.json +++ b/locale/de/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Überprüfen sie, ob ihre Wallet oder ihre Exchange Smart Contracts verwendet, um ETH zurückzuziehen. Wir akzeptieren solche Transaktionen nicht und können sie nicht zurückerstatten. Sie werden dieses Geld verlieren.", "warningTitle": "Bitte hinterlegen sie ETH nicht von Smart Contracts! Hinterlegen sie keine ERC20 Tokens! Nur Ethereum ist erlaubt." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Sobald die Transaktion bestätigt ist, verarbeitet das Gateway die Übertragung der WEST Token zu einem Token in ihrem Waves Account.", "helpDescrTitle": "Geben Sie diese Adresse in Ihren WEST-Kunden oder Ihr Wallet ein.", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes übrig: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/en/app.dex.json b/locale/en/app.dex.json index 9cad1ab1d..f61ce82dd 100644 --- a/locale/en/app.dex.json +++ b/locale/en/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "No markets matching your filters" }, "price": "Price", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/en/app.utils.json b/locale/en/app.utils.json index 9921c2d5e..529d0101d 100644 --- a/locale/en/app.utils.json +++ b/locale/en/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw ETH. We do not accept such transactions and can’t refund them. You will lose that money.", "warningTitle": "Please do not deposit ETH from smart contracts! Do not deposit ERC20 tokens! Only Ethereum is allowed." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes left: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/es/app.dex.json b/locale/es/app.dex.json index cdefbc120..487e05af9 100644 --- a/locale/es/app.dex.json +++ b/locale/es/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "No hay mercados en base a sus filtros" }, "price": "Precio", + "vol": "Vol", "volume": "Volumen" } }, diff --git a/locale/es/app.utils.json b/locale/es/app.utils.json index 471520036..61a7a6578 100644 --- a/locale/es/app.utils.json +++ b/locale/es/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Comprueba si tu monedero o tu exchange utiliza Smart-contracts para retirar ETH. No aceptamos ese tipo de transacción y no podemos devolverlo. Perderás ese dinero.", "warningTitle": "!Por favor no deposites ETH desde Smart-Contract! No deposites tokens ERC20, solo se acepta Ethereum." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Una vez que se confirma la transacción, la puerta de enlace procesará la transferencia de WEST en forma de token a su cuenta Waves.", "helpDescrTitle": "Ingrese esta dirección en su cartera o cliente WEST", @@ -999,5 +1005,8 @@ "byte": { "help": "Quedan: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/et_EE/app.dex.json b/locale/et_EE/app.dex.json index 5ae896089..665557801 100644 --- a/locale/et_EE/app.dex.json +++ b/locale/et_EE/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Teie filtritele vastavaid turge ei leitud" }, "price": "Hind", + "vol": "Vol", "volume": "Maht" } }, diff --git a/locale/et_EE/app.utils.json b/locale/et_EE/app.utils.json index e77b278c0..3c7f47325 100644 --- a/locale/et_EE/app.utils.json +++ b/locale/et_EE/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Kontrollige, kas teie rahakott või börs kasutab ETH-i väljavõtmiseks smart-kontrakte. Me ei aktsepteeri selliseid tehinguid ja ei saa neid tagasi maksta. Te kaotate selle raha.", "warningTitle": "Palun ärge tehke sissemakset ETH smart-kontrakrtidelt! Ärge tehkse sissemakseid ERC20 tokenites! Ainult Ethereum on lubatud." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Baite vasakul: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/fr/app.dex.json b/locale/fr/app.dex.json index c5c759df8..5209352c9 100644 --- a/locale/fr/app.dex.json +++ b/locale/fr/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Aucun marché ne correspond à vos filtres" }, "price": "Prix", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/fr/app.utils.json b/locale/fr/app.utils.json index 094e35df7..7b21cc9d7 100644 --- a/locale/fr/app.utils.json +++ b/locale/fr/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Vérifiez si votre portefeuille ou votre plateforme d'échange utilise des smart-contracts pour retirer ETH. Nous n'acceptons pas de telles transactions et ne pouvons pas les rembourser. Vous perdrez cet argent.", "warningTitle": "Ne déposez pas d'ETH à partir de smart-contracts ! Ne déposez pas de tokens ERC20 ! Seul Ethereum est autorisé." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Une fois la transaction confirmée, le portail traitera le transfert de WEST vers un jeton dans votre compte Waves.", "helpDescrTitle": "Entrez cette adresse dans votre client ou portefeuille WEST", @@ -999,5 +1005,8 @@ "byte": { "help": "Octets restants : {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/hi_IN/app.dex.json b/locale/hi_IN/app.dex.json index 9c08f782a..51154cb58 100644 --- a/locale/hi_IN/app.dex.json +++ b/locale/hi_IN/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "आपके फिल्टर से मैच करता कोई मार्केट नहीं" }, "price": "मूल्य", + "vol": "Vol", "volume": "वॉल्यूम" } }, diff --git a/locale/hi_IN/app.utils.json b/locale/hi_IN/app.utils.json index 4b6583094..b899e8a58 100644 --- a/locale/hi_IN/app.utils.json +++ b/locale/hi_IN/app.utils.json @@ -302,6 +302,12 @@ "warningText": "क करें किया क्या आपका वॉलेट या एक्सचेंज, ETH निकासी के लिए स्मार्ट-कॉन्ट्रैक्ट का उपयोग करता है। हम ऐसे लेनेदेन स्वीकार नहीं करते हैं और उनको रिफंड नहीं कर सकते हैं। आपको उस धन की हानि हो जाएगी।", "warningTitle": "कृपया स्मार्ट-कॉन्ट्रैक्ट से ETH जमा ना करें! ERC20 टोकन जमा ना करें! केवल Ethereum अनुमत है।" }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "शेष Bytes: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/id/app.dex.json b/locale/id/app.dex.json index e820b8ccb..99cd5d5d4 100644 --- a/locale/id/app.dex.json +++ b/locale/id/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Tidak ada pasar yang cocok dengan filter Anda" }, "price": "Harga", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/id/app.utils.json b/locale/id/app.utils.json index 331d8db51..e155a6589 100644 --- a/locale/id/app.utils.json +++ b/locale/id/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Periksa apakah dompet atau pertukaran Anda menggunakan kontrak cerdas untuk menarik ETH. Kami tidak menerima transaksi semacam itu dan dapat mengembalikan uang mereka. Anda akan kehilangan uang itu.", "warningTitle": "Tolong jangan depositkan ETH dari kontrak pintar! Jangan setor token ERC20! Hanya Ethereum yang diizinkan." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Setelah transaksi dikonfirmasi, gateway akan memproses transfer WEST ke token di akun Waves Anda.", "helpDescrTitle": "Masukkan alamat ini ke klien atau dompet WEST Anda", @@ -999,5 +1005,8 @@ "byte": { "help": "Byte tersisa: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/it/app.dex.json b/locale/it/app.dex.json index a46de9921..903a47345 100644 --- a/locale/it/app.dex.json +++ b/locale/it/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Nessun mercato in base ai criteri di ricerca" }, "price": "Prezzo", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/it/app.utils.json b/locale/it/app.utils.json index c37e02997..3b7962e30 100644 --- a/locale/it/app.utils.json +++ b/locale/it/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Controlla se il tuo wallet o exchange utilizza smart contract per trasferire ETH. Non accettiamo questo tipo di transazioni e non ci sarà possibile rimborsarle. L'importo trasferito andrà perduto.", "warningTitle": "Per favore, non inviare ETH da smart contracts! Non inviare token ERC20! Accettiamo esclusivamente Ethereum." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Una volta che la transazione sarà confermata, il gateway processerà il trasferimento di WEST in favore di un token nel tuo account Waves.", "helpDescrTitle": "Inserisci questo indirizzo nel tuo client WEST o nel tuo wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Byte restanti: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ja/app.dex.json b/locale/ja/app.dex.json index e320f2740..76369cbac 100644 --- a/locale/ja/app.dex.json +++ b/locale/ja/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "指定されたフィルターに合致するペアはありません" }, "price": "価格", + "vol": "Vol", "volume": "ボリューム" } }, diff --git a/locale/ja/app.utils.json b/locale/ja/app.utils.json index a8288d1a7..a2ff66cf9 100644 --- a/locale/ja/app.utils.json +++ b/locale/ja/app.utils.json @@ -302,6 +302,12 @@ "warningText": "あなたのウォレットと取引所がスマートコントラクトを用いて、ETHを引出していないか、確認してください。私たちはそのような形式のトランザクションを受け入れておらず、返金することもできません。あなたはあなたの資金を失います。", "warningTitle": "ETHをスマートコントラクトからデポジットしないでください。また、ERC20トークンもデポジットしないでください。" }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "トランザクションが承認されると、ゲートウェイはWESTの送信を進め、あなたのWavesアカウントにトークンが反映されます。", "helpDescrTitle": "このアドレスをWESTクライアント、またはウォレットに入力してください", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes 残 : {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ko/app.dex.json b/locale/ko/app.dex.json index acd7af614..0feb367be 100644 --- a/locale/ko/app.dex.json +++ b/locale/ko/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "검색 결과가 없습니다" }, "price": "가격", + "vol": "Vol", "volume": "거래량" } }, diff --git a/locale/ko/app.utils.json b/locale/ko/app.utils.json index 9176d4691..db26f59aa 100644 --- a/locale/ko/app.utils.json +++ b/locale/ko/app.utils.json @@ -302,6 +302,12 @@ "warningText": "ETH를 출금하려고 하는 지갑 또는 거래소가 Smart-Contracts를 사용하는지 확인하세요. 당사는 해당 트랜잭션을 수신하지 않으며 환불 또한 불가능합니다. 귀하의 자산을 잃게 됩니다.", "warningTitle": "Smart Contracts에서 ETH를 입금하지 마세요! ERC20 토큰을 입금하지 마세요! Ethereum 입금만 가능합니다." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "트랜잭션이 승인되면 게이트웨이가 귀하의 Waves 계정에서 WEST를 토큰으로 전송하는 작업을 처리할 것입니다.", "helpDescrTitle": "이 주소를 WEST 클라이언트 또는 지갑에 입력하세요", @@ -999,5 +1005,8 @@ "byte": { "help": "사용 가능 Bytes: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/nl_NL/app.dex.json b/locale/nl_NL/app.dex.json index 940dfacc2..05f6b8624 100644 --- a/locale/nl_NL/app.dex.json +++ b/locale/nl_NL/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Geen markten die overeenkomen met uw filters" }, "price": "Prijs", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/nl_NL/app.utils.json b/locale/nl_NL/app.utils.json index 7e8b38df2..ade78fc7c 100644 --- a/locale/nl_NL/app.utils.json +++ b/locale/nl_NL/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Controleer of uw wallet of exchange smart-contracts gebruikt om ETH the withdrawen. Wij accepteren zulke transacties niet en kunnen dit niet terug betalen. U raakt op deze manier uw geld kwijt.", "warningTitle": "Verstuur geen ETH vanuit smart contracts naar dit adres. Stort geen ERC20 tokens! Alleen Ethereum is toegestaan." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Zodra de transactie bevestigd is zal de gateway de transactie behandelen en dit omzetten naar een WEST token in uw Waves account.", "helpDescrTitle": "Dit adres invoeren in uw WEST-client of wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes over: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pl/app.dex.json b/locale/pl/app.dex.json index 437cb6f02..19fa46883 100644 --- a/locale/pl/app.dex.json +++ b/locale/pl/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Brak rynków spełniającyh wymagania" }, "price": "Cena", + "vol": "Vol", "volume": "Wolumen" } }, diff --git a/locale/pl/app.utils.json b/locale/pl/app.utils.json index 9771eb56b..5142acf36 100644 --- a/locale/pl/app.utils.json +++ b/locale/pl/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Sprawdź czy portfel lub giełda używają inteligentnych kontraktów (smart contracts) do wycofania ETH. Nie akceptujemy takich transakcji i nie możemy ich zwrócić. Stracisz te pieniądze.", "warningTitle": "Proszę nie deponować ETH z inteligentnych kontraktów (smart contracts)! Proszę nie deponować tokenów ERC20! Tylko Ethereum dozwolone." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Jeżeli transakcja zostanie potwierdzona, system wymieni WEST na tokeny w Twoim koncie Waves.", "helpDescrTitle": "Wprowadź ten adres w swoim kliencie albo portfelu WEST", @@ -999,5 +1005,8 @@ "byte": { "help": "Zostały bajty: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pt_BR/app.dex.json b/locale/pt_BR/app.dex.json index d84a65f32..b1c3f9908 100644 --- a/locale/pt_BR/app.dex.json +++ b/locale/pt_BR/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Nenhum mercado corresponde aos seus filtros" }, "price": "Preço", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/pt_BR/app.utils.json b/locale/pt_BR/app.utils.json index 1a28f2e7f..1458e2898 100644 --- a/locale/pt_BR/app.utils.json +++ b/locale/pt_BR/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Verifique se a sua carteira ou exchange usa smart contracts para transferir ETH. Nós não aceitamos essas transações e você perderá esse dinheiro, pois não podemos reembolsar.", "warningTitle": "Por favor, não deposite ETH através de smart contracts! Não deposite tokens ERC20! Apenas Ethereum é permitido." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes restantes: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pt_PT/app.dex.json b/locale/pt_PT/app.dex.json index 9cad1ab1d..f61ce82dd 100644 --- a/locale/pt_PT/app.dex.json +++ b/locale/pt_PT/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "No markets matching your filters" }, "price": "Price", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/pt_PT/app.utils.json b/locale/pt_PT/app.utils.json index 472c8cb29..90a9f1483 100644 --- a/locale/pt_PT/app.utils.json +++ b/locale/pt_PT/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw ETH. We do not accept such transactions and can’t refund them. You will lose that money.", "warningTitle": "Please do not deposit ETH from smart contracts! Do not deposit ERC20 tokens! Only Ethereum is allowed." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes left: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ru/app.dex.json b/locale/ru/app.dex.json index 8c74dc219..f5fe2447d 100644 --- a/locale/ru/app.dex.json +++ b/locale/ru/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Ничего не найдено" }, "price": "Цена", + "vol": "Объём", "volume": "Объём" } }, diff --git a/locale/ru/app.utils.json b/locale/ru/app.utils.json index e65e745fc..9c9f0bca9 100644 --- a/locale/ru/app.utils.json +++ b/locale/ru/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Проверьте, не использует ли ваш кошелёк или биржа смарт-контракты для отправки ETH. Мы не принимаем такие переводы и не можем возместить их. Вы потеряете эти деньги.", "warningTitle": "Не отправляйте ETH со смарт-контрактов! Не отправляйте ERC20-токены! Только Ethereum." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "Если вы отправите меньше чем {{minAmount, BigNumber}} {{assetTicker}}, вы потеряете деньги.", + "warningMinAmountTitle": "Минимальная сумма депозита {{minAmount, BigNumber}} {{assetTicker}}, максимальная сумма депозита {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Как только транзакция будет подтверждена, шлюз отправит WEST-токен на ваш аккаунт Waves.", "helpDescrTitle": "Введите этот адрес в ваш WEST клиент или кошелёк.", @@ -999,5 +1005,8 @@ "byte": { "help": "Осталось байт: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/tr/app.dex.json b/locale/tr/app.dex.json index a0a235523..4e724a284 100644 --- a/locale/tr/app.dex.json +++ b/locale/tr/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Filtrelerinize uygun bir pazar bulunamadı" }, "price": "Fiyat", + "vol": "Vol", "volume": "Hacim" } }, diff --git a/locale/tr/app.utils.json b/locale/tr/app.utils.json index 10db62190..69fba3dc1 100644 --- a/locale/tr/app.utils.json +++ b/locale/tr/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Cüzdanınızın veya Kripto para borsasının ETH çekimlerinde akıllı kontrat kullanıp kullanmadığını kontrol edin. Akıllı kontratlar tarafından gelen transferleri kabul edemiyoruz. Paranızı kaybedersiniz.", "warningTitle": "ETH akıllı kontratlarından yatırma işlemi yapmayınız. ERC20 tokenleri yatırmayınız! Sadece Ethereum transferleri kabul edilir." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "İşlem onaylandıktan sonra WESTlar Waves adresinize geçit tarafından gönderilir.", "helpDescrTitle": "Bu adresi WEST cüzdanına ya da uygulamasına giriniz.", @@ -999,5 +1005,8 @@ "byte": { "help": "Byte kaldı: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/zh_CN/app.dex.json b/locale/zh_CN/app.dex.json index 3e7bddf2f..3ee464b99 100644 --- a/locale/zh_CN/app.dex.json +++ b/locale/zh_CN/app.dex.json @@ -47,7 +47,7 @@ "last": "最新交易价", "limit": "限价单", "market": "市场订单", - "marketPriceField": "Price", + "marketPriceField": "价格", "matcherFee": "费用", "notifications": { "error": { @@ -76,7 +76,7 @@ "total": "总额" }, "createorder": { - "yourBalance": "Your balance" + "yourBalance": "您的余额" }, "demo": { "createAccount": "创建新账户", @@ -200,6 +200,7 @@ "noMarkets": "没有符合您的筛选的市场" }, "price": "价格", + "vol": "Vol", "volume": "量" } }, diff --git a/locale/zh_CN/app.utils.json b/locale/zh_CN/app.utils.json index ce6ac8aad..6e2c57e95 100644 --- a/locale/zh_CN/app.utils.json +++ b/locale/zh_CN/app.utils.json @@ -279,7 +279,7 @@ "warningTitle": "请不要从智能合约中存入BNT!不要存入其他ERC20代币!只允许Bancor。" }, "wavesGatewayBTC": { - "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of BTC to a token in your Waves account.", + "helpDescrText": "确认交易后,网关将处理BTC到Waves帐户中令牌的转移。", "helpDescrTitle": "在您的BTC客户端或钱包中输入此地址", "warningMinAmountText": "如果您发送的费用低于{{minAmount, BigNumber}} {{assetTicker}},您将失去这笔钱。", "warningMinAmountTitle": "最低存款金额为{{minAmount,BigNumber}} {{assetTicker}} ,最高存款金额为{{maxAmount}} {{assetTicker}}", @@ -295,13 +295,19 @@ "warningTitle": "仅将ERGO发送至此存款地址" }, "wavesGatewayETH": { - "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of ETH to a token in your Waves account.", - "helpDescrTitle": "Enter this address into your ETH client or wallet", + "helpDescrText": "确认交易后,网关将处理ETH到Waves帐户中的代币的转账。", + "helpDescrTitle": "将此地址输入您的ETH客户或钱包", "warningMinAmountText": "如果你发送少于{{minAmount, BigNumber}} {{assetTicker}},你将失去这笔钱。", "warningMinAmountTitle": "最低存款金额为{{minAmount,BigNumber}} {{assetTicker}} ,最高存款金额为{{maxAmount}} {{assetTicker}}", "warningText": "检查您的钱包或交易所是否为收回ETH使用智能合约。我们不接受这种交易,也不能退款。您将会失去这笔钱。", "warningTitle": "请不要从智能合约中交存ETH!别交存ERC20代币!您只能交存以太坊Ethereum。" }, + "wavesGatewayUSDT": { + "warningMinAmountText": "如果您的汇款少于{{minAmount,BigNumber}} {{assetTicker}} ,您将损失这笔钱。", + "warningMinAmountTitle": "最低存款额为{{minAmount,BigNumber}} {{assetTicker}} ,最大存款额为{{maxAmount}} {{assetTicker}}", + "warningText": "检查您的钱包或交易所是否使用智能合约提取Tether USD。我们不接受此类交易,也无法退款。你会赔钱的", + "warningTitle": "这是ERC20 USDT的存款地址。仅将USDT发送到该存款地址。将任何其他硬币或令牌发送到此地址可能会导致您的押金丢失。请不要从智能合约中存入USDT!" + }, "wavesGatewayVST": { "helpDescrText": "确认交易后,网关将处理将WEST转移到Waves帐户中的代币。", "helpDescrTitle": "在您的WEST客户端或钱包中输入此地址", @@ -999,5 +1005,8 @@ "byte": { "help": "剩余字节:{{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/src/img/icons/time-filled.svg b/src/img/icons/time-filled.svg new file mode 100644 index 000000000..96b7c1897 --- /dev/null +++ b/src/img/icons/time-filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/index.hbs b/src/index.hbs index 9cee5a8bd..95e93d846 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -522,7 +522,7 @@
-
+
diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index b050b6a8e..cf512d156 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -1,4 +1,4 @@ -
+
{{$ctrl.days}} @@ -14,8 +14,8 @@
-
+
-
+
diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less index 8e3db5837..ed3ef4b3e 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less @@ -1,21 +1,101 @@ +@import (reference) 'config'; +@import (reference) "icons"; + w-warning-plate { .warning-plate { &-content { display: flex; flex-direction: row; + background: @color-warning-600; + height: 40px; + justify-content: center; + color: #fff; + font-size: 15px; + line-height: 20px; + padding: 9px; } &-button { cursor: pointer; border-radius: 4px; background-color: #fff; - color: #f89300; + color: @color-warning-600; + padding: 5px; + font-size: 11px; + display: flex; + justify-content: center; + align-items: center; + line-height: 13px; + width: 82px; + height: 22px; + } + + &-text { + margin: 0 15px 0 20px; } &-timer { display: flex; flex-direction: row; + padding-left: 20px; + position: relative; + align-items: center; + height: 22px; + font-family: @font-roboto-medium; + + &::before { + content: ""; + display: block; + height: 14px; + width: 14px; + position: absolute; + top: 4px; + left: 0; + background: @timer-icon; + } } } } + +.warning-timer { + position: relative; + z-index: 11; + &+ .ui-view { + height: calc(100% ~"- 40px"); + } +} + +@media screen and (max-width: 860px) { + w-warning-plate { + .warning-plate { + &-content { + height: 56px; + justify-content: space-between; + padding: 10px 12px; + flex-wrap: wrap; + transition: all .2s; + } + + &-text { + text-align: left; + margin-right: 0; + font-size: 13px; + order: 3; + width: 100%; + } + } + } + + .menu-is-shown { + .warning-plate-content { + transform: translateX(-261px); + } + } + + .warning-timer { + &+ .ui-view { + height: calc(100% ~"- 56px"); + } + } +} \ No newline at end of file diff --git a/src/modules/dex/directives/layout/less/dex-layout__column_createorder.less b/src/modules/dex/directives/layout/less/dex-layout__column_createorder.less index eeb7ca7db..fd28b2fcb 100644 --- a/src/modules/dex/directives/layout/less/dex-layout__column_createorder.less +++ b/src/modules/dex/directives/layout/less/dex-layout__column_createorder.less @@ -102,7 +102,7 @@ } &.expanded { - z-index: 7; + z-index: 10; height: calc(100% ~'+ 10px'); top: -5px; diff --git a/src/modules/dex/less/dex.less b/src/modules/dex/less/dex.less index 7ee05d585..e4e1216fc 100644 --- a/src/modules/dex/less/dex.less +++ b/src/modules/dex/less/dex.less @@ -10,7 +10,7 @@ body.dex-demo { color: @color-basic-900; .main-content { - min-height: 520px; + min-height: 466px; .content { max-width: 100%; @@ -262,46 +262,6 @@ body.dex-demo { border: 0 none; border-bottom: 1px solid @color-submit-400; - // .tabs { - // .smart-table { - // &__w-tbody { - // .smart-table { - // &__row { - // position: relative; - - // &:hover { - // .underline:after { - // display: none; - // } - // } - - // .status-mobile { - // display: inline-block; - // } - - // &.active { - // .dropdown { - // transform: rotate(180deg); - // } - - // & + .active::before { - // background: @color-basic-100; - // height: 1px; - // width: calc(100% ~'- 20px'); - // position: absolute; - // top: 0; - // left: 10px; - // display: block; - // content: ''; - // } - // } - // } - // } - // } - - // &__cell { - // padding: 0; - &::after, &::before { display: none; @@ -359,58 +319,6 @@ body.dex-demo { width: 100%; overflow-y: auto; overflow-x: hidden; - - // .dex-layout { - // &__tradehistory { - - // w-dex-my-balance { - // .smart-table { - // &__w-tbody { - // max-height: 217px; - // } - // } - // } - - // .tabs__body .tab-tem { - // padding: 0; - // } - - // w-dex-trade-history { - // .smart-table { - // &__w-tbody { - // max-height: 243px; - // } - - // &.my-trade-history { - // .smart-table { - // &__w-tbody { - // max-height: 255px; - // } - // } - // } - // } - // } - - // w-dex-my-orders { - // .smart-table { - // &__w-tbody { - // max-height: 254px; - // } - // } - // } - - // } - // } - - // .dex-wrapper { - // .tabs { - // w-scroll-box { - // height: 392px; - // width: 100%; - // overflow-y: auto; - // overflow-x: hidden; - // } - // } } } } diff --git a/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less b/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less index 0b6729cf6..d89241a3a 100644 --- a/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less +++ b/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less @@ -95,6 +95,7 @@ & + .main-header { &__header { position: fixed; + top: 40px; } } } @@ -164,7 +165,7 @@ position: fixed; z-index: 10; width: 100%; - top: 0; + top: 40px; left: 0; .main-header__header::after { @@ -174,6 +175,7 @@ &.fixed .main-header__header { position: fixed; + top: 40px; &::after { opacity: 1; diff --git a/src/themeConfig/black/icons.less b/src/themeConfig/black/icons.less index 58d2ba93d..ed1ad6d2b 100644 --- a/src/themeConfig/black/icons.less +++ b/src/themeConfig/black/icons.less @@ -155,3 +155,4 @@ @importBackupFile-icon: url(/img/icons/keystore-file.svg); @importBackupPassword-icon: url(/img/icons/backup-password.svg); @importKeyStore-file-icon: url(/img/icons/dark/import-keystore-file-dark.svg); +@timer-icon: url(/img/icons/time-filled.svg); diff --git a/src/themeConfig/default/icons.less b/src/themeConfig/default/icons.less index 6c638bd51..f7016a39c 100644 --- a/src/themeConfig/default/icons.less +++ b/src/themeConfig/default/icons.less @@ -154,4 +154,5 @@ @dex-screenshot: url(/img/landing/dex-screenshot.png); @importBackupFile-icon: url(/img/icons/keystore-file.svg); @importBackupPassword-icon: url(/img/icons/backup-password.svg); -@importKeyStore-file-icon: url(/img/icons/import-keystore-file.svg); \ No newline at end of file +@importKeyStore-file-icon: url(/img/icons/import-keystore-file.svg); +@timer-icon: url(/img/icons/time-filled.svg); \ No newline at end of file From 6d9dc584afaf682237f07165e190be6a66780be6 Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Thu, 7 Nov 2019 11:30:59 +0300 Subject: [PATCH 024/144] DEXW-2282: some fix --- .../componentWarningPlate.html | 18 +++++++++--------- .../componentWarningPlate.less | 19 +++++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index cf512d156..38c475fd9 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -1,21 +1,21 @@ -
-
+
+
- {{$ctrl.days}} - d: + {{$ctrl.days}} + d :
- {{$ctrl.hours}} - h: + {{$ctrl.hours}} + h :
- {{$ctrl.minutes}} + {{$ctrl.minutes}} m
-
+
-
+
diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less index ed3ef4b3e..ca3a476ee 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less @@ -3,8 +3,7 @@ w-warning-plate { .warning-plate { - - &-content { + &__content { display: flex; flex-direction: row; background: @color-warning-600; @@ -16,7 +15,7 @@ w-warning-plate { padding: 9px; } - &-button { + &__button { cursor: pointer; border-radius: 4px; background-color: #fff; @@ -31,11 +30,11 @@ w-warning-plate { height: 22px; } - &-text { + &__text { margin: 0 15px 0 20px; } - &-timer { + &__timer { display: flex; flex-direction: row; padding-left: 20px; @@ -54,6 +53,10 @@ w-warning-plate { left: 0; background: @timer-icon; } + + &-value { + margin-left: 3px; + } } } } @@ -69,7 +72,7 @@ w-warning-plate { @media screen and (max-width: 860px) { w-warning-plate { .warning-plate { - &-content { + &__content { height: 56px; justify-content: space-between; padding: 10px 12px; @@ -77,7 +80,7 @@ w-warning-plate { transition: all .2s; } - &-text { + &__text { text-align: left; margin-right: 0; font-size: 13px; @@ -88,7 +91,7 @@ w-warning-plate { } .menu-is-shown { - .warning-plate-content { + .warning-plate__content { transform: translateX(-261px); } } From 3ce88b470e53ba3502a133a6569a339704a3480a Mon Sep 17 00:00:00 2001 From: finico Date: Thu, 7 Nov 2019 14:50:01 +0300 Subject: [PATCH 025/144] DEXW-2225: Add info about successful migration --- src/modules/utils/modals/migrateModal/migrateModal.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 2023d60d1..ddff18664 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -10,8 +10,9 @@ * @param {ng.ILogService} $log * @param {*} $mdDialog * @param {*} storageExporter + * @param {*} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter) { + const controller = function (Base, $log, $mdDialog, storageExporter, storage) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -47,8 +48,12 @@ }).then((result) => { if (result.payload === 'ok') { $log.log('done'); + + return storage.save('migrationSuccess', true); } else { $log.log('fail', result); + + return storage.save('migrationSuccess', false); } }).catch((e) => { $log.error(e); @@ -85,7 +90,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', 'storage']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 433386428bc5d6d14a5b6e5e09e172613931fe90 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Thu, 7 Nov 2019 16:43:51 +0300 Subject: [PATCH 026/144] DEXW-2282: refactor timer --- .../componentWarningPlate/ComponentWarningPlate.js | 2 +- src/modules/utils/services/utils.js | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index 2bc1a616d..2af64223e 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -24,7 +24,7 @@ minutes = 0; constructor() { - utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this)); + utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); } showMovingModal() { diff --git a/src/modules/utils/services/utils.js b/src/modules/utils/services/utils.js index 78d841cc0..b6c757613 100644 --- a/src/modules/utils/services/utils.js +++ b/src/modules/utils/services/utils.js @@ -1984,12 +1984,17 @@ /** * @param {TTimerOptions} options * @param cb + * @param {number} timeout */ - startTimer(options, cb) { + startTimer(options, cb, timeout) { const getLastTime = _time.bind(null, options); let lastTime = {}; + let timer; function loop() { + if (timer) { + clearTimeout(timer); + } const currentTime = getLastTime(); if (lastTime.minutes !== currentTime.minutes || lastTime.seconds !== currentTime.seconds) { cb(currentTime); @@ -1997,7 +2002,7 @@ } if ((currentTime.seconds + currentTime.hours + currentTime.minutes + currentTime.days) > 0) { - requestAnimationFrame(loop); + timer = setTimeout(loop, timeout); } } From 5b0d0b5ba80043b7cad800dff3bd92db00bc8a6f Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Thu, 7 Nov 2019 18:09:45 +0300 Subject: [PATCH 027/144] DEXW-2282: migrate modal add steps --- .../modals/migrateModal/migrateModal.html | 20 ++++++++++++++++--- .../utils/modals/migrateModal/migrateModal.js | 15 ++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html index 760c29e41..00c2c5a8a 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.html +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -1,5 +1,19 @@
- - Export - +
+ + + + + Cancel + + + Start moving + + + + + You have been redirected to waves.exchange + + +
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 2023d60d1..b5790fce7 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -11,11 +11,16 @@ * @param {*} $mdDialog * @param {*} storageExporter */ - const controller = function (Base, $log, $mdDialog, storageExporter) { + const controller = function (Base, $log, $mdDialog, storageExporter, $scope) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { + /** + * @type {number} + */ + step = 0; + export() { const connectProvider = this._getConnectProvider(); const message = JSON.stringify({ event: 'connect' }); @@ -47,6 +52,8 @@ }).then((result) => { if (result.payload === 'ok') { $log.log('done'); + this.step++; + $scope.$apply(); } else { $log.log('fail', result); } @@ -55,6 +62,10 @@ }); } + cancel() { + $mdDialog.cancel(); + } + /** * @returns {ConnectProvider} */ @@ -85,7 +96,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 5c7c0a137699be9852bca3fe05a0bb73e4a7e732 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Thu, 7 Nov 2019 19:08:20 +0300 Subject: [PATCH 028/144] DEXW-2282: add migrateModal auto open logic --- src/modules/app/initialize/AppRun.js | 16 ++++++++++++++++ src/modules/signIn/controllers/SignInCtrl.js | 13 +++++++++++-- .../utils/modals/migrateModal/migrateModal.html | 2 +- .../utils/modals/migrateModal/migrateModal.js | 6 ++++-- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 0274145b2..5645f24d1 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -152,6 +152,7 @@ this._stopLoader(); this._initializeLogin(); this._initializeOutLinks(); + this._openMigrationModal(); if (WavesApp.isDesktop()) { window.listenMainProcessEvent((type, url) => { @@ -728,6 +729,21 @@ }); } + /** + * @private + */ + _openMigrationModal() { + Promise.all([ + user.getMultiAccountData(), + user.getFilteredUserList(), + storage.load('notAutoOpenMigrationModal') + ]).then(([multiAccountData, userList, notAutoOpenMigrationModal]) => { + if (!notAutoOpenMigrationModal && !multiAccountData && userList && userList.length) { + modalManager.showMigrateModal(); + } + }); + } + /** * @private */ diff --git a/src/modules/signIn/controllers/SignInCtrl.js b/src/modules/signIn/controllers/SignInCtrl.js index 22a8e4eb3..d051e2f48 100644 --- a/src/modules/signIn/controllers/SignInCtrl.js +++ b/src/modules/signIn/controllers/SignInCtrl.js @@ -10,9 +10,10 @@ * @param {User} user * @param {ModalManager} modalManager * @param {ConfigService} configService + * @param {Storage} storage * @returns {SignInCtrl} */ - const controller = function (Base, $scope, $state, user, modalManager, configService) { + const controller = function (Base, $scope, $state, user, modalManager, configService, storage) { class SignInCtrl extends Base { @@ -36,6 +37,14 @@ this.legacyUserList = userList; } }); + + user.onLogin().then(() => { + storage.load('notAutoOpenMigrationModal').then((notAutoOpenMigrationModal) => { + if (!notAutoOpenMigrationModal) { + modalManager.showMigrateModal(); + } + }); + }); } onLogin() { @@ -99,7 +108,7 @@ return new SignInCtrl(); }; - controller.$inject = ['Base', '$scope', '$state', 'user', 'modalManager', 'configService']; + controller.$inject = ['Base', '$scope', '$state', 'user', 'modalManager', 'configService', 'storage']; angular.module('app.signIn').controller('SignInCtrl', controller); })(); diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html index 00c2c5a8a..66b34ee98 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.html +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -1,5 +1,5 @@
-
+
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index b5790fce7..51afd36b0 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -10,8 +10,9 @@ * @param {ng.ILogService} $log * @param {*} $mdDialog * @param {*} storageExporter + * @param {Storage} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter, $scope) { + const controller = function (Base, $log, $mdDialog, storageExporter, $scope, storage) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -64,6 +65,7 @@ cancel() { $mdDialog.cancel(); + storage.save('notAutoOpenMigrationModal', true); } /** @@ -96,7 +98,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope', 'storage']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From b6503fccfda7c1432b32f13e850671d97128f454 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 8 Nov 2019 10:38:13 +0300 Subject: [PATCH 029/144] DEXW-2282: delete try desctop modal --- src/modules/app/initialize/AppRun.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 5645f24d1..e6bd14a45 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -205,9 +205,10 @@ case 'web': return Promise.resolve(true); default: - return modalManager.showTryDesktopModal() - .then(() => this._runDesktop()) - .catch(() => true); + return Promise.resolve(true); + // return modalManager.showTryDesktopModal() + // .then(() => this._runDesktop()) + // .catch(() => true); } }); } From 25c44d1515f37fce2ae939116dffd19924ae3ab3 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 8 Nov 2019 11:37:41 +0300 Subject: [PATCH 030/144] DEXW-2282: add warning plate logic --- .../ComponentWarningPlate.js | 56 ++++++++++++++++++- .../componentWarningPlate.html | 6 +- .../componentWarningPlate.less | 10 +++- .../utils/modals/migrateModal/migrateModal.js | 3 + src/modules/utils/services/Storage.js | 7 +++ 5 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index 2af64223e..669fdf5e7 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -2,11 +2,14 @@ 'use strict'; /** + * @param {*} $scope * @param {ModalManager} modalManager * @param {app.utils} utils + * @param {User} user + * @param {Storage} storage * @return {ComponentWarningPlate} */ - const controller = function (modalManager, utils) { + const controller = function ($scope, modalManager, utils, user, storage) { class ComponentWarningPlate { @@ -22,8 +25,21 @@ * @type {number} */ minutes = 0; + /** + * @type {boolean} + */ + hasAccounts = false; + /** + * @type {boolean} + */ + migrationSuccess = false; constructor() { + this._initHasAccounts(); + this._initMigrationSuccess(); + + storage.change.on(this._initMigrationSuccess, this); + utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); } @@ -31,23 +47,59 @@ modalManager.showMigrateModal(); } + /** + * @param last + * @private + */ _setTime(last) { this.days = this._to2Digest(last.days); this.hours = this._to2Digest(last.hours); this.minutes = this._to2Digest(last.minutes); } + /** + * @param num + * @return {string} + * @private + */ _to2Digest(num) { return num < 10 ? `0${num}` : String(num); } + /** + * @private + */ + _initHasAccounts() { + Promise.all([ + user.getFilteredUserList(), + user.getMultiAccountData() + ]).then(([userList, multiAccountData]) => { + if (multiAccountData || (userList && userList.length)) { + this.hasAccounts = true; + } else { + this.hasAccounts = false; + } + $scope.$apply(); + }); + } + + /** + * @private + */ + _initMigrationSuccess() { + storage.load('migrationSuccess').then((migrationSuccess) => { + this.migrationSuccess = migrationSuccess; + $scope.$apply(); + }); + } + } return new ComponentWarningPlate(); }; - controller.$inject = ['modalManager', 'utils']; + controller.$inject = ['$scope', 'modalManager', 'utils', 'user', 'storage']; angular.module('app').component('wWarningPlate', { templateUrl: 'modules/app/directives/componentWarningPlate/componentWarningPlate.html', diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index 38c475fd9..caa56ee4e 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -1,4 +1,5 @@ -
+
{{$ctrl.days}} @@ -16,6 +17,7 @@
-
+
diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less index ca3a476ee..726e5b3ac 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less @@ -13,6 +13,10 @@ w-warning-plate { font-size: 15px; line-height: 20px; padding: 9px; + + &.info { + background: @color-submit-300; + } } &__button { @@ -28,6 +32,10 @@ w-warning-plate { line-height: 13px; width: 82px; height: 22px; + + &.info { + color: @color-submit-300; + } } &__text { @@ -101,4 +109,4 @@ w-warning-plate { height: calc(100% ~"- 56px"); } } -} \ No newline at end of file +} diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 8deee2717..f6d21bd8f 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -53,6 +53,7 @@ }).then((result) => { if (result.payload === 'ok') { $log.log('done'); + this.step++; $scope.$apply(); @@ -62,6 +63,8 @@ return storage.save('migrationSuccess', false); } + }).then(() => { + storage.change.dispatch('migrationSuccess'); }).catch((e) => { $log.error(e); }); diff --git a/src/modules/utils/services/Storage.js b/src/modules/utils/services/Storage.js index 699f46a12..db8c20e0c 100644 --- a/src/modules/utils/services/Storage.js +++ b/src/modules/utils/services/Storage.js @@ -31,6 +31,8 @@ '1.4.6': storage => fixMigrateCommonSettings(storage) }; + const { Signal } = require('ts-utils'); + function newTerms(storage) { return storage.load('userList').then(users => { const needShowNewTerms = (users || []).some((user) => { @@ -206,6 +208,11 @@ class Storage { + /** + * @type {Signal} + */ + change = new Signal(); + constructor() { usedStorage.init(); this._isNewDefer = $q.defer(); From 1d4c27d73656c58ff7acecbe7ffe07319fa8564f Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Fri, 8 Nov 2019 11:39:49 +0300 Subject: [PATCH 031/144] DEXW-2282: modal migration --- src/img/icons/Closed-Dark.svg | 23 ++++++++++ src/img/icons/directed-icon-dark.svg | 23 ++++++++++ src/img/icons/directed-icon.svg | 17 ++++++++ src/img/icons/moving-dark.svg | 25 +++++++++++ src/img/icons/moving.svg | 20 +++++++++ .../modals/migrateModal/migrateModal.html | 32 ++++++++++---- .../modals/migrateModal/migrateModal.less | 42 +++++++++++++++++++ src/themeConfig/black/icons.less | 2 + src/themeConfig/default/icons.less | 4 +- 9 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 src/img/icons/Closed-Dark.svg create mode 100644 src/img/icons/directed-icon-dark.svg create mode 100644 src/img/icons/directed-icon.svg create mode 100644 src/img/icons/moving-dark.svg create mode 100644 src/img/icons/moving.svg create mode 100644 src/modules/utils/modals/migrateModal/migrateModal.less diff --git a/src/img/icons/Closed-Dark.svg b/src/img/icons/Closed-Dark.svg new file mode 100644 index 000000000..4c1b29397 --- /dev/null +++ b/src/img/icons/Closed-Dark.svg @@ -0,0 +1,23 @@ + + + + Icons/100/Closed-Dark + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/img/icons/directed-icon-dark.svg b/src/img/icons/directed-icon-dark.svg new file mode 100644 index 000000000..c002e0e68 --- /dev/null +++ b/src/img/icons/directed-icon-dark.svg @@ -0,0 +1,23 @@ + + + + Icons/100/NewTab-Dark + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/img/icons/directed-icon.svg b/src/img/icons/directed-icon.svg new file mode 100644 index 000000000..df50aa3dc --- /dev/null +++ b/src/img/icons/directed-icon.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/img/icons/moving-dark.svg b/src/img/icons/moving-dark.svg new file mode 100644 index 000000000..8d3ac38e2 --- /dev/null +++ b/src/img/icons/moving-dark.svg @@ -0,0 +1,25 @@ + + + + Style/Icons/Other/90/Moving-Dark + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/img/icons/moving.svg b/src/img/icons/moving.svg new file mode 100644 index 000000000..77a1fcf0d --- /dev/null +++ b/src/img/icons/moving.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html index 00c2c5a8a..eb5d717be 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.html +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -1,19 +1,33 @@ -
+
- - Cancel - - - Start moving - +
+

We are moving

+
+

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Iusto tempore ea hic quam quidem reprehenderit dolorum dolore maiores, quaerat, delectus excepturi aut, eligendi laborum. Aspernatur repellat dolorum atque dolore ipsa.

+

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

+
+
+ + Cancel + + + Start moving + +
- You have been redirected to waves.exchange +
+

You have been redirected to + waves.exchange +

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+
-
+
\ No newline at end of file diff --git a/src/modules/utils/modals/migrateModal/migrateModal.less b/src/modules/utils/modals/migrateModal/migrateModal.less new file mode 100644 index 000000000..b88cc307c --- /dev/null +++ b/src/modules/utils/modals/migrateModal/migrateModal.less @@ -0,0 +1,42 @@ +@import (reference) 'config'; +@import (reference) "icons"; + +.migrate-modal { + &__image { + background-size: 100% 100%; + margin: 62px auto 20px; + + &_moving { + background: @moving-icon; + width: 90px; + height: 90px; + } + + &_directed { + background: @directed-icon; + width: 100px; + height: 100px; + } + } + + &__title { + text-align: center; + font-family: @font-roboto-medium; + color: @color-basic-700; + } + + &__text { + color: @color-basic-500; + margin-bottom: 30px; + + &_directed { + text-align: center; + padding: 0 10px; + } + } + + &__link { + text-align: center; + display: block; + } +} \ No newline at end of file diff --git a/src/themeConfig/black/icons.less b/src/themeConfig/black/icons.less index ed1ad6d2b..bca2e1505 100644 --- a/src/themeConfig/black/icons.less +++ b/src/themeConfig/black/icons.less @@ -156,3 +156,5 @@ @importBackupPassword-icon: url(/img/icons/backup-password.svg); @importKeyStore-file-icon: url(/img/icons/dark/import-keystore-file-dark.svg); @timer-icon: url(/img/icons/time-filled.svg); +@moving-icon: url(/img/icons/moving-dark.svg); +@directed-icon: url(/img/icons/directed-icon-dark.svg); \ No newline at end of file diff --git a/src/themeConfig/default/icons.less b/src/themeConfig/default/icons.less index f7016a39c..af588f559 100644 --- a/src/themeConfig/default/icons.less +++ b/src/themeConfig/default/icons.less @@ -155,4 +155,6 @@ @importBackupFile-icon: url(/img/icons/keystore-file.svg); @importBackupPassword-icon: url(/img/icons/backup-password.svg); @importKeyStore-file-icon: url(/img/icons/import-keystore-file.svg); -@timer-icon: url(/img/icons/time-filled.svg); \ No newline at end of file +@timer-icon: url(/img/icons/time-filled.svg); +@moving-icon: url(/img/icons/moving.svg); +@directed-icon: url(/img/icons/directed-icon.svg); \ No newline at end of file From 8094bc4fbc7fedac3eb4bf729510bf98cf0ca2fc Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 8 Nov 2019 11:41:02 +0300 Subject: [PATCH 032/144] DEXW-2282: warning plate switch text --- .../componentWarningPlate/componentWarningPlate.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index caa56ee4e..2eb0b59cb 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -15,7 +15,8 @@
-
+
+
From 4effac03495f8c3acef5bb5f65a1f5074b0570a7 Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Fri, 8 Nov 2019 12:24:06 +0300 Subject: [PATCH 033/144] DEXW-2282: change link --- src/modules/utils/modals/migrateModal/migrateModal.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html index edf13012c..f1d8a61fc 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.html +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -22,7 +22,8 @@

We are moving

You have been redirected to - waves.exchange + waves.exchange

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

From 1c6abdc2692608ae9d64693fdae9b51eeb55f3d8 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 8 Nov 2019 12:59:01 +0300 Subject: [PATCH 034/144] DEXW-2282: add warning plate dexw-2294 logic --- configs/mainnet.json | 3 ++- configs/stagenet.json | 3 ++- configs/testnet.json | 3 ++- src/index.hbs | 3 ++- .../ComponentWarningPlate.js | 5 +++++ .../componentWarningPlate.html | 22 +++++++++++++++++++ 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/configs/mainnet.json b/configs/mainnet.json index 8d20eb754..11dca9fd1 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -60,5 +60,6 @@ { "ticker": "DASH", "id": "B3uGHFRpSUuGEDWjqB9LWWxafQj8VTvpMucEyoxzws5H"}, { "ticker": "Monero", "id": "5WvPKSJXzVE2orvbkJ8wsQmmQKqTv9sGBPksV4adViw3"}, { "ticker": "ZEC", "id": "BrjUWjndUanm5VsJkbUip8VRYy6LWJePtxya3FNv4TQa"} - ] + ], + "wavesExchangeLink": "https://waves.exchange" } diff --git a/configs/stagenet.json b/configs/stagenet.json index bf4e295c3..23244c0c0 100644 --- a/configs/stagenet.json +++ b/configs/stagenet.json @@ -53,5 +53,6 @@ { "ticker": "USD", "id": "HETgTyfn5grcHWGRKHi7p3hvMB4QxWVrPD8Fnfi9tfD9"}, { "ticker": "EUR", "id": "EqZfxiqYKkByP42hqNsvuPdXxVYMHaQDwfKgFnAz5D1x"}, { "ticker": "CNY", "id": "8CfhN5MmaiAW1kCG5tDXasVTSafJP8cf6TZqbPRkNGxQ"} - ] + ], + "wavesExchangeLink": "https://waves.exchange" } diff --git a/configs/testnet.json b/configs/testnet.json index 9934a4729..34d09da19 100644 --- a/configs/testnet.json +++ b/configs/testnet.json @@ -53,5 +53,6 @@ { "ticker": "USD", "id": "HyFJ3rrq5m7FxdkWtQXkZrDat1F7LjVVGfpSkUuEXQHj"}, { "ticker": "EUR", "id": "2xnE3EdpqXtFgCP156qt1AbyjpqdZ5jGjWo3CwTawcux"}, { "ticker": "CNY", "id": "6pmDivReTLikwYqQtJTv6dTcE59knriaodB3AK8T9cF8"} - ] + ], + "wavesExchangeLink": "https://waves.exchange" } diff --git a/src/index.hbs b/src/index.hbs index 95e93d846..4a0eb3e1d 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -350,7 +350,8 @@ feeConfigUrl: config.feeConfigUrl, tokenrating: config.network.tokenrating, featuresConfig: config.network.featuresConfig, - feeConfig: config.network.feeConfig + feeConfig: config.network.feeConfig, + wavesExchangeLink: config.network.wavesExchangeLink }, defaultAssets: { WAVES: 'WAVES', diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index 669fdf5e7..f62aef422 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -33,11 +33,16 @@ * @type {boolean} */ migrationSuccess = false; + /** + * @type {string} + */ + newDexLink = WavesApp.network.wavesExchangeLink; constructor() { this._initHasAccounts(); this._initMigrationSuccess(); + user.loginSignal.on(this._initHasAccounts, this); storage.change.on(this._initMigrationSuccess, this); utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index 2eb0b59cb..00bfdaae5 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -22,3 +22,25 @@ w-i18n="warningPlate.startMoving">
+
+
+
+ {{$ctrl.days}} + d : +
+
+ {{$ctrl.hours}} + h : +
+
+ {{$ctrl.minutes}} + m +
+
+ +
+ + +
+ From 13e5eb8de5499a7ea7ae9f3df99956a4bf0b7f66 Mon Sep 17 00:00:00 2001 From: ekomarovskaya Date: Fri, 8 Nov 2019 14:03:51 +0300 Subject: [PATCH 035/144] DEXW-2314: add-toaster --- src/img/icons/close-tokenomica.svg | 4 + src/img/icons/logotype.svg | 15 ++ src/modules/ui/directives/footer/footer.html | 18 +++ .../ui/directives/footer/toaster-mobiles.less | 128 +++++++++++++++++- .../directives/footer/toaster-tokenomica.less | 127 +++++++++++++++++ src/themeConfig/black/icons.less | 3 + src/themeConfig/default/icons.less | 5 +- 7 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 src/img/icons/close-tokenomica.svg create mode 100644 src/img/icons/logotype.svg create mode 100644 src/modules/ui/directives/footer/toaster-tokenomica.less diff --git a/src/img/icons/close-tokenomica.svg b/src/img/icons/close-tokenomica.svg new file mode 100644 index 000000000..2691e52ac --- /dev/null +++ b/src/img/icons/close-tokenomica.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/img/icons/logotype.svg b/src/img/icons/logotype.svg new file mode 100644 index 000000000..83c61c7e3 --- /dev/null +++ b/src/img/icons/logotype.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/modules/ui/directives/footer/footer.html b/src/modules/ui/directives/footer/footer.html index f3bd1347a..5a70bdeb4 100644 --- a/src/modules/ui/directives/footer/footer.html +++ b/src/modules/ui/directives/footer/footer.html @@ -113,4 +113,22 @@
+ + + diff --git a/src/modules/ui/directives/footer/toaster-mobiles.less b/src/modules/ui/directives/footer/toaster-mobiles.less index 2aba44640..8bda3a8c3 100644 --- a/src/modules/ui/directives/footer/toaster-mobiles.less +++ b/src/modules/ui/directives/footer/toaster-mobiles.less @@ -59,7 +59,7 @@ } } } - + &.hidden-toaster { transform: translateY(100%); } @@ -67,4 +67,128 @@ @media screen and (max-width: 768px) { display: flex; } -} \ No newline at end of file +} + +.toaster-tokenomica { + display: flex; + position: fixed; + bottom: 0; + left: 0; + justify-content: space-between; + background: @color-black; + padding: 25px 32px; + width: 100%; + z-index: 5; + transform: translateY(0); + transition: transform 0.2s; + + &__link { + display: flex; + flex: 1 0; + justify-content: space-between; + align-items: center; + } + + &__logo { + background: @logo-tokenomica-icon center no-repeat; + background-size: 100%; + width: 184px; + height: 40px; + flex-shrink: 0; + margin-right: 16px; + } + + &__text { + font-size: 20px; + color: @color-white; + line-height: 18px; + } + + &__text-wrapper { + display: flex; + flex: 1 0; + justify-content: space-between; + align-items: center; + margin-left: 80px; + } + + &__button { + button { + border-radius: 0; + } + + .button__content { + font-size: 20px; + font-weight: bold; + } + } + + &__close { + display: flex; + align-items: center; + margin-left: 36px; + + &-icon { + background: @close-tokenomica-icon center no-repeat; + border: 0; + width: 16px; + height: 16px; + + &:hover { + opacity: .5; + } + } + } + + &.hidden-toaster { + transform: translateY(100%); + } + + @media screen and (max-width: 768px) { + display: flex; + padding: 24px; + border-radius: 16px 16px 0 0; + align-items: flex-start; + + &__link { + flex-direction: column; + align-items: flex-start; + } + + &__logo { + margin: 0 0 16px 0; + width: 109px; + height: 24px; + } + + &__text-wrapper { + flex-direction: column; + align-items: flex-start; + width: 100%; + margin-left: 0; + } + + &__text { + font-size: 14px; + margin: 0 0 16px 0; + line-height: 20px; + width: 100%; + } + + &__button { + width: 100%; + + .button { + width: 100%; + } + + .button__content { + font-size: 16px; + } + } + + &__close { + margin: -6px; + } + } +} diff --git a/src/modules/ui/directives/footer/toaster-tokenomica.less b/src/modules/ui/directives/footer/toaster-tokenomica.less new file mode 100644 index 000000000..1e616b51d --- /dev/null +++ b/src/modules/ui/directives/footer/toaster-tokenomica.less @@ -0,0 +1,127 @@ +@import (reference) 'config'; +@import (reference) 'icons'; +@import (reference) '../../../app/less/typography'; + +.toaster-tokenomica { + display: flex; + position: fixed; + bottom: 0; + left: 0; + justify-content: space-between; + background: @color-black; + padding: 25px 32px; + width: 100%; + z-index: 5; + transform: translateY(0); + transition: transform 0.2s; + + &__link { + display: flex; + flex: 1 0; + justify-content: space-between; + align-items: center; + } + + &__logo { + background: @logo-tokenomica-icon center no-repeat; + background-size: 100%; + width: 184px; + height: 40px; + flex-shrink: 0; + margin-right: 16px; + } + + &__text { + font-size: 20px; + color: @color-white; + line-height: 18px; + } + + &__text-wrapper { + display: flex; + flex: 1 0; + justify-content: space-between; + align-items: center; + margin-left: 80px; + } + + &__button { + button { + border-radius: 0; + } + + .button__content { + font-size: 20px; + font-weight: bold; + } + } + + &__close { + display: flex; + align-items: center; + margin-left: 36px; + + &-icon { + background: @close-tokenomica-icon center no-repeat; + border: 0; + width: 16px; + height: 16px; + + &:hover { + opacity: .5; + } + } + } + + &.hidden-toaster { + transform: translateY(100%); + } + + @media screen and (max-width: 768px) { + display: flex; + padding: 24px; + border-radius: 16px 16px 0 0; + align-items: flex-start; + + &__link { + flex-direction: column; + align-items: flex-start; + } + + &__logo { + margin: 0 0 16px 0; + width: 109px; + height: 24px; + } + + &__text-wrapper { + flex-direction: column; + align-items: flex-start; + width: 100%; + margin-left: 0; + } + + &__text { + font-size: 14px; + margin: 0 0 16px 0; + line-height: 20px; + width: 100%; + } + + &__button { + width: 100%; + + .button { + width: 100%; + } + + .button__content { + font-size: 16px; + } + } + + &__close { + margin: -6px; + } + } +} diff --git a/src/themeConfig/black/icons.less b/src/themeConfig/black/icons.less index 58d2ba93d..9f1e8ac76 100644 --- a/src/themeConfig/black/icons.less +++ b/src/themeConfig/black/icons.less @@ -155,3 +155,6 @@ @importBackupFile-icon: url(/img/icons/keystore-file.svg); @importBackupPassword-icon: url(/img/icons/backup-password.svg); @importKeyStore-file-icon: url(/img/icons/dark/import-keystore-file-dark.svg); + +@close-tokenomica-icon: url(/img/icons/close-tokenomica.svg); +@logo-tokenomica-icon: url(/img/icons/logotype.svg); diff --git a/src/themeConfig/default/icons.less b/src/themeConfig/default/icons.less index 6c638bd51..9cebab144 100644 --- a/src/themeConfig/default/icons.less +++ b/src/themeConfig/default/icons.less @@ -154,4 +154,7 @@ @dex-screenshot: url(/img/landing/dex-screenshot.png); @importBackupFile-icon: url(/img/icons/keystore-file.svg); @importBackupPassword-icon: url(/img/icons/backup-password.svg); -@importKeyStore-file-icon: url(/img/icons/import-keystore-file.svg); \ No newline at end of file +@importKeyStore-file-icon: url(/img/icons/import-keystore-file.svg); + +@close-tokenomica-icon: url(/img/icons/close-tokenomica.svg); +@logo-tokenomica-icon: url(/img/icons/logotype.svg); From 64fcaf031c8e21e2a5ea08be8b2a747f0f21297c Mon Sep 17 00:00:00 2001 From: ekomarovskaya Date: Fri, 8 Nov 2019 14:23:58 +0300 Subject: [PATCH 036/144] DEXW-2314: add locale --- locale/de/app.dex.json | 1 + locale/de/app.utils.json | 9 +++++++++ locale/de/app.welcome.json | 2 ++ locale/en/app.dex.json | 1 + locale/en/app.utils.json | 9 +++++++++ locale/en/app.welcome.json | 2 ++ locale/es/app.dex.json | 1 + locale/es/app.utils.json | 9 +++++++++ locale/es/app.welcome.json | 2 ++ locale/et_EE/app.dex.json | 1 + locale/et_EE/app.utils.json | 9 +++++++++ locale/et_EE/app.welcome.json | 2 ++ locale/fr/app.dex.json | 1 + locale/fr/app.utils.json | 9 +++++++++ locale/fr/app.welcome.json | 2 ++ locale/hi_IN/app.dex.json | 1 + locale/hi_IN/app.utils.json | 9 +++++++++ locale/hi_IN/app.welcome.json | 2 ++ locale/id/app.dex.json | 1 + locale/id/app.utils.json | 9 +++++++++ locale/id/app.welcome.json | 2 ++ locale/it/app.dex.json | 1 + locale/it/app.utils.json | 9 +++++++++ locale/it/app.welcome.json | 2 ++ locale/ja/app.dex.json | 1 + locale/ja/app.utils.json | 9 +++++++++ locale/ja/app.welcome.json | 2 ++ locale/ko/app.dex.json | 1 + locale/ko/app.utils.json | 9 +++++++++ locale/ko/app.welcome.json | 2 ++ locale/nl_NL/app.dex.json | 1 + locale/nl_NL/app.utils.json | 9 +++++++++ locale/nl_NL/app.welcome.json | 2 ++ locale/pl/app.dex.json | 1 + locale/pl/app.utils.json | 9 +++++++++ locale/pl/app.welcome.json | 2 ++ locale/pt_BR/app.dex.json | 1 + locale/pt_BR/app.utils.json | 9 +++++++++ locale/pt_BR/app.welcome.json | 2 ++ locale/pt_PT/app.dex.json | 1 + locale/pt_PT/app.utils.json | 9 +++++++++ locale/pt_PT/app.welcome.json | 2 ++ locale/ru/app.dex.json | 1 + locale/ru/app.utils.json | 9 +++++++++ locale/ru/app.welcome.json | 2 ++ locale/tr/app.dex.json | 1 + locale/tr/app.utils.json | 9 +++++++++ locale/tr/app.welcome.json | 2 ++ locale/zh_CN/app.dex.json | 5 +++-- locale/zh_CN/app.utils.json | 15 ++++++++++++--- locale/zh_CN/app.welcome.json | 2 ++ 51 files changed, 209 insertions(+), 5 deletions(-) diff --git a/locale/de/app.dex.json b/locale/de/app.dex.json index 14b69846b..52811f4b1 100644 --- a/locale/de/app.dex.json +++ b/locale/de/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Keine Märkte, die ihren Filtern entsprechen" }, "price": "Preis", + "vol": "Vol", "volume": "Volumen" } }, diff --git a/locale/de/app.utils.json b/locale/de/app.utils.json index 25b393b3e..706f0de62 100644 --- a/locale/de/app.utils.json +++ b/locale/de/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Überprüfen sie, ob ihre Wallet oder ihre Exchange Smart Contracts verwendet, um ETH zurückzuziehen. Wir akzeptieren solche Transaktionen nicht und können sie nicht zurückerstatten. Sie werden dieses Geld verlieren.", "warningTitle": "Bitte hinterlegen sie ETH nicht von Smart Contracts! Hinterlegen sie keine ERC20 Tokens! Nur Ethereum ist erlaubt." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Sobald die Transaktion bestätigt ist, verarbeitet das Gateway die Übertragung der WEST Token zu einem Token in ihrem Waves Account.", "helpDescrTitle": "Geben Sie diese Adresse in Ihren WEST-Kunden oder Ihr Wallet ein.", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes übrig: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/de/app.welcome.json b/locale/de/app.welcome.json index da9ac4984..f33accaa6 100644 --- a/locale/de/app.welcome.json +++ b/locale/de/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Nutzungsbedingungen", "tokenCreation": "Schnelle Tokenerstellung", "tokenCreationCosts": "Die Erstellung von Token kostet nur 1 WAVES und dauert 1 Minute.", + "tokenomicaToasterButton": "Mehr Erfahren", + "tokenomicaToasterText": "Werden Sie Aktionär der ersten All-in-One-Plattform für die Ausgabe und den Sekundärhandell der digitalisierten Wertpapiere", "tradeOnWaves": "Handel an der Waves Decentralized Exchange", "tradeOnWavesDescription": "Kaufen und verkaufen Sie Token schnell und sicher mit allen Vorteilen einer zentralen Börse, behalten Sie jedoch die vollständige Kontrolle über Ihre Gelder.", "transactions": "Transaktionen", diff --git a/locale/en/app.dex.json b/locale/en/app.dex.json index 9cad1ab1d..f61ce82dd 100644 --- a/locale/en/app.dex.json +++ b/locale/en/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "No markets matching your filters" }, "price": "Price", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/en/app.utils.json b/locale/en/app.utils.json index 9921c2d5e..529d0101d 100644 --- a/locale/en/app.utils.json +++ b/locale/en/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw ETH. We do not accept such transactions and can’t refund them. You will lose that money.", "warningTitle": "Please do not deposit ETH from smart contracts! Do not deposit ERC20 tokens! Only Ethereum is allowed." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes left: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/en/app.welcome.json b/locale/en/app.welcome.json index 19dd5f568..07ca72a16 100644 --- a/locale/en/app.welcome.json +++ b/locale/en/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Terms of use", "tokenCreation": "Fast token creation", "tokenCreationCosts": "Token creation costs just 1 WAVES and takes 1 minute", + "tokenomicaToasterButton": "Learn more", + "tokenomicaToasterText": "Become a shareholder of the first-ever all-in-one platform for issuance and trading of tokenized assets.", "tradeOnWaves": "Trade on the Waves Decentralised Exchange", "tradeOnWavesDescription": "Buy and sell tokens quickly and securely with all advantages of a centralised exchange, but retaining complete control of your funds.", "transactions": "Transactions", diff --git a/locale/es/app.dex.json b/locale/es/app.dex.json index cdefbc120..487e05af9 100644 --- a/locale/es/app.dex.json +++ b/locale/es/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "No hay mercados en base a sus filtros" }, "price": "Precio", + "vol": "Vol", "volume": "Volumen" } }, diff --git a/locale/es/app.utils.json b/locale/es/app.utils.json index 471520036..61a7a6578 100644 --- a/locale/es/app.utils.json +++ b/locale/es/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Comprueba si tu monedero o tu exchange utiliza Smart-contracts para retirar ETH. No aceptamos ese tipo de transacción y no podemos devolverlo. Perderás ese dinero.", "warningTitle": "!Por favor no deposites ETH desde Smart-Contract! No deposites tokens ERC20, solo se acepta Ethereum." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Una vez que se confirma la transacción, la puerta de enlace procesará la transferencia de WEST en forma de token a su cuenta Waves.", "helpDescrTitle": "Ingrese esta dirección en su cartera o cliente WEST", @@ -999,5 +1005,8 @@ "byte": { "help": "Quedan: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/es/app.welcome.json b/locale/es/app.welcome.json index 69c53b03b..b7938918b 100644 --- a/locale/es/app.welcome.json +++ b/locale/es/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Términos de uso", "tokenCreation": "Creación rápida de tokens", "tokenCreationCosts": "La creación de tokens cuesta solo 1 WAVES y tarda 1 minuto", + "tokenomicaToasterButton": "Aprende Más", + "tokenomicaToasterText": "Conviértase en accionista de la primera plataforma todo-en-uno para la emisión y comercialización de activos tokenizados.", "tradeOnWaves": "Utilizar el intercambio descentralizado de Waves", "tradeOnWavesDescription": "Compre y venda tokens de forma rápida y segura con todas las ventajas de un intercambio centralizado, pero conservando el control total de sus fondos.", "transactions": "Transacciones", diff --git a/locale/et_EE/app.dex.json b/locale/et_EE/app.dex.json index 5ae896089..665557801 100644 --- a/locale/et_EE/app.dex.json +++ b/locale/et_EE/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Teie filtritele vastavaid turge ei leitud" }, "price": "Hind", + "vol": "Vol", "volume": "Maht" } }, diff --git a/locale/et_EE/app.utils.json b/locale/et_EE/app.utils.json index e77b278c0..3c7f47325 100644 --- a/locale/et_EE/app.utils.json +++ b/locale/et_EE/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Kontrollige, kas teie rahakott või börs kasutab ETH-i väljavõtmiseks smart-kontrakte. Me ei aktsepteeri selliseid tehinguid ja ei saa neid tagasi maksta. Te kaotate selle raha.", "warningTitle": "Palun ärge tehke sissemakset ETH smart-kontrakrtidelt! Ärge tehkse sissemakseid ERC20 tokenites! Ainult Ethereum on lubatud." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Baite vasakul: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/et_EE/app.welcome.json b/locale/et_EE/app.welcome.json index b42d0f8c6..f236b58a2 100644 --- a/locale/et_EE/app.welcome.json +++ b/locale/et_EE/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Terms of use", "tokenCreation": "Fast token creation", "tokenCreationCosts": "Token creation costs just 1 WAVES and takes 1 minute", + "tokenomicaToasterButton": "Lisateavet", + "tokenomicaToasterText": "Saage esimese digitaalne väärtpaberite universaalse platvormi aktsionäriks", "tradeOnWaves": "Trade on the Waves Decentralised Exchange", "tradeOnWavesDescription": "Buy and sell tokens quickly and securely with all advantages of a centralised exchange, but retaining complete control of your funds.", "transactions": "Transactions", diff --git a/locale/fr/app.dex.json b/locale/fr/app.dex.json index c5c759df8..5209352c9 100644 --- a/locale/fr/app.dex.json +++ b/locale/fr/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Aucun marché ne correspond à vos filtres" }, "price": "Prix", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/fr/app.utils.json b/locale/fr/app.utils.json index 094e35df7..7b21cc9d7 100644 --- a/locale/fr/app.utils.json +++ b/locale/fr/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Vérifiez si votre portefeuille ou votre plateforme d'échange utilise des smart-contracts pour retirer ETH. Nous n'acceptons pas de telles transactions et ne pouvons pas les rembourser. Vous perdrez cet argent.", "warningTitle": "Ne déposez pas d'ETH à partir de smart-contracts ! Ne déposez pas de tokens ERC20 ! Seul Ethereum est autorisé." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Une fois la transaction confirmée, le portail traitera le transfert de WEST vers un jeton dans votre compte Waves.", "helpDescrTitle": "Entrez cette adresse dans votre client ou portefeuille WEST", @@ -999,5 +1005,8 @@ "byte": { "help": "Octets restants : {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/fr/app.welcome.json b/locale/fr/app.welcome.json index 8f7450fef..360300599 100644 --- a/locale/fr/app.welcome.json +++ b/locale/fr/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Conditions d'utilisation", "tokenCreation": "Création rapide de jetons", "tokenCreationCosts": "La création de jetons coûte seulement 1 WAVES et dure 1 minute", + "tokenomicaToasterButton": "Plus d'informations", + "tokenomicaToasterText": "Devenez actionnaire de la première plateforme tout en un d’émission et d’échange de Security Token", "tradeOnWaves": "Échangez sur la plateforme d'échange décentralisé de Waves", "tradeOnWavesDescription": "Achetez et vendez des jetons rapidement et en toute sécurité avec tous les avantages d'un échange centralisé, tout en gardant le contrôle total de vos fonds.", "transactions": "Transactions", diff --git a/locale/hi_IN/app.dex.json b/locale/hi_IN/app.dex.json index 9c08f782a..51154cb58 100644 --- a/locale/hi_IN/app.dex.json +++ b/locale/hi_IN/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "आपके फिल्टर से मैच करता कोई मार्केट नहीं" }, "price": "मूल्य", + "vol": "Vol", "volume": "वॉल्यूम" } }, diff --git a/locale/hi_IN/app.utils.json b/locale/hi_IN/app.utils.json index 4b6583094..b899e8a58 100644 --- a/locale/hi_IN/app.utils.json +++ b/locale/hi_IN/app.utils.json @@ -302,6 +302,12 @@ "warningText": "क करें किया क्या आपका वॉलेट या एक्सचेंज, ETH निकासी के लिए स्मार्ट-कॉन्ट्रैक्ट का उपयोग करता है। हम ऐसे लेनेदेन स्वीकार नहीं करते हैं और उनको रिफंड नहीं कर सकते हैं। आपको उस धन की हानि हो जाएगी।", "warningTitle": "कृपया स्मार्ट-कॉन्ट्रैक्ट से ETH जमा ना करें! ERC20 टोकन जमा ना करें! केवल Ethereum अनुमत है।" }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "शेष Bytes: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/hi_IN/app.welcome.json b/locale/hi_IN/app.welcome.json index ca5e92d17..8c1bdbe9f 100644 --- a/locale/hi_IN/app.welcome.json +++ b/locale/hi_IN/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Terms of use", "tokenCreation": "Fast token creation", "tokenCreationCosts": "Token creation costs just 1 WAVES and takes 1 minute", + "tokenomicaToasterButton": "और अधिक जानें", + "tokenomicaToasterText": "टोकेन अस्सेट्स के प्रकाशन और व्यापार के लिए पहले कभी ऑल-इन-वन प्लेटफॉर्म का हिस्सेदार बनो", "tradeOnWaves": "Trade on the Waves Decentralised Exchange", "tradeOnWavesDescription": "Buy and sell tokens quickly and securely with all advantages of a centralised exchange, but retaining complete control of your funds.", "transactions": "Transactions", diff --git a/locale/id/app.dex.json b/locale/id/app.dex.json index e820b8ccb..99cd5d5d4 100644 --- a/locale/id/app.dex.json +++ b/locale/id/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Tidak ada pasar yang cocok dengan filter Anda" }, "price": "Harga", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/id/app.utils.json b/locale/id/app.utils.json index 331d8db51..e155a6589 100644 --- a/locale/id/app.utils.json +++ b/locale/id/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Periksa apakah dompet atau pertukaran Anda menggunakan kontrak cerdas untuk menarik ETH. Kami tidak menerima transaksi semacam itu dan dapat mengembalikan uang mereka. Anda akan kehilangan uang itu.", "warningTitle": "Tolong jangan depositkan ETH dari kontrak pintar! Jangan setor token ERC20! Hanya Ethereum yang diizinkan." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Setelah transaksi dikonfirmasi, gateway akan memproses transfer WEST ke token di akun Waves Anda.", "helpDescrTitle": "Masukkan alamat ini ke klien atau dompet WEST Anda", @@ -999,5 +1005,8 @@ "byte": { "help": "Byte tersisa: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/id/app.welcome.json b/locale/id/app.welcome.json index dabdc2d50..613d39ad6 100644 --- a/locale/id/app.welcome.json +++ b/locale/id/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Syarat Penggunaan", "tokenCreation": "Pembuatan token cepat", "tokenCreationCosts": "Biaya pembuatan token hanya 1 WAVES dan memakan waktu 1 menit", + "tokenomicaToasterButton": "Belajarlah lagi", + "tokenomicaToasterText": "Menjadi pemegang saham platform bersama pertama untuk penerbitan dan perdagangan aset tokenized", "tradeOnWaves": "Perdagangan di Bursa Desentralisasi Waves", "tradeOnWavesDescription": "Beli dan jual token dengan cepat dan aman dengan semua keuntungan dari pertukaran terpusat, tetapi tetap memegang kendali penuh atas dana Anda.", "transactions": "Transaksi", diff --git a/locale/it/app.dex.json b/locale/it/app.dex.json index a46de9921..903a47345 100644 --- a/locale/it/app.dex.json +++ b/locale/it/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Nessun mercato in base ai criteri di ricerca" }, "price": "Prezzo", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/it/app.utils.json b/locale/it/app.utils.json index c37e02997..3b7962e30 100644 --- a/locale/it/app.utils.json +++ b/locale/it/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Controlla se il tuo wallet o exchange utilizza smart contract per trasferire ETH. Non accettiamo questo tipo di transazioni e non ci sarà possibile rimborsarle. L'importo trasferito andrà perduto.", "warningTitle": "Per favore, non inviare ETH da smart contracts! Non inviare token ERC20! Accettiamo esclusivamente Ethereum." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Una volta che la transazione sarà confermata, il gateway processerà il trasferimento di WEST in favore di un token nel tuo account Waves.", "helpDescrTitle": "Inserisci questo indirizzo nel tuo client WEST o nel tuo wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Byte restanti: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/it/app.welcome.json b/locale/it/app.welcome.json index 31715a0a8..b8ca34dd1 100644 --- a/locale/it/app.welcome.json +++ b/locale/it/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Termini di utilizzo", "tokenCreation": "Creazione rapida di token", "tokenCreationCosts": "La creazione di token costa solo 1 Waves e richiede 1 minuto", + "tokenomicaToasterButton": "Ulteriori Informazioni", + "tokenomicaToasterText": "Diventi azionista della prima tutto-in-uno piattaforma per l'emissione e il secondario commercio di attività tokenizzate", "tradeOnWaves": "Commercia sull'Exchange Decentrato Waves", "tradeOnWavesDescription": "Compra e vendi i token in modo rapido e sicuro con tutti i vantaggi di uno scambio centralizzato, ma mantenendo il controllo completo dei tuoi fondi.", "transactions": "Transazioni", diff --git a/locale/ja/app.dex.json b/locale/ja/app.dex.json index e320f2740..76369cbac 100644 --- a/locale/ja/app.dex.json +++ b/locale/ja/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "指定されたフィルターに合致するペアはありません" }, "price": "価格", + "vol": "Vol", "volume": "ボリューム" } }, diff --git a/locale/ja/app.utils.json b/locale/ja/app.utils.json index a8288d1a7..a2ff66cf9 100644 --- a/locale/ja/app.utils.json +++ b/locale/ja/app.utils.json @@ -302,6 +302,12 @@ "warningText": "あなたのウォレットと取引所がスマートコントラクトを用いて、ETHを引出していないか、確認してください。私たちはそのような形式のトランザクションを受け入れておらず、返金することもできません。あなたはあなたの資金を失います。", "warningTitle": "ETHをスマートコントラクトからデポジットしないでください。また、ERC20トークンもデポジットしないでください。" }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "トランザクションが承認されると、ゲートウェイはWESTの送信を進め、あなたのWavesアカウントにトークンが反映されます。", "helpDescrTitle": "このアドレスをWESTクライアント、またはウォレットに入力してください", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes 残 : {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ja/app.welcome.json b/locale/ja/app.welcome.json index 50c5fdab5..e21f51264 100644 --- a/locale/ja/app.welcome.json +++ b/locale/ja/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "利用規約", "tokenCreation": "高速なトークン生成", "tokenCreationCosts": "トークン生成にかかる費用はわずか1 WAVESで、わずか1分で完了", + "tokenomicaToasterButton": "もっと詳しく知る", + "tokenomicaToasterText": "トークン化された資産の発行と取引のための史上初のオールインワンプラットフォームの株主になる", "tradeOnWaves": "Wavesの分散型取引所でトレード", "tradeOnWavesDescription": "中央型取引所のすべての利点をすべて提供しつつ、資金を完全に管理しながらトークンを迅速かつ安全に売買できます。", "transactions": "トランザクション", diff --git a/locale/ko/app.dex.json b/locale/ko/app.dex.json index acd7af614..0feb367be 100644 --- a/locale/ko/app.dex.json +++ b/locale/ko/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "검색 결과가 없습니다" }, "price": "가격", + "vol": "Vol", "volume": "거래량" } }, diff --git a/locale/ko/app.utils.json b/locale/ko/app.utils.json index 9176d4691..db26f59aa 100644 --- a/locale/ko/app.utils.json +++ b/locale/ko/app.utils.json @@ -302,6 +302,12 @@ "warningText": "ETH를 출금하려고 하는 지갑 또는 거래소가 Smart-Contracts를 사용하는지 확인하세요. 당사는 해당 트랜잭션을 수신하지 않으며 환불 또한 불가능합니다. 귀하의 자산을 잃게 됩니다.", "warningTitle": "Smart Contracts에서 ETH를 입금하지 마세요! ERC20 토큰을 입금하지 마세요! Ethereum 입금만 가능합니다." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "트랜잭션이 승인되면 게이트웨이가 귀하의 Waves 계정에서 WEST를 토큰으로 전송하는 작업을 처리할 것입니다.", "helpDescrTitle": "이 주소를 WEST 클라이언트 또는 지갑에 입력하세요", @@ -999,5 +1005,8 @@ "byte": { "help": "사용 가능 Bytes: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ko/app.welcome.json b/locale/ko/app.welcome.json index efe319523..50a2ade06 100644 --- a/locale/ko/app.welcome.json +++ b/locale/ko/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "이용 약관", "tokenCreation": "빠른 토큰 생성", "tokenCreationCosts": "1 WAVES로 1분만에 토큰을 생성할 수 있습니다", + "tokenomicaToasterButton": "더 알아보기", + "tokenomicaToasterText": "토큰 화 된 자산의 발행 및 거래를위한 최초의 범용 플랫폼의 주주가 되십시오", "tradeOnWaves": "Waves 탈중앙화 거래소에서 거래하세요", "tradeOnWavesDescription": "본인의 자금에 대한 완전한 통제권 및 중앙 집중식 거래소의 이점과 함께 빠르고 안전하게 토큰을 사고 파세요.", "transactions": "트랜잭션", diff --git a/locale/nl_NL/app.dex.json b/locale/nl_NL/app.dex.json index 940dfacc2..05f6b8624 100644 --- a/locale/nl_NL/app.dex.json +++ b/locale/nl_NL/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Geen markten die overeenkomen met uw filters" }, "price": "Prijs", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/nl_NL/app.utils.json b/locale/nl_NL/app.utils.json index 7e8b38df2..ade78fc7c 100644 --- a/locale/nl_NL/app.utils.json +++ b/locale/nl_NL/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Controleer of uw wallet of exchange smart-contracts gebruikt om ETH the withdrawen. Wij accepteren zulke transacties niet en kunnen dit niet terug betalen. U raakt op deze manier uw geld kwijt.", "warningTitle": "Verstuur geen ETH vanuit smart contracts naar dit adres. Stort geen ERC20 tokens! Alleen Ethereum is toegestaan." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Zodra de transactie bevestigd is zal de gateway de transactie behandelen en dit omzetten naar een WEST token in uw Waves account.", "helpDescrTitle": "Dit adres invoeren in uw WEST-client of wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes over: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/nl_NL/app.welcome.json b/locale/nl_NL/app.welcome.json index e56efd4b8..d935dcf38 100644 --- a/locale/nl_NL/app.welcome.json +++ b/locale/nl_NL/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Gebruiksvoorwaarden", "tokenCreation": "Snelle tokencreatie", "tokenCreationCosts": "Het aanmaken van tokens kost slechts 1 WAVES en duurt 1 minuut", + "tokenomicaToasterButton": "Leer Meer", + "tokenomicaToasterText": "Word aandeelhouder van het allereerste alles-in-één platform voor uitgifte en secundaire handel de gedigitaliseerde activa.", "tradeOnWaves": "Handel op de Waves gedecentraliseerde exchange", "tradeOnWavesDescription": "Koop en verkoop tokens snel en veilig met alle voordelen van een centrale uitwisseling, maar behoud de volledige controle over uw geld.", "transactions": "Transacties", diff --git a/locale/pl/app.dex.json b/locale/pl/app.dex.json index 437cb6f02..19fa46883 100644 --- a/locale/pl/app.dex.json +++ b/locale/pl/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Brak rynków spełniającyh wymagania" }, "price": "Cena", + "vol": "Vol", "volume": "Wolumen" } }, diff --git a/locale/pl/app.utils.json b/locale/pl/app.utils.json index 9771eb56b..5142acf36 100644 --- a/locale/pl/app.utils.json +++ b/locale/pl/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Sprawdź czy portfel lub giełda używają inteligentnych kontraktów (smart contracts) do wycofania ETH. Nie akceptujemy takich transakcji i nie możemy ich zwrócić. Stracisz te pieniądze.", "warningTitle": "Proszę nie deponować ETH z inteligentnych kontraktów (smart contracts)! Proszę nie deponować tokenów ERC20! Tylko Ethereum dozwolone." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Jeżeli transakcja zostanie potwierdzona, system wymieni WEST na tokeny w Twoim koncie Waves.", "helpDescrTitle": "Wprowadź ten adres w swoim kliencie albo portfelu WEST", @@ -999,5 +1005,8 @@ "byte": { "help": "Zostały bajty: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pl/app.welcome.json b/locale/pl/app.welcome.json index 21d577355..6a5154ce9 100644 --- a/locale/pl/app.welcome.json +++ b/locale/pl/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Warunki użytkowania", "tokenCreation": "Szybkie tworzenie tokenów", "tokenCreationCosts": "Tworzenie tokena kosztuje tylko 1 WAVES i trwa 1 minutę", + "tokenomicaToasterButton": "Więcej informacji", + "tokenomicaToasterText": "Zostań akcjonariuszem pierwszej wszechstronnej platformy do emisji i obrotu tokenizowanymi aktywami", "tradeOnWaves": "Handel na zdecentralizowanej giełdzie Waves", "tradeOnWavesDescription": "Kupuj i sprzedawaj żetony szybko i bezpiecznie ze wszystkimi zaletami scentralizowanej wymiany, ale zachowując pełną kontrolę nad swoimi środkami.", "transactions": "Transakcje", diff --git a/locale/pt_BR/app.dex.json b/locale/pt_BR/app.dex.json index d84a65f32..b1c3f9908 100644 --- a/locale/pt_BR/app.dex.json +++ b/locale/pt_BR/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Nenhum mercado corresponde aos seus filtros" }, "price": "Preço", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/pt_BR/app.utils.json b/locale/pt_BR/app.utils.json index 1a28f2e7f..1458e2898 100644 --- a/locale/pt_BR/app.utils.json +++ b/locale/pt_BR/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Verifique se a sua carteira ou exchange usa smart contracts para transferir ETH. Nós não aceitamos essas transações e você perderá esse dinheiro, pois não podemos reembolsar.", "warningTitle": "Por favor, não deposite ETH através de smart contracts! Não deposite tokens ERC20! Apenas Ethereum é permitido." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes restantes: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pt_BR/app.welcome.json b/locale/pt_BR/app.welcome.json index cba10d033..49b1ca064 100644 --- a/locale/pt_BR/app.welcome.json +++ b/locale/pt_BR/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Terms of use", "tokenCreation": "Fast token creation", "tokenCreationCosts": "Token creation costs just 1 WAVES and takes 1 minute", + "tokenomicaToasterButton": "Saber Mais", + "tokenomicaToasterText": "Torne-se acionista da primeira tudo-em-um plataforma para emissão e negociação secundária de ativos tokenizados", "tradeOnWaves": "Trade on the Waves Decentralised Exchange", "tradeOnWavesDescription": "Buy and sell tokens quickly and securely with all advantages of a centralised exchange, but retaining complete control of your funds.", "transactions": "Transações", diff --git a/locale/pt_PT/app.dex.json b/locale/pt_PT/app.dex.json index 9cad1ab1d..f61ce82dd 100644 --- a/locale/pt_PT/app.dex.json +++ b/locale/pt_PT/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "No markets matching your filters" }, "price": "Price", + "vol": "Vol", "volume": "Volume" } }, diff --git a/locale/pt_PT/app.utils.json b/locale/pt_PT/app.utils.json index 472c8cb29..90a9f1483 100644 --- a/locale/pt_PT/app.utils.json +++ b/locale/pt_PT/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw ETH. We do not accept such transactions and can’t refund them. You will lose that money.", "warningTitle": "Please do not deposit ETH from smart contracts! Do not deposit ERC20 tokens! Only Ethereum is allowed." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of WEST to a token in your Waves account.", "helpDescrTitle": "Enter this address into your WEST client or wallet", @@ -999,5 +1005,8 @@ "byte": { "help": "Bytes left: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pt_PT/app.welcome.json b/locale/pt_PT/app.welcome.json index 19dd5f568..da6e931bb 100644 --- a/locale/pt_PT/app.welcome.json +++ b/locale/pt_PT/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Terms of use", "tokenCreation": "Fast token creation", "tokenCreationCosts": "Token creation costs just 1 WAVES and takes 1 minute", + "tokenomicaToasterButton": "Saber Mais", + "tokenomicaToasterText": "Torne-se acionista da primeira tudo-em-um plataforma para emissão e negociação secundária de ativos tokenizados", "tradeOnWaves": "Trade on the Waves Decentralised Exchange", "tradeOnWavesDescription": "Buy and sell tokens quickly and securely with all advantages of a centralised exchange, but retaining complete control of your funds.", "transactions": "Transactions", diff --git a/locale/ru/app.dex.json b/locale/ru/app.dex.json index 8c74dc219..f5fe2447d 100644 --- a/locale/ru/app.dex.json +++ b/locale/ru/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Ничего не найдено" }, "price": "Цена", + "vol": "Объём", "volume": "Объём" } }, diff --git a/locale/ru/app.utils.json b/locale/ru/app.utils.json index e65e745fc..9c9f0bca9 100644 --- a/locale/ru/app.utils.json +++ b/locale/ru/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Проверьте, не использует ли ваш кошелёк или биржа смарт-контракты для отправки ETH. Мы не принимаем такие переводы и не можем возместить их. Вы потеряете эти деньги.", "warningTitle": "Не отправляйте ETH со смарт-контрактов! Не отправляйте ERC20-токены! Только Ethereum." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "Если вы отправите меньше чем {{minAmount, BigNumber}} {{assetTicker}}, вы потеряете деньги.", + "warningMinAmountTitle": "Минимальная сумма депозита {{minAmount, BigNumber}} {{assetTicker}}, максимальная сумма депозита {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "Как только транзакция будет подтверждена, шлюз отправит WEST-токен на ваш аккаунт Waves.", "helpDescrTitle": "Введите этот адрес в ваш WEST клиент или кошелёк.", @@ -999,5 +1005,8 @@ "byte": { "help": "Осталось байт: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ru/app.welcome.json b/locale/ru/app.welcome.json index 7286957c1..3a552ed79 100644 --- a/locale/ru/app.welcome.json +++ b/locale/ru/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Договор на обслуживание", "tokenCreation": "Быстрый запуск токена", "tokenCreationCosts": "Создание токена за 1 WAVES за считанные минуты", + "tokenomicaToasterButton": "Узнать подробнее", + "tokenomicaToasterText": "Cтаньте акционером первой универсальной платформы для токенизированных ценных бумаг. ", "tradeOnWaves": "Торгуйте на децентрализованной бирже Waves", "tradeOnWavesDescription": "Покупайте и продавайте токены быстро и безопасно со всеми преимуществами централизованных бирж, но сохраняя полный контроль над своими средствами.", "transactions": "Транзакции", diff --git a/locale/tr/app.dex.json b/locale/tr/app.dex.json index a0a235523..4e724a284 100644 --- a/locale/tr/app.dex.json +++ b/locale/tr/app.dex.json @@ -200,6 +200,7 @@ "noMarkets": "Filtrelerinize uygun bir pazar bulunamadı" }, "price": "Fiyat", + "vol": "Vol", "volume": "Hacim" } }, diff --git a/locale/tr/app.utils.json b/locale/tr/app.utils.json index 10db62190..69fba3dc1 100644 --- a/locale/tr/app.utils.json +++ b/locale/tr/app.utils.json @@ -302,6 +302,12 @@ "warningText": "Cüzdanınızın veya Kripto para borsasının ETH çekimlerinde akıllı kontrat kullanıp kullanmadığını kontrol edin. Akıllı kontratlar tarafından gelen transferleri kabul edemiyoruz. Paranızı kaybedersiniz.", "warningTitle": "ETH akıllı kontratlarından yatırma işlemi yapmayınız. ERC20 tokenleri yatırmayınız! Sadece Ethereum transferleri kabul edilir." }, + "wavesGatewayUSDT": { + "warningMinAmountText": "If you will send less than {{minAmount, BigNumber}} {{assetTicker}}, you will lose that money.", + "warningMinAmountTitle": "The minimum amount of deposit is {{minAmount, BigNumber}} {{assetTicker}}, the maximum amount of deposit is {{maxAmount}} {{assetTicker}}", + "warningText": "Check if your wallet or exchange uses smart-contracts to withdraw Tether USD. We do not accept such transactions and can’t refund them. You will lose that money", + "warningTitle": "This is ERC20 USDT deposit address. Send only USDT to this deposit address. Sending any other coin or token to this address may result in the loss of your deposit. Please do not deposit USDT from smart contracts!" + }, "wavesGatewayVST": { "helpDescrText": "İşlem onaylandıktan sonra WESTlar Waves adresinize geçit tarafından gönderilir.", "helpDescrTitle": "Bu adresi WEST cüzdanına ya da uygulamasına giriniz.", @@ -999,5 +1005,8 @@ "byte": { "help": "Byte kaldı: {{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/tr/app.welcome.json b/locale/tr/app.welcome.json index 7069812a9..b69b49b15 100644 --- a/locale/tr/app.welcome.json +++ b/locale/tr/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "Kullanım koşulları", "tokenCreation": "Hızlı kripto para oluşturma", "tokenCreationCosts": "Kripto para oluşturma maliyeti yalnızca 1 WAVES ve 1 dakika sürer", + "tokenomicaToasterButton": "Daha fazla bilgi", + "tokenomicaToasterText": "Tokenlenmiş assetlerin çıkarmasi ve alım satımı için ilk bir hepsi bir arada platformun hissedarı olun.", "tradeOnWaves": "Waves Merkezsiz Kripto Para Borsasında Kripto Para Alın ve Satın", "tradeOnWavesDescription": "Merkezi bir borsanın tüm avantajları ile birlikte kripto paralarınızı hızlı ve güvenli bir şekilde alın ve satın, bu esnada varlıklarınızın kontrolünü elinizde tutun.", "transactions": "İşlemler", diff --git a/locale/zh_CN/app.dex.json b/locale/zh_CN/app.dex.json index 3e7bddf2f..3ee464b99 100644 --- a/locale/zh_CN/app.dex.json +++ b/locale/zh_CN/app.dex.json @@ -47,7 +47,7 @@ "last": "最新交易价", "limit": "限价单", "market": "市场订单", - "marketPriceField": "Price", + "marketPriceField": "价格", "matcherFee": "费用", "notifications": { "error": { @@ -76,7 +76,7 @@ "total": "总额" }, "createorder": { - "yourBalance": "Your balance" + "yourBalance": "您的余额" }, "demo": { "createAccount": "创建新账户", @@ -200,6 +200,7 @@ "noMarkets": "没有符合您的筛选的市场" }, "price": "价格", + "vol": "Vol", "volume": "量" } }, diff --git a/locale/zh_CN/app.utils.json b/locale/zh_CN/app.utils.json index ce6ac8aad..6e2c57e95 100644 --- a/locale/zh_CN/app.utils.json +++ b/locale/zh_CN/app.utils.json @@ -279,7 +279,7 @@ "warningTitle": "请不要从智能合约中存入BNT!不要存入其他ERC20代币!只允许Bancor。" }, "wavesGatewayBTC": { - "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of BTC to a token in your Waves account.", + "helpDescrText": "确认交易后,网关将处理BTC到Waves帐户中令牌的转移。", "helpDescrTitle": "在您的BTC客户端或钱包中输入此地址", "warningMinAmountText": "如果您发送的费用低于{{minAmount, BigNumber}} {{assetTicker}},您将失去这笔钱。", "warningMinAmountTitle": "最低存款金额为{{minAmount,BigNumber}} {{assetTicker}} ,最高存款金额为{{maxAmount}} {{assetTicker}}", @@ -295,13 +295,19 @@ "warningTitle": "仅将ERGO发送至此存款地址" }, "wavesGatewayETH": { - "helpDescrText": "Once the transaction is confirmed, the gateway will process the transfer of ETH to a token in your Waves account.", - "helpDescrTitle": "Enter this address into your ETH client or wallet", + "helpDescrText": "确认交易后,网关将处理ETH到Waves帐户中的代币的转账。", + "helpDescrTitle": "将此地址输入您的ETH客户或钱包", "warningMinAmountText": "如果你发送少于{{minAmount, BigNumber}} {{assetTicker}},你将失去这笔钱。", "warningMinAmountTitle": "最低存款金额为{{minAmount,BigNumber}} {{assetTicker}} ,最高存款金额为{{maxAmount}} {{assetTicker}}", "warningText": "检查您的钱包或交易所是否为收回ETH使用智能合约。我们不接受这种交易,也不能退款。您将会失去这笔钱。", "warningTitle": "请不要从智能合约中交存ETH!别交存ERC20代币!您只能交存以太坊Ethereum。" }, + "wavesGatewayUSDT": { + "warningMinAmountText": "如果您的汇款少于{{minAmount,BigNumber}} {{assetTicker}} ,您将损失这笔钱。", + "warningMinAmountTitle": "最低存款额为{{minAmount,BigNumber}} {{assetTicker}} ,最大存款额为{{maxAmount}} {{assetTicker}}", + "warningText": "检查您的钱包或交易所是否使用智能合约提取Tether USD。我们不接受此类交易,也无法退款。你会赔钱的", + "warningTitle": "这是ERC20 USDT的存款地址。仅将USDT发送到该存款地址。将任何其他硬币或令牌发送到此地址可能会导致您的押金丢失。请不要从智能合约中存入USDT!" + }, "wavesGatewayVST": { "helpDescrText": "确认交易后,网关将处理将WEST转移到Waves帐户中的代币。", "helpDescrTitle": "在您的WEST客户端或钱包中输入此地址", @@ -999,5 +1005,8 @@ "byte": { "help": "剩余字节:{{bytes}}" } + }, + "warningPlate": { + "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/zh_CN/app.welcome.json b/locale/zh_CN/app.welcome.json index 885d0f202..9f499288c 100644 --- a/locale/zh_CN/app.welcome.json +++ b/locale/zh_CN/app.welcome.json @@ -216,6 +216,8 @@ "termsOfUse": "使用条款", "tokenCreation": "快速令牌创建", "tokenCreationCosts": "令牌创建成本仅为1 WAVES,需要1分钟", + "tokenomicaToasterButton": "了解更多", + "tokenomicaToasterText": "成为有史以来第一个用于发行和交易令牌化资产的多平台的股东", "tradeOnWaves": "波浪分散交易所的交易", "tradeOnWavesDescription": "快速,安全地购买和出售代币,具有集中交易的所有优势,但保留对资金的完全控制。", "transactions": "交易记录", From b8ea2299e75ec1e4036596a0b476b64dc28afb29 Mon Sep 17 00:00:00 2001 From: ekomarovskaya Date: Fri, 8 Nov 2019 16:03:31 +0300 Subject: [PATCH 037/144] DEXW-2314: add link --- src/modules/ui/directives/footer/footer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/ui/directives/footer/footer.html b/src/modules/ui/directives/footer/footer.html index 5a70bdeb4..bc412ec4d 100644 --- a/src/modules/ui/directives/footer/footer.html +++ b/src/modules/ui/directives/footer/footer.html @@ -115,7 +115,7 @@ -
+ diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less index 726e5b3ac..194c9feb3 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.less @@ -40,6 +40,12 @@ w-warning-plate { &__text { margin: 0 15px 0 20px; + + a { + color: #fff; + text-decoration: underline; + margin-left: 3px; + } } &__timer { @@ -86,8 +92,17 @@ w-warning-plate { padding: 10px 12px; flex-wrap: wrap; transition: all .2s; + + &_no-user { + justify-content: flex-start; + + .warning-plate__text { + width: auto; + } + } } + &__text { text-align: left; margin-right: 0; diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index f6d21bd8f..b5790fce7 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -10,9 +10,8 @@ * @param {ng.ILogService} $log * @param {*} $mdDialog * @param {*} storageExporter - * @param {*} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter, $scope, storage) { + const controller = function (Base, $log, $mdDialog, storageExporter, $scope) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -53,18 +52,11 @@ }).then((result) => { if (result.payload === 'ok') { $log.log('done'); - this.step++; $scope.$apply(); - - return storage.save('migrationSuccess', true); } else { $log.log('fail', result); - - return storage.save('migrationSuccess', false); } - }).then(() => { - storage.change.dispatch('migrationSuccess'); }).catch((e) => { $log.error(e); }); @@ -72,7 +64,6 @@ cancel() { $mdDialog.cancel(); - storage.save('notAutoOpenMigrationModal', true); } /** @@ -105,7 +96,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope', 'storage']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 84c2a9a3a01d5768e1cf790767cc16064cb030b6 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Fri, 8 Nov 2019 16:51:02 +0300 Subject: [PATCH 039/144] DEXW-2282: warning plate fix --- .../componentWarningPlate/ComponentWarningPlate.js | 6 ++++-- src/modules/utils/modals/migrateModal/migrateModal.js | 2 -- src/modules/utils/services/Storage.js | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index f62aef422..d028347bf 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -42,8 +42,10 @@ this._initHasAccounts(); this._initMigrationSuccess(); - user.loginSignal.on(this._initHasAccounts, this); - storage.change.on(this._initMigrationSuccess, this); + storage.change.on(() => { + this._initMigrationSuccess(); + this._initHasAccounts(); + }); utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); } diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index f6d21bd8f..686aa08a1 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -63,8 +63,6 @@ return storage.save('migrationSuccess', false); } - }).then(() => { - storage.change.dispatch('migrationSuccess'); }).catch((e) => { $log.error(e); }); diff --git a/src/modules/utils/services/Storage.js b/src/modules/utils/services/Storage.js index db8c20e0c..61364fa3d 100644 --- a/src/modules/utils/services/Storage.js +++ b/src/modules/utils/services/Storage.js @@ -260,7 +260,12 @@ save(key, value) { return this._canWrite.promise.then(() => { - this._activeWrite = this._activeWrite.then(() => utils.when(usedStorage.write(key, value))); + this._activeWrite = this._activeWrite + .then(() => utils.when(usedStorage.write(key, value))) + .then((data) => { + this.change.dispatch(); + return data; + }); return this._activeWrite; }); } From 3444c9e610d34c3ab3994b2a922a04268bcd2bc1 Mon Sep 17 00:00:00 2001 From: dtsigelnitskiy Date: Fri, 8 Nov 2019 17:26:36 +0300 Subject: [PATCH 040/144] DEXW-2316: fix fetch asset from node --- data-service/api/assets/assets.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/data-service/api/assets/assets.ts b/data-service/api/assets/assets.ts index 9c049bf37..37a89001d 100644 --- a/data-service/api/assets/assets.ts +++ b/data-service/api/assets/assets.ts @@ -69,7 +69,7 @@ export function getAssetFromNode(assetId: string): Promise { return Promise.resolve(wavesAsset); } - return request({ url: `${configGet('node')}/assets/details/${assetId}` }) + return request({ url: `${configGet('node')}/assets/details/${assetId}` }) .then((data) => new Asset({ id: data.assetId, name: data.name, @@ -77,9 +77,9 @@ export function getAssetFromNode(assetId: string): Promise { height: data.issueHeight, precision: data.decimals, quantity: data.quantity, - hasScript: !!data.script, + hasScript: data.scripted, reissuable: data.reissuable, - minSponsoredFee: data.minSponsoredFee, + minSponsoredFee: data.minSponsoredAssetFee, sender: data.issuer, timestamp: new Date(data.issueTimestamp) })); @@ -265,3 +265,17 @@ export interface INodeAssetData { reissuable: boolean; script: string | null; } + +export interface INodeAssetInfo { + assetId: string; + issueHeight: number; + issueTimestamp: number; + issuer: string; + name: string; + description: string; + decimals: number; + reissuable: boolean; + quantity: number; + scripted: boolean; + minSponsoredAssetFee: number | string; +} From 0958a8e9b8155e71b5a6f115435ddbc714e41e1d Mon Sep 17 00:00:00 2001 From: Viktor Voronin Date: Fri, 8 Nov 2019 18:26:17 +0300 Subject: [PATCH 041/144] DEXW-2314: add close button behaviour --- src/modules/ui/directives/footer/footer.html | 18 --- .../ui/directives/footer/toaster-mobiles.less | 124 ----------------- .../directives/footer/toaster-tokenomica.less | 127 ----------------- .../modules/assets/controllers/AssetsCtrl.js | 27 +++- .../assets/less/toaster-tokenomica.less | 130 ++++++++++++++++++ .../modules/assets/templates/assets.html | 18 +++ 6 files changed, 172 insertions(+), 272 deletions(-) delete mode 100644 src/modules/ui/directives/footer/toaster-tokenomica.less create mode 100644 src/modules/wallet/modules/assets/less/toaster-tokenomica.less diff --git a/src/modules/ui/directives/footer/footer.html b/src/modules/ui/directives/footer/footer.html index bc412ec4d..f3bd1347a 100644 --- a/src/modules/ui/directives/footer/footer.html +++ b/src/modules/ui/directives/footer/footer.html @@ -113,22 +113,4 @@
- - - diff --git a/src/modules/ui/directives/footer/toaster-mobiles.less b/src/modules/ui/directives/footer/toaster-mobiles.less index 8bda3a8c3..3705d1301 100644 --- a/src/modules/ui/directives/footer/toaster-mobiles.less +++ b/src/modules/ui/directives/footer/toaster-mobiles.less @@ -68,127 +68,3 @@ display: flex; } } - -.toaster-tokenomica { - display: flex; - position: fixed; - bottom: 0; - left: 0; - justify-content: space-between; - background: @color-black; - padding: 25px 32px; - width: 100%; - z-index: 5; - transform: translateY(0); - transition: transform 0.2s; - - &__link { - display: flex; - flex: 1 0; - justify-content: space-between; - align-items: center; - } - - &__logo { - background: @logo-tokenomica-icon center no-repeat; - background-size: 100%; - width: 184px; - height: 40px; - flex-shrink: 0; - margin-right: 16px; - } - - &__text { - font-size: 20px; - color: @color-white; - line-height: 18px; - } - - &__text-wrapper { - display: flex; - flex: 1 0; - justify-content: space-between; - align-items: center; - margin-left: 80px; - } - - &__button { - button { - border-radius: 0; - } - - .button__content { - font-size: 20px; - font-weight: bold; - } - } - - &__close { - display: flex; - align-items: center; - margin-left: 36px; - - &-icon { - background: @close-tokenomica-icon center no-repeat; - border: 0; - width: 16px; - height: 16px; - - &:hover { - opacity: .5; - } - } - } - - &.hidden-toaster { - transform: translateY(100%); - } - - @media screen and (max-width: 768px) { - display: flex; - padding: 24px; - border-radius: 16px 16px 0 0; - align-items: flex-start; - - &__link { - flex-direction: column; - align-items: flex-start; - } - - &__logo { - margin: 0 0 16px 0; - width: 109px; - height: 24px; - } - - &__text-wrapper { - flex-direction: column; - align-items: flex-start; - width: 100%; - margin-left: 0; - } - - &__text { - font-size: 14px; - margin: 0 0 16px 0; - line-height: 20px; - width: 100%; - } - - &__button { - width: 100%; - - .button { - width: 100%; - } - - .button__content { - font-size: 16px; - } - } - - &__close { - margin: -6px; - } - } -} diff --git a/src/modules/ui/directives/footer/toaster-tokenomica.less b/src/modules/ui/directives/footer/toaster-tokenomica.less deleted file mode 100644 index 1e616b51d..000000000 --- a/src/modules/ui/directives/footer/toaster-tokenomica.less +++ /dev/null @@ -1,127 +0,0 @@ -@import (reference) 'config'; -@import (reference) 'icons'; -@import (reference) '../../../app/less/typography'; - -.toaster-tokenomica { - display: flex; - position: fixed; - bottom: 0; - left: 0; - justify-content: space-between; - background: @color-black; - padding: 25px 32px; - width: 100%; - z-index: 5; - transform: translateY(0); - transition: transform 0.2s; - - &__link { - display: flex; - flex: 1 0; - justify-content: space-between; - align-items: center; - } - - &__logo { - background: @logo-tokenomica-icon center no-repeat; - background-size: 100%; - width: 184px; - height: 40px; - flex-shrink: 0; - margin-right: 16px; - } - - &__text { - font-size: 20px; - color: @color-white; - line-height: 18px; - } - - &__text-wrapper { - display: flex; - flex: 1 0; - justify-content: space-between; - align-items: center; - margin-left: 80px; - } - - &__button { - button { - border-radius: 0; - } - - .button__content { - font-size: 20px; - font-weight: bold; - } - } - - &__close { - display: flex; - align-items: center; - margin-left: 36px; - - &-icon { - background: @close-tokenomica-icon center no-repeat; - border: 0; - width: 16px; - height: 16px; - - &:hover { - opacity: .5; - } - } - } - - &.hidden-toaster { - transform: translateY(100%); - } - - @media screen and (max-width: 768px) { - display: flex; - padding: 24px; - border-radius: 16px 16px 0 0; - align-items: flex-start; - - &__link { - flex-direction: column; - align-items: flex-start; - } - - &__logo { - margin: 0 0 16px 0; - width: 109px; - height: 24px; - } - - &__text-wrapper { - flex-direction: column; - align-items: flex-start; - width: 100%; - margin-left: 0; - } - - &__text { - font-size: 14px; - margin: 0 0 16px 0; - line-height: 20px; - width: 100%; - } - - &__button { - width: 100%; - - .button { - width: 100%; - } - - .button__content { - font-size: 16px; - } - } - - &__close { - margin: -6px; - } - } -} diff --git a/src/modules/wallet/modules/assets/controllers/AssetsCtrl.js b/src/modules/wallet/modules/assets/controllers/AssetsCtrl.js index c022ac0c7..df27b4ebb 100644 --- a/src/modules/wallet/modules/assets/controllers/AssetsCtrl.js +++ b/src/modules/wallet/modules/assets/controllers/AssetsCtrl.js @@ -13,8 +13,18 @@ * @param {BalanceWatcher} balanceWatcher * @return {Assets} */ - const controller = function (waves, assetsData, $scope, utils, Base, - user, modalManager, createPoll, balanceWatcher) { + const controller = function ( + waves, + assetsData, + $scope, + utils, + Base, + user, + modalManager, + createPoll, + balanceWatcher, + storage + ) { const { date } = require('ts-utils'); const ds = require('data-service'); @@ -95,6 +105,10 @@ constructor() { super($scope); + storage.load('hideTokenomicaToast').then((flag) => { + this.toastTokenomikaVisible = !flag; + }); + this.options.axes.x.tickFormat = (date) => { if (this.chartMode === 'hour' || this.chartMode === 'day') { return this.dateToHours(date); @@ -404,6 +418,12 @@ return hasYear ? tsUtils.date('DD.MM.YYYY')(date) : tsUtils.date('DD.MM')(date); } + hideTokenomicaToast() { + storage.save('hideTokenomicaToast', true).then(() => { + this.toastTokenomikaVisible = false; + }); + } + } return new Assets(); @@ -418,7 +438,8 @@ 'user', 'modalManager', 'createPoll', - 'balanceWatcher' + 'balanceWatcher', + 'storage' ]; angular.module('app.wallet.assets') diff --git a/src/modules/wallet/modules/assets/less/toaster-tokenomica.less b/src/modules/wallet/modules/assets/less/toaster-tokenomica.less new file mode 100644 index 000000000..cd6e52be0 --- /dev/null +++ b/src/modules/wallet/modules/assets/less/toaster-tokenomica.less @@ -0,0 +1,130 @@ +@import (reference) 'config'; +@import (reference) 'icons'; + +.toaster-tokenomica { + display: none; + position: fixed; + bottom: 0; + left: 0; + justify-content: space-between; + background: @color-black; + padding: 25px 32px; + width: 100%; + z-index: 5; + transform: translateY(0); + transition: transform 0.2s; + + &__link { + display: flex; + flex: 1 0; + justify-content: space-between; + align-items: center; + } + + &__logo { + background: @logo-tokenomica-icon center no-repeat; + background-size: 100%; + width: 184px; + height: 40px; + flex-shrink: 0; + margin-right: 16px; + } + + &__text { + font-size: 20px; + color: @color-white; + line-height: 18px; + } + + &__text-wrapper { + display: flex; + flex: 1 0; + justify-content: space-between; + align-items: center; + margin-left: 80px; + } + + &__button { + button { + border-radius: 0; + } + + .button__content { + font-size: 20px; + font-weight: bold; + } + } + + &__close { + display: flex; + align-items: center; + margin-left: 36px; + + &-icon { + background: @close-tokenomica-icon center no-repeat; + border: 0; + width: 16px; + height: 16px; + + &:hover { + opacity: .5; + } + } + } + + &.hidden-toaster { + transform: translateY(100%); + } + + @media screen and (max-width: 768px) { + display: flex; + padding: 24px; + border-radius: 16px 16px 0 0; + align-items: flex-start; + + &__link { + flex-direction: column; + align-items: flex-start; + } + + &__logo { + margin: 0 0 16px 0; + width: 109px; + height: 24px; + } + + &__text-wrapper { + flex-direction: column; + align-items: flex-start; + width: 100%; + margin-left: 0; + } + + &__text { + font-size: 14px; + margin: 0 0 16px 0; + line-height: 20px; + width: 100%; + } + + &__button { + width: 100%; + + .button { + width: 100%; + } + + .button__content { + font-size: 16px; + } + } + + &__close { + margin: -6px; + } + } +} + +.toaster_tokenomica_visible { + display: flex; +} \ No newline at end of file diff --git a/src/modules/wallet/modules/assets/templates/assets.html b/src/modules/wallet/modules/assets/templates/assets.html index 29cbb318f..d302b1a29 100644 --- a/src/modules/wallet/modules/assets/templates/assets.html +++ b/src/modules/wallet/modules/assets/templates/assets.html @@ -108,4 +108,22 @@

{{$ctrl.change > 0 ? '+' : '-'}}{{$ctrl.abs($ctrl.changePercent)}}%

+ + +
From 33ff0af525e880014c9c0dc4a471fd7f91ae9cd9 Mon Sep 17 00:00:00 2001 From: finico Date: Fri, 8 Nov 2019 17:50:59 +0300 Subject: [PATCH 042/144] DEXW-2320: Migration urls to configs --- configs/mainnet.json | 5 +++++ configs/stagenet.json | 5 +++++ configs/testnet.json | 5 +++++ src/index.hbs | 3 ++- src/modules/utils/modals/migrateModal/migrateModal.js | 6 +++--- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/configs/mainnet.json b/configs/mainnet.json index 11dca9fd1..a97c3690b 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -26,6 +26,11 @@ "origin": "https://client.wavesplatform.com", "featuresConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/config.json", "feeConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/fee.json", + "migration": { + "webUrl": "https://localhost:8080/migration", + "desktopUrl": "http://localhost:8888/connect", + "desktopPort": 8888 + }, "WESTNetworkByte": "V", "tokenrating": "https://tokenrating.wavesexplorer.com", "assets": { diff --git a/configs/stagenet.json b/configs/stagenet.json index 23244c0c0..0a4278dbe 100644 --- a/configs/stagenet.json +++ b/configs/stagenet.json @@ -26,6 +26,11 @@ "origin": "https://testnet.wavesplatform.com", "featuresConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/testnet.config.json", "feeConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/fee.json", + "migration": { + "webUrl": "https://localhost:8080/migration", + "desktopUrl": "http://localhost:8888/connect", + "desktopPort": 8888 + }, "WESTNetworkByte": "S", "tokenrating": "https://dev.voting.wavesplatform.com", "assets": { diff --git a/configs/testnet.json b/configs/testnet.json index 34d09da19..c73edc32e 100644 --- a/configs/testnet.json +++ b/configs/testnet.json @@ -26,6 +26,11 @@ "origin": "https://testnet.wavesplatform.com", "featuresConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/testnet.config.json", "feeConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/fee.json", + "migration": { + "webUrl": "https://localhost:8080/migration", + "desktopUrl": "http://localhost:8888/connect", + "desktopPort": 8888 + }, "WESTNetworkByte": "F", "tokenrating": "https://dev.voting.wavesplatform.com", "assets": { diff --git a/src/index.hbs b/src/index.hbs index 4a0eb3e1d..cc4c02598 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -351,7 +351,8 @@ tokenrating: config.network.tokenrating, featuresConfig: config.network.featuresConfig, feeConfig: config.network.feeConfig, - wavesExchangeLink: config.network.wavesExchangeLink + wavesExchangeLink: config.network.wavesExchangeLink, + migration: config.network.migration }, defaultAssets: { WAVES: 'WAVES', diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index b5790fce7..fdef35fa1 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -76,12 +76,12 @@ if (WavesApp.isDesktop()) { return new ds.connect.HttpConnectProvider({ - port: 8888, - url: 'http://localhost:8888/connect', + port: WavesApp.network.migration.desktopPort, + url: WavesApp.network.migration.desktopUrl, origins }); } else { - const childWindow = window.open('https://localhost:8080/migration'); + const childWindow = window.open(WavesApp.network.migration.webUrl); return new ds.connect.PostMessageConnectProvider({ win: childWindow, From ce2514bbb330e3f10694cdb2f92ca765fe3f929b Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Mon, 11 Nov 2019 11:39:18 +0300 Subject: [PATCH 043/144] DEXW-2282: save migrations flag in storage --- src/modules/utils/modals/migrateModal/migrateModal.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index b5790fce7..8deee2717 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -10,8 +10,9 @@ * @param {ng.ILogService} $log * @param {*} $mdDialog * @param {*} storageExporter + * @param {*} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter, $scope) { + const controller = function (Base, $log, $mdDialog, storageExporter, $scope, storage) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -54,8 +55,12 @@ $log.log('done'); this.step++; $scope.$apply(); + + return storage.save('migrationSuccess', true); } else { $log.log('fail', result); + + return storage.save('migrationSuccess', false); } }).catch((e) => { $log.error(e); @@ -64,6 +69,7 @@ cancel() { $mdDialog.cancel(); + storage.save('notAutoOpenMigrationModal', true); } /** @@ -96,7 +102,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope', 'storage']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 858d47de22ac5f1ea71714d7516e809d8677701e Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Mon, 11 Nov 2019 12:11:48 +0300 Subject: [PATCH 044/144] DEXW-2322: added auuid --- src/modules/app/initialize/AppRun.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 0e1217410..e75307150 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -4,6 +4,8 @@ 'use strict'; const { Money } = require('@waves/data-entities'); + const { libs } = require('@waves/waves-transactions'); + const { base64Encode, blake2b, stringToBytes } = libs.crypto; const locationHref = location.href; const i18next = require('i18next'); @@ -352,6 +354,7 @@ }); user.loginSignal.on(() => { + analytics.addDefaultParams({ auuid: base64Encode(blake2b(stringToBytes(user.address))) }); userNotification.destroyAll(); i18nextReady.then(() => { this._updateUserNotifications(); From cad32f3492dea767dd06e606b373efeff6def9f5 Mon Sep 17 00:00:00 2001 From: vk Date: Mon, 11 Nov 2019 14:56:39 +0300 Subject: [PATCH 045/144] DEXW-2331: update ver and locales --- locale/de/app.migrate.json | 7 +++++-- locale/de/app.utils.json | 5 +++++ locale/en/app.migrate.json | 7 +++++-- locale/en/app.utils.json | 5 +++++ locale/es/app.migrate.json | 7 +++++-- locale/es/app.utils.json | 5 +++++ locale/et_EE/app.migrate.json | 7 +++++-- locale/et_EE/app.utils.json | 5 +++++ locale/fr/app.migrate.json | 7 +++++-- locale/fr/app.utils.json | 5 +++++ locale/hi_IN/app.migrate.json | 7 +++++-- locale/hi_IN/app.utils.json | 5 +++++ locale/id/app.migrate.json | 7 +++++-- locale/id/app.utils.json | 5 +++++ locale/it/app.migrate.json | 7 +++++-- locale/it/app.utils.json | 5 +++++ locale/ja/app.migrate.json | 7 +++++-- locale/ja/app.utils.json | 5 +++++ locale/ko/app.migrate.json | 7 +++++-- locale/ko/app.utils.json | 5 +++++ locale/nl_NL/app.migrate.json | 7 +++++-- locale/nl_NL/app.utils.json | 5 +++++ locale/pl/app.migrate.json | 7 +++++-- locale/pl/app.utils.json | 5 +++++ locale/pt_BR/app.migrate.json | 7 +++++-- locale/pt_BR/app.utils.json | 5 +++++ locale/pt_PT/app.migrate.json | 7 +++++-- locale/pt_PT/app.utils.json | 5 +++++ locale/ru/app.migrate.json | 7 +++++-- locale/ru/app.utils.json | 5 +++++ locale/tr/app.migrate.json | 7 +++++-- locale/tr/app.utils.json | 5 +++++ locale/zh_CN/app.migrate.json | 7 +++++-- locale/zh_CN/app.utils.json | 5 +++++ package.json | 2 +- 35 files changed, 171 insertions(+), 35 deletions(-) diff --git a/locale/de/app.migrate.json b/locale/de/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/de/app.migrate.json +++ b/locale/de/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/de/app.utils.json b/locale/de/app.utils.json index 706f0de62..fb8e71b34 100644 --- a/locale/de/app.utils.json +++ b/locale/de/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Wie man sich vor Phishing schützt" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ich verstehe" } }, "modals": { diff --git a/locale/en/app.migrate.json b/locale/en/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/en/app.migrate.json +++ b/locale/en/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/en/app.utils.json b/locale/en/app.utils.json index 529d0101d..b55f5b171 100644 --- a/locale/en/app.utils.json +++ b/locale/en/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "How To Protect Yourself from Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "I Understand" } }, "modals": { diff --git a/locale/es/app.migrate.json b/locale/es/app.migrate.json index dbf38ef43..819159488 100644 --- a/locale/es/app.migrate.json +++ b/locale/es/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Introduzca la contraseña de su cuenta o", "goBack": "Volver", - "unlock": "Desbloquee sus cuentas. Puedes volver a este paso más tarde" + "goBackExchange": "go back", + "unlock": "Desbloquee sus cuentas. Puedes volver a este paso más tarde", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Desbloquee sus cuentas", - "unlockAccount": "Desbloquear cuenta" + "unlockAccount": "Desbloquear cuenta", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Cuenta", diff --git a/locale/es/app.utils.json b/locale/es/app.utils.json index 61a7a6578..533307e91 100644 --- a/locale/es/app.utils.json +++ b/locale/es/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "¿Cómo protegerte de los estafadores?" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Lo entiendo" } }, "modals": { diff --git a/locale/et_EE/app.migrate.json b/locale/et_EE/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/et_EE/app.migrate.json +++ b/locale/et_EE/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/et_EE/app.utils.json b/locale/et_EE/app.utils.json index 3c7f47325..d1ab71dc3 100644 --- a/locale/et_EE/app.utils.json +++ b/locale/et_EE/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Kuidas Kaitsta End Andmepüüdjate Eest" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ma saan aru" } }, "modals": { diff --git a/locale/fr/app.migrate.json b/locale/fr/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/fr/app.migrate.json +++ b/locale/fr/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/fr/app.utils.json b/locale/fr/app.utils.json index 7b21cc9d7..d7f84d37f 100644 --- a/locale/fr/app.utils.json +++ b/locale/fr/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Comment vous protéger des escrocs" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Je comprends" } }, "modals": { diff --git a/locale/hi_IN/app.migrate.json b/locale/hi_IN/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/hi_IN/app.migrate.json +++ b/locale/hi_IN/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/hi_IN/app.utils.json b/locale/hi_IN/app.utils.json index b899e8a58..cfdd97baa 100644 --- a/locale/hi_IN/app.utils.json +++ b/locale/hi_IN/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "फिशर्स से खुद की सुरक्षा कैसे करें" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "मैं समझा" } }, "modals": { diff --git a/locale/id/app.migrate.json b/locale/id/app.migrate.json index 939b4c944..9886e0d28 100644 --- a/locale/id/app.migrate.json +++ b/locale/id/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Masukkan kata sandi akun Anda atau", "goBack": "kembali", - "unlock": "Buka kunci akun Anda. Anda dapat kembali ke langkah ini nanti" + "goBackExchange": "go back", + "unlock": "Buka kunci akun Anda. Anda dapat kembali ke langkah ini nanti", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Buka kunci akun Anda", - "unlockAccount": "Membuka akun" + "unlockAccount": "Membuka akun", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Akun", diff --git a/locale/id/app.utils.json b/locale/id/app.utils.json index e155a6589..131f8a67f 100644 --- a/locale/id/app.utils.json +++ b/locale/id/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Cara Melindungi Diri dari Phisher" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Saya mengerti" } }, "modals": { diff --git a/locale/it/app.migrate.json b/locale/it/app.migrate.json index 7ad71bc5b..a0905835e 100644 --- a/locale/it/app.migrate.json +++ b/locale/it/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Inserisci la password del tuo account oppure", "goBack": "torna indietro", - "unlock": "Sblocca i tuoi account. Potrai tornare a questo passaggio successivamente" + "goBackExchange": "go back", + "unlock": "Sblocca i tuoi account. Potrai tornare a questo passaggio successivamente", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Sblocca i tuoi account", - "unlockAccount": "Sblocca account" + "unlockAccount": "Sblocca account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/it/app.utils.json b/locale/it/app.utils.json index 3b7962e30..8ea3096f3 100644 --- a/locale/it/app.utils.json +++ b/locale/it/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Salva la tua frase SEED", "title": "Come proteggersi dai Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ho capito" } }, "modals": { diff --git a/locale/ja/app.migrate.json b/locale/ja/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/ja/app.migrate.json +++ b/locale/ja/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/ja/app.utils.json b/locale/ja/app.utils.json index a2ff66cf9..9e9667b55 100644 --- a/locale/ja/app.utils.json +++ b/locale/ja/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "あなたを詐欺師から守る方法" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "理解しました" } }, "modals": { diff --git a/locale/ko/app.migrate.json b/locale/ko/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/ko/app.migrate.json +++ b/locale/ko/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/ko/app.utils.json b/locale/ko/app.utils.json index db26f59aa..64a5e2502 100644 --- a/locale/ko/app.utils.json +++ b/locale/ko/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "피싱으로부터 자신을 보호하는 방법" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "모두 이해했습니다" } }, "modals": { diff --git a/locale/nl_NL/app.migrate.json b/locale/nl_NL/app.migrate.json index dddc1d627..04873dcd2 100644 --- a/locale/nl_NL/app.migrate.json +++ b/locale/nl_NL/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Voer uw accountwachtwoord of in", "goBack": "Ga terug", - "unlock": "Ontgrendel uw accounts. U kunt later naar deze stap terugkeren" + "goBackExchange": "go back", + "unlock": "Ontgrendel uw accounts. U kunt later naar deze stap terugkeren", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Ontgrendel uw accounts", - "unlockAccount": "Account ontgrendelen" + "unlockAccount": "Account ontgrendelen", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/nl_NL/app.utils.json b/locale/nl_NL/app.utils.json index ade78fc7c..fc402a86b 100644 --- a/locale/nl_NL/app.utils.json +++ b/locale/nl_NL/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Hoe u zichzelf tegen phishing kunt beschermen" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ik begrijp het" } }, "modals": { diff --git a/locale/pl/app.migrate.json b/locale/pl/app.migrate.json index 7734943ba..5e2abc2ce 100644 --- a/locale/pl/app.migrate.json +++ b/locale/pl/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Wprowadź swoje hasło do konta lub", "goBack": "powrót", - "unlock": "Odblokuj swoje konta. Możesz wrócić do tego kroku później." + "goBackExchange": "go back", + "unlock": "Odblokuj swoje konta. Możesz wrócić do tego kroku później.", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Odblokuj swoje konta", - "unlockAccount": "Odblokuj konto" + "unlockAccount": "Odblokuj konto", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Konto", diff --git a/locale/pl/app.utils.json b/locale/pl/app.utils.json index 5142acf36..c6706daff 100644 --- a/locale/pl/app.utils.json +++ b/locale/pl/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Jak uchronić się przed phishingiem" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Rozumiem" } }, "modals": { diff --git a/locale/pt_BR/app.migrate.json b/locale/pt_BR/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/pt_BR/app.migrate.json +++ b/locale/pt_BR/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/pt_BR/app.utils.json b/locale/pt_BR/app.utils.json index 1458e2898..f04fa7220 100644 --- a/locale/pt_BR/app.utils.json +++ b/locale/pt_BR/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Como se proteger de Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Eu Entendi" } }, "modals": { diff --git a/locale/pt_PT/app.migrate.json b/locale/pt_PT/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/pt_PT/app.migrate.json +++ b/locale/pt_PT/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/pt_PT/app.utils.json b/locale/pt_PT/app.utils.json index 90a9f1483..d8ec8e16d 100644 --- a/locale/pt_PT/app.utils.json +++ b/locale/pt_PT/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "How To Protect Yourself from Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "I Understand" } }, "modals": { diff --git a/locale/ru/app.migrate.json b/locale/ru/app.migrate.json index 1f11851ad..878885f9f 100644 --- a/locale/ru/app.migrate.json +++ b/locale/ru/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Введите пароль от вашего аккаунта или", "goBack": "вернитесь назад", - "unlock": "Разблокируйте аккаунты. Вы можете вернуться к этому шагу позже" + "goBackExchange": "go back", + "unlock": "Разблокируйте аккаунты. Вы можете вернуться к этому шагу позже", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Разблокируйте аккаунты", - "unlockAccount": "Разблокируйте аккаунт" + "unlockAccount": "Разблокируйте аккаунт", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Адрес/ Название аккаунта", diff --git a/locale/ru/app.utils.json b/locale/ru/app.utils.json index 9c9f0bca9..08dffc381 100644 --- a/locale/ru/app.utils.json +++ b/locale/ru/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Сохраните SEED", "title": "Как защититься от фишинга" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Я понял" } }, "modals": { diff --git a/locale/tr/app.migrate.json b/locale/tr/app.migrate.json index 168ea76e1..6fa827321 100644 --- a/locale/tr/app.migrate.json +++ b/locale/tr/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "Account", diff --git a/locale/tr/app.utils.json b/locale/tr/app.utils.json index 69fba3dc1..e348d717d 100644 --- a/locale/tr/app.utils.json +++ b/locale/tr/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Kendinizi nasıl koruyacaksınız?" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Anladım" } }, "modals": { diff --git a/locale/zh_CN/app.migrate.json b/locale/zh_CN/app.migrate.json index 00b679741..f0956ab58 100644 --- a/locale/zh_CN/app.migrate.json +++ b/locale/zh_CN/app.migrate.json @@ -6,11 +6,14 @@ "description": { "enterPass": "输入您的帐户密码或", "goBack": "回来", - "unlock": "解锁您的帐户。您可以稍后返回此步骤" + "goBackExchange": "go back", + "unlock": "解锁您的帐户。您可以稍后返回此步骤", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "解锁您的帐户", - "unlockAccount": "解锁帐户" + "unlockAccount": "解锁帐户", + "unlockExchange": "Unlock Accounts" }, "subtitle": { "account": "帐户", diff --git a/locale/zh_CN/app.utils.json b/locale/zh_CN/app.utils.json index 6e2c57e95..d980ce68f 100644 --- a/locale/zh_CN/app.utils.json +++ b/locale/zh_CN/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "保存SEED短语", "title": "如何防止网络钓鱼攻击" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "我了解" } }, "modals": { diff --git a/package.json b/package.json index ec8daae8f..684d2e475 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "waves-client", - "version": "1.4.11", + "version": "1.4.12", "description": "The official client application for the Waves platform", "private": true, "repository": { From 7b64933e6bcb4f6c0b6024acc1f52fbc7ebeafd2 Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Mon, 11 Nov 2019 15:05:13 +0300 Subject: [PATCH 046/144] DEXW-2314: fix buttin --- src/modules/wallet/modules/assets/less/toaster-tokenomica.less | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/wallet/modules/assets/less/toaster-tokenomica.less b/src/modules/wallet/modules/assets/less/toaster-tokenomica.less index cd6e52be0..7be7854bf 100644 --- a/src/modules/wallet/modules/assets/less/toaster-tokenomica.less +++ b/src/modules/wallet/modules/assets/less/toaster-tokenomica.less @@ -77,7 +77,6 @@ } @media screen and (max-width: 768px) { - display: flex; padding: 24px; border-radius: 16px 16px 0 0; align-items: flex-start; From d28527a3664c668ef9363c58008fd5950fcfe539 Mon Sep 17 00:00:00 2001 From: Boris Volkov Date: Mon, 11 Nov 2019 16:04:53 +0300 Subject: [PATCH 047/144] Revert "Dexw 2282 day x old" --- src/modules/utils/modals/migrateModal/migrateModal.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index bd4c23578..fdef35fa1 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -10,9 +10,8 @@ * @param {ng.ILogService} $log * @param {*} $mdDialog * @param {*} storageExporter - * @param {*} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter, $scope, storage) { + const controller = function (Base, $log, $mdDialog, storageExporter, $scope) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -55,12 +54,8 @@ $log.log('done'); this.step++; $scope.$apply(); - - return storage.save('migrationSuccess', true); } else { $log.log('fail', result); - - return storage.save('migrationSuccess', false); } }).catch((e) => { $log.error(e); @@ -69,7 +64,6 @@ cancel() { $mdDialog.cancel(); - storage.save('notAutoOpenMigrationModal', true); } /** @@ -102,7 +96,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope', 'storage']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 5a053bc60c612aee916832cba65cf4cbbe2864b0 Mon Sep 17 00:00:00 2001 From: Boris Volkov Date: Mon, 11 Nov 2019 16:05:26 +0300 Subject: [PATCH 048/144] Revert "Revert "Dexw 2282 day x old"" --- src/modules/utils/modals/migrateModal/migrateModal.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index fdef35fa1..bd4c23578 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -10,8 +10,9 @@ * @param {ng.ILogService} $log * @param {*} $mdDialog * @param {*} storageExporter + * @param {*} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter, $scope) { + const controller = function (Base, $log, $mdDialog, storageExporter, $scope, storage) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -54,8 +55,12 @@ $log.log('done'); this.step++; $scope.$apply(); + + return storage.save('migrationSuccess', true); } else { $log.log('fail', result); + + return storage.save('migrationSuccess', false); } }).catch((e) => { $log.error(e); @@ -64,6 +69,7 @@ cancel() { $mdDialog.cancel(); + storage.save('notAutoOpenMigrationModal', true); } /** @@ -96,7 +102,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope', 'storage']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); From 76d4aad857441ca9087e7de2ea72ecc714a12582 Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Mon, 11 Nov 2019 16:49:03 +0300 Subject: [PATCH 049/144] DEXW-2282: fix header --- .../less/largeHeader/largeHeader.less | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less b/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less index d89241a3a..db68f832e 100644 --- a/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less +++ b/src/modules/ui/directives/mainHeader/less/largeHeader/largeHeader.less @@ -300,11 +300,23 @@ } @media screen and (max-width: 860px) { - .main-header__header { - .top-menu, - .header-logout, - .buttons-wrapper { - display: none; + .main-header { + &__header { + .top-menu, + .header-logout, + .buttons-wrapper { + display: none; + } + } + + &_new-user { + top: 56px; + + &.fixed { + .main-header__header { + top: 56px; + } + } } } From 0479afd7280ea174efb88d02f31d441761de420a Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Mon, 11 Nov 2019 18:05:43 +0300 Subject: [PATCH 050/144] DEXW-2332: change warning plate logic --- .../ComponentWarningPlate.js | 17 ++++++++++------- .../componentWarningPlate.html | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index d028347bf..1e08ac37a 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -28,7 +28,7 @@ /** * @type {boolean} */ - hasAccounts = false; + canMoveAccounts = false; /** * @type {boolean} */ @@ -39,14 +39,17 @@ newDexLink = WavesApp.network.wavesExchangeLink; constructor() { - this._initHasAccounts(); + this._initCanMoveAccounts(); this._initMigrationSuccess(); storage.change.on(() => { this._initMigrationSuccess(); - this._initHasAccounts(); + this._initCanMoveAccounts(); }); + user.loginSignal.on(this._initCanMoveAccounts, this); + user.logoutSignal.on(this._initCanMoveAccounts, this); + utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); } @@ -76,15 +79,15 @@ /** * @private */ - _initHasAccounts() { + _initCanMoveAccounts() { Promise.all([ user.getFilteredUserList(), user.getMultiAccountData() ]).then(([userList, multiAccountData]) => { - if (multiAccountData || (userList && userList.length)) { - this.hasAccounts = true; + if ((multiAccountData && user.isAuthorised) || (userList && userList.length)) { + this.canMoveAccounts = true; } else { - this.hasAccounts = false; + this.canMoveAccounts = false; } $scope.$apply(); }); diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index f4c3b1764..a5605f652 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -1,4 +1,4 @@ -
@@ -22,7 +22,7 @@ w-i18n="warningPlate.startMoving">
-
+
{{$ctrl.days}} From c38335af2cb610054e20ef759f16acaa6217359f Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Tue, 12 Nov 2019 10:32:15 +0300 Subject: [PATCH 051/144] DEXW-2333: fix show migrate modal --- src/modules/signIn/controllers/SignInCtrl.js | 26 ++++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/modules/signIn/controllers/SignInCtrl.js b/src/modules/signIn/controllers/SignInCtrl.js index d051e2f48..f1d763f88 100644 --- a/src/modules/signIn/controllers/SignInCtrl.js +++ b/src/modules/signIn/controllers/SignInCtrl.js @@ -21,6 +21,11 @@ * @type {Array|null} */ legacyUserList = null; + /** + * @type {Array} + * @private + */ + _onLoginHandlers = []; constructor() { super($scope); @@ -38,15 +43,18 @@ } }); + this._onLoginHandlers.push(this._showMigrateModal); + user.onLogin().then(() => { - storage.load('notAutoOpenMigrationModal').then((notAutoOpenMigrationModal) => { - if (!notAutoOpenMigrationModal) { - modalManager.showMigrateModal(); - } - }); + this._onLoginHandlers.forEach((handler) => handler()); }); } + $onDestroy() { + super.$onDestroy(); + this._onLoginHandlers = []; + } + onLogin() { Promise.all([ user.getMultiAccountUsers(), @@ -103,6 +111,14 @@ } } + _showMigrateModal = () => { + storage.load('notAutoOpenMigrationModal').then((notAutoOpenMigrationModal) => { + if (!notAutoOpenMigrationModal) { + modalManager.showMigrateModal(); + } + }); + }; + } return new SignInCtrl(); From 1aafe3415ba0c510e72c132566bee31727738759 Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Tue, 12 Nov 2019 10:56:50 +0300 Subject: [PATCH 052/144] DEXW-2225: update electron-packager --- package-lock.json | 855 ++++++++++++++++++++++++++-------------------- package.json | 2 +- 2 files changed, 492 insertions(+), 365 deletions(-) diff --git a/package-lock.json b/package-lock.json index d717e80c7..7cad4c24c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "waves-client", - "version": "1.4.7", + "version": "1.4.10", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -177,6 +177,71 @@ "ajv-keywords": "^3.1.0" } }, + "@electron/get": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.6.0.tgz", + "integrity": "sha512-xuvAzbN9iBApfAMvW0hKUpxHR5wPVbG9RaoSTbpu/WaHISDu0MVfMWYhfeU0X730CpBV0G2RkLgwAs9WDan3GA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^2.0.2", + "global-tunnel-ng": "^2.7.1", + "got": "^9.6.0", + "sanitize-filename": "^1.6.2", + "sumchecker": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "sumchecker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.0.tgz", + "integrity": "sha512-yreseuC/z4iaodVoq07XULEOO9p4jnQazO7mbrnDSvWAU/y2cbyIKs+gWJptfcGu9R+1l27K8Rkj0bfvqnBpgQ==", + "dev": true, + "requires": { + "debug": "^4.1.0" + } + } + } + }, "@ledgerhq/devices": { "version": "4.70.0", "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-4.70.0.tgz", @@ -974,12 +1039,6 @@ "through": ">=2.2.7 <3" } }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "accord": { "version": "0.29.0", "resolved": "https://registry.npmjs.org/accord/-/accord-0.29.0.tgz", @@ -1647,33 +1706,25 @@ "optional": true }, "asar": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/asar/-/asar-0.14.5.tgz", - "integrity": "sha512-2Di/TnY1sridHFKMFgxBh0Wk0gVxSZN4qQhRhjJn3UywZAvP5MHI0RNVSkpzmJ+n6t0BC8w/+1257wtSgQ3Kdg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/asar/-/asar-2.0.1.tgz", + "integrity": "sha512-Vo9yTuUtyFahkVMFaI6uMuX6N7k5DWa6a/8+7ov0/f8Lq9TVR0tUjzSzxQSxT1Y+RJIZgnP7BVb6Uhi+9cjxqA==", "dev": true, "requires": { "chromium-pickle-js": "^0.2.0", - "commander": "^2.9.0", - "cuint": "^0.2.1", - "glob": "^6.0.4", - "minimatch": "^3.0.3", - "mkdirp": "^0.5.0", - "mksnapshot": "^0.3.0", - "tmp": "0.0.28" + "commander": "^2.20.0", + "cuint": "^0.2.2", + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "tmp-promise": "^1.0.5" }, "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true } } }, @@ -1983,15 +2034,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, - "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -2940,16 +2989,6 @@ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-8.1.1.tgz", "integrity": "sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ==" }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, "binary-extensions": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", @@ -2957,9 +2996,9 @@ "dev": true }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", "dev": true }, "bluebird-lst": { @@ -2991,6 +3030,12 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, + "boolean": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-2.0.3.tgz", + "integrity": "sha512-iHzXeFCXWrpjYE7DToXGCBPGZf0eVISqzL+4sgrOSYEKXnb59WHPFvGTTyCj6zJ/MuuLAxEn8zPkrTHHzlt3IA==", + "dev": true + }, "boxen": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", @@ -3461,12 +3506,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, "builder-util": { "version": "21.2.0", "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz", @@ -3795,15 +3834,6 @@ "lazy-cache": "^1.0.3" } }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -4256,6 +4286,17 @@ } } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "optional": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "configstore": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", @@ -4401,6 +4442,26 @@ "which": "^1.2.9" } }, + "cross-zip": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/cross-zip/-/cross-zip-2.1.6.tgz", + "integrity": "sha512-xLIETNkzRcU6jGRzenJyRFxahbtP4628xEKMTI/Ql0Vu8m4h8M7uRLVi7E5OYHuJ6VQPsG4icJumKAFUvfm0+A==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -4906,21 +4967,6 @@ "mimic-response": "^1.0.0" } }, - "decompress-zip": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.2.tgz", - "integrity": "sha512-Ab1QY4LrWMrUuo53lLnmGOby7v8ryqxJ+bKibKSiPisx+25mhut1dScVBXAYx14i/PqSrFZvR2FRRazhLbvL+g==", - "dev": true, - "requires": { - "binary": "^0.3.0", - "graceful-fs": "^4.1.3", - "mkpath": "^0.1.0", - "nopt": "^3.0.1", - "q": "^1.1.2", - "readable-stream": "^1.1.8", - "touch": "0.0.3" - } - }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -5219,6 +5265,13 @@ "repeating": "^2.0.0" } }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true, + "optional": true + }, "diff": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", @@ -5790,10 +5843,54 @@ } } }, + "electron-notarize": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-0.1.1.tgz", + "integrity": "sha512-TpKfJcz4LXl5jiGvZTs5fbEx+wUFXV5u8voeG5WCHWfY/cdgdD8lDZIZRqLVOtR3VO+drgJ9aiSHIO9TYn/fKg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^8.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "electron-osx-sign": { - "version": "0.4.10", - "resolved": "http://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.10.tgz", - "integrity": "sha1-vk87ibKnWh3F8eckkIGrKSnKOiY=", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.14.tgz", + "integrity": "sha512-72vtrz9I3dOeFDaNvO5thwIjrimDiXMmYEbN0hEBqnvcSSMOWugjim2wiY9ox3dhuBFUhxp3owmuZCoH3Ij08A==", "dev": true, "requires": { "bluebird": "^3.5.0", @@ -5801,152 +5898,94 @@ "debug": "^2.6.8", "isbinaryfile": "^3.0.2", "minimist": "^1.2.0", - "plist": "^2.1.0" + "plist": "^3.0.1" }, "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "electron-packager": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-12.1.0.tgz", - "integrity": "sha1-BI3U/zhIvhnFhzwxW1sxLfYhUyg=", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-14.1.0.tgz", + "integrity": "sha512-4oGtQYYjSA/M4BGOwG0NBqEtThBf7aCV76C2AZsD71eGocYqZNvtvfzeeMnKkc3EW1nPq7iJ4Wge+GXma0kwIA==", "dev": true, "requires": { - "asar": "^0.14.0", - "debug": "^3.0.0", - "electron-download": "^4.0.0", - "electron-osx-sign": "^0.4.1", - "extract-zip": "^1.0.3", - "fs-extra": "^5.0.0", + "@electron/get": "^1.6.0", + "asar": "^2.0.1", + "cross-zip": "^2.1.5", + "debug": "^4.0.1", + "electron-notarize": "^0.1.1", + "electron-osx-sign": "^0.4.11", + "fs-extra": "^8.1.0", "galactus": "^0.2.1", "get-package-info": "^1.0.0", - "nodeify": "^1.0.1", + "junk": "^3.1.0", "parse-author": "^2.0.0", - "pify": "^3.0.0", - "plist": "^2.0.0", - "rcedit": "^1.0.0", + "plist": "^3.0.0", + "rcedit": "^2.0.0", "resolve": "^1.1.6", "sanitize-filename": "^1.6.0", - "semver": "^5.3.0", - "yargs-parser": "^10.0.0" + "semver": "^6.0.0", + "yargs-parser": "^16.0.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, - "electron-download": { + "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", - "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "debug": "^3.0.0", - "env-paths": "^1.0.0", - "fs-extra": "^4.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.1", - "path-exists": "^3.0.0", - "rc": "^1.2.1", - "semver": "^5.4.1", - "sumchecker": "^2.0.2" - }, - "dependencies": { - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - } + "ms": "^2.1.1" } }, "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "sumchecker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", - "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", - "dev": true, - "requires": { - "debug": "^2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -6132,6 +6171,13 @@ "next-tick": "1" } }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", @@ -6770,28 +6816,39 @@ } }, "flora-colossus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.0.tgz", - "integrity": "sha1-VHKcNh7ezuAU3UQWeeGjfB13OkU=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.1.tgz", + "integrity": "sha512-d+9na7t9FyH8gBJoNDSi28mE4NgQVGGvxQ4aHtFRetjyh5SXjuus+V5EZaxFmFdXVemSOrx0lsgEl/ZMjnOWJA==", "dev": true, "requires": { - "debug": "^3.1.0", - "fs-extra": "^4.0.0" + "debug": "^4.1.1", + "fs-extra": "^7.0.0" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" } }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -7015,8 +7072,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -7037,14 +7093,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7059,20 +7113,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -7189,8 +7240,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -7202,7 +7252,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7217,7 +7266,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7225,14 +7273,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7251,7 +7297,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7339,8 +7384,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7352,7 +7396,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7438,8 +7481,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7475,7 +7517,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7495,7 +7536,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7539,14 +7579,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -7583,9 +7621,9 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -7647,6 +7685,20 @@ "assert-plus": "^1.0.0" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", @@ -7672,15 +7724,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, - "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -7775,6 +7825,38 @@ "object.defaults": "^1.1.0" } }, + "global-agent": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.6.tgz", + "integrity": "sha512-fL+xfraAlc1MXU8Gs0DAg/eHH+H1CjxbK+BLU3Qt55dAVMAQ8fH8k/UrLwV4A+Vk/hl/TePWuTxFnqJzCV1/Kw==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^2.0.3", + "core-js": "^3.4.0", + "es6-error": "^4.1.1", + "matcher": "^2.0.0", + "roarr": "^2.14.4", + "semver": "^6.3.0", + "serialize-error": "^5.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.1.tgz", + "integrity": "sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg==", + "dev": true, + "optional": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "optional": true + } + } + }, "global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -7808,12 +7890,46 @@ "which": "^1.2.14" } }, + "global-tunnel-ng": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", + "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", + "dev": true, + "optional": true, + "requires": { + "encodeurl": "^1.0.2", + "lodash": "^4.17.10", + "npm-conf": "^1.1.3", + "tunnel": "^0.0.6" + } + }, "globals": { "version": "11.9.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", "dev": true }, + "globalthis": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.0.tgz", + "integrity": "sha512-vcCAZTJ3r5Qcu5l8/2oyVdoFwxKgfYnMTR2vwWeux/NAVZK3PwcMaWkdUIn4GJbmKuRK7xcvDsLuK+CKcXyodg==", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "object-keys": "^1.0.12" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "optional": true + } + } + }, "globby": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", @@ -10350,12 +10466,6 @@ "dev": true, "optional": true }, - "is-promise": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", - "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=", - "dev": true - }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -10588,9 +10698,9 @@ "dev": true }, "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "^4.1.6" @@ -10620,6 +10730,12 @@ "verror": "1.10.0" } }, + "junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true + }, "just-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", @@ -10641,15 +10757,6 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, "labeled-stream-splicer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", @@ -11156,7 +11263,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { @@ -11548,6 +11655,25 @@ "stack-trace": "0.0.10" } }, + "matcher": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-2.0.0.tgz", + "integrity": "sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng==", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "optional": true + } + } + }, "math-expression-evaluator": { "version": "1.2.17", "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", @@ -11817,38 +11943,6 @@ "minimist": "0.0.8" } }, - "mkpath": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", - "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=", - "dev": true - }, - "mksnapshot": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.5.tgz", - "integrity": "sha512-PSBoZaj9h9myC3uRRW62RxmX8mrN3XbOkMEyURUD7v5CeJgtYTar50XU738t7Q0LtG1pBPtp5n5QwDGggRnEvw==", - "dev": true, - "requires": { - "decompress-zip": "0.3.x", - "fs-extra": "0.26.7", - "request": "2.x" - }, - "dependencies": { - "fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - } - } - }, "mobile-detect": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/mobile-detect/-/mobile-detect-1.4.3.tgz", @@ -12040,36 +12134,6 @@ "semver": "^5.3.0" } }, - "nodeify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", - "integrity": "sha1-ZKtpp7268DzhB7TwM1yHwLnpGx0=", - "dev": true, - "requires": { - "is-promise": "~1.0.0", - "promise": "~1.3.0" - }, - "dependencies": { - "promise": { - "version": "1.3.0", - "resolved": "http://registry.npmjs.org/promise/-/promise-1.3.0.tgz", - "integrity": "sha1-5cyaTIJ45GZP/twBx9qEhCsEAXU=", - "dev": true, - "requires": { - "is-promise": "~1" - } - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -12112,6 +12176,26 @@ "once": "^1.3.2" } }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "optional": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "optional": true + } + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -12634,8 +12718,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-glob": { "version": "2.0.1", @@ -12884,22 +12967,14 @@ } }, "plist": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", - "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", "dev": true, "requires": { - "base64-js": "1.2.0", - "xmlbuilder": "8.2.2", + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", "xmldom": "0.1.x" - }, - "dependencies": { - "base64-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", - "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", - "dev": true - } } }, "plugin-error": { @@ -15045,6 +15120,13 @@ "asap": "~2.0.3" } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true, + "optional": true + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -15228,9 +15310,9 @@ } }, "rcedit": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-1.1.1.tgz", - "integrity": "sha512-6NjOhOpkvbc/gpMEfk2hpXuWyHfbLFN8as5jx3jf4bhELvouRoYvc8d/W3NVVPwEBF1ICfbpwp1oRm8OJ2WDWw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-2.1.0.tgz", + "integrity": "sha512-Nrd/65LzMjFmKpS9d2fqIxVYdW0M8ovsN0PgZhCrPMQss2yznkp6/zjEQ1a9DzzoGv2uuN3yDJAeHybOD5ZNKA==", "dev": true }, "read-cache": { @@ -15870,6 +15952,30 @@ "inherits": "^2.0.1" } }, + "roarr": { + "version": "2.14.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.14.4.tgz", + "integrity": "sha512-QMzRAQGZFPgnx4nNWp4Q+WHfiZh2HTSEjNaxFLrEIj3PmcQ1GHL5OjaaIyF9ybUDD2aZ9t3Awc/obrRPils9ng==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^2.0.3", + "detect-node": "^2.0.4", + "globalthis": "^1.0.0", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true + } + } + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -15938,9 +16044,9 @@ "dev": true }, "sanitize-filename": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", - "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "dev": true, "requires": { "truncate-utf8-bytes": "^1.0.0" @@ -16015,6 +16121,25 @@ } } }, + "serialize-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-5.0.0.tgz", + "integrity": "sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==", + "dev": true, + "optional": true, + "requires": { + "type-fest": "^0.8.0" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "optional": true + } + } + }, "serve-static": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", @@ -17135,12 +17260,33 @@ "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" }, "tmp": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", - "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.1" + "rimraf": "^2.6.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "tmp-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-1.1.0.tgz", + "integrity": "sha512-8+Ah9aB1IRXCnIOxXZ0uFozV1nMU5xiu7hhFVUSxZ3bYu+psD4TzagCzVbexUCgNNGJnsmNDQlS4nG3mTyoNkw==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "tmp": "0.1.0" } }, "to-absolute-glob": { @@ -17270,26 +17416,6 @@ } } }, - "touch": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", - "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", - "dev": true, - "requires": { - "nopt": "~1.0.10" - }, - "dependencies": { - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - } - } - }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -17308,12 +17434,6 @@ } } }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -17379,6 +17499,13 @@ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "optional": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -18119,9 +18246,9 @@ "dev": true }, "xmlbuilder": { - "version": "8.2.2", - "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, "xmldom": { diff --git a/package.json b/package.json index d1225ec19..ad2022d00 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cssnano": "4.1.10", "electron": "^6.0.12", "electron-builder": "^21.2.0", - "electron-packager": "12.1.0", + "electron-packager": "^14.1.0", "eslint": "4.18.2", "fs-extra": "4.0.2", "gulp": "4.0.2", From 88e51065577c97502121b151b66b30b9da9693ec Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Tue, 12 Nov 2019 11:14:30 +0300 Subject: [PATCH 053/144] DEXW-2282: fix --- src/themeConfig/default/icons.less | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/themeConfig/default/icons.less b/src/themeConfig/default/icons.less index 2c9cecbcc..b1b3189c1 100644 --- a/src/themeConfig/default/icons.less +++ b/src/themeConfig/default/icons.less @@ -155,12 +155,8 @@ @importBackupFile-icon: url(/img/icons/keystore-file.svg); @importBackupPassword-icon: url(/img/icons/backup-password.svg); @importKeyStore-file-icon: url(/img/icons/import-keystore-file.svg); -<<<<<<< HEAD @timer-icon: url(/img/icons/time-filled.svg); @moving-icon: url(/img/icons/moving.svg); @directed-icon: url(/img/icons/directed-icon.svg); -======= - @close-tokenomica-icon: url(/img/icons/close-tokenomica.svg); @logo-tokenomica-icon: url(/img/icons/logotype.svg); ->>>>>>> dev From e238c2682e4449ad615b87b73b63daa3bce49f50 Mon Sep 17 00:00:00 2001 From: vba2000 Date: Tue, 12 Nov 2019 14:35:49 +0300 Subject: [PATCH 054/144] DEXW-2225: fix index.hbs --- src/index.hbs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.hbs b/src/index.hbs index cc4c02598..3036b61f4 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -352,7 +352,8 @@ featuresConfig: config.network.featuresConfig, feeConfig: config.network.feeConfig, wavesExchangeLink: config.network.wavesExchangeLink, - migration: config.network.migration + migration: config.network.migration, + migrationOrigins: config.network.migrationOrigins, }, defaultAssets: { WAVES: 'WAVES', From 078561fc8bd9a05195be63051124cf10d8394c4b Mon Sep 17 00:00:00 2001 From: finico Date: Tue, 12 Nov 2019 17:43:38 +0300 Subject: [PATCH 055/144] DEXW-2225: Desktop migration over https --- configs/mainnet.json | 2 +- configs/stagenet.json | 2 +- configs/testnet.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configs/mainnet.json b/configs/mainnet.json index a97c3690b..1036fe3a5 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -28,7 +28,7 @@ "feeConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/fee.json", "migration": { "webUrl": "https://localhost:8080/migration", - "desktopUrl": "http://localhost:8888/connect", + "desktopUrl": "https://localhost:8888/connect", "desktopPort": 8888 }, "WESTNetworkByte": "V", diff --git a/configs/stagenet.json b/configs/stagenet.json index 0a4278dbe..e7fb0665c 100644 --- a/configs/stagenet.json +++ b/configs/stagenet.json @@ -28,7 +28,7 @@ "feeConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/fee.json", "migration": { "webUrl": "https://localhost:8080/migration", - "desktopUrl": "http://localhost:8888/connect", + "desktopUrl": "https://localhost:8888/connect", "desktopPort": 8888 }, "WESTNetworkByte": "S", diff --git a/configs/testnet.json b/configs/testnet.json index c73edc32e..3d03b8616 100644 --- a/configs/testnet.json +++ b/configs/testnet.json @@ -28,7 +28,7 @@ "feeConfigUrl": "https://raw.githubusercontent.com/wavesplatform/waves-client-config/master/fee.json", "migration": { "webUrl": "https://localhost:8080/migration", - "desktopUrl": "http://localhost:8888/connect", + "desktopUrl": "https://localhost:8888/connect", "desktopPort": 8888 }, "WESTNetworkByte": "F", From fdfeb6c5636947676c78ed229fcb7a772803f8b8 Mon Sep 17 00:00:00 2001 From: Vusal Gakhramanov Date: Tue, 12 Nov 2019 18:56:55 +0300 Subject: [PATCH 056/144] DEXW-2342: add text --- locale/de/app.migrate.json | 21 +++++++++++++++++-- locale/de/app.utils.json | 10 +++++++++ locale/en/app.migrate.json | 21 +++++++++++++++++-- locale/en/app.utils.json | 10 +++++++++ locale/es/app.migrate.json | 21 +++++++++++++++++-- locale/es/app.utils.json | 10 +++++++++ locale/et_EE/app.migrate.json | 21 +++++++++++++++++-- locale/et_EE/app.utils.json | 10 +++++++++ locale/fr/app.migrate.json | 21 +++++++++++++++++-- locale/fr/app.utils.json | 10 +++++++++ locale/hi_IN/app.migrate.json | 21 +++++++++++++++++-- locale/hi_IN/app.utils.json | 10 +++++++++ locale/id/app.migrate.json | 21 +++++++++++++++++-- locale/id/app.utils.json | 10 +++++++++ locale/it/app.migrate.json | 21 +++++++++++++++++-- locale/it/app.utils.json | 10 +++++++++ locale/ja/app.migrate.json | 21 +++++++++++++++++-- locale/ja/app.utils.json | 10 +++++++++ locale/ko/app.migrate.json | 21 +++++++++++++++++-- locale/ko/app.utils.json | 10 +++++++++ locale/nl_NL/app.migrate.json | 21 +++++++++++++++++-- locale/nl_NL/app.utils.json | 10 +++++++++ locale/pl/app.migrate.json | 21 +++++++++++++++++-- locale/pl/app.utils.json | 10 +++++++++ locale/pt_BR/app.migrate.json | 21 +++++++++++++++++-- locale/pt_BR/app.utils.json | 10 +++++++++ locale/pt_PT/app.migrate.json | 21 +++++++++++++++++-- locale/pt_PT/app.utils.json | 10 +++++++++ locale/ru/app.migrate.json | 21 +++++++++++++++++-- locale/ru/app.utils.json | 10 +++++++++ locale/tr/app.migrate.json | 21 +++++++++++++++++-- locale/tr/app.utils.json | 10 +++++++++ locale/zh_CN/app.migrate.json | 21 +++++++++++++++++-- locale/zh_CN/app.utils.json | 10 +++++++++ .../componentWarningPlate.html | 12 +++++------ .../modals/migrateModal/migrateModal.html | 17 ++++++++------- 36 files changed, 508 insertions(+), 48 deletions(-) diff --git a/locale/de/app.migrate.json b/locale/de/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/de/app.migrate.json +++ b/locale/de/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/de/app.utils.json b/locale/de/app.utils.json index 706f0de62..b71df5e5f 100644 --- a/locale/de/app.utils.json +++ b/locale/de/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Wie man sich vor Phishing schützt" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ich verstehe" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/en/app.migrate.json b/locale/en/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/en/app.migrate.json +++ b/locale/en/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/en/app.utils.json b/locale/en/app.utils.json index 529d0101d..087e171c4 100644 --- a/locale/en/app.utils.json +++ b/locale/en/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "How To Protect Yourself from Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "I Understand" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/es/app.migrate.json b/locale/es/app.migrate.json index dbf38ef43..98d953066 100644 --- a/locale/es/app.migrate.json +++ b/locale/es/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Introduzca la contraseña de su cuenta o", "goBack": "Volver", - "unlock": "Desbloquee sus cuentas. Puedes volver a este paso más tarde" + "goBackExchange": "go back", + "unlock": "Desbloquee sus cuentas. Puedes volver a este paso más tarde", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Desbloquee sus cuentas", - "unlockAccount": "Desbloquear cuenta" + "unlockAccount": "Desbloquear cuenta", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Cuenta", diff --git a/locale/es/app.utils.json b/locale/es/app.utils.json index 61a7a6578..a3fd1a389 100644 --- a/locale/es/app.utils.json +++ b/locale/es/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "¿Cómo protegerte de los estafadores?" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Lo entiendo" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/et_EE/app.migrate.json b/locale/et_EE/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/et_EE/app.migrate.json +++ b/locale/et_EE/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/et_EE/app.utils.json b/locale/et_EE/app.utils.json index 3c7f47325..3c02f35fd 100644 --- a/locale/et_EE/app.utils.json +++ b/locale/et_EE/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Kuidas Kaitsta End Andmepüüdjate Eest" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ma saan aru" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/fr/app.migrate.json b/locale/fr/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/fr/app.migrate.json +++ b/locale/fr/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/fr/app.utils.json b/locale/fr/app.utils.json index 7b21cc9d7..52d4d1389 100644 --- a/locale/fr/app.utils.json +++ b/locale/fr/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Comment vous protéger des escrocs" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Je comprends" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/hi_IN/app.migrate.json b/locale/hi_IN/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/hi_IN/app.migrate.json +++ b/locale/hi_IN/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/hi_IN/app.utils.json b/locale/hi_IN/app.utils.json index b899e8a58..05d749904 100644 --- a/locale/hi_IN/app.utils.json +++ b/locale/hi_IN/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "फिशर्स से खुद की सुरक्षा कैसे करें" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "मैं समझा" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/id/app.migrate.json b/locale/id/app.migrate.json index 939b4c944..008dbbe94 100644 --- a/locale/id/app.migrate.json +++ b/locale/id/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Masukkan kata sandi akun Anda atau", "goBack": "kembali", - "unlock": "Buka kunci akun Anda. Anda dapat kembali ke langkah ini nanti" + "goBackExchange": "go back", + "unlock": "Buka kunci akun Anda. Anda dapat kembali ke langkah ini nanti", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Buka kunci akun Anda", - "unlockAccount": "Membuka akun" + "unlockAccount": "Membuka akun", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Akun", diff --git a/locale/id/app.utils.json b/locale/id/app.utils.json index e155a6589..dcb8f93a3 100644 --- a/locale/id/app.utils.json +++ b/locale/id/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Cara Melindungi Diri dari Phisher" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Saya mengerti" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/it/app.migrate.json b/locale/it/app.migrate.json index 7ad71bc5b..74744df07 100644 --- a/locale/it/app.migrate.json +++ b/locale/it/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Inserisci la password del tuo account oppure", "goBack": "torna indietro", - "unlock": "Sblocca i tuoi account. Potrai tornare a questo passaggio successivamente" + "goBackExchange": "go back", + "unlock": "Sblocca i tuoi account. Potrai tornare a questo passaggio successivamente", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Sblocca i tuoi account", - "unlockAccount": "Sblocca account" + "unlockAccount": "Sblocca account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/it/app.utils.json b/locale/it/app.utils.json index 3b7962e30..b1283a1e5 100644 --- a/locale/it/app.utils.json +++ b/locale/it/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Salva la tua frase SEED", "title": "Come proteggersi dai Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ho capito" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ja/app.migrate.json b/locale/ja/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/ja/app.migrate.json +++ b/locale/ja/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/ja/app.utils.json b/locale/ja/app.utils.json index a2ff66cf9..b079a72c6 100644 --- a/locale/ja/app.utils.json +++ b/locale/ja/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "あなたを詐欺師から守る方法" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "理解しました" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ko/app.migrate.json b/locale/ko/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/ko/app.migrate.json +++ b/locale/ko/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/ko/app.utils.json b/locale/ko/app.utils.json index db26f59aa..c6bf0b00f 100644 --- a/locale/ko/app.utils.json +++ b/locale/ko/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "피싱으로부터 자신을 보호하는 방법" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "모두 이해했습니다" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/nl_NL/app.migrate.json b/locale/nl_NL/app.migrate.json index dddc1d627..54992ec05 100644 --- a/locale/nl_NL/app.migrate.json +++ b/locale/nl_NL/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Voer uw accountwachtwoord of in", "goBack": "Ga terug", - "unlock": "Ontgrendel uw accounts. U kunt later naar deze stap terugkeren" + "goBackExchange": "go back", + "unlock": "Ontgrendel uw accounts. U kunt later naar deze stap terugkeren", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Ontgrendel uw accounts", - "unlockAccount": "Account ontgrendelen" + "unlockAccount": "Account ontgrendelen", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/nl_NL/app.utils.json b/locale/nl_NL/app.utils.json index ade78fc7c..f8a5d8537 100644 --- a/locale/nl_NL/app.utils.json +++ b/locale/nl_NL/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Hoe u zichzelf tegen phishing kunt beschermen" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Ik begrijp het" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pl/app.migrate.json b/locale/pl/app.migrate.json index 7734943ba..3dcbfb600 100644 --- a/locale/pl/app.migrate.json +++ b/locale/pl/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Wprowadź swoje hasło do konta lub", "goBack": "powrót", - "unlock": "Odblokuj swoje konta. Możesz wrócić do tego kroku później." + "goBackExchange": "go back", + "unlock": "Odblokuj swoje konta. Możesz wrócić do tego kroku później.", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Odblokuj swoje konta", - "unlockAccount": "Odblokuj konto" + "unlockAccount": "Odblokuj konto", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Konto", diff --git a/locale/pl/app.utils.json b/locale/pl/app.utils.json index 5142acf36..0e6a794bf 100644 --- a/locale/pl/app.utils.json +++ b/locale/pl/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Jak uchronić się przed phishingiem" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Rozumiem" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pt_BR/app.migrate.json b/locale/pt_BR/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/pt_BR/app.migrate.json +++ b/locale/pt_BR/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/pt_BR/app.utils.json b/locale/pt_BR/app.utils.json index 1458e2898..5e57ee185 100644 --- a/locale/pt_BR/app.utils.json +++ b/locale/pt_BR/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Como se proteger de Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Eu Entendi" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/pt_PT/app.migrate.json b/locale/pt_PT/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/pt_PT/app.migrate.json +++ b/locale/pt_PT/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/pt_PT/app.utils.json b/locale/pt_PT/app.utils.json index 90a9f1483..160e7db7f 100644 --- a/locale/pt_PT/app.utils.json +++ b/locale/pt_PT/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "How To Protect Yourself from Phishers" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "I Understand" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/ru/app.migrate.json b/locale/ru/app.migrate.json index 1f11851ad..ae23c0118 100644 --- a/locale/ru/app.migrate.json +++ b/locale/ru/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Введите пароль от вашего аккаунта или", "goBack": "вернитесь назад", - "unlock": "Разблокируйте аккаунты. Вы можете вернуться к этому шагу позже" + "goBackExchange": "go back", + "unlock": "Разблокируйте аккаунты. Вы можете вернуться к этому шагу позже", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Разблокируйте аккаунты", - "unlockAccount": "Разблокируйте аккаунт" + "unlockAccount": "Разблокируйте аккаунт", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Адрес/ Название аккаунта", diff --git a/locale/ru/app.utils.json b/locale/ru/app.utils.json index 9c9f0bca9..6f6ad992f 100644 --- a/locale/ru/app.utils.json +++ b/locale/ru/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Сохраните SEED", "title": "Как защититься от фишинга" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Я понял" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "д", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "ч", + "min": "м", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/tr/app.migrate.json b/locale/tr/app.migrate.json index 168ea76e1..1364025fc 100644 --- a/locale/tr/app.migrate.json +++ b/locale/tr/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "Enter your account password or", "goBack": "return back", - "unlock": "Unlock your accounts. You can return to this step later" + "goBackExchange": "go back", + "unlock": "Unlock your accounts. You can return to this step later", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "Unlock your accounts", - "unlockAccount": "Unlock account" + "unlockAccount": "Unlock account", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "Account", diff --git a/locale/tr/app.utils.json b/locale/tr/app.utils.json index 69fba3dc1..d25309918 100644 --- a/locale/tr/app.utils.json +++ b/locale/tr/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "Save the SEED phrase", "title": "Kendinizi nasıl koruyacaksınız?" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "Anladım" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/locale/zh_CN/app.migrate.json b/locale/zh_CN/app.migrate.json index 00b679741..eff3c5bf5 100644 --- a/locale/zh_CN/app.migrate.json +++ b/locale/zh_CN/app.migrate.json @@ -6,11 +6,28 @@ "description": { "enterPass": "输入您的帐户密码或", "goBack": "回来", - "unlock": "解锁您的帐户。您可以稍后返回此步骤" + "goBackExchange": "go back", + "unlock": "解锁您的帐户。您可以稍后返回此步骤", + "unlockExchange": "You need to enter a password to transfer your account to [waves.exchange](https://waves.exchange/)" }, "headers": { "unlock": "解锁您的帐户", - "unlockAccount": "解锁帐户" + "unlockAccount": "解锁帐户", + "unlockExchange": "Unlock Accounts" + }, + "modalButton": { + "cancel": "Cancel", + "moving": "Start moving" + }, + "modalDesc": { + "firstPart": "To offer users a better experience and wider range of tools, we are moving from Waves DEX to [Waves Exchange](https://waves.exchange). ", + "redirected": "Please go there to complete the miration process.", + "secondPart": "On December 2, 2019 Waves DEX will stop operating! To continue trading you have to move your accounts to Waves Exchange. We strongly recommend that you do this in advance.", + "thirdPart": "The moving is fast, easy, and, of course, absolutely secure. " + }, + "modalTitle": { + "moving": "We are moving!", + "redirected": "You have been redirected to" }, "subtitle": { "account": "帐户", diff --git a/locale/zh_CN/app.utils.json b/locale/zh_CN/app.utils.json index 6e2c57e95..84a4afcb8 100644 --- a/locale/zh_CN/app.utils.json +++ b/locale/zh_CN/app.utils.json @@ -918,6 +918,11 @@ "saveSeedButton": "保存SEED短语", "title": "如何防止网络钓鱼攻击" } + }, + "unsuccessfulMigration": { + "checkbox": "Do not show again", + "title": "Unsuccessful Migration!", + "understand": "我了解" } }, "modals": { @@ -1007,6 +1012,11 @@ } }, "warningPlate": { + "day": "d", + "dexMoves": "We are moving soon! Stay with us at", + "hour": "h", + "min": "m", + "notification": "We're moving from Waves DEX to Waves Exchange. Hurry up to move your accounts!", "startMoving": "Start moving" } } \ No newline at end of file diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index a5605f652..bd08f75d5 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -3,15 +3,15 @@
{{$ctrl.days}} - d : + d :
{{$ctrl.hours}} - h : + h :
{{$ctrl.minutes}} - m + m
@@ -26,15 +26,15 @@
{{$ctrl.days}} - d : + d :
{{$ctrl.hours}} - h : + h :
{{$ctrl.minutes}} - m + m
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html index f1d8a61fc..b8b6a0a50 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.html +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -1,32 +1,33 @@ -
+
-

We are moving

+

-

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Iusto tempore ea hic quam quidem reprehenderit dolorum dolore maiores, quaerat, delectus excepturi aut, eligendi laborum. Aspernatur repellat dolorum atque dolore ipsa.

-

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

+

+

+

- Cancel + - Start moving +
-

You have been redirected to +

waves.exchange

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+

From 541f5b1ef29a9eacb9790dad590c055080a86704 Mon Sep 17 00:00:00 2001 From: vba2000 Date: Tue, 12 Nov 2019 19:33:23 +0300 Subject: [PATCH 057/144] DEXW-2225: fix config --- data-service/utils/ConfigService.ts | 115 +++++++++++++ data-service/utils/utils.ts | 18 ++- src/index.hbs | 2 +- src/modules/app/initialize/AppRun.js | 188 +++++++++++----------- src/modules/app/services/ConfigService.js | 115 ++----------- 5 files changed, 234 insertions(+), 204 deletions(-) create mode 100644 data-service/utils/ConfigService.ts diff --git a/data-service/utils/ConfigService.ts b/data-service/utils/ConfigService.ts new file mode 100644 index 000000000..62007acb8 --- /dev/null +++ b/data-service/utils/ConfigService.ts @@ -0,0 +1,115 @@ +import {fetch} from '../' +import {Signal, getPaths, get, clone} from 'ts-utils'; +import {BigNumber} from '@waves/bignumber'; + + +interface IFeeItem { + add_smart_asset_fee: boolean; + add_smart_account_fee: boolean; + min_price_step: T | BigNumber; + fee: T | BigNumber; +} + +interface IFeeConfig { + smart_asset_extra_fee: T | BigNumber; + smart_account_extra_fee: T | BigNumber; + calculate_fee_rules: Record> & { default: IFeeItem }>; +} + +interface IConfig { + PERMISSIONS: Record; + SETTINGS: Record & { DEX: Record & { WATCH_LIST_PAIRS: Array } } & {}; + SERVICE_TEMPORARILY_UNAVAILABLE: boolean; +} + +export class ConfigService { + + protected config = Object.create(null) as IConfig; + + protected feeConfig = Object.create(null) as IFeeItem; + + protected wavesApp: any; + + protected _instance: ConfigService | null = null; + + public change = new Signal() as Signal; + + public configReady: Promise; + + constructor(wavesApp: any) { + if (this._instance) { + return this._instance; + } + this._instance = this; + this.wavesApp = wavesApp; + this.configReady = this.fetchConfig(); + } + + public getConfig(path: string) { + const config = path ? get(this.config, path) : this.config; + return clone(config); + } + + public getFeeConfig() { + return clone(this.feeConfig); + } + + public fetchConfig(): Promise { + return Promise.all([ + this._getConfig().then(config => this._setConfig(config)), + this._getFeeConfig().then(config => this._setFeeConfig(config)) + ]); + } + + protected _getConfig(): Promise { + return fetch(this.wavesApp.network.featuresConfigUrl) + .then(data => { + if (typeof data === 'string') { + return JSON.parse(data); + } + return data; + }) + .catch(() => Promise.resolve(this.wavesApp.network.featuresConfig)); + } + + protected _getFeeConfig(): Promise> { + return fetch(this.wavesApp.network.feeConfigUrl) + .then(this.wavesApp.parseJSON) + .then(ConfigService.parseFeeConfig) + .catch(() => Promise.resolve(this.wavesApp.network.feeConfig)); + } + + protected _setFeeConfig(config) { + this.feeConfig = config; + } + + protected _setConfig(config) { + const myConfig = this.config; + this.config = config; + + ConfigService.getDifferencePaths(myConfig, config) + .forEach(path => this.change.dispatch(String(path))); + } + + protected static getDifferencePaths(previous, next) { + const paths = getPaths(next); + return paths + .filter(path => get(previous, path) !== get(next, path)) + .map(String); + } + + protected static parseFeeConfig(data) { + switch (typeof data) { + case 'number': + case 'string': + return new BigNumber(data); + case 'object': + Object.entries(data).forEach(([key, value]) => { + data[key] = ConfigService.parseFeeConfig(value); + }); + return data; + default: + return data; + } + } +} diff --git a/data-service/utils/utils.ts b/data-service/utils/utils.ts index e79546cbf..19d250db6 100644 --- a/data-service/utils/utils.ts +++ b/data-service/utils/utils.ts @@ -1,9 +1,11 @@ -import { IAssetPair, IHash } from '../interface'; -import { WAVES_ID } from '@waves/signature-adapter'; -import { Asset, Money, AssetPair, OrderPrice } from '@waves/data-entities'; -import { BigNumber } from '@waves/bignumber'; -import { get } from '../api/assets/assets'; -import { get as configGet, timeDiff } from '../config'; +import {IAssetPair, IHash} from '../interface'; +import {WAVES_ID} from '@waves/signature-adapter'; +import {Asset, Money, AssetPair, OrderPrice} from '@waves/data-entities'; +import {BigNumber} from '@waves/bignumber'; +import {get} from '../api/assets/assets'; +import {get as configGet, timeDiff} from '../config'; + +export * from './ConfigService'; export function normalizeTime(time: number): number; export function normalizeTime(time: Date): Date; @@ -34,7 +36,7 @@ export function priceMoneyFactory(money: string | number | BigNumber, pair: Asse export function normalizeAssetPair(assetPair: IAssetPair): IAssetPair { const priceAsset = normalizeAssetId(assetPair.priceAsset); const amountAsset = normalizeAssetId(assetPair.amountAsset); - return { priceAsset, amountAsset }; + return {priceAsset, amountAsset}; } export function normalizeUrl(url: string): string { @@ -154,7 +156,7 @@ export function defer(): TDefer { resolve = res; reject = rej; }); - return { resolve, reject, promise }; + return {resolve, reject, promise}; } export function stringifyJSON(data: any): string { diff --git a/src/index.hbs b/src/index.hbs index 3036b61f4..eaa509f4c 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -1,7 +1,7 @@ - + diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 016bf4c63..8215d2a10 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -3,6 +3,10 @@ (function () { 'use strict'; + const onContentLoad = new Promise((resolve) => { + document.addEventListener('DOMContentLoaded', resolve); + }); + const { Money } = require('@waves/data-entities'); const { libs } = require('@waves/waves-transactions'); const { base64Encode, blake2b, stringToBytes } = libs.crypto; @@ -56,6 +60,7 @@ LOADER.addProgress(PROGRESS_MAP.RUN_SCRIPT); WavesApp.state = 'initApp'; + /** * @param {$rootScope.Scope} $rootScope * @param {User} user @@ -129,68 +134,97 @@ _unavailable = false; constructor() { - configService.configReadyPromise.then(() => { - const identityImg = require('identity-img'); + const identityImg = require('identity-img'); + + LOADER.addProgress(PROGRESS_MAP.APP_RUN); + + /** + * List of css class on body (from current state) + * @type {Array} + */ + this.activeClasses = []; + /** + * @type {ModalRouter} + * @private + */ + this._modalRouter = new ModalRouter(); + + /** + * Configure library generation avatar by address + */ + identityImg.config({ rows: 8, cells: 8 }); + + this._stopLoader(); + this._setHandlers(); + this._initializeLogin(); + this._initializeOutLinks(); + this._openMigrationModal(); - LOADER.addProgress(PROGRESS_MAP.APP_RUN); - - /** - * List of css class on body (from current state) - * @type {Array} - */ - this.activeClasses = []; - /** - * @type {ModalRouter} - * @private - */ - this._modalRouter = new ModalRouter(); - - /** - * Configure library generation avatar by address - */ - identityImg.config({ rows: 8, cells: 8 }); - - this._setHandlers(); - this._stopLoader(); - this._initializeLogin(); - this._initializeOutLinks(); - this._openMigrationModal(); - - if (WavesApp.isDesktop()) { - window.listenMainProcessEvent((type, url) => { - const parts = utils.parseElectronUrl(url); - const path = parts.path.replace(/\/$/, '') || parts.path; - - if (path) { - const noLogin = path === '/' || WavesApp.stateTree.where({ noLogin: true }) - .some(item => { - const url = item.get('url') || item.id; - return path === url; - }); - - if (noLogin) { - location.hash = `#!${path}${parts.search}`; - } else { - user.onLogin().then(() => { - setTimeout(() => { - location.hash = `#!${path}${parts.search}`; - }, 1000); - }); - } + if (WavesApp.isDesktop()) { + window.listenMainProcessEvent((type, url) => { + const parts = utils.parseElectronUrl(url); + const path = parts.path.replace(/\/$/, '') || parts.path; + + if (path) { + const noLogin = path === '/' || WavesApp.stateTree.where({ noLogin: true }) + .some(item => { + const url = item.get('url') || item.id; + return path === url; + }); + + if (noLogin) { + location.hash = `#!${path}${parts.search}`; + } else { + user.onLogin().then(() => { + setTimeout(() => { + location.hash = `#!${path}${parts.search}`; + }, 1000); + }); } - }); - } + } + }); + } + + if (configService.get('DEXW_LOCKED') && $state.current.name !== 'migration') { + $state.go('migration'); + } else { + $state.go('signIn'); + } - if (configService.get('DEXW_LOCKED') && $state.current.name !== 'migration') { - $state.go('migration'); - } else { - $state.go('signIn'); - } - }); $rootScope.WavesApp = WavesApp; } + static getLoadImagePromise(length) { + return function (path) { + return new Promise(resolve => { + const img = new Image(); + const apply = () => { + LOADER.addProgress(PROGRESS_MAP.IMAGES_LOADED / length); + resolve(); + }; + + img.onload = apply; + img.onerror = () => { + console.warn(`Can't load image! "${path}"`); + apply(); + }; + img.src = path; + }); + }; + } + + static _getUrlFromState(state) { + return ( + WavesApp + .stateTree + .getPath(state.name.split('.').slice(-1)[0]) + .filter((id) => !WavesApp.stateTree.find(id).get('abstract')) + .map((id) => WavesApp.stateTree.find(id).get('url') || id) + .reduce((url, id) => `${url}/${id}`, '') + ); + } + _initTryDesktop() { if (multiAccount.isSignedIn || !isDesktop || WavesApp.isDesktop()) { return Promise.resolve(true); @@ -208,9 +242,9 @@ return Promise.resolve(true); default: return Promise.resolve(true); - // return modalManager.showTryDesktopModal() - // .then(() => this._runDesktop()) - // .catch(() => true); + // return modalManager.showTryDesktopModal() + // .then(() => this._runDesktop()) + // .catch(() => true); } }); } @@ -758,36 +792,6 @@ }); } - static getLoadImagePromise(length) { - return function (path) { - return new Promise(resolve => { - const img = new Image(); - const apply = () => { - LOADER.addProgress(PROGRESS_MAP.IMAGES_LOADED / length); - resolve(); - }; - - img.onload = apply; - img.onerror = () => { - console.warn(`Can't load image! "${path}"`); - apply(); - }; - img.src = path; - }); - }; - } - - static _getUrlFromState(state) { - return ( - WavesApp - .stateTree - .getPath(state.name.split('.').slice(-1)[0]) - .filter((id) => !WavesApp.stateTree.find(id).get('abstract')) - .map((id) => WavesApp.stateTree.find(id).get('url') || id) - .reduce((url, id) => `${url}/${id}`, '') - ); - } - } return new AppRun(); @@ -813,8 +817,12 @@ 'whatsNew' ]; - angular.module('app') - .run(run); + angular.module('app').run(run); + + const { utils } = require('data-service'); + Promise.all([onContentLoad, (new utils.ConfigService(WavesApp)).configReady]).then(() => { + angular.bootstrap(document.querySelector('html'), ['app']); + }); })(); /** diff --git a/src/modules/app/services/ConfigService.js b/src/modules/app/services/ConfigService.js index 8087d6b3c..82b84844a 100644 --- a/src/modules/app/services/ConfigService.js +++ b/src/modules/app/services/ConfigService.js @@ -1,30 +1,15 @@ (function () { 'use strict'; - - const { fetch } = require('data-service'); - const { Signal, getPaths, get, clone } = require('ts-utils'); - const { BigNumber } = require('@waves/bignumber'); + const { utils } = require('data-service'); + const BaseConfigService = utils.ConfigService; const factory = function (Base, createPoll) { class ConfigService extends Base { - /** - * @type {ConfigService.IConfig} - * @private - */ - _config = Object.create(null); - /** - * @type {ConfigService.IFeeConfig} - * @private - */ - _feeConfig = Object.create(null); - /** - * @type {Signal} - */ - change = new Signal(); + change; /** * @type Promise */ @@ -34,108 +19,28 @@ */ configReadyPromise; + service = new BaseConfigService(WavesApp); + constructor() { super(); - this.configReadyPromise = new Promise((resolve) => { - this._resolve = resolve; - }); - this.configReady = createPoll(this, this._getConfig, this._setConfig, 30000); - createPoll(this, this._getFeeConfig, this._setFeeConfig, 30000); + this.change = this.service.change; + this.configReadyPromise = this.service.configReady; + this.configReady = createPoll(this, () => this.service.fetchConfig(), null, 30000); } /** * @param {string} path */ get(path) { - return clone(get(this._config, path)); + return this.service.getConfig(path); } /** * @return {ConfigService.IFeeConfig} */ getFeeConfig() { - return clone(this._feeConfig); - } - - /** - * @return {Promise} - * @private - */ - _getConfig() { - return fetch(WavesApp.network.featuresConfigUrl) - .then(data => { - if (typeof data === 'string') { - return JSON.parse(data); - } - return data; - }) - .catch(() => Promise.resolve(WavesApp.network.featuresConfig)); - } - - /** - * @return {Promise} - * @private - */ - _getFeeConfig() { - return fetch(WavesApp.network.feeConfigUrl) - .then(WavesApp.parseJSON) - .then(ConfigService._parseFeeConfig) - .catch(() => Promise.resolve(WavesApp.network.feeConfig)); - } - - /** - * @param {ConfigService.IFeeConfig} config - * @private - */ - _setFeeConfig(config) { - this._feeConfig = config; - } - - /** - * @param {ConfigService.IConfig} config - * @private - */ - _setConfig(config) { - this._resolve(); - const myConfig = this._config; - this._config = config; - - ConfigService._getDifferencePaths(myConfig, config) - .forEach(path => this.change.dispatch(String(path))); - } - - /** - * @param {object} previous - * @param {object} next - * @return {string[]} - * @private - */ - static _getDifferencePaths(previous, next) { - const paths = getPaths(next); - return paths - .filter(path => get(previous, path) !== get(next, path)) - .map(String); - } - - /** - * @param data - * @return {*} - * @private - */ - static _parseFeeConfig(data) { - switch (typeof data) { - case 'number': - case 'string': - return new BigNumber(data); - case 'object': - Object.entries(data).forEach(([key, value]) => { - data[key] = ConfigService._parseFeeConfig(value); - }); - return data; - default: - return data; - } + return this.service.getFeeConfig(); } } From 607e5d80c386317cd344978ff7de85f5722d6324 Mon Sep 17 00:00:00 2001 From: vba2000 Date: Tue, 12 Nov 2019 20:19:35 +0300 Subject: [PATCH 058/144] DEXW-2225: fix --- src/modules/app/services/ConfigService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/app/services/ConfigService.js b/src/modules/app/services/ConfigService.js index 82b84844a..226b3c30a 100644 --- a/src/modules/app/services/ConfigService.js +++ b/src/modules/app/services/ConfigService.js @@ -26,7 +26,7 @@ super(); this.change = this.service.change; this.configReadyPromise = this.service.configReady; - this.configReady = createPoll(this, () => this.service.fetchConfig(), null, 30000); + this.configReady = createPoll(this, this.service.fetchConfig, () => null, 30000); } /** From bf6624821355d4fe7d7447e151f1d7271575d175 Mon Sep 17 00:00:00 2001 From: vba2000 Date: Tue, 12 Nov 2019 20:31:03 +0300 Subject: [PATCH 059/144] DEXW-2225: fix --- src/modules/app/services/ConfigService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/app/services/ConfigService.js b/src/modules/app/services/ConfigService.js index 226b3c30a..602a02655 100644 --- a/src/modules/app/services/ConfigService.js +++ b/src/modules/app/services/ConfigService.js @@ -26,7 +26,7 @@ super(); this.change = this.service.change; this.configReadyPromise = this.service.configReady; - this.configReady = createPoll(this, this.service.fetchConfig, () => null, 30000); + this.configReady = createPoll(this, () => this.service.fetchConfig(), () => null, 30000); } /** From f8259fe62a007e1843cb0673fb1df65c8c695cb0 Mon Sep 17 00:00:00 2001 From: vba2000 Date: Wed, 13 Nov 2019 10:44:56 +0300 Subject: [PATCH 060/144] DEXW-2346: return coinomat to BTC --- package-lock.json | 6 +++--- src/modules/utils/services/gateways/CoinomatService.js | 3 ++- src/modules/utils/services/gateways/WavesGatewayService.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccee284aa..55acf7367 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "waves-client", - "version": "1.4.10", + "version": "1.4.11", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -5788,7 +5788,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -11117,7 +11117,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { diff --git a/src/modules/utils/services/gateways/CoinomatService.js b/src/modules/utils/services/gateways/CoinomatService.js index 3173166cf..30c850b49 100644 --- a/src/modules/utils/services/gateways/CoinomatService.js +++ b/src/modules/utils/services/gateways/CoinomatService.js @@ -2,6 +2,7 @@ 'use strict'; const GATEWAYS = { + [WavesApp.defaultAssets.BTC]: { waves: 'WBTC', gateway: 'BTC' }, [WavesApp.defaultAssets.BSV]: { waves: 'WBSV', gateway: 'BSV' }, [WavesApp.defaultAssets.LTC]: { waves: 'WLTC', gateway: 'LTC' }, [WavesApp.defaultAssets.ZEC]: { waves: 'WZEC', gateway: 'ZEC' }, @@ -90,7 +91,7 @@ getSupportMap(asset) { if (GATEWAYS[asset.id]) { return { - deposit: true, + deposit: asset.id !== WavesApp.defaultAssets.BTC, withdraw: true, errorAddressMessage: true }; diff --git a/src/modules/utils/services/gateways/WavesGatewayService.js b/src/modules/utils/services/gateways/WavesGatewayService.js index 71030eaa6..0fd39bff4 100644 --- a/src/modules/utils/services/gateways/WavesGatewayService.js +++ b/src/modules/utils/services/gateways/WavesGatewayService.js @@ -31,7 +31,7 @@ if (GATEWAYS[asset.id]) { return { deposit: true, - withdraw: true, + withdraw: asset.id !== WavesApp.defaultAssets.BTC, errorAddressMessage: true, wrongAddressMessage: true }; From 95dafcc726b646e302d4043c27f1a024b0a2ca49 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Wed, 13 Nov 2019 11:29:26 +0300 Subject: [PATCH 061/144] DEXW-2282: add routing logic --- data-service/utils/ConfigService.ts | 8 ++++---- src/modules/app/initialize/AppRun.js | 9 +-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/data-service/utils/ConfigService.ts b/data-service/utils/ConfigService.ts index 62007acb8..89b3ea104 100644 --- a/data-service/utils/ConfigService.ts +++ b/data-service/utils/ConfigService.ts @@ -30,17 +30,17 @@ export class ConfigService { protected wavesApp: any; - protected _instance: ConfigService | null = null; + protected static _instance: ConfigService | void; public change = new Signal() as Signal; public configReady: Promise; constructor(wavesApp: any) { - if (this._instance) { - return this._instance; + if (ConfigService._instance) { + return ConfigService._instance; } - this._instance = this; + ConfigService._instance = this; this.wavesApp = wavesApp; this.configReady = this.fetchConfig(); } diff --git a/src/modules/app/initialize/AppRun.js b/src/modules/app/initialize/AppRun.js index 8215d2a10..6441167e0 100644 --- a/src/modules/app/initialize/AppRun.js +++ b/src/modules/app/initialize/AppRun.js @@ -185,13 +185,6 @@ }); } - if (configService.get('DEXW_LOCKED') && $state.current.name !== 'migration') { - $state.go('migration'); - } else { - $state.go('signIn'); - } - - $rootScope.WavesApp = WavesApp; } @@ -415,7 +408,7 @@ const START_STATES = WavesApp.stateTree.where({ noLogin: true }) .map((item) => WavesApp.stateTree.getPath(item.id).join('.')); - const DEXW_LOCKED_STATES = ['migration', 'signIn']; + const DEXW_LOCKED_STATES = ['migration']; const offInitialTransitions = $transitions.onStart({}, transition => { const DEXW_LOCKED = configService.get('DEXW_LOCKED'); From 5a0e0de5f5499328ac58313042840bf152ec6181 Mon Sep 17 00:00:00 2001 From: vk Date: Wed, 13 Nov 2019 11:49:53 +0300 Subject: [PATCH 062/144] DEXW-2346: update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 684d2e475..3e482096b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "waves-client", - "version": "1.4.12", + "version": "1.4.13", "description": "The official client application for the Waves platform", "private": true, "repository": { From ab27e6ea461dc45c354f0b2e903b6dcb7c2c6524 Mon Sep 17 00:00:00 2001 From: Viktor Voronin Date: Tue, 12 Nov 2019 18:23:14 +0300 Subject: [PATCH 063/144] DEXW-2340: add dist download link to warning plate on desktop --- .../componentWarningPlate/ComponentWarningPlate.js | 13 +++++++++++-- .../componentWarningPlate.html | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index 1e08ac37a..a743948de 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -9,7 +9,7 @@ * @param {Storage} storage * @return {ComponentWarningPlate} */ - const controller = function ($scope, modalManager, utils, user, storage) { + const controller = function ($scope, modalManager, utils, user, storage, configService) { class ComponentWarningPlate { @@ -37,6 +37,7 @@ * @type {string} */ newDexLink = WavesApp.network.wavesExchangeLink; + isDesktop = WavesApp.isDesktop(); constructor() { this._initCanMoveAccounts(); @@ -51,6 +52,8 @@ user.logoutSignal.on(this._initCanMoveAccounts, this); utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); + + this._getDistUrl(); } showMovingModal() { @@ -102,6 +105,12 @@ $scope.$apply(); }); } + _getDistUrl() { + configService.configReadyPromise.then(() => { + const urls = configService.get('DESKTOP_URLS'); + this.distUrl = new URL(urls[WavesApp.platform]); + }); + } } @@ -109,7 +118,7 @@ }; - controller.$inject = ['$scope', 'modalManager', 'utils', 'user', 'storage']; + controller.$inject = ['$scope', 'modalManager', 'utils', 'user', 'storage', 'configService']; angular.module('app').component('wWarningPlate', { templateUrl: 'modules/app/directives/componentWarningPlate/componentWarningPlate.html', diff --git a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html index bd08f75d5..e371972a0 100644 --- a/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html +++ b/src/modules/app/directives/componentWarningPlate/componentWarningPlate.html @@ -41,3 +41,6 @@
+ From 05dcedf4ba75930462aca4cf70924f0b5bdbb30c Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Wed, 13 Nov 2019 12:24:58 +0300 Subject: [PATCH 064/144] DEXW-2326: desktopUpgrade page --- data-service/index.ts | 3 +- data-service/utils/DownloadFile.ts | 34 +++++++ .../controllers/DesktopUpdateCtrl.js | 21 ++-- .../desktopUpdate/less/desktopUpdate.less | 25 +++++ .../templates/desktopUpdate.html | 96 ++++++++++++++----- 5 files changed, 149 insertions(+), 30 deletions(-) create mode 100644 data-service/utils/DownloadFile.ts create mode 100644 src/modules/desktopUpdate/less/desktopUpdate.less diff --git a/data-service/index.ts b/data-service/index.ts index 9c09b5f65..af3737a59 100644 --- a/data-service/index.ts +++ b/data-service/index.ts @@ -3,6 +3,7 @@ import { DataManager } from './classes/DataManager'; import * as configApi from './config'; import * as sign from './sign'; import * as utilsModule from './utils/utils'; +import { downloadFile } from './utils/DownloadFile'; import { request } from './utils/request'; import { IFetchOptions } from './utils/request'; import * as wavesDataEntitiesModule from '@waves/data-entities'; @@ -31,7 +32,7 @@ export const wavesDataEntities = { export const api = { ...apiMethods }; export const dataManager = new DataManager(); export const config = { ...configApi }; -export const utils = { ...utilsModule }; +export const utils = { ...utilsModule, downloadFile }; export const signature = { ...sign }; diff --git a/data-service/utils/DownloadFile.ts b/data-service/utils/DownloadFile.ts new file mode 100644 index 000000000..f6a2368c7 --- /dev/null +++ b/data-service/utils/DownloadFile.ts @@ -0,0 +1,34 @@ +export async function downloadFile (url: string, progressCb?: (progress: number, size?: number) => void): Promise { + const response = await fetch(url); + const contentLength = Number(response.headers.get('Content-Length') || response.headers.get('content-length')) || 0; + const reader = response.body.getReader(); + let receivedLength = 0; + let chunks = []; + + while(true) { + const { done, value } = await reader.read(); + + if (done) { + progressCb(100); + break; + } + + chunks.push(value); + receivedLength += value.length; + + if (typeof progressCb === 'function') { + progressCb(contentLength ? receivedLength / contentLength * 100 : 0, receivedLength); + } + } + + let chunksAll = new Uint8Array(receivedLength); + let position = 0; + + for(let chunk of chunks) { + chunksAll.set(chunk, position); + position += chunk.length; + } + + return chunksAll; +} + diff --git a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js index 0ca2f8ae8..810bc630c 100644 --- a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js +++ b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js @@ -2,6 +2,13 @@ 'use strict'; const ds = require('data-service'); + const STATES = [ + 'askDownload', + 'downloading', + 'installAndRun', + 'success', + 'fail' + ]; /** * @param {ng.IScope} $scope @@ -11,7 +18,7 @@ const controller = ($scope, $state, configService) => { class DesktopUpdateCtrl { - step = 0; + state = 'askDownload'; progress = 0; error = null; isDownloading = false; @@ -27,6 +34,7 @@ const [fileName] = url.pathname.split('/').slice(-1); this.isDownloading = true; + this.state = 'downloading'; ds.utils.downloadFile(url, (progress) => { this.progress = Math.ceil(progress); @@ -36,7 +44,8 @@ fileName, fileContent: content }).then(() => { - this._nextStep(); + // @TODO вернуть + // this.state = 'installAndRun'; this.isDownloading = false; $scope.$digest(); }).catch((e) => { @@ -61,14 +70,14 @@ return new URL(urls[WavesApp.platform]); } - _nextStep() { - this.step = this.step + 1; - } - _resetProgress() { this.progress = 0; } + _toWelcome() { + $state.go('welcome'); + } + } return new DesktopUpdateCtrl(); diff --git a/src/modules/desktopUpdate/less/desktopUpdate.less b/src/modules/desktopUpdate/less/desktopUpdate.less new file mode 100644 index 000000000..59472891a --- /dev/null +++ b/src/modules/desktopUpdate/less/desktopUpdate.less @@ -0,0 +1,25 @@ +@import (reference) 'config'; + +.progress-bar { + &__item { + &.active { + color: @color-submit-500; + } + &.done { + background-color: @color-submit-500; + } + } +} + +.download-bar { + height: 100%; + box-shadow: 2px 2px 5px 0 rgba(31, 90, 246, 0.25); + background-color: @color-submit-500; + &__wrapper { + height: 8px; + width: 440px; + display: flex; + justify-content: flex-start; + border-radius: 4px; + } +} \ No newline at end of file diff --git a/src/modules/desktopUpdate/templates/desktopUpdate.html b/src/modules/desktopUpdate/templates/desktopUpdate.html index d66e43a8b..4dec3ea8b 100644 --- a/src/modules/desktopUpdate/templates/desktopUpdate.html +++ b/src/modules/desktopUpdate/templates/desktopUpdate.html @@ -1,35 +1,85 @@ -
+
- - -
-

Update App

- -
{{$ctrl.progress}} %
-
{{$ctrl.error}}
- - - +
+
+
1
+
+
+
+
2
+
+
+
+
3
+
+
+
+
+ +
+

+
+ + + + +
- +
- -
-

Install App

+
+ +

+
+
+
+
+
-
Then we'll continue
+
+

+ +
+ + + + + +
- - +
+ +
+

+
+ + + +
+ +
+

+
+ + + +
+
+ +
From 5b2d236899e3f8ceab937593e1bcaf629ed1cd3b Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Wed, 13 Nov 2019 15:31:15 +0300 Subject: [PATCH 065/144] DEXW-2326: added export storage service --- .../utils/modals/migrateModal/migrateModal.js | 57 +++---------- .../utils/services/ExportStorageService.js | 85 +++++++++++++++++++ 2 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 src/modules/utils/services/ExportStorageService.js diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index bd4c23578..520975f12 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -12,7 +12,7 @@ * @param {*} storageExporter * @param {*} storage */ - const controller = function (Base, $log, $mdDialog, storageExporter, $scope, storage) { + const controller = function (Base, $log, $mdDialog, storageExporter, $state, $scope, storage, exportStorageService) { const SEED_LENGTH = 20; class MigrateModalCtrl extends Base { @@ -24,33 +24,14 @@ export() { const connectProvider = this._getConnectProvider(); - const message = JSON.stringify({ event: 'connect' }); - connectProvider.send(message, { - event: 'data', + exportStorageService.export({ + provider: connectProvider, attempts: 3, - timeout: 10000 - }).then((result) => { - if (!result || result.event !== 'connect') { - throw new Error(`Message event is not valid: ${result.event}`); - } + timeout: 3000 + }); - const publicKeyTo = result.payload; - const { publicKey, privateKey } = keyPair(seedUtils.generateNewSeed(SEED_LENGTH)); - - return storageExporter.export( - privateKey, - publicKeyTo - ).then((data) => { - return connectProvider.send(JSON.stringify({ - event: 'data', - payload: { - publicKey, - data - } - }), { event: 'data' }); - }); - }).then((result) => { + exportStorageService.onData().then(result => { if (result.payload === 'ok') { $log.log('done'); this.step++; @@ -62,8 +43,6 @@ return storage.save('migrationSuccess', false); } - }).catch((e) => { - $log.error(e); }); } @@ -80,21 +59,13 @@ WavesApp.network.migrationOrigins : '*'; - if (WavesApp.isDesktop()) { - return new ds.connect.HttpConnectProvider({ - port: WavesApp.network.migration.desktopPort, - url: WavesApp.network.migration.desktopUrl, - origins - }); - } else { - const childWindow = window.open(WavesApp.network.migration.webUrl); - - return new ds.connect.PostMessageConnectProvider({ - win: childWindow, - mode: 'export', - origins - }); - } + const childWindow = window.open(WavesApp.network.migration.webUrl); + + return new ds.connect.PostMessageConnectProvider({ + win: childWindow, + mode: 'export', + origins + }); } } @@ -102,7 +73,7 @@ return new MigrateModalCtrl(); }; - controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$scope', 'storage']; + controller.$inject = ['Base', '$log', '$mdDialog', 'storageExporter', '$state', '$scope', 'storage', 'exportStorageService']; angular.module('app.utils').controller('MigrateModalCtrl', controller); })(); diff --git a/src/modules/utils/services/ExportStorageService.js b/src/modules/utils/services/ExportStorageService.js new file mode 100644 index 000000000..4103e964d --- /dev/null +++ b/src/modules/utils/services/ExportStorageService.js @@ -0,0 +1,85 @@ +(() => { + 'use strict'; + + const { libs, seedUtils } = require('@waves/waves-transactions'); + const { keyPair } = libs.crypto; + + const noop = () => undefined; + const SEED_LENGTH = 20; + + class ExportStorageService { + + static $inject = ['storageExporter']; + + _onConnectResolve = noop; + _onConnectReject = noop; + _onDataResolve = noop; + _onDataReject = noop; + + constructor(storageExporter) { + this._storageExporter = storageExporter; + } + + _connectPromise = new Promise((resolve, reject) => { + this._onConnectResolve = resolve; + this._onConnectReject = reject; + }); + + _dataPromise = new Promise((resolve, reject) => { + this._onDataResolve = resolve; + this._onDataReject = reject; + }); + + onConnect() { + return this._connectPromise; + } + + onData() { + return this._dataPromise; + } + + export({ provider, attempts, timeout }) { + const message = JSON.stringify({ event: 'connect' }); + console.log(provider); + provider.send(message, { + event: 'data', + attempts, + timeout, + }).then((result) => { + if (!result || result.event !== 'connect') { + this._onConnectReject(); + throw new Error(`Message event is not valid: ${result.event}`); + } + this._onConnectResolve(); + + const publicKeyTo = result.payload; + const { publicKey, privateKey } = keyPair(seedUtils.generateNewSeed(SEED_LENGTH)); + + return this._storageExporter.export( + privateKey, + publicKeyTo + ).then((data) => { + return provider.send(JSON.stringify({ + event: 'data', + payload: { + publicKey, + data + } + }), { event: 'data' }); + }) + }).then((result) => { + if (result.payload === 'ok') { + this._onDataResolve(result); + } else { + this._onDataReject(); + } + }) + .catch(error => { + this._onConnectReject(error); + }); + } + + } + + angular.module('app').service('exportStorageService', ExportStorageService); +})(); From 729d4b58563caeb6e941cead12c6effcab08dd5b Mon Sep 17 00:00:00 2001 From: vba2000 Date: Wed, 13 Nov 2019 16:39:18 +0300 Subject: [PATCH 066/144] DEXW-2346: fix --- .../confirmGatewayTransaction/ConfirmGatewayTransaction.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/ui/directives/confirmGatewayTransaction/ConfirmGatewayTransaction.js b/src/modules/ui/directives/confirmGatewayTransaction/ConfirmGatewayTransaction.js index 47908e543..12f9fdaf3 100644 --- a/src/modules/ui/directives/confirmGatewayTransaction/ConfirmGatewayTransaction.js +++ b/src/modules/ui/directives/confirmGatewayTransaction/ConfirmGatewayTransaction.js @@ -8,8 +8,8 @@ WavesApp.defaultAssets.WEST, WavesApp.defaultAssets.ERGO, WavesApp.defaultAssets.BNT, - WavesApp.defaultAssets.ETH, - WavesApp.defaultAssets.BTC + WavesApp.defaultAssets.ETH + // WavesApp.defaultAssets.BTC ]; /** From 9ab01bea23623ad6b3cb0e7d867d4ea5afa9d6a9 Mon Sep 17 00:00:00 2001 From: okanishcheva Date: Wed, 13 Nov 2019 17:26:25 +0300 Subject: [PATCH 067/144] DEXW-2332: fix notifications --- .../componentWarningPlate/ComponentWarningPlate.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js index a743948de..0601d1e39 100644 --- a/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js +++ b/src/modules/app/directives/componentWarningPlate/ComponentWarningPlate.js @@ -52,7 +52,7 @@ user.logoutSignal.on(this._initCanMoveAccounts, this); utils.startTimer({ year: 2019, month: 12, day: 2, hours: 15 }, this._setTime.bind(this), 1000); - + this._getDistUrl(); } @@ -87,7 +87,10 @@ user.getFilteredUserList(), user.getMultiAccountData() ]).then(([userList, multiAccountData]) => { - if ((multiAccountData && user.isAuthorised) || (userList && userList.length)) { + if ( + (multiAccountData && user.isAuthorised) || + (userList && userList.length && !multiAccountData) + ) { this.canMoveAccounts = true; } else { this.canMoveAccounts = false; From 22ce2ca74295997ac7b904ef9fb599b1af653943 Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Wed, 13 Nov 2019 19:08:38 +0300 Subject: [PATCH 068/144] DEXW-2326: desktop update elements --- src/index.hbs | 2 +- .../controllers/DesktopUpdateCtrl.js | 50 +++++++++++-- .../desktopUpdate/less/desktopUpdate.less | 71 +++++++++++++++++-- .../templates/desktopUpdate.html | 32 +++++---- .../modals/migrateModal/migrateModal.html | 2 +- .../utils/modals/migrateModal/migrateModal.js | 10 ++- .../utils/services/ExportStorageService.js | 2 +- 7 files changed, 141 insertions(+), 28 deletions(-) diff --git a/src/index.hbs b/src/index.hbs index 3036b61f4..3f06392c0 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -735,7 +735,7 @@ id: 'desktopUpdate', data: { url: '/desktop-update', - noLogin: true, + noLogin: false, views: [{ name: 'main' }] } }, diff --git a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js index 810bc630c..77c47f81a 100644 --- a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js +++ b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js @@ -15,9 +15,12 @@ * @param {*} $state * @param {*} configService */ - const controller = ($scope, $state, configService) => { + const controller = ($scope, $state, configService, exportStorageService, $log, storage, user) => { class DesktopUpdateCtrl { + /** + * @type {'askDownload' | 'downloading' | 'installAndRun' | 'success' | 'fail' } + */ state = 'askDownload'; progress = 0; error = null; @@ -25,8 +28,30 @@ constructor() { if (!WavesApp.isDesktop()) { - $state.go('/'); + $state.go(user.getActiveState('wallet')); } + + const connectProvider = this._getConnectProvider(); + + exportStorageService.export({ + provider: connectProvider, + attempts: 10, + timeout: 1000 + }); + + exportStorageService.onData().then(result => { + if (result.payload === 'ok') { + $log.log('done'); + this.state = 'success'; + $scope.$apply(); + + return storage.save('migrationSuccess', true); + } else { + this.state = 'fail'; + + return storage.save('migrationSuccess', false); + } + }); } download() { @@ -74,8 +99,23 @@ this.progress = 0; } - _toWelcome() { - $state.go('welcome'); + _toHome() { + $state.go(user.getActiveState('wallet')); + } + + /** + * @returns {ConnectProvider} + */ + _getConnectProvider() { + const origins = WavesApp.isProduction() ? + WavesApp.network.migrationOrigins : + '*'; + + return new ds.connect.HttpConnectProvider({ + port: WavesApp.network.migration.desktopPort, + url: WavesApp.network.migration.desktopUrl, + origins + }); } } @@ -83,7 +123,7 @@ return new DesktopUpdateCtrl(); }; - controller.$inject = ['$scope', '$state', 'configService']; + controller.$inject = ['$scope', '$state', 'configService', 'exportStorageService', '$log' , 'storage', 'user']; angular.module('app.desktopUpdate').controller('DesktopUpdateCtrl', controller); })(); diff --git a/src/modules/desktopUpdate/less/desktopUpdate.less b/src/modules/desktopUpdate/less/desktopUpdate.less index 59472891a..506986487 100644 --- a/src/modules/desktopUpdate/less/desktopUpdate.less +++ b/src/modules/desktopUpdate/less/desktopUpdate.less @@ -1,12 +1,74 @@ @import (reference) 'config'; +.return-button { + float: left; + display: flex; + cursor: pointer; + &__arrow { + width: 24px; + height: 24px; + border-radius: 4px; + background-color: rgba(31, 90, 246, 0.06); + } + &__text { + font-size: 13px; + color: @color-submit-500; + } +} + .progress-bar { + display: flex; + align-items: center; + &__item { - &.active { - color: @color-submit-500; - } + &-number { + display: flex; + justify-content: center; + align-items: center; + position: relative; + width: 20px; + height: 20px; + border: solid 2px @color-basic-500; + border-radius: 50%; + &::after { + content: ''; + position: absolute; + width: 120px; + height: 2px; + background-color: @color-basic-100; + top: 7px; + left: 20px; + } + } + + &.active { + color: @color-submit-500; + + .progress-bar__item-number, + .progress-bar__item-text { + border: solid 2px @color-submit-500; + } + } + &.done { - background-color: @color-submit-500; + .progress-bar__item-number { + &::after { + content: ''; + width: 120px; + height: 2px; + background-color: @color-basic-100; + } + } + + .progress-bar__item-number, + .progress-bar__item-text { + color: @color-submit-500; + border: solid 2px @color-submit-500; + } + } + + &.fail { + background-color: red; } } } @@ -15,6 +77,7 @@ height: 100%; box-shadow: 2px 2px 5px 0 rgba(31, 90, 246, 0.25); background-color: @color-submit-500; + &__wrapper { height: 8px; width: 440px; diff --git a/src/modules/desktopUpdate/templates/desktopUpdate.html b/src/modules/desktopUpdate/templates/desktopUpdate.html index 4dec3ea8b..f9c7e835a 100644 --- a/src/modules/desktopUpdate/templates/desktopUpdate.html +++ b/src/modules/desktopUpdate/templates/desktopUpdate.html @@ -2,28 +2,32 @@
-
+
+
s
+
+
+
-
1
-
+
1
+
-
2
-
+
2
+
-
3
-
+
3
+
@@ -31,32 +35,30 @@

- + - +
-

-

- + - +
@@ -65,7 +67,7 @@

- +
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.html b/src/modules/utils/modals/migrateModal/migrateModal.html index f1d8a61fc..714e9a5b3 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.html +++ b/src/modules/utils/modals/migrateModal/migrateModal.html @@ -13,7 +13,7 @@

We are moving

Cancel - + Start moving
diff --git a/src/modules/utils/modals/migrateModal/migrateModal.js b/src/modules/utils/modals/migrateModal/migrateModal.js index 520975f12..42f268d91 100644 --- a/src/modules/utils/modals/migrateModal/migrateModal.js +++ b/src/modules/utils/modals/migrateModal/migrateModal.js @@ -22,7 +22,15 @@ */ step = 0; - export() { + moving() { + if (WavesApp.isDesktop()) { + $state.go('desktopUpdate'); + } else { + this._export() + } + } + + _export() { const connectProvider = this._getConnectProvider(); exportStorageService.export({ diff --git a/src/modules/utils/services/ExportStorageService.js b/src/modules/utils/services/ExportStorageService.js index 4103e964d..4c038b380 100644 --- a/src/modules/utils/services/ExportStorageService.js +++ b/src/modules/utils/services/ExportStorageService.js @@ -40,7 +40,7 @@ export({ provider, attempts, timeout }) { const message = JSON.stringify({ event: 'connect' }); - console.log(provider); + provider.send(message, { event: 'data', attempts, From 6eacd5ad05e33e15fe5653105245b466bd924307 Mon Sep 17 00:00:00 2001 From: Max Axenov Date: Wed, 13 Nov 2019 20:36:44 +0300 Subject: [PATCH 069/144] DEXW-2326: added faq modal --- .../controllers/DesktopUpdateCtrl.js | 4 +- .../ui/directives/accordion/Accordion.js | 51 ++++++++++++++++ .../ui/directives/accordion/accordion.html | 9 +++ .../ui/directives/accordion/accordion.less | 58 +++++++++++++++++++ src/modules/ui/directives/footer/Footer.js | 9 ++- src/modules/ui/directives/footer/footer.html | 5 +- src/modules/utils/modals/ModalManager.js | 8 +++ .../utils/modals/migrateFaq/MigrateFaqCtrl.js | 37 ++++++++++++ .../utils/modals/migrateFaq/migrateFaq.html | 4 ++ .../utils/modals/migrateFaq/migrateFaq.less | 42 ++++++++++++++ 10 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 src/modules/ui/directives/accordion/Accordion.js create mode 100644 src/modules/ui/directives/accordion/accordion.html create mode 100644 src/modules/ui/directives/accordion/accordion.less create mode 100644 src/modules/utils/modals/migrateFaq/MigrateFaqCtrl.js create mode 100644 src/modules/utils/modals/migrateFaq/migrateFaq.html create mode 100644 src/modules/utils/modals/migrateFaq/migrateFaq.less diff --git a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js index 77c47f81a..63c0e2ee8 100644 --- a/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js +++ b/src/modules/desktopUpdate/controllers/DesktopUpdateCtrl.js @@ -69,8 +69,7 @@ fileName, fileContent: content }).then(() => { - // @TODO вернуть - // this.state = 'installAndRun'; + this.state = 'installAndRun'; this.isDownloading = false; $scope.$digest(); }).catch((e) => { @@ -84,6 +83,7 @@ $scope.$digest(); }); }).catch((e) => { + console.log('%c e', 'color: #e5b6ed', e); this.error = String(e); $scope.$digest(); }); diff --git a/src/modules/ui/directives/accordion/Accordion.js b/src/modules/ui/directives/accordion/Accordion.js new file mode 100644 index 000000000..40bce796f --- /dev/null +++ b/src/modules/ui/directives/accordion/Accordion.js @@ -0,0 +1,51 @@ +(function () { + 'use strict'; + + /** + * @param {typeof Base} Base + */ + const controller = function (Base) { + + class Accordion extends Base { + + /** + * @type boolean + */ + allOpen = false; + + /** + * @type Array + */ + items = []; + + constructor() { + super(); + + this.observe('items', () => { + if (this.allOpen) { + this._accordeonItems = this.items.map(item => ({ + ...item, + isOpen: true + })); + } else { + this._accordeonItems = this.items; + } + }); + } + + } + + return new Accordion(); + }; + + controller.$inject = ['Base']; + + angular.module('app.ui').component('wAccordion', { + bindings: { + allOpen: '<', + items: '<' + }, + templateUrl: 'modules/ui/directives/accordion/accordion.html', + controller + }); +})(); diff --git a/src/modules/ui/directives/accordion/accordion.html b/src/modules/ui/directives/accordion/accordion.html new file mode 100644 index 000000000..b3f5e4be5 --- /dev/null +++ b/src/modules/ui/directives/accordion/accordion.html @@ -0,0 +1,9 @@ +
    +
  • +

    + + +

    +
    +
  • +
diff --git a/src/modules/ui/directives/accordion/accordion.less b/src/modules/ui/directives/accordion/accordion.less new file mode 100644 index 000000000..336b4f4cd --- /dev/null +++ b/src/modules/ui/directives/accordion/accordion.less @@ -0,0 +1,58 @@ +@import (reference) 'config'; +@import (reference) 'icons'; + +.accordion { + &__list { + padding: 0; + margin: 40px 0; + list-style-type: none; + } + + &__item { + margin-bottom: 10px; + } + + &__title { + cursor: pointer; + font-size: 15px; + font-weight: 500; + } + + &__arrow { + background: @expand-icon no-repeat center 5px; + width: 10px; + height: 18px; + z-index: 10; + transition: transform 0.3s; + opacity: .5; + + &.up { + transform: rotate(-180deg); + opacity: 1; + } + } +} + +.accordion__item { + &-text { + transition: max-height 0.3s; + max-height: 400px; + font-size: 15px; + font-weight: 500; + color: @color-basic-300; + padding: 2px 16px; + overflow: auto; + + &.ng-hide { + max-height: 0; + } + } + + &-title { + border-radius: @border-radius; + padding: 14px 16px; + display: flex; + align-items: center; + justify-content: space-between; + } +} diff --git a/src/modules/ui/directives/footer/Footer.js b/src/modules/ui/directives/footer/Footer.js index f3ac1e68b..fec085090 100644 --- a/src/modules/ui/directives/footer/Footer.js +++ b/src/modules/ui/directives/footer/Footer.js @@ -3,7 +3,7 @@ const analytics = require('@waves/event-sender'); - const controller = function (Base, $scope, $element, utils, storage) { + const controller = function (Base, $scope, $element, utils, storage, modalManager, $state) { class FooterCtrl extends Base { @@ -36,6 +36,7 @@ constructor() { super(); + this._isDesktopUpdate = $state.current.name === 'desktopUpdate'; this.hovered = false; this.mobileAppLink = navigator.userAgent.match(/iPhone|iPad|iPod/i) ? @@ -73,12 +74,16 @@ storage.save(this._toasterMobilesStorageKey, true); } + showFAQ() { + modalManager.showMigrateFAQ() + } + } return new FooterCtrl(); }; - controller.$inject = ['Base', '$scope', '$element', 'utils', 'storage']; + controller.$inject = ['Base', '$scope', '$element', 'utils', 'storage', 'modalManager', '$state']; angular.module('app.ui').component('wFooter', { templateUrl: 'modules/ui/directives/footer/footer.html', diff --git a/src/modules/ui/directives/footer/footer.html b/src/modules/ui/directives/footer/footer.html index f3bd1347a..ceff08c60 100644 --- a/src/modules/ui/directives/footer/footer.html +++ b/src/modules/ui/directives/footer/footer.html @@ -1,10 +1,11 @@