From 41df3c6ef4897b576bd793cedc2501d36dd40f19 Mon Sep 17 00:00:00 2001 From: Aleksei Lebedev Date: Sun, 2 Aug 2020 00:03:16 +0300 Subject: [PATCH 1/6] Add Atomars exchange --- src/components/BuyTokensDialog.vue | 16 ++++++++++++++-- src/components/icons/common/Atomars.vue | 5 +++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 src/components/icons/common/Atomars.vue diff --git a/src/components/BuyTokensDialog.vue b/src/components/BuyTokensDialog.vue index 4f2afeb92..093f525a2 100644 --- a/src/components/BuyTokensDialog.vue +++ b/src/components/BuyTokensDialog.vue @@ -31,7 +31,7 @@ - + @@ -40,6 +40,16 @@ CoinDeal + + + + + + + + Atomars + + @@ -52,6 +62,7 @@ import validateAddress from '@/lib/validateAddress' import Icon from '@/components/icons/BaseIcon' import CryptoIcon from '@/components/icons/CryptoIcon' import CdlIcon from '@/components/icons/common/Cdl' +import AtomarsIcon from '@/components/icons/common/Atomars' export default { computed: { @@ -94,7 +105,8 @@ export default { components: { Icon, CryptoIcon, - CdlIcon + CdlIcon, + AtomarsIcon }, props: { value: { diff --git a/src/components/icons/common/Atomars.vue b/src/components/icons/common/Atomars.vue new file mode 100644 index 000000000..e5e7b6bbc --- /dev/null +++ b/src/components/icons/common/Atomars.vue @@ -0,0 +1,5 @@ + From 3f4caf1ee148f3c18f848b61badd48dd49809af8 Mon Sep 17 00:00:00 2001 From: Aleksei Lebedev Date: Wed, 19 Aug 2020 17:09:07 +0300 Subject: [PATCH 2/6] Decrease Eth & ERC20 fees --- src/components/SendFundsForm.vue | 7 ++++--- src/lib/constants.js | 21 ++++++++++++++----- src/store/modules/erc20/erc20-actions.js | 14 +++++++++---- .../modules/eth-base/eth-base-actions.js | 4 ++-- src/store/modules/eth/actions.js | 16 ++++++++------ 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/components/SendFundsForm.vue b/src/components/SendFundsForm.vue index eedfd0c47..573070ac6 100644 --- a/src/components/SendFundsForm.vue +++ b/src/components/SendFundsForm.vue @@ -174,6 +174,7 @@ import QrcodeCapture from '@/components/QrcodeCapture' import QrcodeScannerDialog from '@/components/QrcodeScannerDialog' import get from 'lodash/get' import { BigNumber } from 'bignumber.js' +import { INCREASE_FEE_MULTIPLIER } from '../lib/constants' import { parseURI } from '@/lib/uri' import { sendMessage } from '@/lib/adamant-api' @@ -369,7 +370,7 @@ export default { } }, allowIncreaseFee () { - return this.currency === Cryptos.BTC + return (this.currency === Cryptos.BTC) || (this.currency === Cryptos.ETH) || (isErc20(this.currency)) } }, watch: { @@ -423,7 +424,7 @@ export default { } else { this.$store.dispatch('snackbar/show', { message: abstract, - timeout: 3000 + timeout: 5000 }) } }, @@ -620,7 +621,7 @@ export default { return right.length <= units }, calculateTransferFee (amount) { - const coef = this.increaseFee ? 2 : 1 + const coef = this.increaseFee ? INCREASE_FEE_MULTIPLIER : 1 return coef * this.$store.getters[`${this.currency.toLowerCase()}/fee`](amount) } }, diff --git a/src/lib/constants.js b/src/lib/constants.js index 6bd912f2a..ba71cd4ca 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -88,7 +88,7 @@ export const CryptoNaturalUnits = { export const Fees = { /** Storing a value into the KVS */ KVS: 0.001, - /** Transfering tokens */ + /** Transferring tokens */ ADM_TRANSFER: 0.5, NOT_ADM_TRANSFER: 0.001 } @@ -117,11 +117,22 @@ export const WelcomeMessage = { ADAMANT_ICO: 'ADAMANT Tokens' } -/** Gas value for the ETH transfers */ -export const ETH_TRANSFER_GAS = 21000 +/** + * These gas limit values are used only for estimate fees for ETH & ERC-20 transfers in the Send tokens form, + * Actual gas limit values are calculated with estimateGas(transactionObject) + * when each specific transaction is created + */ + +/** Gas limit value for the ETH transfers */ +export const ETH_TRANSFER_GAS = 22000 // Default gas limit; while to be calculated with estimateGas(transactionObject) +/** Gas limit value for the ERC-20 transfers */ +export const ERC20_TRANSFER_GAS = ETH_TRANSFER_GAS * 2 + +/** Gas price multiplier. To be sure a transaction will be confirmed */ +export const ETH_GASPRICE_MULTIPLIER = 1.1 -/** Gas value for the ERC-20 transfers */ -export const ERC20_TRANSFER_GAS = ETH_TRANSFER_GAS * 10 +/** Increase fee multiplier. Used in SendFundsForm */ +export const INCREASE_FEE_MULTIPLIER = 2 export default { EPOCH, diff --git a/src/store/modules/erc20/erc20-actions.js b/src/store/modules/erc20/erc20-actions.js index 8d0834716..271fe3784 100644 --- a/src/store/modules/erc20/erc20-actions.js +++ b/src/store/modules/erc20/erc20-actions.js @@ -1,7 +1,7 @@ import abiDecoder from 'abi-decoder' import * as ethUtils from '../../../lib/eth-utils' -import { ERC20_TRANSFER_GAS } from '../../../lib/constants' +import { INCREASE_FEE_MULTIPLIER } from '../../../lib/constants' import Erc20 from './erc20.abi.json' import createActions from '../eth-base/eth-base-actions' @@ -13,17 +13,23 @@ const STATUS_INTERVAL = 8000 // Setup decoder abiDecoder.addABI(Erc20) -const initTransaction = (api, context, ethAddress, amount) => { +const initTransaction = (api, context, ethAddress, amount, increaseFee) => { const contract = api.eth.contract(Erc20).at(context.state.contractAddress) - return { + const transaction = { from: context.state.address, to: context.state.contractAddress, value: api.fromDecimal('0'), - gasLimit: api.fromDecimal(ERC20_TRANSFER_GAS), + // gasLimit: api.fromDecimal(ERC20_TRANSFER_GAS), // Don't take default value, instead calculate with estimateGas(transactionObject) gasPrice: api.fromDecimal(context.getters.gasPrice), data: contract.transfer.getData(ethAddress, ethUtils.toWhole(amount, context.state.decimals)) } + + let gasLimit = api.eth.estimateGas(transaction) + gasLimit = increaseFee ? (gasLimit * INCREASE_FEE_MULTIPLIER).toString(16) : gasLimit.toString(16) + transaction.gas = '0x' + gasLimit + + return transaction } const parseTransaction = (context, tx) => { diff --git a/src/store/modules/eth-base/eth-base-actions.js b/src/store/modules/eth-base/eth-base-actions.js index 94ee48df3..0074186d9 100644 --- a/src/store/modules/eth-base/eth-base-actions.js +++ b/src/store/modules/eth-base/eth-base-actions.js @@ -69,10 +69,10 @@ export default function createActions (config) { } }, - sendTokens (context, { amount, admAddress, address, comments }) { + sendTokens (context, { amount, admAddress, address, comments, increaseFee }) { address = address.trim() const crypto = context.state.crypto - const ethTx = initTransaction(api, context, address, amount) + const ethTx = initTransaction(api, context, address, amount, increaseFee) return utils.promisify(api.eth.getTransactionCount, context.state.address, 'pending') .then(count => { diff --git a/src/store/modules/eth/actions.js b/src/store/modules/eth/actions.js index 8f28075a1..ad81db699 100644 --- a/src/store/modules/eth/actions.js +++ b/src/store/modules/eth/actions.js @@ -1,7 +1,7 @@ import * as utils from '../../../lib/eth-utils' import createActions from '../eth-base/eth-base-actions' -import { ETH_TRANSFER_GAS } from '../../../lib/constants' +import { ETH_TRANSFER_GAS, ETH_GASPRICE_MULTIPLIER, INCREASE_FEE_MULTIPLIER } from '../../../lib/constants' import { storeCryptoAddress } from '../../../lib/store-crypto-address' /** Timestamp of the most recent status update */ @@ -17,15 +17,19 @@ function storeEthAddress (context) { storeCryptoAddress(context.state.crypto, context.state.address) } -const initTransaction = (api, context, ethAddress, amount) => { +const initTransaction = (api, context, ethAddress, amount, increaseFee) => { const transaction = { from: context.state.address, to: ethAddress, value: api.fromDecimal(utils.toWei(amount)), - // gas: api.fromDecimal(ETH_TRANSFER_GAS), + // gas: api.fromDecimal(ETH_TRANSFER_GAS), // Don't take default value, instead calculate with estimateGas(transactionObject) gasPrice: api.fromDecimal(context.getters.gasPrice) } - transaction.gas = '0x' + api.eth.estimateGas(transaction).toString(16) + + let gasLimit = api.eth.estimateGas(transaction) + gasLimit = increaseFee ? (gasLimit * INCREASE_FEE_MULTIPLIER).toString(16) : gasLimit.toString(16) + transaction.gas = '0x' + gasLimit + return transaction } @@ -67,10 +71,10 @@ const createSpecificActions = (api, queue) => ({ // Current gas price api.eth.getGasPrice.request((err, price) => { if (!err) { - const gasPrice = 3 * price.toNumber() + const gasPrice = ETH_GASPRICE_MULTIPLIER * price.toNumber() context.commit('gasPrice', { gasPrice, - fee: utils.calculateFee(ETH_TRANSFER_GAS, gasPrice) + fee: +(+utils.calculateFee(ETH_TRANSFER_GAS, gasPrice)).toFixed(7) }) } }), From 0ce3983c6af6e6e104b824db656d27d25236ba57 Mon Sep 17 00:00:00 2001 From: Aleksei Lebedev Date: Wed, 19 Aug 2020 20:09:59 +0300 Subject: [PATCH 3/6] Add estimate transfer fee label --- src/components/SendFundsForm.vue | 17 +++++++++++++---- src/i18n/en.json | 1 + src/i18n/ru.json | 1 + src/lib/constants.js | 4 ++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/components/SendFundsForm.vue b/src/components/SendFundsForm.vue index 573070ac6..b67a6f0f9 100644 --- a/src/components/SendFundsForm.vue +++ b/src/components/SendFundsForm.vue @@ -79,7 +79,7 @@ @@ -178,7 +178,7 @@ import { INCREASE_FEE_MULTIPLIER } from '../lib/constants' import { parseURI } from '@/lib/uri' import { sendMessage } from '@/lib/adamant-api' -import { Cryptos, CryptoAmountPrecision, CryptoNaturalUnits, TransactionStatus as TS, isErc20, getMinAmount } from '@/lib/constants' +import { Cryptos, CryptoAmountPrecision, CryptoNaturalUnits, TransactionStatus as TS, isErc20, isFeeEstimate, isEthBased, getMinAmount } from '@/lib/constants' import validateAddress from '@/lib/validateAddress' import { formatNumber, isNumeric } from '@/lib/numericHelpers' import partnerName from '@/mixins/partnerName' @@ -239,6 +239,14 @@ export default { return BigNumber(this.transferFee).toFixed() }, + /** + * Label for fee field. Estimate fee or precise value. + * @returns {string} + */ + transferFeeLabel () { + return isFeeEstimate(this.currency) ? this.$t('transfer.commission_estimate_label') : this.$t('transfer.commission_label') + }, + /** * Transfer currency (may differ from the amount currency in case of ERC-20 tokens) * @returns {string} @@ -370,7 +378,7 @@ export default { } }, allowIncreaseFee () { - return (this.currency === Cryptos.BTC) || (this.currency === Cryptos.ETH) || (isErc20(this.currency)) + return (this.currency === Cryptos.BTC) || isEthBased(this.currency) } }, watch: { @@ -563,7 +571,8 @@ export default { admAddress: this.address, address: this.cryptoAddress, comments: this.comment, - fee: this.transferFee + fee: this.transferFee, + increaseFee: this.increaseFee }) } }, diff --git a/src/i18n/en.json b/src/i18n/en.json index 4ae8ad174..2fb1ae588 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -230,6 +230,7 @@ "balance": "Balance", "comments_label": "Comment", "commission_label": "Transfer fee", + "commission_estimate_label": "Estimated transfer fee", "confirm_approve": "Confirm", "confirm_cancel": "Cancel", "confirm_message": "Confirm transfer of {amount} {crypto} to address {address}.", diff --git a/src/i18n/ru.json b/src/i18n/ru.json index d6d37bf54..288a0bd20 100644 --- a/src/i18n/ru.json +++ b/src/i18n/ru.json @@ -232,6 +232,7 @@ "balance": "Баланс", "comments_label": "Комментарий", "commission_label": "Комиссия за перевод", + "commission_estimate_label": "Приблизительная комиссия за перевод", "confirm_approve": "Подтвердить", "confirm_cancel": "Отмена", "confirm_message": "Подтвердите перевод {amount} {crypto} на адрес {address}.", diff --git a/src/lib/constants.js b/src/lib/constants.js index ba71cd4ca..eb74de226 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -55,6 +55,10 @@ export const BTC_BASED = Object.freeze([ export const isErc20 = crypto => ERC20.includes(crypto) +export const isEthBased = crypto => isErc20(crypto) || crypto === Cryptos.ETH + +export const isFeeEstimate = crypto => isEthBased(crypto) + export const isBtcBased = crypto => BTC_BASED.includes(crypto) /** Number of decimal places for the different crypto amounts */ From 768d23f861501838ca9be30c11682b5fcb369ce3 Mon Sep 17 00:00:00 2001 From: Aleksei Lebedev Date: Thu, 20 Aug 2020 23:09:59 +0300 Subject: [PATCH 4/6] Fix gasPrice --- src/store/modules/eth/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/modules/eth/actions.js b/src/store/modules/eth/actions.js index ad81db699..a6edb2ce8 100644 --- a/src/store/modules/eth/actions.js +++ b/src/store/modules/eth/actions.js @@ -71,7 +71,7 @@ const createSpecificActions = (api, queue) => ({ // Current gas price api.eth.getGasPrice.request((err, price) => { if (!err) { - const gasPrice = ETH_GASPRICE_MULTIPLIER * price.toNumber() + const gasPrice = Math.round(ETH_GASPRICE_MULTIPLIER * price.toNumber()) context.commit('gasPrice', { gasPrice, fee: +(+utils.calculateFee(ETH_TRANSFER_GAS, gasPrice)).toFixed(7) From 4bbdb2c2bf940c1c73c180f54279190991c8ad6d Mon Sep 17 00:00:00 2001 From: Aleksei Lebedev Date: Sun, 23 Aug 2020 13:14:34 +0300 Subject: [PATCH 5/6] Fix copy to clipboard on iOS devices --- src/lib/textHelpers.js | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/lib/textHelpers.js b/src/lib/textHelpers.js index eccbd86fe..f8d2d0163 100644 --- a/src/lib/textHelpers.js +++ b/src/lib/textHelpers.js @@ -6,13 +6,37 @@ export function copyToClipboard (data) { let el = document.createElement('textarea') el.value = data - document.body.appendChild(el) - el.select() - document.execCommand('copy') + + var isiOSDevice = navigator.userAgent.match(/ipad|iphone/i) + if (isiOSDevice) { + copyToClipboardIos(el) + } else { + el.select() + document.execCommand('copy') + } document.body.removeChild(el) } +/** + * Copy to clipboard helper for iOS devices + * + * @param {HTMLTextAreaElement} el + */ +function copyToClipboardIos (el) { + var range = document.createRange() + el.contentEditable = true + el.readOnly = false + range.selectNodeContents(el) + + var s = window.getSelection() + s.removeAllRanges() + s.addRange(range) + el.setSelectionRange(0, 999999) // A big number, to cover anything that could be inside the element. + + document.execCommand('copy') +} + /** * Download file helper. * From 1437e3c0a48ad6be5735962fedd768cb62ff0c7d Mon Sep 17 00:00:00 2001 From: adamant-al <33592982+adamant-al@users.noreply.github.com> Date: Thu, 27 Aug 2020 18:39:54 +0300 Subject: [PATCH 6/6] Bump version to 2.8.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index be3405670..d331a46df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adamant-im", - "version": "2.7.0", + "version": "2.8.0", "private": true, "scripts": { "serve": "vue-cli-service serve",