JS and CSS refactorings, fixes, and improvements

staking
Vadim 5 years ago committed by Victor Baranov
parent fbcf251f74
commit 187a8dd37d
  1. 5
      apps/block_scout_web/assets/css/_mixins.scss
  2. 8
      apps/block_scout_web/assets/css/components/_form.scss
  3. 9
      apps/block_scout_web/assets/css/theme/_dai_variables.scss
  4. 12
      apps/block_scout_web/assets/css/theme/_dark-theme.scss
  5. 1
      apps/block_scout_web/assets/js/pages/stakes.js
  6. 51
      apps/block_scout_web/assets/js/pages/stakes/claim_reward.js
  7. 15
      apps/block_scout_web/assets/js/pages/stakes/make_stake.js
  8. 19
      apps/block_scout_web/assets/js/pages/stakes/remove_pool.js
  9. 110
      apps/block_scout_web/assets/js/pages/stakes/utils.js

@ -172,8 +172,9 @@
&[disabled] { &[disabled] {
&, &,
&:hover { &:hover {
background-color: $bg-color; background-color: $bg-color!important;
border-color: $text-color; border-color: $primary!important;
color: $primary!important;
cursor: default; cursor: default;
opacity: 0.5; opacity: 0.5;
} }

@ -92,6 +92,14 @@ $form-control-border-color-active: $primary !default;
color: white; color: white;
background: #FF7884; background: #FF7884;
border-radius: 0 0 2px 2px; border-radius: 0 0 2px 2px;
.link-helptip {
border-bottom-width: 1px;
border-bottom-style: dotted;
color: inherit;
cursor: help;
text-decoration: none;
}
} }
} }

@ -105,6 +105,15 @@ $dark-tertiary: #5a77ff;
background-color: transparent!important; background-color: transparent!important;
border-color: $dark-tertiary!important; border-color: $dark-tertiary!important;
color: $dark-tertiary!important; color: $dark-tertiary!important;
&[disabled] {
&,
&:hover {
background-color: transparent!important;
border-color: $dark-tertiary!important;
color: $dark-tertiary!important;
}
}
} }
.dark-theme-applied .btn-line:hover { .dark-theme-applied .btn-line:hover {

@ -296,6 +296,14 @@ $dark-stakes-banned-background: #3e314c;
color: $labels-dark; color: $labels-dark;
} }
.stakes-table-body {
.refresh-informer {
a {
color: inherit;
}
}
}
.stakes-td { .stakes-td {
border-bottom-color: darken($labels-dark, 30); border-bottom-color: darken($labels-dark, 30);
} }
@ -554,6 +562,10 @@ $dark-stakes-banned-background: #3e314c;
color: #fff; color: #fff;
transition: border-color 0.15s ease-in-out; transition: border-color 0.15s ease-in-out;
&[readonly] {
background-color: $dark-light!important;
}
&::placeholder { &::placeholder {
color: $labels-dark; color: $labels-dark;
} }

@ -29,6 +29,7 @@ export const initialState = {
network: null, network: null,
refreshBlockNumber: 0, // last page refresh block number refreshBlockNumber: 0, // last page refresh block number
refreshInterval: null, refreshInterval: null,
refreshPageFunc: refreshPageWrapper,
stakingAllowed: false, stakingAllowed: false,
stakingTokenDefined: false, stakingTokenDefined: false,
stakingContract: null, stakingContract: null,

@ -9,7 +9,7 @@ import {
unlockModal unlockModal
} from '../../lib/modals' } from '../../lib/modals'
import { displayInputError, hideInputError } from '../../lib/validation' import { displayInputError, hideInputError } from '../../lib/validation'
import { isSupportedNetwork } from './utils' import { isSupportedNetwork, makeContractCall } from './utils'
let status = 'modalClosed' let status = 'modalClosed'
@ -230,53 +230,20 @@ function onPoolsFound ($modal, $modalBody, channel, store) {
const gasLimit = parseInt($('#tx-gas-limit', $modalBody).text().replace(/~/g, '').trim(), 10) const gasLimit = parseInt($('#tx-gas-limit', $modalBody).text().replace(/~/g, '').trim(), 10)
const state = store.getState() const state = store.getState()
const stakingContract = state.stakingContract const stakingContract = state.stakingContract
const from = state.account
const web3 = state.web3
if (isNaN(gasLimit)) { if (isNaN(gasLimit)) {
claimFinished('Invalid gas limit. Please, contact support.') claimFinished('Invalid gas limit. Please, contact support.')
} else if (!stakingContract) { } else if (!stakingContract) {
claimFinished('Staking contract is undefined. Please, contact support.') claimFinished('Staking contract is undefined. Please, contact support.')
} else if (!from) {
claimFinished('Your MetaMask account is undefined. Please, contact support.')
} else if (!web3) {
claimFinished('Web3 is undefined. Please, contact support.')
} else if (!poolStakingAddress) { } else if (!poolStakingAddress) {
claimFinished('Pool staking address is undefined. Please, contact support.') claimFinished('Pool staking address is undefined. Please, contact support.')
} else { } else {
stakingContract.methods.claimReward(epochs, poolStakingAddress).send({ makeContractCall(
from, stakingContract.methods.claimReward(epochs, poolStakingAddress),
gasPrice: web3.utils.toWei('1', 'gwei'), store,
gas: Math.ceil(gasLimit * 1.2) // +20% reserve to ensure enough gas gasLimit,
}, async function (error, txHash) { claimFinished
if (error) { )
claimFinished(error.message)
} else {
try {
let tx
let currentBlockNumber
const maxWaitBlocks = 6
const startBlockNumber = (await web3.eth.getBlockNumber()) - 0
const finishBlockNumber = startBlockNumber + maxWaitBlocks
do {
await sleep(5) // seconds
tx = await web3.eth.getTransactionReceipt(txHash)
currentBlockNumber = await web3.eth.getBlockNumber()
} while (tx === null && currentBlockNumber <= finishBlockNumber)
if (tx) {
if (tx.status === true || tx.status === '0x1') {
claimFinished()
} else {
claimFinished('Transaction reverted')
}
} else {
claimFinished(`Your transaction was not mined in ${maxWaitBlocks} blocks. Please, try again with the increased gas price or fixed nonce (use Reset Account feature of MetaMask).`)
}
} catch (e) {
claimFinished(e.message)
}
}
})
} }
} }
function claimFinished (error) { function claimFinished (error) {
@ -303,10 +270,6 @@ function lockUI (lock, $modal, $button, $poolsDropdown, $epochChoiceRadio, $spec
$specifiedEpochsText.prop('disabled', lock) $specifiedEpochsText.prop('disabled', lock)
} }
function sleep (seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000))
}
function showButton (type, $modalBody, calculations) { function showButton (type, $modalBody, calculations) {
const $recalculateButton = $('button.recalculate', $modalBody) const $recalculateButton = $('button.recalculate', $modalBody)
const $submitButton = $('button.submit', $modalBody) const $submitButton = $('button.submit', $modalBody)

@ -2,19 +2,22 @@ import $ from 'jquery'
import { BigNumber } from 'bignumber.js' import { BigNumber } from 'bignumber.js'
import { openErrorModal, openModal, openWarningModal, lockModal } from '../../lib/modals' import { openErrorModal, openModal, openWarningModal, lockModal } from '../../lib/modals'
import { setupValidation } from '../../lib/validation' import { setupValidation } from '../../lib/validation'
import { makeContractCall, setupChart, isSupportedNetwork } from './utils' import { makeContractCall, setupChart, isSupportedNetwork, isStakingAllowed } from './utils'
export function openMakeStakeModal (event, store) { export function openMakeStakeModal (event, store) {
if (!store.getState().account) { const state = store.getState()
if (!state.account) {
openWarningModal('Unauthorized', 'You haven\'t approved the reading of account list from your MetaMask or MetaMask is not installed.') openWarningModal('Unauthorized', 'You haven\'t approved the reading of account list from your MetaMask or MetaMask is not installed.')
return return
} }
if (!isSupportedNetwork(store)) return if (!isSupportedNetwork(store)) return
if (!isStakingAllowed(state)) return
const address = $(event.target).closest('[data-address]').data('address') || store.getState().account const address = $(event.target).closest('[data-address]').data('address') || store.getState().account
store.getState().channel state.channel
.push('render_make_stake', { address }) .push('render_make_stake', { address })
.receive('ok', msg => { .receive('ok', msg => {
const $modal = $(msg.html) const $modal = $(msg.html)
@ -47,8 +50,6 @@ export function openMakeStakeModal (event, store) {
} }
async function makeStake ($modal, address, store, msg) { async function makeStake ($modal, address, store, msg) {
lockModal($modal)
const state = store.getState() const state = store.getState()
const stakingContract = state.stakingContract const stakingContract = state.stakingContract
const validatorSetContract = state.validatorSetContract const validatorSetContract = state.validatorSetContract
@ -56,6 +57,10 @@ async function makeStake ($modal, address, store, msg) {
const stake = new BigNumber($modal.find('[delegator-stake]').val().replace(',', '.').trim()).shiftedBy(decimals).integerValue() const stake = new BigNumber($modal.find('[delegator-stake]').val().replace(',', '.').trim()).shiftedBy(decimals).integerValue()
if (!isSupportedNetwork(store)) return
if (!isStakingAllowed(state)) return
lockModal($modal)
let miningAddress = msg.mining_address let miningAddress = msg.mining_address
if (!miningAddress || miningAddress === '0x0000000000000000000000000000000000000000') { if (!miningAddress || miningAddress === '0x0000000000000000000000000000000000000000') {
miningAddress = await validatorSetContract.methods.miningByStakingAddress(address).call() miningAddress = await validatorSetContract.methods.miningByStakingAddress(address).call()

@ -1,4 +1,4 @@
import { openQuestionModal } from '../../lib/modals' import { openErrorModal, openQuestionModal } from '../../lib/modals'
import { makeContractCall, isSupportedNetwork } from './utils' import { makeContractCall, isSupportedNetwork } from './utils'
export function openRemovePoolModal (store) { export function openRemovePoolModal (store) {
@ -7,6 +7,19 @@ export function openRemovePoolModal (store) {
} }
async function removePool (store) { async function removePool (store) {
const contract = store.getState().stakingContract const state = store.getState()
makeContractCall(contract.methods.removeMyPool(), store) const call = state.stakingContract.methods.removeMyPool()
let gasLimit
try {
gasLimit = await call.estimateGas({
from: state.account,
gasPrice: 1000000000
})
} catch (err) {
openErrorModal('Error', 'Currently you cannot remove your pool. Please try again during the next epoch.')
return
}
makeContractCall(call, store, gasLimit)
} }

@ -1,55 +1,79 @@
import $ from 'jquery' import $ from 'jquery'
import Chart from 'chart.js' import Chart from 'chart.js'
import { refreshPage } from '../../lib/async_listing_load'
import { openErrorModal, openSuccessModal, openWarningModal } from '../../lib/modals' import { openErrorModal, openSuccessModal, openWarningModal } from '../../lib/modals'
export async function makeContractCall (call, store) { export async function makeContractCall (call, store, gasLimit, callbackFunc) {
let gas, timeout const state = store.getState()
let resultShown = false const from = state.account
const account = store.getState().account const web3 = state.web3
try { if (!callbackFunc) {
gas = await call.estimateGas({ callbackFunc = function (errorMessage) {
from: account, if (!errorMessage) {
gasPrice: 1000000000 state.refreshPageFunc(store)
}) openSuccessModal('Success', 'Transaction is confirmed.')
} catch (err) { } else {
openErrorModal('Error', 'Your transaction cannot be mined at the moment. Please, try again in a few blocks.') openErrorModal('Error', errorMessage)
return }
}
} }
try { if (!from) {
await call.send({ return callbackFunc('Your MetaMask account is undefined. Please, contact support.')
from: account, } else if (!web3) {
gas: Math.ceil(gas * 1.2), return callbackFunc('Web3 is undefined. Please, contact support.')
gasPrice: 1000000000 }
}).once('transactionHash', (hash) => {
timeout = setTimeout(() => {
if (!resultShown) {
openErrorModal('Error', 'Your transaction cannot be mined at the moment. Please, try again with the increased gas price or fixed nonce (use Reset Account feature of MetaMask).')
resultShown = true
}
}, 30000)
})
clearTimeout(timeout) const gasPrice = web3.utils.toWei('1', 'gwei')
refreshPage(store)
if (!resultShown) { if (!gasLimit) {
openSuccessModal('Success', 'Transaction is confirmed.') try {
resultShown = true gasLimit = await call.estimateGas({ from, gasPrice })
} } catch (e) {
} catch (err) { return callbackFunc('Your transaction cannot be mined at the moment. Please, try again in a few blocks.')
clearTimeout(timeout)
let errorMessage = 'Your MetaMask transaction was not processed, please try again in a few minutes.'
if (err.message) {
const detailsMessage = err.message.replace(/["]/g, '&quot;')
console.log(detailsMessage)
const detailsHTML = ` <a href="javascript:void(0);" data-boundary="window" data-container="body" data-html="false" data-placement="top" data-toggle="tooltip" title="${detailsMessage}" data-original-title="${detailsMessage}" class="link-helptip">Details</a>`
errorMessage = errorMessage + detailsHTML
} }
openErrorModal('Error', errorMessage)
} }
call.send({
from,
gasPrice,
gas: Math.ceil(gasLimit * 1.2) // +20% reserve to ensure enough gas
}, async function (error, txHash) {
if (error) {
let errorMessage = 'Your transaction wasn\'t processed, please try again in a few blocks.'
if (error.message) {
const detailsMessage = error.message.replace(/["]/g, '&quot;')
console.log(detailsMessage)
const detailsHTML = ` <a href="javascript:void(0);" data-boundary="window" data-container="body" data-html="false" data-placement="top" data-toggle="tooltip" title="${detailsMessage}" data-original-title="${detailsMessage}" class="link-helptip">Details</a>`
errorMessage = errorMessage + detailsHTML
}
callbackFunc(errorMessage)
} else {
try {
let tx
let currentBlockNumber
const maxWaitBlocks = 6
const startBlockNumber = (await web3.eth.getBlockNumber()) - 0
const finishBlockNumber = startBlockNumber + maxWaitBlocks
do {
await sleep(5) // seconds
tx = await web3.eth.getTransactionReceipt(txHash)
currentBlockNumber = await web3.eth.getBlockNumber()
} while (tx === null && currentBlockNumber <= finishBlockNumber)
if (tx) {
if (tx.status === true || tx.status === '0x1') {
callbackFunc() // success
} else {
callbackFunc('Transaction reverted')
}
} else {
callbackFunc(`Your transaction wasn't processed in ${maxWaitBlocks} blocks. Please, try again with the increased gas price or fixed nonce (use Reset Account feature of MetaMask).`)
}
} catch (e) {
callbackFunc(e.message)
}
}
})
} }
export function setupChart ($canvas, self, total) { export function setupChart ($canvas, self, total) {
@ -107,3 +131,7 @@ export function isSupportedNetwork (store) {
openWarningModal('Unauthorized', 'Please, connect to the xDai Chain.<br /><a href="https://xdaichain.com" target="_blank">Instructions</a>') openWarningModal('Unauthorized', 'Please, connect to the xDai Chain.<br /><a href="https://xdaichain.com" target="_blank">Instructions</a>')
return false return false
} }
function sleep (seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000))
}

Loading…
Cancel
Save