init
This commit is contained in:
commit
44f31f8b9f
402 changed files with 47865 additions and 0 deletions
148
components/settings/EthPurchase.vue
Normal file
148
components/settings/EthPurchase.vue
Normal file
|
@ -0,0 +1,148 @@
|
|||
<template>
|
||||
<b-field :type="type" :message="error">
|
||||
<template slot="label">
|
||||
{{ $t('ethPurchase', { currency }) }}
|
||||
<b-tooltip
|
||||
:label="$t('ethPurchaseTooltip', { currency: selectedStatisticCurrency, networkCurrency: currency })"
|
||||
size="is-small"
|
||||
position="is-right"
|
||||
multilined
|
||||
>
|
||||
<button class="button is-primary has-icon">
|
||||
<span class="icon icon-info"></span>
|
||||
</button>
|
||||
</b-tooltip>
|
||||
</template>
|
||||
<div
|
||||
class="field has-eth-purchase"
|
||||
:class="[type, { 'is-disabled': disabled }]"
|
||||
@click="onEthPurchaseClick"
|
||||
>
|
||||
<div class="columns is-mobile">
|
||||
<div class="column currency-container is-light">
|
||||
<div class="currency">{{ currency }}</div>
|
||||
<b-input
|
||||
ref="input"
|
||||
v-model.number="newValue"
|
||||
type="number"
|
||||
step="0.01"
|
||||
:max="max"
|
||||
:min="min"
|
||||
:disabled="disabled"
|
||||
:use-html5-validation="false"
|
||||
expanded
|
||||
custom-class="hide-spinner"
|
||||
@input="onInput"
|
||||
@focus="$emit('focus', $event)"
|
||||
@blur="$emit('blur', $event)"
|
||||
/>
|
||||
<div class="withdraw-data">
|
||||
<div class="withdraw-data-item">
|
||||
{{ $t('rate') }}
|
||||
<span> {{ toDecimals(tokenRate, 18, 6) }} {{ currency }}/{{ selectedStatisticCurrency }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column arrow-container">
|
||||
<EthPurchaseArrow />
|
||||
</div>
|
||||
<div class="column currency-container is-inverted">
|
||||
<div class="currency">{{ selectedStatisticCurrency }}</div>
|
||||
<div class="input">{{ ethToReceiveInToken }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</b-field>
|
||||
</template>
|
||||
<script>
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import { EthPurchaseArrow } from '@/components/icons'
|
||||
import { debounce } from '@/utils'
|
||||
const { toBN, toWei } = require('web3-utils')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EthPurchaseArrow
|
||||
},
|
||||
props: {
|
||||
disabled: Boolean,
|
||||
value: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
defaultEthToReceive: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: '',
|
||||
min: 0,
|
||||
error: '',
|
||||
newValue: this.value
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('application', ['selectedStatistic']),
|
||||
...mapGetters('application', ['maxEthToReceive', 'selectedStatisticCurrency']),
|
||||
...mapGetters('token', ['toDecimals']),
|
||||
...mapGetters('metamask', ['networkConfig', 'currency']),
|
||||
...mapGetters('price', ['tokenRate']),
|
||||
max() {
|
||||
return Math.max(0, Number(this.toDecimals(this.maxEthToReceive, 18, 5)))
|
||||
},
|
||||
ethToReceiveInToken() {
|
||||
const { currency } = this.selectedStatistic
|
||||
const { decimals } = this.networkConfig.tokens[currency]
|
||||
const price = this.tokenRate
|
||||
|
||||
const ethToReceive = toBN(toWei(Math.min(Math.max(this.min, this.newValue), this.max).toString()))
|
||||
return this.toDecimals(ethToReceive.mul(toBN(10 ** decimals)).div(toBN(price)), null, 6)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(value) {
|
||||
this.newValue = value
|
||||
},
|
||||
newValue(value) {
|
||||
debounce(this.validateEthToReceive, value)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.validateEthToReceive(this.newValue)
|
||||
},
|
||||
methods: {
|
||||
onEthPurchaseClick() {
|
||||
this.$refs.input.focus()
|
||||
},
|
||||
onInput(value) {
|
||||
const parsedValue = parseFloat(value)
|
||||
if (!Number.isNaN(parsedValue)) {
|
||||
this.$emit('input', parsedValue)
|
||||
}
|
||||
},
|
||||
validateEthToReceive(value) {
|
||||
let type = ''
|
||||
let error = ''
|
||||
|
||||
if (value === '') {
|
||||
type = 'is-warning'
|
||||
error = this.$t('incorrectAmount')
|
||||
} else if (value < 0) {
|
||||
type = 'is-warning'
|
||||
error = this.$t('amountIsLow', { value: this.min })
|
||||
} else if (value > this.max) {
|
||||
type = 'is-warning'
|
||||
error = this.$t('amountIsHigh', { value: this.max })
|
||||
} else if (value === this.defaultEthToReceive) {
|
||||
type = 'is-primary'
|
||||
}
|
||||
|
||||
this.error = error
|
||||
this.type = type
|
||||
this.$emit('isValidEthToReceive', type !== 'is-warning')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
66
components/settings/SettingsModalBox.vue
Normal file
66
components/settings/SettingsModalBox.vue
Normal file
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<div class="modal-card box box-modal">
|
||||
<header class="box-modal-header is-spaced">
|
||||
<div class="box-modal-title">{{ $t('withdrawalSettings') }}</div>
|
||||
<button type="button" class="delete" @click="$parent.cancel('escape')" />
|
||||
</header>
|
||||
<b-tabs v-model="withdrawType" :animated="false" class="is-modal">
|
||||
<RelayerTab />
|
||||
<WalletTab />
|
||||
</b-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/* eslint-disable no-console */
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
|
||||
import { RelayerTab, WalletTab } from '@/components/settings/tabs'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
RelayerTab,
|
||||
WalletTab
|
||||
},
|
||||
props: {
|
||||
currency: {
|
||||
type: String,
|
||||
default: 'ETH'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: 'withdrawalSettings'
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
currency: this.currency,
|
||||
save: this.save,
|
||||
reset: this.reset
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
withdrawType: 'relayer'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('application', {
|
||||
defaultWithdrawType: 'withdrawType'
|
||||
})
|
||||
},
|
||||
created() {
|
||||
this.withdrawType = this.defaultWithdrawType
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('application', ['SET_WITHDRAW_TYPE']),
|
||||
reset() {
|
||||
this.withdrawType = 'relayer'
|
||||
this.$root.$emit('resetSettings')
|
||||
},
|
||||
save() {
|
||||
this.SET_WITHDRAW_TYPE({ withdrawType: this.withdrawType })
|
||||
this.$emit('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
259
components/settings/tabs/RelayerTab.vue
Normal file
259
components/settings/tabs/RelayerTab.vue
Normal file
|
@ -0,0 +1,259 @@
|
|||
<template>
|
||||
<b-tab-item :label="$t('relayer')" value="relayer">
|
||||
<div class="field">
|
||||
<b-field :label="$t('relayer')">
|
||||
<b-dropdown v-model="selectedRelayer" expanded aria-role="list" @change="onChangeRelayer">
|
||||
<div slot="trigger" class="control" :class="{ 'is-loading': checkingRelayer || isLoadingRelayers }">
|
||||
<div class="input">
|
||||
<span>{{ dropdownValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<b-dropdown-item
|
||||
v-for="{ name, tornadoServiceFee } in relayers"
|
||||
v-show="!isLoadingRelayers"
|
||||
:key="name"
|
||||
:value="name"
|
||||
aria-role="listitem"
|
||||
>
|
||||
{{ getRelayerName({ name, tornadoServiceFee }) }}
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item value="custom" aria-role="listitem">
|
||||
{{ $t('custom') }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</b-field>
|
||||
<div v-if="isCustomRelayer" class="field has-custom-field">
|
||||
<b-input
|
||||
ref="customInput"
|
||||
v-model="customRelayerUrl"
|
||||
type="url"
|
||||
:placeholder="$t('pasteYourRelayerUrlorEnsRecord')"
|
||||
:custom-class="hasErrorRelayer.type"
|
||||
:use-html5-validation="false"
|
||||
@input="onInputCustomRelayer"
|
||||
></b-input>
|
||||
</div>
|
||||
<div class="withdraw-data is-spaced">
|
||||
<div class="withdraw-data-item">
|
||||
{{ $t('relayerFee') }}
|
||||
<span> {{ relayer.tornadoServiceFee }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="hasErrorRelayer.msg" class="help" :class="hasErrorRelayer.type">
|
||||
{{ hasErrorRelayer.msg }}
|
||||
</p>
|
||||
</div>
|
||||
<eth-purchase
|
||||
v-if="isEnabledEthPurchase"
|
||||
v-model="ethToReceive"
|
||||
:default-eth-to-receive="defaultEthToReceive"
|
||||
@isValidEthToReceive="ethToReceiveErrorHandler"
|
||||
/>
|
||||
<WithdrawTotal
|
||||
:currency="currency"
|
||||
withdraw-type="relayer"
|
||||
:eth-to-receive="ethToReceiveToWei"
|
||||
:service-fee="relayer.tornadoServiceFee"
|
||||
/>
|
||||
<div class="buttons buttons__halfwidth mt-5">
|
||||
<b-button type="is-primary" outlined @mousedown.prevent @click="onReset">
|
||||
{{ $t('reset') }}
|
||||
</b-button>
|
||||
<b-button
|
||||
type="is-primary"
|
||||
:disabled="isDisabledSave"
|
||||
:loading="checkingRelayer || isLoadingRelayers"
|
||||
@click="onSave"
|
||||
>
|
||||
{{ $t('save') }}
|
||||
</b-button>
|
||||
</div>
|
||||
</b-tab-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapGetters, mapMutations } from 'vuex'
|
||||
import EthPurchase from '@/components/settings/EthPurchase'
|
||||
import WithdrawTotal from '@/components/withdraw/WithdrawTotal'
|
||||
import { debounce } from '@/utils'
|
||||
const { fromWei, toWei } = require('web3-utils')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EthPurchase,
|
||||
WithdrawTotal
|
||||
},
|
||||
inject: ['currency', 'save'],
|
||||
data() {
|
||||
return {
|
||||
selectedRelayer: 'custom',
|
||||
checkingRelayer: false,
|
||||
customRelayerUrl: '',
|
||||
hasErrorRelayer: { type: '', msg: '' },
|
||||
isValidEthToReceive: true,
|
||||
isValidRelayer: true,
|
||||
ethToReceive: 0.02,
|
||||
relayer: {
|
||||
name: 'custom',
|
||||
url: '',
|
||||
address: '',
|
||||
tornadoServiceFee: 0.0,
|
||||
miningServiceFee: 0.0,
|
||||
ethPrices: {
|
||||
torn: '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('token', ['toDecimals']),
|
||||
...mapGetters('metamask', ['networkConfig', 'nativeCurrency']),
|
||||
...mapGetters('metamask', {
|
||||
networkCurrency: 'currency'
|
||||
}),
|
||||
...mapState('relayer', ['isLoadingRelayers']),
|
||||
...mapState('relayer', {
|
||||
defaultRelayer: (state) => state.selectedRelayer,
|
||||
relayers: (state) => state.validRelayers
|
||||
}),
|
||||
...mapState('application', {
|
||||
ethToReceiveFromStore: (state) => Number(fromWei(state.ethToReceive)),
|
||||
defaultEthToReceive: (state) => Number(fromWei(state.defaultEthToReceive))
|
||||
}),
|
||||
isEnabledEthPurchase() {
|
||||
return this.currency.toLowerCase() !== this.nativeCurrency
|
||||
},
|
||||
ethToReceiveToWei() {
|
||||
return toWei(this.ethToReceive.toString())
|
||||
},
|
||||
isCustomRelayer() {
|
||||
return this.selectedRelayer === 'custom'
|
||||
},
|
||||
dropdownValue() {
|
||||
if (this.isLoadingRelayers) {
|
||||
return this.$t('loading')
|
||||
}
|
||||
if (this.isCustomRelayer) {
|
||||
return this.$t('custom')
|
||||
}
|
||||
return this.selectedRelayer
|
||||
},
|
||||
isDisabledSave() {
|
||||
return !this.isValidRelayer || this.hasErrorRelayer.type === 'is-warning' || !this.isValidEthToReceive
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultRelayer: {
|
||||
handler(relayer) {
|
||||
this.setRelayer(relayer)
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.setEthToReceive(this.ethToReceiveFromStore)
|
||||
},
|
||||
mounted() {
|
||||
this.$root.$on('resetSettings', this.onReset)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$root.$off('resetSettings', this.onReset)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('relayer', ['SET_SELECTED_RELAYER']),
|
||||
...mapMutations('application', ['SAVE_ETH_TO_RECEIVE']),
|
||||
getRelayerName({ name, tornadoServiceFee }) {
|
||||
return `${name} - ${tornadoServiceFee}%`
|
||||
},
|
||||
onInputCustomRelayer(url) {
|
||||
const trimmedUrl = url.toLowerCase().trim()
|
||||
|
||||
if (!trimmedUrl) {
|
||||
this.hasErrorRelayer = { type: '', msg: '' }
|
||||
this.isValidRelayer = false
|
||||
return
|
||||
}
|
||||
if (
|
||||
window.location.protocol !== 'http:' &&
|
||||
trimmedUrl.startsWith('http:') &&
|
||||
!trimmedUrl.includes('.onion')
|
||||
) {
|
||||
this.hasErrorRelayer.type = 'is-warning'
|
||||
this.hasErrorRelayer.msg = this.$t('relayerShouldSupportSSL')
|
||||
this.isValidRelayer = false
|
||||
return
|
||||
}
|
||||
|
||||
debounce(this.checkRelayer, { url, name: 'custom' })
|
||||
},
|
||||
onChangeRelayer(keyName) {
|
||||
if (keyName === 'custom') {
|
||||
this.hasErrorRelayer = { type: '', msg: '' }
|
||||
this.isValidRelayer = false
|
||||
this.customRelayerUrl = ''
|
||||
return
|
||||
}
|
||||
|
||||
const { realUrl: url, name } = this.relayers.find((el) => el.name === keyName)
|
||||
|
||||
debounce(this.checkRelayer, { url, name })
|
||||
},
|
||||
async checkRelayer({ url, name }) {
|
||||
this.hasErrorRelayer = { type: '', msg: '' }
|
||||
this.isValidRelayer = false
|
||||
this.checkingRelayer = true
|
||||
|
||||
const { isValid, error, ...relayer } = await this.$store.dispatch('relayer/setupRelayer', {
|
||||
name,
|
||||
url
|
||||
})
|
||||
|
||||
if (isValid) {
|
||||
this.hasErrorRelayer.type = 'is-primary'
|
||||
this.hasErrorRelayer.msg = this.$t('relayerStatusOk')
|
||||
this.relayer = relayer
|
||||
} else {
|
||||
this.hasErrorRelayer.type = 'is-warning'
|
||||
this.hasErrorRelayer.msg = error
|
||||
}
|
||||
|
||||
this.checkingRelayer = false
|
||||
this.isValidRelayer = isValid
|
||||
},
|
||||
ethToReceiveErrorHandler(value) {
|
||||
this.isValidEthToReceive = value
|
||||
},
|
||||
setEthToReceive(ethToReceive) {
|
||||
if (this.isEnabledEthPurchase) {
|
||||
this.ethToReceive = ethToReceive
|
||||
}
|
||||
},
|
||||
setRelayer(relayer) {
|
||||
this.relayer = relayer
|
||||
this.selectedRelayer = relayer.name
|
||||
if (this.selectedRelayer === 'custom') {
|
||||
this.customRelayerUrl = relayer.url
|
||||
}
|
||||
},
|
||||
onReset() {
|
||||
this.hasErrorRelayer = { type: '', msg: '' }
|
||||
this.checkingRelayer = false
|
||||
this.isValidRelayer = true
|
||||
|
||||
this.setRelayer(this.defaultRelayer)
|
||||
this.setEthToReceive(this.defaultEthToReceive)
|
||||
},
|
||||
onSave() {
|
||||
this.SET_SELECTED_RELAYER(this.relayer)
|
||||
|
||||
if (this.isEnabledEthPurchase) {
|
||||
this.SAVE_ETH_TO_RECEIVE({
|
||||
ethToReceive: this.ethToReceiveToWei
|
||||
})
|
||||
}
|
||||
|
||||
this.save()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
52
components/settings/tabs/WalletTab.vue
Normal file
52
components/settings/tabs/WalletTab.vue
Normal file
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<b-tab-item :label="$t('wallet')" value="wallet">
|
||||
<fieldset :disabled="isNotLoggedIn">
|
||||
<div class="notice is-warning">
|
||||
<div class="notice__p">{{ $t('withdrawWalletWarning', { currency: networkCurrency }) }}</div>
|
||||
<div v-if="isNotLoggedIn" class="tooltip" :data-label="$t('connectYourWalletFirst')"></div>
|
||||
</div>
|
||||
<WithdrawTotal :currency="currency" withdraw-type="wallet" />
|
||||
</fieldset>
|
||||
<div class="buttons buttons__halfwidth mt-5">
|
||||
<b-button type="is-primary" outlined @mousedown.prevent @click="onReset">
|
||||
{{ $t('reset') }}
|
||||
</b-button>
|
||||
<connect-button v-if="isNotLoggedIn" />
|
||||
<b-button v-else type="is-primary" @click="onSave">
|
||||
{{ $t('save') }}
|
||||
</b-button>
|
||||
</div>
|
||||
</b-tab-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import { ConnectButton } from '@/components/web3Connect'
|
||||
import WithdrawTotal from '@/components/withdraw/WithdrawTotal'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ConnectButton,
|
||||
WithdrawTotal
|
||||
},
|
||||
inject: ['save', 'reset', 'currency'],
|
||||
computed: {
|
||||
...mapGetters('metamask', ['isLoggedIn']),
|
||||
...mapGetters('metamask', {
|
||||
networkCurrency: 'currency'
|
||||
}),
|
||||
isNotLoggedIn() {
|
||||
return !this.isLoggedIn
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onReset() {
|
||||
this.reset()
|
||||
},
|
||||
onSave() {
|
||||
this.save()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
4
components/settings/tabs/index.js
Normal file
4
components/settings/tabs/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import WalletTab from './WalletTab'
|
||||
import RelayerTab from './RelayerTab'
|
||||
|
||||
export { WalletTab, RelayerTab }
|
Loading…
Add table
Add a link
Reference in a new issue