Skip to content

Commit

Permalink
Fixes related to cancel tx
Browse files Browse the repository at this point in the history
  • Loading branch information
chaitanyapotti committed Jul 28, 2021
1 parent 5ca024f commit 82c5157
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 59 deletions.
7 changes: 7 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs"
},
"include": ["src/**/*.js", "src/**/*.vue"]
}
2 changes: 0 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
</template>

<script>
/* eslint-disable vue-scoped-css/require-scoped */
export default {
mounted() {
const pageHtml = document.querySelector('html')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ import {
ACTIVITY_STATUS_CANCELLED,
ACTIVITY_STATUS_SUCCESSFUL,
ACTIVITY_STATUS_UNSUCCESSFUL,
CANCEL_TRANSACTION_MULTIPLIER,
CONTRACT_TYPE_ERC721,
CONTRACT_TYPE_ERC1155,
} from '../../../utils/enums'
Expand Down Expand Up @@ -95,6 +94,10 @@ export default {
type: String,
default: 'USD',
},
cancelGasPrice: {
type: BigNumber,
default: new BigNumber('5'),
},
},
data() {
return {
Expand All @@ -111,9 +114,8 @@ export default {
},
computed: {
cancellationFeeEstimate() {
const { gas, gasPrice } = this.transaction
const cancelMultiplier = new BigNumber(CANCEL_TRANSACTION_MULTIPLIER)
const gweiGasPrice = new BigNumber(gasPrice).times(cancelMultiplier).div(weiInGwei)
const { gas } = this.transaction
const gweiGasPrice = this.cancelGasPrice
const gasCost = gweiGasPrice.times(new BigNumber(gas)).div(new BigNumber('10').pow(new BigNumber('9')))
const txFee = gasCost.times(this.currencyMultiplier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,14 @@
:class="{ 'mr-2': !$vuetify.breakpoint.xsOnly }"
:block="$vuetify.breakpoint.xsOnly"
text
:disabled="timeDiff < allowCancelTime"
@click.stop="showCancelTransaction"
>
{{ t('walletActivity.cancelButton') }}
</v-btn>
</span>
</template>
<span>
<div v-if="timeDiff >= allowCancelTime" class="caption text_3--text text-justify">
{{ t('walletActivity.cancelButtonTooltip') }} {{ cancellationFeeEstimate }}
</div>
<div v-else class="caption text_3--text text-justify">
{{ t('walletActivity.cancelButtonTooltipDisabled') }} {{ allowCancelTime - timeDiff }}min
</div>
<div class="caption text_3--text text-justify">{{ t('walletActivity.cancelButtonTooltip') }} {{ cancellationFeeEstimate }}</div>
</span>
</v-tooltip>
</v-flex>
Expand Down Expand Up @@ -154,18 +148,10 @@ export default {
ACTIVITY_STATUS_PENDING,
CONTRACT_TYPE_ERC721,
CONTRACT_TYPE_ERC1155,
allowCancelTime: 8,
}
},
computed: {
...mapState(['networkType']),
timeDiff() {
const transactionDate = new Date(this.transaction.date)
const currentDate = new Date()
const diff = Math.abs(transactionDate - currentDate) / 1000 / 60
return Math.floor(diff)
},
},
methods: {
showCancelTransaction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
:transaction="transaction"
:currency-multiplier="currencyMultiplier"
:selected-currency="selectedCurrency"
:cancel-gas-price="cancelGasPrice"
@cancelTransaction="cancelTransaction"
/>
</template>
Expand Down Expand Up @@ -66,6 +67,10 @@ export default {
type: String,
default: 'USD',
},
cancelGasPrice: {
type: BigNumber,
default: new BigNumber('5'),
},
},
data() {
return {
Expand Down
65 changes: 41 additions & 24 deletions src/containers/WalletHistory/WalletHistory.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
:selected-period="selectedPeriod"
:transactions="calculatedFinalTx"
:selected-currency="selectedCurrency"
:cancel-gas-price="cancelGasPrice"
@cancelTransaction="cancelTransaction"
/>
</v-flex>
Expand All @@ -80,6 +81,7 @@

<script>
import BigNumber from 'bignumber.js'
import log from 'loglevel'
import { mapState } from 'vuex'
import TxHistoryTable from '../../components/WalletHistory/TxHistoryTable'
Expand All @@ -98,7 +100,6 @@ import {
ACTIVITY_STATUS_PENDING,
ACTIVITY_STATUS_SUCCESSFUL,
ACTIVITY_STATUS_UNSUCCESSFUL,
CANCEL_TRANSACTION_MULTIPLIER,
CONTRACT_INTERACTION_KEY,
CONTRACT_TYPE_ERC20,
CONTRACT_TYPE_ERC721,
Expand All @@ -109,7 +110,7 @@ import {
MAINNET,
TOKEN_METHOD_APPROVE,
} from '../../utils/enums'
import { formatDate } from '../../utils/utils'
import { formatDate, formatTime } from '../../utils/utils'
export default {
name: 'WalletHistory',
Expand All @@ -118,6 +119,7 @@ export default {
return {
selectedAction: ACTIVITY_ACTION_ALL,
selectedPeriod: ACTIVITY_PERIOD_ALL,
cancelGasPrice: new BigNumber(5),
}
},
computed: {
Expand Down Expand Up @@ -172,24 +174,11 @@ export default {
calculatedFinalTx() {
let finalTx = [...this.paymentTx, ...this.pastTx, ...this.etherscanTx]
finalTx = finalTx.reduce((accumulator, x) => {
const failingList = new Set(['rejected', 'denied', 'unapproved', 'failed'])
const cancelTxs = finalTx
.filter((tx) => x.id !== tx.id && tx.is_cancel && tx.nonce === x.nonce && !failingList.has(tx.status))
.sort((a, b) => b.date - a.date)
if (cancelTxs.length > 0) {
x.hasCancel = true
x.status = cancelTxs[0].status === 'confirmed' ? 'cancelled' : 'cancelling'
x.cancelDateInitiated = `${this.formatTime(cancelTxs[0].date)} - ${formatDate(cancelTxs[0].date)}`
x.etherscanLink = cancelTxs[0].etherscanLink
x.cancelGas = cancelTxs[0].gas
x.cancelGasPrice = cancelTxs[0].gasPrice
}
x.actionIcon = this.getIcon(x)
x.actionText = this.getActionText(x)
x.statusText = this.getStatusText(x)
x.dateFormatted = formatDate(x.date)
x.timeFormatted = this.formatTime(x.date)
x.timeFormatted = formatTime(x.date)
if (!x.is_cancel && (x.etherscanLink === '' || accumulator.findIndex((y) => y.etherscanLink === x.etherscanLink) === -1)) accumulator.push(x)
return accumulator
}, [])
Expand All @@ -200,8 +189,36 @@ export default {
return new BigNumber(currencyMultiplierNumber)
},
},
mounted() {
async mounted() {
this.$vuetify.goTo(0)
let gasPrice = this.cancelGasPrice
try {
if (this.networkType.host === MAINNET) {
const resp = await fetch('https://ethgasstation.info/json/ethgasAPI.json', {
headers: {},
referrer: 'http://ethgasstation.info/json/',
referrerPolicy: 'no-referrer-when-downgrade',
body: null,
method: 'GET',
mode: 'cors',
})
const { fastest: fastestTimes10 } = await resp.json()
gasPrice = new BigNumber(fastestTimes10).div(new BigNumber('10'))
} else {
const recommended = await torus.web3.eth.getGasPrice()
gasPrice = new BigNumber(recommended).div(new BigNumber(10).pow(new BigNumber(9))).plus(new BigNumber('5'))
}
const percent10Extra = gasPrice.times(new BigNumber('1.1'))
// Add 5 to fastest recommended by transfer page
const plus5 = gasPrice.plus(new BigNumber('5'))
// 1 gwei -> 1.1 & 10 -> 1.1
// 50 gwei -> 55 & 60 -> 55
// 150 gwei -> 165 & 160 -> 160
// Increase by a Max of (5 gwei , 10%)
this.cancelGasPrice = percent10Extra.isGreaterThan(plus5) ? percent10Extra : plus5
} catch (error) {
log.error(error, 'unable to fetch gas price')
}
},
methods: {
getStatusText(currentTx) {
Expand Down Expand Up @@ -272,19 +289,19 @@ export default {
}
return ''
},
formatTime(time) {
return new Date(time).toTimeString().slice(0, 8)
},
async cancelTransaction(transaction) {
const { from, gas, gasPrice, nonce } = transaction
const cancelGasPrice = gasPrice * CANCEL_TRANSACTION_MULTIPLIER
const { from, gas, nonce } = transaction
const { cancelGasPrice } = this
const sendingWei = 0
torus.web3.eth.sendTransaction({
return torus.web3.eth.sendTransaction({
from,
to: from,
value: `0x${sendingWei.toString(16)}`,
gas,
gasPrice: `0x${cancelGasPrice.toString(16)}`,
gasPrice: `0x${cancelGasPrice
.times(new BigNumber(10).pow(new BigNumber(9)))
.dp(0, BigNumber.ROUND_DOWN)
.toString(16)}`,
customNonceValue: nonce,
})
},
Expand Down
51 changes: 39 additions & 12 deletions src/controllers/PreferencesController.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from '../utils/enums'
import { notifyUser } from '../utils/notifications'
import { setSentryEnabled } from '../utils/sentry'
import { formatPastTx, getEthTxStatus, getIFrameOrigin, getUserLanguage, isMain, storageAvailable } from '../utils/utils'
import { formatDate, formatPastTx, formatTime, getEthTxStatus, getIFrameOrigin, getUserLanguage, isMain, storageAvailable } from '../utils/utils'
import { isErrorObject, prettyPrintData } from './utils/permissionUtils'

// By default, poll every 3 minutes
Expand Down Expand Up @@ -341,7 +341,40 @@ class PreferencesController extends EventEmitter {
if (lowerCaseSelectedAddress === element.from.toLowerCase() && finalObject.status && finalObject.status !== element.status)
this.patchPastTx({ id: element.id, status: finalObject.status }, address)
}
this.updateStore({ pastTransactions: pastTx }, address)

const finalTx = this.cancelTxCalculate(pastTx)

this.updateStore({ pastTransactions: finalTx }, address)
}

cancelTxCalculate(pastTx) {
const nonceMap = {}
for (const x of pastTx) {
if (!nonceMap[x.nonce]) nonceMap[x.nonce] = [x]
else {
nonceMap[x.nonce].push(x)
}
}

for (const [, value] of Object.entries(nonceMap)) {
// has duplicate
if (value.length > 1) {
// get latest and mark it as is_cancel
const latestTxs = value.sort((a, b) => b.date - a.date)
const latestCancelTx = latestTxs[0]
latestCancelTx.is_cancel = true
latestTxs.slice(1).forEach((x) => {
x.hasCancel = true
x.status = latestCancelTx.status === 'confirmed' ? 'cancelled' : 'cancelling'
x.cancelDateInitiated = `${formatTime(latestCancelTx.date)} - ${formatDate(latestCancelTx.date)}`
x.etherscanLink = latestCancelTx.etherscanLink
x.cancelGas = latestCancelTx.gas
x.cancelGasPrice = latestCancelTx.gasPrice
})
}
}

return pastTx
}

async fetchEtherscanTx(address, network) {
Expand All @@ -363,16 +396,10 @@ class PreferencesController extends EventEmitter {
if (duplicateIndex === -1 && tx.status === 'submitted') {
// No duplicate found

// Check if has a cancel transaction
const duplicateNonce = storePastTx.filter(
(x) => x.from.toLowerCase() === address.toLowerCase() && x.nonce === tx.nonce && x.networkType === tx.network
)
if (duplicateNonce.length > 0) {
tx.is_cancel = true
formattedTx.is_cancel = true
}
const finalTx = this.cancelTxCalculate([...storePastTx, formattedTx])
tx.is_cancel = formattedTx.is_cancel

this.updateStore({ pastTransactions: [...storePastTx, formattedTx] }, address)
this.updateStore({ pastTransactions: finalTx }, address)
this.postPastTx(tx, address)
try {
notifyUser(formattedTx.etherscanLink)
Expand All @@ -383,7 +410,7 @@ class PreferencesController extends EventEmitter {
// avoid overriding is_cancel
formattedTx.is_cancel = storePastTx[duplicateIndex].is_cancel
storePastTx[duplicateIndex] = formattedTx
this.updateStore({ pastTransactions: [...storePastTx] }, address)
this.updateStore({ pastTransactions: this.cancelTxCalculate([...storePastTx]) }, address)
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/TorusController.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import createOriginMiddleware from './utils/createOriginMiddleware'
import nodeify from './utils/nodeify'
import WalletConnectController from './WalletConnectController'

EventEmitter.defaultMaxListeners = 100

export default class TorusController extends EventEmitter {
/**
* @constructor
Expand Down
2 changes: 0 additions & 2 deletions src/utils/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,5 +477,3 @@ export const FEATURES_PROVIDER_CHANGE_WINDOW = 'directories=0,titlebar=0,toolbar
export const FEATURES_DEFAULT_WALLET_WINDOW = 'directories=0,titlebar=0,toolbar=0,status=0,location=0,menubar=0,height=740,width=1315'
export const FEATURES_DEFAULT_POPUP_WINDOW = 'directories=0,titlebar=0,toolbar=0,status=0,location=0,menubar=0,height=700,width=1200'
export const FEATURES_CONFIRM_WINDOW = 'directories=0,titlebar=0,toolbar=0,status=0,location=0,menubar=0,height=700,width=450'

export const CANCEL_TRANSACTION_MULTIPLIER = 5
4 changes: 4 additions & 0 deletions src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ export function formatDate(inputDate) {
return `${day} ${month} ${year}`
}

export function formatTime(time) {
return new Date(time).toTimeString().slice(0, 8)
}

export const paymentProviders = {
[SIMPLEX]: {
line1: 'Credit/ Debit Card',
Expand Down

0 comments on commit 82c5157

Please sign in to comment.