forked from tornadocash/classic-ui
223 lines
7.4 KiB
JavaScript
223 lines
7.4 KiB
JavaScript
/* eslint-disable no-console */
|
|
/* eslint-disable import/order */
|
|
import Web3 from 'web3'
|
|
import networkConfig from '@/networkConfig'
|
|
import ERC20ABI from '@/abis/ERC20.abi.json'
|
|
const { numberToHex, toBN, toWei } = require('web3-utils')
|
|
const BN = require('bn.js')
|
|
const zero = new BN(0)
|
|
const negative1 = new BN(-1)
|
|
|
|
export const state = () => {
|
|
return {
|
|
approvalAmount: 'unlimited',
|
|
allowance: '',
|
|
balance: ''
|
|
}
|
|
}
|
|
|
|
export const getters = {
|
|
tokenContract: (state, getters, rootState, rootGetters) => ({ currency, netId }) => {
|
|
const config = networkConfig[`netId${netId}`]
|
|
const { url } = rootState.settings[`netId${netId}`].rpc
|
|
const address = config.tokens[currency].tokenAddress
|
|
const web3 = new Web3(url)
|
|
return new web3.eth.Contract(ERC20ABI, address)
|
|
},
|
|
// similar to fromWei from web3
|
|
toDecimals: (state, getters, rootState, rootGetters) => (value, decimals, fixed) => {
|
|
const { currency } = rootState.application.selectedStatistic
|
|
decimals = decimals || rootGetters['metamask/networkConfig'].tokens[currency].decimals
|
|
fixed = fixed || 2
|
|
|
|
value = new BN(value)
|
|
const negative = value.lt(zero)
|
|
const base = new BN('10').pow(new BN(decimals))
|
|
const baseLength = base.toString(10).length - 1 || 1
|
|
|
|
if (negative) {
|
|
value = value.mul(negative1)
|
|
}
|
|
|
|
let fraction = value.mod(base).toString(10)
|
|
while (fraction.length < baseLength) {
|
|
fraction = `0${fraction}`
|
|
}
|
|
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1]
|
|
const whole = value.div(base).toString(10)
|
|
|
|
if (fixed && fraction !== '0') {
|
|
fraction = fraction.slice(0, fixed)
|
|
}
|
|
value = `${whole}${fraction === '0' ? '' : `.${fraction}`}`
|
|
|
|
if (negative) {
|
|
value = `-${value}`
|
|
}
|
|
|
|
return value
|
|
},
|
|
// similar to toWei from web3
|
|
fromDecimals: (state, getters, rootState, rootGetters) => (value, decimals) => {
|
|
const { currency } = rootState.application.selectedStatistic
|
|
decimals = decimals || rootGetters['metamask/networkConfig'].tokens[currency].decimals
|
|
value = value.toString()
|
|
let ether = value.toString()
|
|
const base = new BN('10').pow(new BN(decimals))
|
|
const baseLength = base.toString(10).length - 1 || 1
|
|
|
|
const negative = ether.substring(0, 1) === '-'
|
|
if (negative) {
|
|
ether = ether.substring(1)
|
|
}
|
|
|
|
if (ether === '.') {
|
|
throw new Error(this.app.i18n.t('unitInvalidValue', { value }))
|
|
}
|
|
|
|
// Split it into a whole and fractional part
|
|
const comps = ether.split('.')
|
|
if (comps.length > 2) {
|
|
throw new Error(this.app.i18n.t('tooManyDecimalPoints', { value }))
|
|
}
|
|
|
|
let whole = comps[0]
|
|
let fraction = comps[1]
|
|
|
|
if (!whole) {
|
|
whole = '0'
|
|
}
|
|
if (!fraction) {
|
|
fraction = '0'
|
|
}
|
|
if (fraction.length > baseLength) {
|
|
throw new Error(this.app.i18n.t('tooManyDecimalPlaces', { value }))
|
|
}
|
|
|
|
while (fraction.length < baseLength) {
|
|
fraction += '0'
|
|
}
|
|
|
|
whole = new BN(whole)
|
|
fraction = new BN(fraction)
|
|
let wei = whole.mul(base).add(fraction)
|
|
|
|
if (negative) {
|
|
wei = wei.mul(negative)
|
|
}
|
|
|
|
return new BN(wei.toString(10), 10)
|
|
},
|
|
isSufficientAllowance: (state, getters, rootState, rootGetters) => {
|
|
const { currency, amount } = rootState.application.selectedInstance
|
|
const { decimals } = rootGetters['metamask/networkConfig'].tokens[currency]
|
|
return toBN(state.allowance).gte(toBN(getters.fromDecimals(amount, decimals)))
|
|
},
|
|
isSufficientBalance: (state, getters, rootState, rootGetters) => {
|
|
const ethBalance = rootState.metamask.ethBalance
|
|
const { currency, amount } = rootState.application.selectedInstance
|
|
const { decimals } = rootGetters['metamask/networkConfig'].tokens[currency]
|
|
const nativeCurrency = rootGetters['metamask/nativeCurrency']
|
|
if (currency === nativeCurrency) {
|
|
return toBN(ethBalance).gte(toBN(toWei(amount.toString())))
|
|
} else {
|
|
return toBN(state.balance).gte(toBN(getters.fromDecimals(amount, decimals)))
|
|
}
|
|
},
|
|
getSymbol: (state, getters, rootState, rootGetters) => (currency) => {
|
|
const tokens = rootGetters['metamask/networkConfig'].tokens
|
|
if (tokens[currency]) {
|
|
return tokens[currency].symbol
|
|
}
|
|
return currency.toUpperCase()
|
|
}
|
|
}
|
|
|
|
export const mutations = {
|
|
SET_APPROVAL_AMOUNT(state, { approvalAmount }) {
|
|
state.approvalAmount = approvalAmount
|
|
},
|
|
SAVE_ALLOWANCE(state, { allowance }) {
|
|
this._vm.$set(state, 'allowance', allowance)
|
|
},
|
|
SAVE_BALANCE(state, { balance }) {
|
|
this._vm.$set(state, 'balance', balance)
|
|
}
|
|
}
|
|
|
|
export const actions = {
|
|
async approve({ rootState, getters, dispatch, rootGetters, state }) {
|
|
try {
|
|
const netId = rootGetters['metamask/netId']
|
|
const { currency } = rootState.application.selectedInstance
|
|
const { decimals } = rootGetters['metamask/networkConfig'].tokens[currency]
|
|
const tokenInstance = getters.tokenContract({ currency, netId })
|
|
const tornadoProxy = rootGetters['application/tornadoProxyContract']({ netId })
|
|
|
|
const { ethAccount } = rootState.metamask
|
|
const amountToApprove =
|
|
state.approvalAmount === 'unlimited'
|
|
? toBN('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
|
|
: toBN(getters.fromDecimals(state.approvalAmount, decimals))
|
|
const data = tokenInstance.methods
|
|
.approve(tornadoProxy._address, amountToApprove.toString())
|
|
.encodeABI()
|
|
const gas = await tokenInstance.methods
|
|
.approve(tornadoProxy._address, amountToApprove.toString())
|
|
.estimateGas({
|
|
from: ethAccount
|
|
})
|
|
|
|
const callParams = {
|
|
method: 'eth_sendTransaction',
|
|
params: {
|
|
to: tokenInstance._address,
|
|
gas: numberToHex(gas + 30000),
|
|
data
|
|
},
|
|
watcherParams: {
|
|
title: 'approve',
|
|
successTitle: 'approved'
|
|
},
|
|
isSaving: false
|
|
}
|
|
|
|
await dispatch('metamask/sendTransaction', callParams, { root: true })
|
|
} catch (e) {
|
|
console.error('approve action', e)
|
|
throw new Error(e.message)
|
|
}
|
|
},
|
|
async fetchTokenAllowance({ getters, rootGetters, commit, rootState }) {
|
|
const netId = rootGetters['metamask/netId']
|
|
const { currency } = rootState.application.selectedInstance
|
|
const { ethAccount } = rootState.metamask
|
|
try {
|
|
const tornadoInstance = rootGetters['application/tornadoProxyContract']({ netId })
|
|
const nativeCurrency = rootGetters['metamask/nativeCurrency']
|
|
if (currency !== nativeCurrency && ethAccount) {
|
|
const tokenInstance = getters.tokenContract({ currency, netId })
|
|
const allowance = await tokenInstance.methods.allowance(ethAccount, tornadoInstance._address).call()
|
|
commit('SAVE_ALLOWANCE', { allowance })
|
|
}
|
|
} catch (e) {
|
|
console.error('fetchTokenAllowance', e.message)
|
|
}
|
|
},
|
|
async fetchTokenBalance({ state, getters, rootGetters, commit, rootState }) {
|
|
try {
|
|
const netId = rootGetters['metamask/netId']
|
|
const { currency } = rootState.application.selectedInstance
|
|
const { ethAccount } = rootState.metamask
|
|
const nativeCurrency = rootGetters['metamask/nativeCurrency']
|
|
if (currency !== nativeCurrency && ethAccount) {
|
|
const tokenInstance = getters.tokenContract({ currency, netId })
|
|
const balance = await tokenInstance.methods.balanceOf(ethAccount).call()
|
|
commit('SAVE_BALANCE', { balance })
|
|
}
|
|
} catch (e) {
|
|
console.error('fetchTokenBalance', e.message)
|
|
}
|
|
}
|
|
}
|