From a3c5aabba15408df9ae811e8199ff4be506d6496 Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Thu, 26 Mar 2020 14:57:32 +0200 Subject: [PATCH 01/58] Fix failing tests --- src/popup/router/pages/Transactions.vue | 2 +- tests/e2e/integration/withdraw.js | 1 - tests/e2e/support/commands.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/popup/router/pages/Transactions.vue b/src/popup/router/pages/Transactions.vue index 80080030b..7b92455b5 100644 --- a/src/popup/router/pages/Transactions.vue +++ b/src/popup/router/pages/Transactions.vue @@ -82,7 +82,7 @@ export default { const checkLoadMore = () => { const { scrollHeight, clientHeight } = document.documentElement; if (scrollHeight - window.scrollY === clientHeight) { - this.loadMore(); + setTimeout(() => this.loadMore(), 1500); } }; window.addEventListener('scroll', checkLoadMore); diff --git a/tests/e2e/integration/withdraw.js b/tests/e2e/integration/withdraw.js index 7d2e7de34..9bff8ee7a 100644 --- a/tests/e2e/integration/withdraw.js +++ b/tests/e2e/integration/withdraw.js @@ -110,7 +110,6 @@ describe('Test cases for Withdraw Page', () => { .get('[data-cy="review-send-button"]') .should('be.visible') .click() - .wait(3000) .get('[data-cy=pending-txs]') .should('be.visible'); }); diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js index dbf2a9486..cb446c34d 100644 --- a/tests/e2e/support/commands.js +++ b/tests/e2e/support/commands.js @@ -223,7 +223,7 @@ Cypress.Commands.add('sendTip', (tip = {}) => { .should('eq', `${Cypress.config().popupUrl}/popup#/account`) .get('[data-cy=pending-txs]') .should('be.visible') - .get('[data-cy=success-tip]', { timeout: 60000 }) + .get('[data-cy=success-tip]', { timeout: 120000 }) .should('be.visible') .url() .should('eq', `${Cypress.config().popupUrl}/popup#/success-tip`) From 6c41d75525dae9c66e8b5e9406b49da984fa48cb Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Fri, 27 Mar 2020 09:49:55 +0200 Subject: [PATCH 02/58] Increase sendTip command timeout --- tests/e2e/support/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js index cb446c34d..e95827b10 100644 --- a/tests/e2e/support/commands.js +++ b/tests/e2e/support/commands.js @@ -223,7 +223,7 @@ Cypress.Commands.add('sendTip', (tip = {}) => { .should('eq', `${Cypress.config().popupUrl}/popup#/account`) .get('[data-cy=pending-txs]') .should('be.visible') - .get('[data-cy=success-tip]', { timeout: 120000 }) + .get('[data-cy=success-tip]', { timeout: 180000 }) .should('be.visible') .url() .should('eq', `${Cypress.config().popupUrl}/popup#/success-tip`) From ea12ca0f23b18693aeb3ce6924a75e14f0f582b9 Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Fri, 27 Mar 2020 10:23:19 +0200 Subject: [PATCH 03/58] Increase timeout --- tests/e2e/support/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js index e95827b10..7d908abd0 100644 --- a/tests/e2e/support/commands.js +++ b/tests/e2e/support/commands.js @@ -223,7 +223,7 @@ Cypress.Commands.add('sendTip', (tip = {}) => { .should('eq', `${Cypress.config().popupUrl}/popup#/account`) .get('[data-cy=pending-txs]') .should('be.visible') - .get('[data-cy=success-tip]', { timeout: 180000 }) + .get('[data-cy=success-tip]', { timeout: 240000 }) .should('be.visible') .url() .should('eq', `${Cypress.config().popupUrl}/popup#/success-tip`) From 62bb120bcfee2b6e0e1cfee7af391beb22f714c7 Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Fri, 27 Mar 2020 17:56:48 +0200 Subject: [PATCH 04/58] Add vuex plugin for persist data, refactor code where browser.storage is used --- src/background.js | 1 - src/lib/rpcWallet.js | 7 +- src/lib/wallet.js | 18 ----- src/popup/App.vue | 18 +---- src/popup/cameraPermission.js | 1 - src/popup/router/components/BalanceInfo.vue | 1 - src/popup/router/components/PendingTxs.vue | 7 +- .../router/components/RecentTransactions.vue | 6 +- src/popup/router/pages/GeneralSettings.vue | 12 +-- src/popup/router/pages/ImportAccount.vue | 12 +-- src/popup/router/pages/Index.vue | 13 +-- src/popup/router/pages/Intro.vue | 2 +- src/popup/router/pages/Retip.vue | 7 +- src/popup/router/pages/Send.vue | 7 +- src/popup/router/pages/SignTransaction.vue | 10 --- src/popup/router/pages/TipPage.vue | 7 +- src/popup/utils/getPopupProps.js | 3 +- src/popup/utils/helper.js | 25 +----- src/popup/utils/index.js | 16 +--- src/store/actions.js | 81 +++++++++++-------- src/store/index.js | 35 ++++++-- src/store/mutation-types.js | 2 + src/store/mutations.js | 3 + src/store/plugins/persistState.js | 38 +++++++++ src/wallet-controller.js | 2 - 25 files changed, 162 insertions(+), 172 deletions(-) create mode 100644 src/store/plugins/persistState.js diff --git a/src/background.js b/src/background.js index b3e36df68..c39dec424 100644 --- a/src/background.js +++ b/src/background.js @@ -22,7 +22,6 @@ if (process.env.IS_EXTENSION) { browser.windows.getAll({}).then(wins => { if (wins.length === 0) { sessionStorage.removeItem('phishing_urls'); - browser.storage.local.remove(['isLogged', 'activeAccount']); } }); }, 5000); diff --git a/src/lib/rpcWallet.js b/src/lib/rpcWallet.js index e9400109e..ea2d5099b 100644 --- a/src/lib/rpcWallet.js +++ b/src/lib/rpcWallet.js @@ -18,6 +18,7 @@ import { } from '../popup/utils/helper'; import { DEFAULT_NETWORK, AEX2_METHODS, NO_POPUP_AEPPS, BLACKLIST_AEPPS, MAX_AMOUNT_WITHOUT_CONFIRM } from '../popup/utils/constants'; import { mockLogin } from '../popup/utils'; +import { getState } from '../store/plugins/persistState'; global.browser = require('webextension-polyfill'); @@ -31,8 +32,10 @@ const rpcWallet = { const { userAccount } = await browser.storage.local.get('userAccount'); if (userAccount) { this.controller.generateWallet({ seed: stringifyForStorage(userAccount.privateKey) }); - const { activeNetwork } = await browser.storage.local.get('activeNetwork'); - this[AEX2_METHODS.INIT_RPC_WALLET]({ address: userAccount.publicKey, network: !activeNetwork ? DEFAULT_NETWORK : activeNetwork }); + const { + current: { network }, + } = await getState(); + this[AEX2_METHODS.INIT_RPC_WALLET]({ address: userAccount.publicKey, network }); } }, async initSubaccounts() { diff --git a/src/lib/wallet.js b/src/lib/wallet.js index 2560c348c..6e84e7cb4 100644 --- a/src/lib/wallet.js +++ b/src/lib/wallet.js @@ -18,30 +18,13 @@ export default { const address = await store.dispatch('generateWallet', { seed: userAccount.privateKey }); store.commit('UPDATE_ACCOUNT', userAccount); store.commit('SET_ACTIVE_ACCOUNT', { publicKey: address, index: 0 }); - let sub = []; - const { subaccounts } = await browser.storage.local.get('subaccounts'); - if (!subaccounts || (subaccounts && !subaccounts.find(f => f.publicKey === userAccount.publicKey))) { - sub.push({ - name: 'Main Account', - publicKey: userAccount.publicKey, - root: true, - balance: 0, - aename: null, - }); - } - if (subaccounts) sub = [...sub, ...subaccounts.filter(s => s.publicKey)]; - store.dispatch('setSubAccounts', sub); /* Get cached balance */ - const { tokenBal } = await browser.storage.local.get('tokenBal'); - if (tokenBal && tokenBal !== '0.000') store.commit('UPDATE_BALANCE', parseFloat(tokenBal)); store.commit('SWITCH_LOGGED_IN', true); /* Get network */ const networks = await getAllNetworks(); store.commit('SET_NETWORKS', networks); - const { activeNetwork } = await browser.storage.local.get(['activeNetwork']); - if (activeNetwork) store.commit('SWITCH_NETWORK', activeNetwork); store.commit('SET_MAIN_LOADING', false); return { loggedIn: true }; @@ -80,7 +63,6 @@ export default { } }, async logout() { - await browser.storage.local.remove(['isLogged', 'activeAccount']); store.commit('SET_ACTIVE_ACCOUNT', { publicKey: '', index: 0 }); store.commit('UNSET_SUBACCOUNTS'); store.commit('UPDATE_ACCOUNT', {}); diff --git a/src/popup/App.vue b/src/popup/App.vue index 2103a19cb..d888c33e1 100644 --- a/src/popup/App.vue +++ b/src/popup/App.vue @@ -20,7 +20,6 @@ import { mapGetters } from 'vuex'; import { clearInterval, setInterval } from 'timers'; import { AEX2_METHODS } from './utils/constants'; import { postMessage, readWebPageDom } from './utils/connection'; -import { getCurrencies } from './utils/helper'; import { fetchAndSetLocale } from './utils/i18nHelper'; import Header from './router/components/Header'; import SidebarMenu from './router/components/SidebarMenu'; @@ -42,10 +41,8 @@ export default { }, }, async created() { - const { language } = await browser.storage.local.get(['language']); - - this.$store.state.current.language = language; - if (language) fetchAndSetLocale(language); + // console.log(this.current.language) + fetchAndSetLocale(this.current.language); if (process.env.IS_EXTENSION) { readWebPageDom((receiver, sendResponse) => { @@ -55,7 +52,7 @@ export default { } this.checkSdkReady(); - this.getCurrencies(); + this.$store.dispatch('getCurrencies'); if (process.env.IS_EXTENSION) { const [update] = await browser.runtime.requestUpdateCheck(); @@ -108,15 +105,6 @@ export default { } }, 2500); }, - async getCurrencies() { - const { currency } = await browser.storage.local.get('currency'); - const currencies = await getCurrencies(); - this.$store.commit('SET_CURRENCIES', currencies); - this.$store.commit('SET_CURRENCY', { - currency: currency || this.current.currency, - currencyRate: currency ? currencies[currency] : currencies[this.current.currency], - }); - }, }, beforeDestroy() { clearInterval(this.polling); diff --git a/src/popup/cameraPermission.js b/src/popup/cameraPermission.js index fad8d3ef7..bdfecc53b 100644 --- a/src/popup/cameraPermission.js +++ b/src/popup/cameraPermission.js @@ -3,7 +3,6 @@ if (navigator.userAgent.indexOf('Firefox') !== -1) { navigator.mediaDevices .getUserMedia({ video: true }) .then(() => { - browser.storage.local.set({ firefoxCameraAllowed: true }); alert('You have allowed the firefox camera. Now, try again scan QR code'); }) .catch(err => { diff --git a/src/popup/router/components/BalanceInfo.vue b/src/popup/router/components/BalanceInfo.vue index 3ee333db9..193f3eb10 100644 --- a/src/popup/router/components/BalanceInfo.vue +++ b/src/popup/router/components/BalanceInfo.vue @@ -53,7 +53,6 @@ export default { this.dropdown[dropdownParent.id] = !this.dropdown[dropdownParent.id]; }, async switchCurrency(currency) { - await browser.storage.local.set({ currency }); this.$store.commit('SET_CURRENCY', { currency, currencyRate: this.currencies[currency] }); this.dropdown.currencies = false; }, diff --git a/src/popup/router/components/PendingTxs.vue b/src/popup/router/components/PendingTxs.vue index 96da34df8..650c672c5 100644 --- a/src/popup/router/components/PendingTxs.vue +++ b/src/popup/router/components/PendingTxs.vue @@ -34,19 +34,16 @@ export default { }, filters: { formatDate }, created() { - this.$store.dispatch('getPendingTxs'); const checkMined = setInterval(() => this.checkPendingTxMined(), 2500); this.$once('hook:destroyed', () => clearInterval(checkMined)); }, methods: { async checkPendingTxMined() { - const { pendingTxs = [] } = await browser.storage.local.get('pendingTxs'); await Promise.all( - pendingTxs.map(async ({ hash, type, amount, domain }) => { + this.transactions.pending.map(async ({ hash, type, amount, domain }) => { const mined = await this.$store.state.sdk.poll(hash); if (!mined) return; - const pending = pendingTxs.filter(p => p.hash !== hash); - await browser.storage.local.set({ pendingTxs: pending }); + const pending = this.transactions.pending.filter(p => p.hash !== hash); this.$store.commit('SET_PENDING_TXS', pending); if (type === 'tip') this.$router.push({ name: 'success-tip', params: { amount, domain } }); if (type === 'spend') this.$router.push({ name: 'send', params: { redirectstep: 3, successtx: mined } }); diff --git a/src/popup/router/components/RecentTransactions.vue b/src/popup/router/components/RecentTransactions.vue index 76bf4bf20..0bb39648e 100644 --- a/src/popup/router/components/RecentTransactions.vue +++ b/src/popup/router/components/RecentTransactions.vue @@ -5,12 +5,12 @@ {{ $t('pages.recentTransactions.viewAll') }} -
+
-
+

{{ $t('pages.recentTransactions.noTransactionsFound') }}

@@ -37,7 +37,7 @@ export default { }; }, created() { - this.updateTransactions(); + if (this.transactions.latest.length) this.loading = false; this.polling = setInterval(() => this.updateTransactions(), 5000); this.$once('hook:beforeDestroy', () => clearInterval(this.polling)); }, diff --git a/src/popup/router/pages/GeneralSettings.vue b/src/popup/router/pages/GeneralSettings.vue index 738ea19d9..4888d6f41 100644 --- a/src/popup/router/pages/GeneralSettings.vue +++ b/src/popup/router/pages/GeneralSettings.vue @@ -45,11 +45,6 @@ export default { computed: { ...mapGetters(['current', 'popup', 'names', 'sdk']), }, - created() { - if (!this.current.language) { - this.current.language = 'en'; - } - }, methods: { toggleDropdown(event, parentClass) { const dropdownParent = event.target.closest(!parentClass ? '.language-settings' : parentClass); @@ -57,11 +52,8 @@ export default { }, async switchLanguage(languageChoose) { fetchAndSetLocale(languageChoose); - browser.storage.local.set({ language: languageChoose }).then(() => { - this.current.language = languageChoose; - this.dropdown.languages = false; - this.$store.state.current.language = languageChoose; - }); + this.dropdown.languages = false; + this.$store.state.current.language = languageChoose; }, navigateToSettings() { this.$router.push('/settings'); diff --git a/src/popup/router/pages/ImportAccount.vue b/src/popup/router/pages/ImportAccount.vue index e514affee..38c239ed8 100644 --- a/src/popup/router/pages/ImportAccount.vue +++ b/src/popup/router/pages/ImportAccount.vue @@ -34,8 +34,8 @@ export default { }, methods: { async importAccount() { + this.loading = true; if (this.mnemonic) { - this.loading = true; this.mnemonic = this.mnemonic.trim(); const mnemonic = this.mnemonic.split(' '); if (mnemonic.length >= 12 && mnemonic.length <= 24 && validateMnemonic(this.mnemonic)) { @@ -48,16 +48,16 @@ export default { privateKey: seed, }; await this.$store.dispatch('setLogin', { keypair }); - this.$router.push('/account'); - } else { - this.loading = false; - this.disabled = true; - this.errorMsg = `${this.$t('pages.index.accountNotFound')}
${this.$t('pages.index.checkSeed')}`; + return setTimeout(() => this.$router.push('/account'), 1000); } + this.disabled = true; + this.errorMsg = `${this.$t('pages.index.accountNotFound')}
${this.$t('pages.index.checkSeed')}`; } else { this.disabled = true; this.errorMsg = `${this.$t('pages.index.accountNotFound')}
${this.$t('pages.index.checkSeed')}`; } + this.loading = false; + return false; }, validateMnemonic() { return validateMnemonic(this.mnemonic); diff --git a/src/popup/router/pages/Index.vue b/src/popup/router/pages/Index.vue index f3e79e765..dfd178b82 100644 --- a/src/popup/router/pages/Index.vue +++ b/src/popup/router/pages/Index.vue @@ -9,16 +9,16 @@ Google Play Or use a web version
- +
{{ $t('pages.index.term1') }} {{ $t('pages.index.termsAndConditions') }}
- - @@ -38,7 +38,7 @@ export default { data() { return { terms: false, - termsAgreedOrNot: false, + termsAgreed: false, IS_WEB: process.env.PLATFORM === 'web', }; }, @@ -46,11 +46,6 @@ export default { ...mapGetters(['account', 'isLoggedIn', 'wallet', 'tokens']), }, mounted() {}, - created() { - browser.storage.local.get('termsAgreed').then(res => { - this.termsAgreedOrNot = res.termsAgreed; - }); - }, methods: { generwateWalletIntro() { this.$router.push('/intro'); diff --git a/src/popup/router/pages/Intro.vue b/src/popup/router/pages/Intro.vue index 855f5abd1..4ebe3a92e 100644 --- a/src/popup/router/pages/Intro.vue +++ b/src/popup/router/pages/Intro.vue @@ -95,7 +95,7 @@ export default { publicKey: address, privateKey: seed, }; - this.$store.dispatch('setLogin', { keypair }); + await this.$store.dispatch('setLogin', { keypair }); this.next(); }, prev() { diff --git a/src/popup/router/pages/Retip.vue b/src/popup/router/pages/Retip.vue index d8e2eaa85..b6fc0f997 100644 --- a/src/popup/router/pages/Retip.vue +++ b/src/popup/router/pages/Retip.vue @@ -35,7 +35,6 @@ import axios from 'axios'; import tipping from 'aepp-raendom/src/utils/tippingContractUtil'; import { MAGNITUDE, calculateFee, TX_TYPES, BACKEND_URL } from '../../utils/constants'; import { pollGetter } from '../../utils/helper'; -import { setPendingTx } from '../../utils'; import openUrl from '../../utils/openUrl'; import CheckIcon from '../../../icons/check-icon.svg?vue-component'; import AmountSend from '../components/AmountSend'; @@ -103,9 +102,9 @@ export default { const amount = BigNumber(this.amount).shiftedBy(MAGNITUDE); this.loading = true; try { - const res = await this.tipping.methods.retip(this.tip.id, { amount, waitMined: false }); - if (res.hash) { - await setPendingTx({ hash: res.hash, amount: this.amount, domain: this.tip.url, time: Date.now(), type: 'tip' }); + const { hash } = await this.tipping.methods.retip(this.tip.id, { amount, waitMined: false }); + if (hash) { + await this.$store.dispatch('setPendingTx', { hash, amount: this.amount, domain: this.tip.url, time: Date.now(), type: 'tip' }); this.openCallbackOrGoHome('x-success'); } } catch (e) { diff --git a/src/popup/router/pages/Send.vue b/src/popup/router/pages/Send.vue index 32b719db4..9a2d0e38a 100644 --- a/src/popup/router/pages/Send.vue +++ b/src/popup/router/pages/Send.vue @@ -99,7 +99,6 @@ import { mapGetters } from 'vuex'; import { calculateFee, TX_TYPES } from '../../utils/constants'; import { checkAddress, chekAensName, checkHashType, aeToAettos, pollGetter } from '../../utils/helper'; -import { setPendingTx } from '../../utils'; import openUrl from '../../utils/openUrl'; import AmountSend from '../components/AmountSend'; import Textarea from '../components/Textarea'; @@ -251,9 +250,9 @@ export default { } this.loading = true; try { - const result = await this.sdk.spend(amount, receiver, { waitMined: false }); - if (result.hash) { - await setPendingTx({ hash: result.hash, amount: this.form.amount, time: Date.parse(new Date()), type: 'spend' }); + const { hash } = await this.sdk.spend(amount, receiver, { waitMined: false }); + if (hash) { + await this.$store.dispatch('setPendingTx', { hash, amount: this.form.amount, time: Date.parse(new Date()), type: 'spend' }); this.$router.push('/account'); } this.loading = false; diff --git a/src/popup/router/pages/SignTransaction.vue b/src/popup/router/pages/SignTransaction.vue index 9e8c13ff3..a4c183d33 100644 --- a/src/popup/router/pages/SignTransaction.vue +++ b/src/popup/router/pages/SignTransaction.vue @@ -275,15 +275,6 @@ export default { } return Promise.resolve(false); }, - async setTxInQueue(tx) { - const { processingTx } = await browser.storage.local.get('processingTx'); - let list = []; - if (typeof processingTx !== 'undefined' && processingTx.length) { - list = [...list, ...processingTx]; - } - list.push(tx); - await browser.storage.local.set({ processingTx: list }); - }, async init() { this.setReceiver(); if (this.isLedger && this.data.type !== 'txSign') { @@ -679,7 +670,6 @@ export default { name: 'account', type: 'added_success', }); - await this.$store.dispatch('removePendingName', { hash: this.data.tx.hash }); } catch (err) { setTxInQueue('error'); this.$store.dispatch('popupAlert', { name: 'spend', type: 'tx_error', msg: err.message }); diff --git a/src/popup/router/pages/TipPage.vue b/src/popup/router/pages/TipPage.vue index 0e8a99a56..256207f7b 100644 --- a/src/popup/router/pages/TipPage.vue +++ b/src/popup/router/pages/TipPage.vue @@ -53,7 +53,6 @@ import { mapGetters } from 'vuex'; import axios from 'axios'; import { calculateFee, TX_TYPES, BACKEND_URL } from '../../utils/constants'; import { escapeSpecialChars, pollGetter, aeToAettos } from '../../utils/helper'; -import { setPendingTx } from '../../utils'; import CheckIcon from '../../../icons/check-icon.svg?vue-component'; import AmountSend from '../components/AmountSend'; import Textarea from '../components/Textarea'; @@ -172,9 +171,9 @@ export default { const amount = aeToAettos(this.amount); this.loading = true; try { - const res = await this.tipping.call('tip', [this.url, escapeSpecialChars(this.note)], { amount, waitMined: false }); - if (res.hash) { - await setPendingTx({ hash: res.hash, amount: this.amount, domain: this.url, time: Date.now(), type: 'tip' }); + const { hash } = await this.tipping.call('tip', [this.url, escapeSpecialChars(this.note)], { amount, waitMined: false }); + if (hash) { + await this.$store.dispatch('setPendingTx', { hash, amount: this.amount, domain: this.url, time: Date.now(), type: 'tip' }); this.$router.push('/account'); } } catch (e) { diff --git a/src/popup/utils/getPopupProps.js b/src/popup/utils/getPopupProps.js index 3397c9992..0b0503354 100644 --- a/src/popup/utils/getPopupProps.js +++ b/src/popup/utils/getPopupProps.js @@ -27,8 +27,7 @@ export default async () => { window.close(); }, 1000); }; - const { txType } = await browser.storage.local.get('txType'); - const payload = process.env.RUNNING_IN_TESTS ? { popupType: window.POPUP_TYPE, txType } : {}; + const payload = process.env.RUNNING_IN_TESTS ? { popupType: window.POPUP_TYPE, txType: (await browser.storage.local.get('txType')).txType } : {}; const props = await postMessage({ type: 'POPUP_INFO', payload }); props.resolve = closingWrapper(resolve); props.reject = closingWrapper(reject); diff --git a/src/popup/utils/helper.js b/src/popup/utils/helper.js index 5628c764e..54b7a4563 100644 --- a/src/popup/utils/helper.js +++ b/src/popup/utils/helper.js @@ -2,6 +2,7 @@ import { Crypto, TxBuilder } from '@aeternity/aepp-sdk/es'; import Swagger from '@aeternity/aepp-sdk/es/utils/swagger'; import { AE_AMOUNT_FORMATS, formatAmount } from '@aeternity/aepp-sdk/es/utils/amount-formatter'; import { MAGNITUDE_EXA, MAGNITUDE_GIGA, MAGNITUDE_PICO, CONNECTION_TYPES, networks, DEFAULT_NETWORK } from './constants'; +import { getState } from '../../store/plugins/persistState'; export const aeToAettos = v => formatAmount(v, { denomination: AE_AMOUNT_FORMATS.AE, targetDenomination: AE_AMOUNT_FORMATS.AETTOS }); export const aettosToAe = v => formatAmount(v, { denomination: AE_AMOUNT_FORMATS.AETTOS, targetDenomination: AE_AMOUNT_FORMATS.AE }); @@ -142,25 +143,6 @@ const middleware = async (network, current) => { })({ swag }); }; -const getCurrencies = async () => { - const { convertTimer } = await browser.storage.local.get('convertTimer'); - const time = new Date().getTime(); - if (!convertTimer || (convertTimer && (convertTimer === '' || convertTimer <= time))) { - const fetched = await fetchData( - 'https://api.coingecko.com/api/v3/simple/price?ids=aeternity&vs_currencies=usd,eur,aud,ron,brl,cad,chf,cny,czk,dkk,gbp,hkd,hrk,huf,idr,ils,inr,isk,jpy,krw,mxn,myr,nok,nzd,php,pln,ron,rub,sek,sgd,thb,try,zar,xau', - 'get', - '' - ); - await browser.storage.local.set({ convertTimer: time + 3600000 }); - await browser.storage.local.set({ allCurrencies: JSON.stringify(fetched.aeternity) }); - - return fetched.aeternity; - } - - const { allCurrencies } = await browser.storage.local.get('allCurrencies'); - return JSON.parse(allCurrencies); -}; - const convertAmountToCurrency = (currency, amount) => currency * amount; const checkAddress = value => Crypto.isAddressValid(value, 'ak') || Crypto.isAddressValid(value, 'ct') || Crypto.isAddressValid(value, 'ok'); @@ -411,9 +393,9 @@ export const pollGetter = getter => export const getActiveNetwork = async () => { const all = await getAllNetworks(); - const { activeNetwork } = await browser.storage.local.get('activeNetwork'); + const { current } = await getState(); return { - network: all[activeNetwork || DEFAULT_NETWORK], + network: all[current.network || DEFAULT_NETWORK], all, }; }; @@ -425,7 +407,6 @@ export { fetchData, detectBrowser, middleware, - getCurrencies, convertAmountToCurrency, checkAddress, chekAensName, diff --git a/src/popup/utils/index.js b/src/popup/utils/index.js index abb57aa70..4b0ee09ab 100644 --- a/src/popup/utils/index.js +++ b/src/popup/utils/index.js @@ -13,18 +13,6 @@ export const setTxInQueue = async tx => { await browser.storage.local.set({ processingTx: list }); }; -export const setPendingTx = async tx => { - const { pendingTxs } = await browser.storage.local.get('pendingTxs'); - let list = []; - if (pendingTxs && pendingTxs.length) { - list = [...list, ...pendingTxs]; - } - list.push(tx); - await setTxInQueue(tx.hash); - await browser.storage.local.set({ pendingTxs: list }); - return true; -}; - export const formatTime = time => new Date(parseInt(time)).toLocaleTimeString(navigator.language, { timeStyle: 'short', hourCycle: 'h24', hour: '2-digit', minute: '2-digit' }); export const formatDate = time => @@ -46,7 +34,7 @@ export const mockLogin = async (options = {}) => { publicKey, privateKey: seed, }; - await browser.storage.local.set({ userAccount: keypair, isLogged: true, termsAgreed: true }); + await browser.storage.local.set({ userAccount: keypair }); const sub = []; sub.push({ name: 'Main Account', @@ -55,7 +43,7 @@ export const mockLogin = async (options = {}) => { root: true, aename: options.name ? options.name : null, }); - await browser.storage.local.set({ subaccounts: sub, activeAccount: 0, mnemonic }); + await browser.storage.local.set({ subaccounts: sub, mnemonic }); if (options.balance) await browser.storage.local.set({ tokenBal: options.balance }); if (options.lastRoute) await localStorage.setItem('lsroute', options.lastRoute); diff --git a/src/store/actions.js b/src/store/actions.js index 841faf245..76b2c3144 100644 --- a/src/store/actions.js +++ b/src/store/actions.js @@ -5,6 +5,7 @@ import * as popupMessages from '../popup/utils/popup-messages'; import { convertToAE, stringifyForStorage, parseFromStorage, aettosToAe } from '../popup/utils/helper'; import { BACKEND_URL, DEFAULT_NETWORK } from '../popup/utils/constants'; import { postMessage } from '../popup/utils/connection'; +import { setTxInQueue } from '../popup/utils'; export default { setAccount({ commit }, payload) { @@ -18,12 +19,10 @@ export default { commit(types.SET_SUBACCOUNTS, payload); }, async switchNetwork({ commit }, payload) { - await browser.storage.local.set({ activeNetwork: payload }); return commit(types.SWITCH_NETWORK, payload); }, async updateBalance({ commit, state }) { const balance = await state.sdk.balance(state.account.publicKey).catch(() => 0); - await browser.storage.local.set({ tokenBal: convertToAE(balance).toFixed(3) }); commit(types.UPDATE_BALANCE, convertToAE(balance)); }, popupAlert({ commit }, payload) { @@ -180,7 +179,7 @@ export default { initSdk({ commit }, payload) { commit(types.INIT_SDK, payload); }, - async getRegisteredNames({ commit, state }) { + async getRegisteredNames({ commit, state, dispatch }) { if (!state.middleware) return; const { middlewareUrl } = state.network[state.current.network]; const res = await Promise.all( @@ -218,7 +217,10 @@ export default { return []; }) ); - await browser.storage.local.set({ subaccounts: state.subaccounts.filter(s => s.publicKey) }); + await dispatch( + 'setSubAccounts', + state.subaccounts.filter(s => s.publicKey) + ); commit(types.SET_NAMES, { names: Array.prototype.concat.apply([], res) }); }, async fetchAuctionEntry({ state: { sdk } }, name) { @@ -231,13 +233,6 @@ export default { })), }; }, - async removePendingName({ commit, state }, { hash }) { - let pending = state.pendingNames; - pending = pending.filter(p => p.hash !== hash); - await browser.storage.local.set({ pendingNames: { list: pending } }); - commit(types.SET_PENDING_NAMES, { names: pending }); - await new Promise(resolve => setTimeout(resolve, 1500)); - }, unlockWallet(context, payload) { return postMessage({ type: 'unlockWallet', payload }); @@ -261,34 +256,31 @@ export default { return (await postMessage({ type: 'generateWallet', payload: { seed: stringifyForStorage(seed) } })).address; }, - async setLogin({ commit, dispatch }, { keypair }) { - await browser.storage.local.set({ userAccount: keypair, isLogged: true, termsAgreed: true }); + async setLogin({ commit, dispatch, state }, { keypair }) { + await browser.storage.local.set({ userAccount: keypair }); - const sub = []; - sub.push({ - name: 'Main Account', - publicKey: keypair.publicKey, - balance: 0, - root: true, - aename: null, - }); - await browser.storage.local.set({ subaccounts: sub, activeAccount: 0 }); + const sub = [ + { + name: 'Main Account', + publicKey: keypair.publicKey, + balance: 0, + root: true, + aename: null, + }, + ]; commit('SET_ACTIVE_ACCOUNT', { publicKey: keypair.publicKey, index: 0 }); await dispatch('setSubAccounts', sub); commit('UPDATE_ACCOUNT', keypair); commit('SWITCH_LOGGED_IN', true); }, - async getPendingTxs({ state: { current }, commit }) { - const { pendingTxs } = await browser.storage.local.get('pendingTxs'); - let txs = []; - if (pendingTxs && pendingTxs.length) { - txs = pendingTxs.map(el => { - const { time, domain } = el; - const amount = parseFloat(el.amount).toFixed(3); - const amountCurrency = parseFloat(current.currencyRate ? amount * current.currencyRate : amount).toFixed(3); - return { ...el, amount, time, amountCurrency, domain }; - }); - } + async setPendingTx({ commit, state: { transactions, current } }, tx) { + await setTxInQueue(tx.hash); + const txs = [...transactions.pending, tx].map(el => { + const { time, domain } = el; + const amount = parseFloat(el.amount).toFixed(3); + const amountCurrency = parseFloat(current.currencyRate ? amount * current.currencyRate : amount).toFixed(3); + return { ...el, amount, time, amountCurrency, domain }; + }); commit('SET_PENDING_TXS', txs); }, async checkExtensionUpdate({ state: { network } }) { @@ -311,4 +303,27 @@ export default { return true; }, + async setCurrency({ + commit, + state: { + currencies, + current: { currency }, + }, + }) { + commit('SET_CURRENCY', { + currency, + currencyRate: currencies[currency], + }); + }, + async getCurrencies({ state: { nextCurrenciesFetch }, commit, dispatch }) { + if (!nextCurrenciesFetch || nextCurrenciesFetch <= new Date().getTime()) { + const res = await fetch( + 'https://api.coingecko.com/api/v3/simple/price?ids=aeternity&vs_currencies=usd,eur,aud,ron,brl,cad,chf,cny,czk,dkk,gbp,hkd,hrk,huf,idr,ils,inr,isk,jpy,krw,mxn,myr,nok,nzd,php,pln,ron,rub,sek,sgd,thb,try,zar,xau' + ); + const { aeternity } = await res.json(); + commit('SET_CURRENCIES', aeternity); + commit('SET_NEXT_CURRENCY_FETCH', new Date().getTime() + 3600000); + } + dispatch('setCurrency'); + }, }; diff --git a/src/store/index.js b/src/store/index.js index 1f9aeccd5..59da0fea6 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,9 +1,10 @@ import Vue from 'vue'; import Vuex from 'vuex'; - +import { mergeWith } from 'lodash-es'; import { getters } from './getters'; import mutations from './mutations'; import actions from './actions'; +import persistState from './plugins/persistState'; import { POPUP_PROPS } from '../popup/utils/popup-messages'; import { networks, DEFAULT_NETWORK } from '../popup/utils/constants'; @@ -15,12 +16,11 @@ export default new Vuex.Store({ account: {}, activeAccount: 0, names: [], - pendingNames: [], wallet: [], balance: 0, current: { network: DEFAULT_NETWORK, - language: '', + language: 'en', token: 0, currency: 'usd', currencyRate: 0, @@ -43,10 +43,35 @@ export default new Vuex.Store({ mainLoading: true, nodeStatus: 'connecting', currencies: {}, + nextCurrenciesFetch: null, notifications: [], }, getters, - mutations, + mutations: { + syncState(state, remoteState) { + const customizer = (objValue, srcValue) => { + if (!Array.isArray(srcValue)) return undefined; + if (!Array.isArray(objValue)) return srcValue; + return srcValue.map((el, idx) => (el && typeof el === 'object' ? mergeWith({}, objValue[idx], el, customizer) : el)); + }; + Object.entries(mergeWith({}, state, remoteState, customizer)).forEach(([name, value]) => Vue.set(state, name, value)); + }, + ...mutations, + }, actions, - plugins: [], + plugins: [ + persistState( + state => state, + ({ current, transactions, balance, subaccounts, currencies, userNetworks, names, nextCurrenciesFetch }) => ({ + current, + transactions, + balance, + subaccounts, + currencies, + userNetworks, + names, + nextCurrenciesFetch, + }) + ), + ], }); diff --git a/src/store/mutation-types.js b/src/store/mutation-types.js index c0bf8f915..61356acb2 100644 --- a/src/store/mutation-types.js +++ b/src/store/mutation-types.js @@ -35,3 +35,5 @@ export const SET_NODE_STATUS = 'SET_NODE_STATUS'; export const SET_CURRENCY = 'SET_CURRENCY'; export const SET_CURRENCIES = 'SET_CURRENCIES'; export const ADD_NOTIFICATION = 'ADD_NOTIFICATION'; +export const SET_BACKED_UP_SEED = 'SET_BACKED_UP_SEED'; +export const SET_NEXT_CURRENCY_FETCH = 'SET_NEXT_CURRENCY_FETCH'; diff --git a/src/store/mutations.js b/src/store/mutations.js index a88603901..2783ea75d 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -114,6 +114,9 @@ export default { [types.SET_CURRENCIES](state, payload) { state.currencies = payload; }, + [types.SET_NEXT_CURRENCY_FETCH](state, payload) { + state.nextCurrenciesFetch = payload; + }, [types.ADD_NOTIFICATION](state, payload) { state.notifications = [...state.notifications, payload]; }, diff --git a/src/store/plugins/persistState.js b/src/store/plugins/persistState.js new file mode 100644 index 000000000..a273ee2ff --- /dev/null +++ b/src/store/plugins/persistState.js @@ -0,0 +1,38 @@ +const KEY = 'state'; + +const setState = async state => { + browser.storage.local.set({ [KEY]: state }); +} + +export const getState = async () => { + const { [KEY]: state } = await browser.storage.local.get(KEY); + return state; +} + +export const resetState = () => { + browser.storage.remove.local(KEY); +} + + +export default (reducerLoad, reducerSave) => async store => { + let resetting = false; + let lastEmitedState = reducerLoad(await getState(), store); + store.commit('syncState', lastEmitedState); + store.subscribe(({ type, payload }, state) => { + if (resetting || (type === 'syncState' && payload === lastEmitedState)) return; + setState(reducerSave(state)); + }); + store.registerModule('persistState', { + actions: { + reset() { + resetting = true; + resetState(); + }, + }, + }); + + chrome.storage.onChanged.addListener(async () => { + lastEmitedState = reducerLoad(await getState()); + store.commit('syncState', lastEmitedState); + }); +}; \ No newline at end of file diff --git a/src/wallet-controller.js b/src/wallet-controller.js index dc6a49f0a..1cf63cdb2 100644 --- a/src/wallet-controller.js +++ b/src/wallet-controller.js @@ -15,7 +15,6 @@ export default class WalletController { if (wins.length === 0) { this.lockWallet(); sessionStorage.removeItem('phishing_urls'); - browser.storage.local.remove('activeAccount'); } }); if (!this.wallet) { @@ -40,7 +39,6 @@ export default class WalletController { lockWallet() { this.wallet = null; - browser.storage.local.remove('isLogged'); } generateWallet({ seed }) { From bf5bda8ace2604baba1a484a23fc67c326411f4d Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 28 Mar 2020 00:25:59 +1000 Subject: [PATCH 05/58] Enable "no-empty" eslint rule --- .eslintrc.js | 1 - src/aepp/App.vue | 26 +++++++++---------- src/lib/background-utils.js | 8 ++++-- src/lib/rpcWallet.js | 12 ++++++--- src/lib/tip-claim-relay.js | 4 ++- .../router/components/TransactionItem.vue | 19 +++++--------- src/popup/router/pages/QrCodeReader.vue | 8 +++--- src/popup/router/pages/SignTransaction.vue | 8 ++++-- src/popup/router/pages/TipPage.vue | 4 ++- src/popup/utils/helper.js | 11 ++++---- src/store/actions.js | 4 ++- 11 files changed, 56 insertions(+), 49 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 16b7919fc..903089e99 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -47,7 +47,6 @@ module.exports = { // allow debugger during development 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', "class-methods-use-this": "warn", - "no-empty": "warn", "no-restricted-globals": "warn" } } diff --git a/src/aepp/App.vue b/src/aepp/App.vue index 45f9b6c9e..0e8fc7aa3 100644 --- a/src/aepp/App.vue +++ b/src/aepp/App.vue @@ -126,22 +126,20 @@ contract Example = }; }, async scanForWallets() { - try { - // eslint-disable-next-line func-names - const handleWallets = async function({ wallets, newWallet }) { - const wallet = newWallet || Object.values(wallets)[0]; - this.detector.stopScan(); + // eslint-disable-next-line func-names + const handleWallets = async function({ wallets, newWallet }) { + const wallet = newWallet || Object.values(wallets)[0]; + this.detector.stopScan(); - await this.connectToWallet(wallet); - // let addr = await this.client.askAddresses() - }; + await this.connectToWallet(wallet); + // let addr = await this.client.askAddresses() + }; - const scannerConnection = await BrowserWindowMessageConnection({ - connectionInfo: { id: 'spy' }, - }); - this.detector = await Detector({ connection: scannerConnection }); - this.detector.scan(handleWallets.bind(this)); - } catch (e) {} + const scannerConnection = await BrowserWindowMessageConnection({ + connectionInfo: { id: 'spy' }, + }); + this.detector = await Detector({ connection: scannerConnection }); + this.detector.scan(handleWallets.bind(this)); }, }, }; diff --git a/src/lib/background-utils.js b/src/lib/background-utils.js index 42d16acde..b6541ab34 100644 --- a/src/lib/background-utils.js +++ b/src/lib/background-utils.js @@ -33,7 +33,9 @@ export const switchNode = async () => { const node = await Node({ url: network.internalUrl, internalUrl: network.internalUrl }); try { await sdk.addNode(network.name, node, true); - } catch (e) {} + } catch (e) { + console.error(`switchNode: ${e}`); + } sdk.selectNode(network.name); } }; @@ -49,7 +51,9 @@ export const getSDK = async () => { nativeMode: true, compilerUrl: network.compilerUrl, }); - } catch (e) {} + } catch (e) { + console.error(`getSDK: ${e}`); + } } return sdk; diff --git a/src/lib/rpcWallet.js b/src/lib/rpcWallet.js index e9400109e..6a96778dd 100644 --- a/src/lib/rpcWallet.js +++ b/src/lib/rpcWallet.js @@ -185,7 +185,9 @@ const rpcWallet = { if (typeof cb !== 'undefined') { cb(); } - } catch (e) {} + } catch (e) { + console.error(`checkAeppPermissions: ${e}`); + } } else if (typeof cb === 'undefined') { action.accept(); } else { @@ -218,7 +220,9 @@ const rpcWallet = { } = aepp; const { protocol } = new URL(url); this.popups.setAeppInfo(id, { type, action: { params: action.params, method: action.method }, url, icons, name, protocol, host: extractHostName(url) }); - } catch (e) {} + } catch (e) { + console.error(`showPopup: ${e}`); + } }); }, @@ -278,7 +282,9 @@ const rpcWallet = { if (this.sdk) { try { await this.sdk.addNode(network, node, true); - } catch (e) {} + } catch (e) { + console.error(`addNewNetwork: ${e}`); + } this.sdk.selectNode(network); } }, diff --git a/src/lib/tip-claim-relay.js b/src/lib/tip-claim-relay.js index 64adaea94..cfad8d320 100644 --- a/src/lib/tip-claim-relay.js +++ b/src/lib/tip-claim-relay.js @@ -41,6 +41,8 @@ export default { await axios.post(`${TIP_SERVICE}`, { url, address: account.publicKey }); } } - } catch (err) {} + } catch (e) { + console.error(`checkUrlHasBalance: ${e}`); + } }, }; diff --git a/src/popup/router/components/TransactionItem.vue b/src/popup/router/components/TransactionItem.vue index bc7747316..f8089aed1 100644 --- a/src/popup/router/components/TransactionItem.vue +++ b/src/popup/router/components/TransactionItem.vue @@ -22,7 +22,7 @@ diff --git a/src/popup/popup.js b/src/popup/popup.js index 1fcb1b415..fec4aba18 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -4,8 +4,7 @@ import store from '../store'; import router from './router'; import { i18n } from './utils/i18nHelper'; import '../lib/initEnv'; - -global.browser = require('webextension-polyfill'); +import '../lib/initPolyfills'; Vue.prototype.$browser = global.browser; diff --git a/src/popup/router/components/Header.vue b/src/popup/router/components/Header.vue index aecd4ba55..6834dbc5e 100644 --- a/src/popup/router/components/Header.vue +++ b/src/popup/router/components/Header.vue @@ -11,7 +11,7 @@
- {{ notifications.length }} + {{ notifications.length }} - +
diff --git a/src/popup/router/pages/TipPage.vue b/src/popup/router/pages/TipPage.vue index d60325f68..cb6b8de9b 100644 --- a/src/popup/router/pages/TipPage.vue +++ b/src/popup/router/pages/TipPage.vue @@ -97,11 +97,7 @@ export default { }, watch: { amount() { - if (isNaN(this.amount) || parseFloat(this.amount) === 0) { - this.amountError = true; - } else { - this.amountError = false; - } + this.amountError = !+this.amount || this.amount <= 0; }, urlVerified(val) { if (val) this.$store.dispatch('popupAlert', { name: 'account', type: 'tip_url_verified' }); @@ -166,7 +162,7 @@ export default { }, toConfirm() { this.amountError = !this.amount || !this.minCallFee || this.maxValue - this.amount <= 0; - this.amountError = this.amountError || isNaN(this.amount) || this.amount <= 0 || isNaN(this.amount); + this.amountError = this.amountError || !+this.amount || this.amount <= 0; this.noteError = !this.note || !this.url; this.confirmMode = !this.amountError && !this.noteError; }, diff --git a/tests/e2e/integration/tip.js b/tests/e2e/integration/tip.js index 2444e532c..720c4c5a5 100644 --- a/tests/e2e/integration/tip.js +++ b/tests/e2e/integration/tip.js @@ -40,7 +40,7 @@ describe('Test cases for tip page', () => { .enterTipDetails({ amount: tip.amount }) .buttonShouldBeDisabled('[data-cy=send-tip]') .enterTipDetails({ note: tip.note }) - .buttonShouldNotBeDisabled('[data-cy=send-tip]') + .buttonShouldBeDisabled('[data-cy=send-tip]') .enterTipDetails({ amount: 'asd' }) .buttonShouldBeDisabled('[data-cy=send-tip]') .enterTipDetails({ note: '' }) From 3ace31bcb313b25c71a8cf9855f7ca83e59c5068 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Mon, 30 Mar 2020 15:01:42 +1000 Subject: [PATCH 20/58] Avoid polling of reactive variables --- src/popup/App.vue | 33 ++- src/popup/popup.js | 14 ++ .../router/components/TransactionItem.vue | 2 +- src/popup/router/pages/Retip.vue | 5 +- src/popup/router/pages/Send.vue | 4 +- src/popup/router/pages/SignTransaction.vue | 202 +++++++++--------- src/popup/router/pages/TipPage.vue | 4 +- src/popup/router/pages/Transactions.vue | 3 +- 8 files changed, 132 insertions(+), 135 deletions(-) diff --git a/src/popup/App.vue b/src/popup/App.vue index 2103a19cb..82ea67e8d 100644 --- a/src/popup/App.vue +++ b/src/popup/App.vue @@ -85,28 +85,24 @@ export default { if (notifCounter !== 0) await browser.storage.local.set({ notifCounter: this.notifications.length }); }, methods: { - checkSdkReady() { - const checkSDKReady = setInterval(async () => { - if (this.sdk) { - if (!window.RUNNING_IN_POPUP && process.env.IS_EXTENSION) { - postMessage({ type: AEX2_METHODS.INIT_RPC_WALLET, payload: { address: this.account.publicKey, network: this.current.network } }); - } - this.pollData(); - clearInterval(checkSDKReady); - } - }, 100); + async checkSdkReady() { + await this.$watchUntilTruly(() => this.sdk); + if (!window.RUNNING_IN_POPUP && process.env.IS_EXTENSION) { + postMessage({ type: AEX2_METHODS.INIT_RPC_WALLET, payload: { address: this.account.publicKey, network: this.current.network } }); + } + this.pollData(); }, pollData() { let triggerOnce = false; - this.polling = setInterval(async () => { - if (this.sdk != null && this.isLoggedIn) { - if (!process.env.RUNNING_IN_TESTS) this.$store.dispatch('updateBalance'); - if (!triggerOnce) { - this.$store.dispatch('getRegisteredNames'); - triggerOnce = true; - } + const polling = setInterval(async () => { + if (!this.isLoggedIn) return; + if (!process.env.RUNNING_IN_TESTS) this.$store.dispatch('updateBalance'); + if (!triggerOnce) { + this.$store.dispatch('getRegisteredNames'); + triggerOnce = true; } }, 2500); + this.$once('hook:beforeDestroy', () => clearInterval(polling)); }, async getCurrencies() { const { currency } = await browser.storage.local.get('currency'); @@ -118,9 +114,6 @@ export default { }); }, }, - beforeDestroy() { - clearInterval(this.polling); - }, }; diff --git a/src/popup/popup.js b/src/popup/popup.js index a205b9fb3..44047987f 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -1,4 +1,5 @@ import Vue from 'vue'; +import { defer } from 'lodash-es'; import App from './App'; import store from '../store'; import router from './router'; @@ -8,6 +9,19 @@ import '../lib/initEnv'; global.browser = require('webextension-polyfill'); Vue.prototype.$browser = global.browser; +Vue.prototype.$watchUntilTruly = function watchUntilTruly(getter) { + return new Promise(resolve => { + const unwatch = this.$watch( + getter, + value => { + if (!value) return; + resolve(); + defer(() => unwatch()); + }, + { immediate: true } + ); + }); +}; new Vue({ store, diff --git a/src/popup/router/components/TransactionItem.vue b/src/popup/router/components/TransactionItem.vue index f8089aed1..24a3cd478 100644 --- a/src/popup/router/components/TransactionItem.vue +++ b/src/popup/router/components/TransactionItem.vue @@ -37,7 +37,7 @@ export default { }; }, async created() { - await pollGetter(() => this.sdk); + await this.$watchUntilTruly(() => this.sdk); this.getEventData(); }, computed: { diff --git a/src/popup/router/pages/Retip.vue b/src/popup/router/pages/Retip.vue index d8e2eaa85..c63412974 100644 --- a/src/popup/router/pages/Retip.vue +++ b/src/popup/router/pages/Retip.vue @@ -34,7 +34,6 @@ import BigNumber from 'bignumber.js'; import axios from 'axios'; import tipping from 'aepp-raendom/src/utils/tippingContractUtil'; import { MAGNITUDE, calculateFee, TX_TYPES, BACKEND_URL } from '../../utils/constants'; -import { pollGetter } from '../../utils/helper'; import { setPendingTx } from '../../utils'; import openUrl from '../../utils/openUrl'; import CheckIcon from '../../../icons/check-icon.svg?vue-component'; @@ -75,14 +74,14 @@ export default { this.loading = true; this.verifiedUrls = (await axios.get(`${BACKEND_URL}/verified`)).data; - await pollGetter(() => this.sdk); + await this.$watchUntilTruly(() => this.sdk); this.minCallFee = calculateFee(TX_TYPES.contractCall, { ...this.sdk.Ae.defaults, contractId: this.network[this.current.network].tipContract, callerId: this.account.publicKey, }).min; - await pollGetter(() => this.tipping); + await this.$watchUntilTruly(() => this.tipping); const tipId = +this.urlParams.get('id'); if (!tipId) throw new Error('"id" param is missed'); const { decodedResult } = await this.tipping.methods.get_state(); diff --git a/src/popup/router/pages/Send.vue b/src/popup/router/pages/Send.vue index 32b719db4..21c7dad18 100644 --- a/src/popup/router/pages/Send.vue +++ b/src/popup/router/pages/Send.vue @@ -98,7 +98,7 @@ + + diff --git a/src/popup/router/pages/Account.vue b/src/popup/router/pages/Account.vue index 8f29d5192..2cc6e9cb9 100644 --- a/src/popup/router/pages/Account.vue +++ b/src/popup/router/pages/Account.vue @@ -11,7 +11,8 @@ + @@ -31,6 +33,7 @@ import RecentTransactions from '../components/RecentTransactions'; import ClaimTipButton from '../components/ClaimTipButton'; import BalanceInfo from '../components/BalanceInfo'; import AccountInfo from '../components/AccountInfo'; +import ClaimTips from '../components/ClaimTips'; export default { name: 'Account', @@ -40,14 +43,17 @@ export default { ClaimTipButton, BalanceInfo, AccountInfo, + ClaimTips, }, data() { return { backup_seed_notif: false, + loading: false, + IS_EXTENSION: process.env.IS_EXTENSION, }; }, computed: { - ...mapGetters(['account', 'balance', 'activeAccount', 'popup', 'current', 'network']), + ...mapGetters(['account', 'balance', 'activeAccount', 'current', 'network']), publicKey() { return this.account.publicKey; }, @@ -64,12 +70,6 @@ export default { this.backup_seed_notif = false; }, 3000); }, - mounted() {}, - methods: { - navigateTips() { - this.$router.push('/tip'); - }, - }, }; @@ -100,4 +100,7 @@ export default { .submenu-bg { background: $submenu-bg; } +.send-tips { + margin-bottom: 26px; +} diff --git a/src/popup/utils/connection.js b/src/popup/utils/connection.js index 1e18d37f5..034bee0cd 100644 --- a/src/popup/utils/connection.js +++ b/src/popup/utils/connection.js @@ -3,6 +3,7 @@ import '../../lib/initPolyfills'; import { handleMessage } from '../../background'; let internalPostMessage; +let contentPostMessage; const ensureBackgroundInitialised = async () => { if (internalPostMessage) return; @@ -32,16 +33,27 @@ export const postMessage = async ({ type, payload }) => { return internalPostMessage({ type, payload }); }; -export const setMessageListener = async cb => { - browser.runtime.onMessage.addListener((message, sender, sendResponse) => { - cb(message, sender, sendResponse); - }); +export const ensureContentScriptInitialized = async () => { + if (contentPostMessage) return; + if (process.env.IS_EXTENSION) { + const pendingMessages = {}; + browser.runtime.onMessage.addListener(({ uuid, data }) => { + if (!pendingMessages[uuid]) { + throw new Error(`Can't find message with id: ${uuid}`); + } + pendingMessages[uuid].resolve(data); + }); + contentPostMessage = (message, tab) => { + const id = genUuid(); + browser.tabs.sendMessage(tab, { data: { ...message, uuid: id } }); + return new Promise((resolve, reject) => { + pendingMessages[id] = { resolve, reject }; + }); + }; + } }; -export const readWebPageDom = cb => { - setMessageListener((message, sender, sendResponse) => { - if (message.from === 'content' && message.type === 'readDom' && sender.id === browser.runtime.id) { - cb({ address: message.data, host: sender.url }, sendResponse); - } - }); +export const postMessageToContent = async (message, tab) => { + await ensureContentScriptInitialized(); + return contentPostMessage(message, tab); }; diff --git a/src/popup/utils/popup-messages.js b/src/popup/utils/popup-messages.js index 930a35c3d..27af52e2a 100644 --- a/src/popup/utils/popup-messages.js +++ b/src/popup/utils/popup-messages.js @@ -48,6 +48,7 @@ export const TX_LIMIT_PER_DAY = { type: 'error', title: 'Oops! Something went wr export const TOKEN_MIGRATION_ERROR = { type: 'error', title: 'Oops! Something went wrong', msg: 'Token is not migrated! ' }; export const REVEAL_SEED_IMPOSSIBLE = { type: 'error', title: 'Аttention to security', msg: 'This is only available after generating an account or after importing a phrase. ' }; export const ERROR_QRCODE = { type: 'error', title: '', msg: '' }; +export const CLAIM_ERROR = { type: 'error', title: '', msg: '' }; // success messages export const SIGNED_MESSAGE = { type: 'success', @@ -113,3 +114,4 @@ This means that the creator of the content there or the website owner has successfully claimed tips for this url. `, }; +export const CLAIM_SUCCESS = { type: 'success', title: '', msg: '' }; diff --git a/src/store/actions.js b/src/store/actions.js index 340de4524..2d12969ab 100644 --- a/src/store/actions.js +++ b/src/store/actions.js @@ -153,6 +153,18 @@ export default { break; } break; + case 'tipping': + switch (payload.type) { + case 'claim_error': + commit(types.SHOW_POPUP, { show: true, ...popupMessages.CLAIM_ERROR, msg: payload.msg }); + break; + case 'claim_success': + commit(types.SHOW_POPUP, { show: true, ...popupMessages.CLAIM_SUCCESS, msg: payload.msg }); + break; + default: + break; + } + break; default: break; } From e53e28a8ada7fd0eff7f4ea8f6b39edee0bbf582 Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Thu, 2 Apr 2020 13:02:01 +0300 Subject: [PATCH 30/58] Update colors and apply part of new home styles --- src/common/variables.scss | 8 ++++++-- src/popup/locales/en.json | 3 ++- src/popup/router/components/AccountInfo.vue | 2 +- src/popup/router/components/AmountSend.vue | 4 ++-- src/popup/router/components/BalanceInfo.vue | 9 ++++++++- src/popup/router/components/Header.vue | 6 ++++-- src/popup/router/components/Input.vue | 4 ++-- .../router/components/RecentTransactions.vue | 3 ++- src/popup/router/components/SidebarMenu.vue | 4 ++-- src/popup/router/components/Textarea.vue | 4 ++-- src/popup/router/components/TransactionItem.vue | 17 +++++++++++------ src/popup/router/pages/Account.vue | 1 - src/store/getters.js | 4 ++-- 13 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/common/variables.scss b/src/common/variables.scss index 572e0dcfe..140b6fbd8 100644 --- a/src/common/variables.scss +++ b/src/common/variables.scss @@ -24,10 +24,14 @@ $button-color: #3F4048; $button-text-color: #CFCFCF; $placeholder-color: #67676D; $text-color: #BCBCC4; -$accent-color: #6A8EBE; -$secondary-color: #FF4784; +$accent-color: #67f7b8; +$secondary-color: #2a9cff; $nav-bg-color: #21212A; +$input-focus-color: #6A8EBE; +$input-error-color: #FF4784; +$transactions-bg: #12121b; $nav-border-color: #3A3A47; +$tx-border-color: #33343e; $scrollbar-color:#707075; $submenu-bg: #1B1B23; $black-color: #000; diff --git a/src/popup/locales/en.json b/src/popup/locales/en.json index 080977933..5c353d064 100644 --- a/src/popup/locales/en.json +++ b/src/popup/locales/en.json @@ -35,7 +35,8 @@ "notifications": "Notifications", "names": "Names", "bidding": "Bidding", - "networks": "Networks" + "networks": "Networks", + "home": "Superhero Home" }, "appVUE": { "systemName": "SuperHero", diff --git a/src/popup/router/components/AccountInfo.vue b/src/popup/router/components/AccountInfo.vue index da732ac32..c44baff83 100644 --- a/src/popup/router/components/AccountInfo.vue +++ b/src/popup/router/components/AccountInfo.vue @@ -72,7 +72,7 @@ export default { .ae-address { color: $text-color; - font-size: 10px; + font-size: 11px; letter-spacing: -0.1px; } } diff --git a/src/popup/router/components/AmountSend.vue b/src/popup/router/components/AmountSend.vue index a005810d5..f321bb3f5 100644 --- a/src/popup/router/components/AmountSend.vue +++ b/src/popup/router/components/AmountSend.vue @@ -49,8 +49,8 @@ export default { computed: { ...mapGetters(['tokenBalance', 'balanceCurrency', 'current', 'currentCurrency']), getCurrencyAmount() { - if (!+this.finalAmount) return '0.000'; - return (this.finalAmount * this.current.currencyRate).toFixed(3); + if (!+this.finalAmount) return '0.00'; + return (this.finalAmount * this.current.currencyRate).toFixed(2); }, }, }; diff --git a/src/popup/router/components/BalanceInfo.vue b/src/popup/router/components/BalanceInfo.vue index 193f3eb10..9ea22e581 100644 --- a/src/popup/router/components/BalanceInfo.vue +++ b/src/popup/router/components/BalanceInfo.vue @@ -12,7 +12,7 @@
{{ balanceCurrency }} - {{ currentCurrency }} + {{ currentCurrency }}
@@ -74,6 +74,9 @@ export default { .approx-sign { padding: 3px 10px; } + .currency { + color: $white-color; + } } .currenciesgroup li:first-of-type { z-index: 1; @@ -132,6 +135,7 @@ export default { position: relative; text-align: center; background-image: url('../../../icons/acc_balance.png'); + border-bottom: 2px solid $transactions-bg; .title { position: absolute; left: 20px; @@ -156,6 +160,9 @@ export default { .ae-button { font-family: 'Roboto', sans-serif; } + .amount { + color: $text-color; + } .amount :last-child { color: $secondary-color; } diff --git a/src/popup/router/components/Header.vue b/src/popup/router/components/Header.vue index 6834dbc5e..fcf0beace 100644 --- a/src/popup/router/components/Header.vue +++ b/src/popup/router/components/Header.vue @@ -6,7 +6,7 @@
{{ $t(`pages.titles.${title}`) }} - {{ $t('pages.appVUE.walletName') }} + {{ $t('pages.titles.home') }}
@@ -97,6 +97,7 @@ export default { left: 0; right: 0; text-align: center; + font-weight: bold; } } @@ -123,9 +124,10 @@ export default { height: 16px; text-align: center; vertical-align: middle; - left: -8px; + left: -9px; top: 2px; line-height: 16px; + border: 1px solid $nav-bg-color; } } } diff --git a/src/popup/router/components/Input.vue b/src/popup/router/components/Input.vue index 4bfb18678..dabf9fa20 100644 --- a/src/popup/router/components/Input.vue +++ b/src/popup/router/components/Input.vue @@ -59,10 +59,10 @@ input.input { margin-right: auto; } .input:focus { - border-color: $accent-color !important; + border-color: $input-focus-color !important; } .input.has-error { - border-color: $secondary-color !important; + border-color: $input-error-color !important; } .input.sm { font-size: 14px; diff --git a/src/popup/router/components/RecentTransactions.vue b/src/popup/router/components/RecentTransactions.vue index 0bb39648e..cb9fb2f51 100644 --- a/src/popup/router/components/RecentTransactions.vue +++ b/src/popup/router/components/RecentTransactions.vue @@ -1,6 +1,6 @@ @@ -25,20 +37,30 @@ @@ -98,5 +114,8 @@ export default { } .submenu-bg { background: $submenu-bg; + padding: 10px; + display: flex; + flex-wrap: wrap; } From 1a54e2122e613fa1ceb341ab2afc376b2301db5f Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Thu, 2 Apr 2020 17:35:25 +0300 Subject: [PATCH 34/58] Invoke payfortx after tip send Fixes #121 --- src/popup/router/components/ClaimTips.vue | 21 +++----------------- src/popup/router/pages/SuccessTip.vue | 20 ++++++++++--------- src/store/actions.js | 24 ++++++++++++++++++++--- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/popup/router/components/ClaimTips.vue b/src/popup/router/components/ClaimTips.vue index 7fc4f0efe..be73e5d89 100644 --- a/src/popup/router/components/ClaimTips.vue +++ b/src/popup/router/components/ClaimTips.vue @@ -12,10 +12,8 @@ \ No newline at end of file + diff --git a/src/popup/router/pages/Transactions.vue b/src/popup/router/pages/Transactions.vue index cc920d24b..b7d4bde0c 100644 --- a/src/popup/router/pages/Transactions.vue +++ b/src/popup/router/pages/Transactions.vue @@ -3,10 +3,10 @@ - +
{{ $t('pages.recentTransactions.pendingStatus') }}
- +

{{ $t('pages.transactions.noTransactions') }}

@@ -133,4 +133,7 @@ export default { .popup { padding: 0; } +.all-transactions { + background: $transactions-bg; +} From 932e1b6926699174bd1583f5247163ca09bef4f8 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Thu, 2 Apr 2020 22:06:00 +1000 Subject: [PATCH 40/58] Add CommentNew page --- .babelrc | 7 +- package-lock.json | 194 +++++++++++++++++++++++--- package.json | 1 + src/lib/backend.js | 99 +++++++++++++ src/popup/locales/en.json | 3 +- src/popup/router/pages/CommentNew.vue | 65 +++++++++ src/popup/router/routes.js | 8 ++ tests/pages/index.html | 9 +- 8 files changed, 357 insertions(+), 29 deletions(-) create mode 100644 src/lib/backend.js create mode 100644 src/popup/router/pages/CommentNew.vue diff --git a/.babelrc b/.babelrc index 5b5c5037c..4eab6e529 100644 --- a/.babelrc +++ b/.babelrc @@ -1,11 +1,12 @@ { "plugins": [ "@babel/plugin-proposal-optional-chaining", - "@babel/plugin-transform-spread" + "@babel/plugin-transform-spread", + "@babel/plugin-proposal-class-properties" ], "presets": [ - ["@babel/preset-env", { - "useBuiltIns": "usage", + ["@babel/preset-env", { + "useBuiltIns": "usage", "targets": { // https://jamie.build/last-2-versions "browsers": ["> 0.25%", "not ie 11", "not op_mini all"] diff --git a/package-lock.json b/package-lock.json index e11feb757..2ae281078 100644 --- a/package-lock.json +++ b/package-lock.json @@ -267,6 +267,107 @@ } } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz", + "integrity": "sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", + "@babel/helper-split-export-declaration": "^7.8.3" + }, + "dependencies": { + "@babel/generator": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", + "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==", + "dev": true, + "requires": { + "@babel/types": "^7.9.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", + "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/parser": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "dev": true + }, + "@babel/traverse": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", + "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", + "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "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" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "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 + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "@babel/helper-create-regexp-features-plugin": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", @@ -455,6 +556,12 @@ "@babel/types": "^7.8.3" } }, + "@babel/helper-validator-identifier": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", + "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", + "dev": true + }, "@babel/helper-wrap-function": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", @@ -504,6 +611,16 @@ "@babel/plugin-syntax-async-generators": "^7.8.0" } }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-proposal-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", @@ -2485,33 +2602,60 @@ "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" }, "aepp-raendom": { - "version": "github:aeternity/aepp-raendom#9bf50b4c526e81ee6d26f3eb57c7becfba3cdd5e", + "version": "github:aeternity/aepp-raendom#f867209f207bbc18ae1e83047d56da402323b747", "from": "github:aeternity/aepp-raendom#feature/layout-superhero", "requires": { - "@aeternity/aepp-sdk": "7.1.1", + "@aeternity/aepp-sdk": "7.2.1", "axios": "^0.19.0", "bignumber.js": "^9.0.0", "bootstrap": "^4.4.1", "bootstrap-vue": "^2.4.0", + "core-js": "^3.6.4", "detect-browser": "^4.8.0", "i18n": "^0.8.5", "lodash-es": "^4.17.15", - "timers": "^0.1.1", - "vue": "^2.6.10", + "vue": "^2.6.11", "vue-i18n": "^8.15.3", "vue-router": "^3.1.3", "vuex": "^3.1.2" }, "dependencies": { + "@aeternity/aepp-sdk": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@aeternity/aepp-sdk/-/aepp-sdk-7.2.1.tgz", + "integrity": "sha512-ok15jB7FB6QkHf3kjFBKQ0GCp/2QHIFYq+TvBh59l6D7pYfb/7eU4/tLZKdxJPqYDtO9I7t3KIzCWG39yCWzhQ==", + "requires": { + "@aeternity/bip39": "^0.1.0", + "@stamp/it": "^1.0.3", + "@stamp/required": "^1.0.1", + "aes-js": "^3.1.1", + "axios": "^0.19.0", + "bignumber.js": "^9.0.0", + "bip32-path": "^0.4.2", + "blakejs": "^1.1.0", + "bs58check": "^2.1.1", + "ed2curve": "^0.3.0", + "joi-browser": "^13.4.0", + "libsodium-wrappers-sumo": "0.7.6", + "ramda": "^0.27.0", + "rlp": "2.2.4", + "serialize-javascript": "^3.0.0", + "sha.js": "^2.4.11", + "tweetnacl": "^1.0.0", + "tweetnacl-auth": "^1.0.1", + "uuid": "^7.0.0", + "websocket": "^1.0.26" + } + }, "bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" }, "bootstrap-vue": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.6.0.tgz", - "integrity": "sha512-6p28wh/nnA5b8H0iVb6cIEkS6VUQikpQPRnCTSNEg3k1T8SNDXads7lJPn1Cxi268SXfrWttb8Pxct1c+0qKyA==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.10.0.tgz", + "integrity": "sha512-N0nsx0VLzUi1DbUPNsShadD57DoUwQ/12lt84iPZTiyxR8qI9rcX0TUEPL9Sof+KCd8f/8cz46bNOK8dhsUKXQ==", "requires": { "@nuxt/opencollective": "^0.3.0", "bootstrap": ">=4.4.1 <5.0.0", @@ -2519,6 +2663,16 @@ "portal-vue": "^2.1.7", "vue-functional-data-merge": "^3.1.0" } + }, + "serialize-javascript": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz", + "integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==" + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" } } }, @@ -5465,8 +5619,7 @@ "core-js": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", - "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", - "dev": true + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==" }, "core-js-compat": { "version": "3.6.4", @@ -10033,9 +10186,9 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" }, "i18n": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.8.5.tgz", - "integrity": "sha512-6UgLbhJGgn4XFeuZc/dDdrrri0ij24EK4hxv4Pbi5hloYAZ1B2+0eQchEryBFezLKYOHhVGV/5+H4i0oxng94w==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.8.6.tgz", + "integrity": "sha512-aMsJq8i1XXrb+BBsgmJBwak9mr69zPEIAUPb6c5yw2G/O4k1Q52lBxL+agZdQDN/RGf1ylQzrCswsOOgIiC1FA==", "requires": { "debug": "*", "make-plural": "^6.0.1", @@ -11635,9 +11788,9 @@ } }, "make-plural": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.0.1.tgz", - "integrity": "sha512-h0uBNi4tpDkiWUyYKrJNj8Kif6q3Ba5zp/8jnfPy3pQE+4XcTj6h3eZM5SYVUyDNX9Zk69Isr/dx0I+78aJUaQ==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.1.0.tgz", + "integrity": "sha512-0ekbPHqxcdRcmjZ43TkRuejK5rXgMF1OjG4FVnVHgCvOcjrexaSX7a0dfAvqhOm1qWPgjYnXtmz3cHpHW5ZewA==" }, "mamacro": { "version": "0.0.3", @@ -12312,9 +12465,9 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, "mustache": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.0.0.tgz", - "integrity": "sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.0.1.tgz", + "integrity": "sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==" }, "mute-stream": { "version": "0.0.7", @@ -18132,11 +18285,6 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, - "timers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/timers/-/timers-0.1.1.tgz", - "integrity": "sha1-hqxceMHuQZaU81pY3k/UGDz7nB4=" - }, "timers-browserify": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", diff --git a/package.json b/package.json index f9ef5809e..38a319381 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ }, "devDependencies": { "@babel/core": "^7.6.4", + "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-optional-chaining": "^7.6.0", "@babel/preset-env": "^7.6.3", "@cypress/webpack-preprocessor": "^4.1.3", diff --git a/src/lib/backend.js b/src/lib/backend.js new file mode 100644 index 000000000..d25bc6059 --- /dev/null +++ b/src/lib/backend.js @@ -0,0 +1,99 @@ +// copied from https://github.com/aeternity/aepp-raendom/blob/246c75e6fb773cbe8cfe3960975779ab9d81186c/src/utils/backend.js + +const BACKEND_URL = 'https://raendom-backend.z52da5wt.xyz'; + +const wrapTry = async promise => { + try { + return Promise.race([ + promise.then(res => { + if (!res.ok) throw new Error(`Request failed with ${res.status}`); + return res.json(); + }), + new Promise((resolve, reject) => { + setTimeout(reject, 3000, 'TIMEOUT'); + }), + ]); + } catch (e) { + console.error('backend error', e); + return null; + } +}; + +const backendFetch = (path, ...args) => wrapTry(fetch(`${BACKEND_URL}/${path}`, ...args)); + +export default class Backend { + static getTipComments = async tipId => backendFetch(`comment/api/tip/${encodeURIComponent(tipId)}`); + + static async sendTipComment(tipId, text, author, signCb) { + const sendComment = async postParam => + backendFetch(`comment/api/`, { + method: 'post', + body: JSON.stringify(postParam), + headers: { 'Content-Type': 'application/json' }, + }); + + const responseChallenge = await sendComment({ tipId, text, author }); + const signedChallenge = await signCb(responseChallenge.challenge); + const respondChallenge = { + challenge: responseChallenge.challenge, + signature: signedChallenge, + }; + + return sendComment(respondChallenge); + } + + static getAllComments = async () => backendFetch(`comment/api/`); + + static getProfile = async address => backendFetch(`profile/${address}`); + + static sendProfileData = async postParam => + backendFetch(`profile`, { + method: 'post', + body: JSON.stringify(postParam), + headers: { 'Content-Type': 'application/json' }, + }); + + static setProfileImage = async (address, data, image = true) => { + const request = { + method: 'post', + body: image ? data : JSON.stringify(data), + }; + Object.assign(request, !image && { headers: { 'Content-Type': 'application/json' } }); + console.log(request); + return wrapTry(fetch(Backend.getProfileImageUrl(address), request)); + }; + + static getProfileImageUrl = address => `${BACKEND_URL}/profile/image/${address}`; + + static getStats = async () => backendFetch(`static/stats/`); + + static getCacheTipById = async id => backendFetch(`cache/tip?id=${id}`); + + static getCacheUserStats = async address => backendFetch(`cache/userStats?address=${address}`); + + static getCacheTips = async (ordering, page, address = null, search = null) => { + let query = `?ordering=${ordering}&page=${page}`; + if (address) query += `&address=${address}`; + if (search) query += `&search=${encodeURIComponent(search)}`; + + return backendFetch(`cache/tips${query}`); + }; + + static getCacheStats = async () => backendFetch(`cache/stats`); + + static getCacheChainNames = async () => backendFetch(`cache/chainnames`); + + static getPrice = async () => backendFetch(`cache/price`); + + static getOracleCache = async () => backendFetch(`cache/oracle`); + + static getTopicsCache = async () => backendFetch(`cache/topics`); + + static cacheInvalidateTips = async () => backendFetch(`cache/invalidate/tips`); + + static getCommentCountForAddress = async address => backendFetch(`comment/count/author/${address}`); + + static getTipPreviewUrl = previewLink => `${BACKEND_URL}${previewLink}`; + + static getProfileImageUrl = address => `${BACKEND_URL}/profile/image/${address}`; +} diff --git a/src/popup/locales/en.json b/src/popup/locales/en.json index 080977933..18b413af3 100644 --- a/src/popup/locales/en.json +++ b/src/popup/locales/en.json @@ -35,7 +35,8 @@ "notifications": "Notifications", "names": "Names", "bidding": "Bidding", - "networks": "Networks" + "networks": "Networks", + "comment-new": "Add comment" }, "appVUE": { "systemName": "SuperHero", diff --git a/src/popup/router/pages/CommentNew.vue b/src/popup/router/pages/CommentNew.vue new file mode 100644 index 000000000..58560b182 --- /dev/null +++ b/src/popup/router/pages/CommentNew.vue @@ -0,0 +1,65 @@ + + + diff --git a/src/popup/router/routes.js b/src/popup/router/routes.js index cff06b9ef..76f2ed915 100644 --- a/src/popup/router/routes.js +++ b/src/popup/router/routes.js @@ -24,6 +24,7 @@ import NotificationsPage from './pages/Notifications'; import NamesPage from './pages/Names'; import AuctionBid from './pages/AuctionBid'; import Networks from './pages/Networks'; +import CommentNew from './pages/CommentNew'; import NotFound from './pages/NotFound'; export default [ @@ -237,6 +238,13 @@ export default [ title: 'networks', }, }, + { + path: '/comment', + component: CommentNew, + meta: { + title: 'comment-new', + }, + }, { name: 'not-found', path: '*', diff --git a/tests/pages/index.html b/tests/pages/index.html index 25a44663f..e6c6813fd 100644 --- a/tests/pages/index.html +++ b/tests/pages/index.html @@ -11,8 +11,9 @@ const successUrl = encodeURIComponent(`${window.location.origin}?result=success`); const cancelUrl = encodeURIComponent(`${window.location.origin}?result=cancel`); + const comment = encodeURIComponent(`This is a test comment! http://example.com`); - const prefixes = ['superhero:', 'https://wallet.superhero.com/']; + const prefixes = ['superhero:', 'https://wallet.superhero.com/', 'http://localhost:5000/']; const paths = [ '404', 'tip', @@ -24,11 +25,15 @@ `retip?id=26&x-cancel=${cancelUrl}`, `retip?id=25&x-success=${successUrl}&x-cancel=${cancelUrl}`, `retip?id=26&x-success=${successUrl}&x-cancel=${cancelUrl}`, + `comment?id=26&text=${comment}`, + `comment?id=26&text=${comment}&x-success=${successUrl}`, + `comment?id=26&text=${comment}&x-cancel=${cancelUrl}`, + `comment?id=26&text=${comment}&x-success=${successUrl}&x-cancel=${cancelUrl}`, ]; prefixes.forEach(prefix => paths.forEach(path => { const url = prefix + path; - document.write(`${url}
`); + document.write(`${url}

`); })); From a50192fc7f0ca4826ad5ebe2280d4b79e4b2e833 Mon Sep 17 00:00:00 2001 From: Petar Baykov Date: Fri, 3 Apr 2020 09:07:59 +0300 Subject: [PATCH 41/58] Integrate claim button functionaity in new UI of the button --- src/popup/router/components/ClaimTips.vue | 18 ++++++------------ src/popup/router/pages/Account.vue | 6 +----- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/popup/router/components/ClaimTips.vue b/src/popup/router/components/ClaimTips.vue index be73e5d89..5a25e1269 100644 --- a/src/popup/router/components/ClaimTips.vue +++ b/src/popup/router/components/ClaimTips.vue @@ -1,13 +1,7 @@ + + \ No newline at end of file diff --git a/src/popup/router/index.js b/src/popup/router/index.js index c32d5a607..df59c6343 100644 --- a/src/popup/router/index.js +++ b/src/popup/router/index.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import VueRouter from 'vue-router'; import VueClipboard from 'vue-clipboard2'; import Components from '@aeternity/aepp-components-3'; +import VueTour from 'vue-tour' import routes from './routes'; import '@aeternity/aepp-components-3/dist/aepp.components.css'; import LoaderComponent from './components/Loader'; @@ -22,12 +23,13 @@ const plugin = { Vue.prototype.$helpers = helper; }, }; +require('vue-tour/dist/vue-tour.css'); Vue.use(plugin); Vue.use(VueRouter); Vue.use(VueClipboard); Vue.use(Components); - +Vue.use(VueTour); Vue.component('Loader', LoaderComponent); Vue.component('TransactionItem', TransactionItemComponent); Vue.component('Popup', Popup); diff --git a/src/popup/router/pages/Account.vue b/src/popup/router/pages/Account.vue index 673e6ad23..272fbd1df 100644 --- a/src/popup/router/pages/Account.vue +++ b/src/popup/router/pages/Account.vue @@ -7,23 +7,25 @@ {{ $t('pages.account.yourSeedPhrase') }}
- - +
+ + +
diff --git a/src/popup/router/pages/TipPage.vue b/src/popup/router/pages/TipPage.vue index 6e52c00be..20de74c18 100644 --- a/src/popup/router/pages/TipPage.vue +++ b/src/popup/router/pages/TipPage.vue @@ -1,50 +1,55 @@