forked from cerc-io/cosmos-explorer
Merge pull request #102 from donne1226/master
reimplement operation modal
This commit is contained in:
commit
f5126c553a
@ -21,9 +21,6 @@
|
||||
</b-input-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<operation-transfer-component
|
||||
:recipient-address.sync="selectedAddress"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -36,7 +33,6 @@ import Ripple from 'vue-ripple-directive'
|
||||
import {
|
||||
addressEnCode, addressDecode,
|
||||
} from '@/libs/utils'
|
||||
import OperationTransferComponent from '@/views/OperationTransferComponent.vue'
|
||||
|
||||
export default {
|
||||
name: 'AppFooter',
|
||||
@ -47,7 +43,6 @@ export default {
|
||||
BFormInput,
|
||||
BInputGroupPrepend,
|
||||
BInputGroup,
|
||||
OperationTransferComponent,
|
||||
},
|
||||
directives: {
|
||||
Ripple,
|
||||
|
@ -106,16 +106,26 @@
|
||||
</b-button>
|
||||
</template>
|
||||
|
||||
<!-- <b-dropdown-item
|
||||
:to="{ name: 'portfolio' }"
|
||||
class="d-none"
|
||||
<b-dropdown-item
|
||||
v-for="(item,k) in accounts"
|
||||
:key="k"
|
||||
:disabled="!item.address"
|
||||
@click="updateDefaultWallet(item.wallet)"
|
||||
>
|
||||
<feather-icon
|
||||
icon="PieChartIcon"
|
||||
size="16"
|
||||
/>
|
||||
<span class="align-middle ml-50">Portofolio</span>
|
||||
</b-dropdown-item> -->
|
||||
<div class="d-flex flex-column">
|
||||
<span class="font-weight-bolder">{{ item.wallet }}
|
||||
<b-avatar
|
||||
v-if="item.wallet===walletName"
|
||||
variant="success"
|
||||
size="sm"
|
||||
>
|
||||
<feather-icon icon="CheckIcon" />
|
||||
</b-avatar>
|
||||
</span>
|
||||
<small>{{ item.address ? formatAddr(item.address.addr) : `Not available for ${selected_chain.chain_name}` }}</small>
|
||||
</div>
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-divider />
|
||||
|
||||
<b-dropdown-item :to="{ name: 'accounts' }">
|
||||
<feather-icon
|
||||
@ -155,7 +165,7 @@
|
||||
<script>
|
||||
import {
|
||||
BLink, BNavbarNav, BMedia, BMediaAside, BAvatar, BMediaBody, VBTooltip, BButton,
|
||||
BDropdown, BDropdownItem,
|
||||
BDropdown, BDropdownItem, BDropdownDivider,
|
||||
} from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import DarkToggler from '@core/layouts/components/app-navbar/components/DarkToggler.vue'
|
||||
@ -176,6 +186,7 @@ export default {
|
||||
BButton,
|
||||
BDropdown,
|
||||
BDropdownItem,
|
||||
BDropdownDivider,
|
||||
|
||||
// Navbar Components
|
||||
DarkToggler,
|
||||
@ -224,14 +235,26 @@ export default {
|
||||
}
|
||||
return [conf.api]
|
||||
},
|
||||
accounts() {
|
||||
let accounts = getLocalAccounts() || {}
|
||||
accounts = Object.entries(accounts).map(v => ({ wallet: v[0], address: v[1].address.find(x => x.chain === this.selected_chain.chain_name) }))
|
||||
|
||||
if (!this.$store.state.chains.defaultWallet && this.accounts.length > 0) {
|
||||
this.updateDefaultWallet(this.accounts[0].wallet)
|
||||
}
|
||||
return accounts
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const accounts = Object.keys(getLocalAccounts() || {})
|
||||
if (!this.$store.state.chains.defaultWallet && accounts.length > 0) {
|
||||
this.$store.commit('setDefaultWallet', accounts[0])
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
formatAddr(v) {
|
||||
return v.substring(0, 10).concat('...', v.substring(v.length - 10))
|
||||
},
|
||||
updateDefaultWallet(v) {
|
||||
this.$store.commit('setDefaultWallet', v)
|
||||
},
|
||||
change(v) {
|
||||
this.index = v
|
||||
const conf = this.$store.state.chains.selected
|
||||
|
@ -60,7 +60,7 @@ export default class ChainFetch {
|
||||
if (conf.chain_name === 'injective') {
|
||||
return ChainFetch.fetch('https://tm.injective.network', '/block').then(data => Block.create(commonProcess(data)))
|
||||
}
|
||||
return this.get('/blocks/latest', config).then(data => Block.create(data))
|
||||
return this.get(`/blocks/latest?${new Date().getTime()}`, config).then(data => Block.create(data))
|
||||
}
|
||||
|
||||
async getBlockByHeight(height, config = null) {
|
||||
@ -386,6 +386,19 @@ export default class ChainFetch {
|
||||
return ChainFetch.fetchCoinMarketCap(`/quote/${symbol}`)
|
||||
}
|
||||
|
||||
// Simulate Execution of tx
|
||||
async simulate(tx, config = null) {
|
||||
return this.post('/cosmos/tx/v1beta1/simulate', tx, config).then(res => {
|
||||
if (res.code && res.code !== 0) {
|
||||
throw new Error(res.message)
|
||||
}
|
||||
if (res.tx_response && res.tx_response.code !== 0) {
|
||||
throw new Error(res.tx_response.raw_log)
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
// Tx Submit
|
||||
async broadcastTx(bodyBytes, config = null) {
|
||||
const txString = toBase64(TxRaw.encode(bodyBytes).finish())
|
||||
|
@ -157,19 +157,19 @@
|
||||
</router-link>
|
||||
<b-button
|
||||
v-if="p.status===1"
|
||||
v-b-modal.deposit-window
|
||||
v-b-modal.operation-modal
|
||||
variant="primary"
|
||||
class="btn float-right mg-2"
|
||||
@click="selectProposal(p.id, p.title)"
|
||||
@click="selectProposal('GovDeposit',p.id, p.title)"
|
||||
>
|
||||
{{ $t('btn_deposit') }}
|
||||
</b-button>
|
||||
<b-button
|
||||
v-if="p.status===2"
|
||||
v-b-modal.vote-window
|
||||
v-b-modal.operation-modal
|
||||
variant="primary"
|
||||
class="btn float-right mg-2"
|
||||
@click="selectProposal(p.id, p.title)"
|
||||
@click="selectProposal('Vote',p.id, p.title)"
|
||||
>
|
||||
{{ $t('btn_vote') }}
|
||||
</b-button>
|
||||
@ -177,13 +177,10 @@
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<operation-vote-component
|
||||
<operation-modal
|
||||
:type="operationModalType"
|
||||
:proposal-id="selectedProposalId"
|
||||
:title="selectedTitle"
|
||||
/>
|
||||
<operation-gov-deposit-component
|
||||
:proposal-id="selectedProposalId"
|
||||
:title="selectedTitle"
|
||||
:proposal-title="selectedTitle"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -196,8 +193,7 @@ import Ripple from 'vue-ripple-directive'
|
||||
import { Proposal } from '@/libs/data'
|
||||
import { percent, tokenFormatter } from '@/libs/utils'
|
||||
import dayjs from 'dayjs'
|
||||
import OperationVoteComponent from './OperationVoteComponent.vue'
|
||||
import OperationGovDepositComponent from './OperationGovDepositComponent.vue'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -212,8 +208,7 @@ export default {
|
||||
BCardBody,
|
||||
BRow,
|
||||
BCol,
|
||||
OperationVoteComponent,
|
||||
OperationGovDepositComponent,
|
||||
OperationModal,
|
||||
},
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
@ -225,6 +220,7 @@ export default {
|
||||
selectedTitle: '',
|
||||
proposals: [new Proposal()],
|
||||
max: 1,
|
||||
operationModalType: '',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -234,7 +230,8 @@ export default {
|
||||
percent: v => percent(v),
|
||||
formatDate: v => dayjs(v).format('YYYY-MM-DD'),
|
||||
formatToken: v => tokenFormatter(v, {}),
|
||||
selectProposal(pid, title) {
|
||||
selectProposal(modal, pid, title) {
|
||||
this.operationModalType = modal
|
||||
this.selectedProposalId = Number(pid)
|
||||
this.selectedTitle = title
|
||||
},
|
||||
|
@ -109,10 +109,11 @@
|
||||
</b-button>
|
||||
</router-link>
|
||||
<b-button
|
||||
v-b-modal.vote-window
|
||||
v-b-modal.operation-modal
|
||||
:disabled="proposal.status!=2"
|
||||
variant="primary"
|
||||
class="btn float-right mg-2"
|
||||
@click="openModal('Vote')"
|
||||
>
|
||||
{{ $t('btn_vote') }}
|
||||
</b-button>
|
||||
@ -232,30 +233,29 @@
|
||||
</b-button>
|
||||
</router-link>
|
||||
<b-button
|
||||
v-b-modal.deposit-window
|
||||
v-b-modal.operation-modal
|
||||
:disabled="proposal.status!=1"
|
||||
variant="primary"
|
||||
class="btn float-right mg-2"
|
||||
@click="openModal('GovDeposit')"
|
||||
>
|
||||
{{ $t('btn_deposit') }}
|
||||
</b-button>
|
||||
<b-button
|
||||
v-b-modal.vote-window
|
||||
v-b-modal.operation-modal
|
||||
:disabled="proposal.status!=2"
|
||||
variant="primary"
|
||||
class="btn float-right mg-2 mr-1"
|
||||
@click="openModal('Vote')"
|
||||
>
|
||||
{{ $t('btn_vote') }}
|
||||
</b-button>
|
||||
</b-card-footer>
|
||||
</b-card>
|
||||
<operation-vote-component
|
||||
<operation-modal
|
||||
:type="operationModalType"
|
||||
:proposal-id="Number(proposal.id)"
|
||||
:title="proposal.title"
|
||||
/>
|
||||
<operation-gov-deposit-component
|
||||
:proposal-id="Number(proposal.id)"
|
||||
:title="proposal.title"
|
||||
:proposal-title="proposal.title"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
@ -273,9 +273,9 @@ import {
|
||||
} from '@/libs/utils'
|
||||
import { Proposal, Proposer } from '@/libs/data'
|
||||
import dayjs from 'dayjs'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||
import OperationVoteComponent from './OperationVoteComponent.vue'
|
||||
import OperationGovDepositComponent from './OperationGovDepositComponent.vue'
|
||||
|
||||
// import { formatToken } from '@/libs/data/data'
|
||||
|
||||
export default {
|
||||
@ -295,9 +295,8 @@ export default {
|
||||
BTooltip,
|
||||
BBadge,
|
||||
ObjectFieldComponent,
|
||||
OperationVoteComponent,
|
||||
OperationGovDepositComponent,
|
||||
FlipCountdown,
|
||||
OperationModal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -307,6 +306,7 @@ export default {
|
||||
proposer: new Proposer(),
|
||||
deposits: [],
|
||||
votes: [],
|
||||
operationModalType: '',
|
||||
votes_fields: [
|
||||
{
|
||||
key: 'voter',
|
||||
@ -411,6 +411,9 @@ export default {
|
||||
formatAddress(v) {
|
||||
return getStakingValidatorByAccount(this.$http.config.chain_name, v)
|
||||
},
|
||||
openModal(type) {
|
||||
this.operationModalType = type
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -78,7 +78,7 @@
|
||||
</template>
|
||||
<template #cell(operation)="data">
|
||||
<b-button
|
||||
v-b-modal.delegate-window
|
||||
v-b-modal.operation-modal
|
||||
:name="data.item.operator_address"
|
||||
variant="primary"
|
||||
size="sm"
|
||||
@ -186,7 +186,7 @@
|
||||
</template>
|
||||
<template #cell(operation)="data">
|
||||
<b-button
|
||||
v-b-modal.delegate-window
|
||||
v-b-modal.operation-modal
|
||||
:name="data.item.operator_address"
|
||||
variant="primary"
|
||||
size="sm"
|
||||
@ -210,7 +210,10 @@
|
||||
</small>
|
||||
</template>
|
||||
</b-card>
|
||||
<operation-delegate-component :validator-address="validator_address" />
|
||||
<operation-modal
|
||||
type="Delegate"
|
||||
:validator-address="validator_address"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -222,9 +225,9 @@ import {
|
||||
percent, StakingParameters, formatToken,
|
||||
} from '@/libs/utils'
|
||||
import { keybase } from '@/libs/fetch'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
// import { toHex } from '@cosmjs/encoding'
|
||||
// import fetch from 'node-fetch'
|
||||
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -237,32 +240,15 @@ export default {
|
||||
BCardTitle,
|
||||
BCardBody,
|
||||
BButton,
|
||||
OperationDelegateComponent,
|
||||
BFormRadioGroup,
|
||||
BFormGroup,
|
||||
OperationModal,
|
||||
},
|
||||
directives: {
|
||||
'b-tooltip': VBTooltip,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
keys: [
|
||||
'bitsongvaloper1jxv0u20scum4trha72c7ltfgfqef6nscl86wxa',
|
||||
'akashvaloper1vgstlgtsx4w80gphwgre0fcvc04lcnaelukvll',
|
||||
'certikvaloper1jxv0u20scum4trha72c7ltfgfqef6nsczkvcu7',
|
||||
'cosmosvaloper1jxv0u20scum4trha72c7ltfgfqef6nsch7q6cu',
|
||||
'iva16plp8cmfkjssp222taq6pv6mkm8c5pa9lcktta',
|
||||
'junovaloper1jxv0u20scum4trha72c7ltfgfqef6nscm9pmg2',
|
||||
'kavavaloper1xftqdxvq0xkv2mu8c5y0jrsc578tak4m9u0s44',
|
||||
'kivaloper1jxv0u20scum4trha72c7ltfgfqef6nschqtan9',
|
||||
'osmovaloper1jxv0u20scum4trha72c7ltfgfqef6nscqx0u46',
|
||||
'persistencevaloper1jxv0u20scum4trha72c7ltfgfqef6nsc4zjpnj',
|
||||
'starsvaloper1jxv0u20scum4trha72c7ltfgfqef6nscdghxyx',
|
||||
'digvaloper1jxv0u20scum4trha72c7ltfgfqef6nsc4s577p',
|
||||
'bcnavaloper1jxv0u20scum4trha72c7ltfgfqef6nsc384wxf',
|
||||
'pbvaloper1jxv0u20scum4trha72c7ltfgfqef6nsc5nn6cf',
|
||||
'rizonvaloper1jxv0u20scum4trha72c7ltfgfqef6nsczn2l68',
|
||||
],
|
||||
islive: true,
|
||||
validator_address: null,
|
||||
mintInflation: 0,
|
||||
@ -314,7 +300,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
pingVals() {
|
||||
return this.list.filter(x => this.keys.includes(x.operator_address))
|
||||
return this.list.filter(x => x.description.identity === '6783E9F948541962')
|
||||
},
|
||||
list() {
|
||||
return this.validators.map(x => {
|
||||
|
@ -6,7 +6,7 @@
|
||||
<b-card-header>
|
||||
<b-card-title>Outstanding Rewards</b-card-title>
|
||||
<feather-icon
|
||||
v-b-modal.withdraw-commission-window
|
||||
v-b-modal.WithdrawCommission
|
||||
icon="MoreVerticalIcon"
|
||||
size="18"
|
||||
class="cursor-pointer"
|
||||
@ -76,7 +76,7 @@
|
||||
</b-card-body>
|
||||
<b-card-body class="pt-0">
|
||||
<b-button
|
||||
v-b-modal.withdraw-commission-window
|
||||
v-b-modal.WithdrawCommission
|
||||
block
|
||||
size="sm"
|
||||
variant="primary"
|
||||
@ -84,9 +84,11 @@
|
||||
Withdraw Commission
|
||||
</b-button>
|
||||
</b-card-body>
|
||||
<operation-withdraw-commission-component
|
||||
:validator-address="validator"
|
||||
<operation-modal
|
||||
type="WithdrawCommission"
|
||||
modal-id="WithdrawCommission"
|
||||
:address="address"
|
||||
:validator-address="validator"
|
||||
/>
|
||||
</b-card>
|
||||
</template>
|
||||
@ -98,7 +100,7 @@ import {
|
||||
import { sha256 } from '@cosmjs/crypto'
|
||||
import { toHex } from '@cosmjs/encoding'
|
||||
import { formatToken, numberWithCommas } from '@/libs/utils'
|
||||
import OperationWithdrawCommissionComponent from './OperationWithdrawCommissionComponent.vue'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -111,7 +113,7 @@ export default {
|
||||
BMedia,
|
||||
BMediaAside,
|
||||
BAvatar,
|
||||
OperationWithdrawCommissionComponent,
|
||||
OperationModal,
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
|
@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div class="d-flex flex-wrap">
|
||||
<b-button
|
||||
v-b-modal.delegate-window
|
||||
v-b-modal.operation-modal
|
||||
variant="primary"
|
||||
class="mr-25 mb-25"
|
||||
>
|
||||
@ -268,7 +268,10 @@
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
<operation-delegate-component :validator-address="validator.operator_address" />
|
||||
<operation-modal
|
||||
type="Delegate"
|
||||
:validator-address="validator.operator_address"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -281,10 +284,10 @@ import {
|
||||
percent, formatToken, StakingParameters, Validator, operatorAddressToAccount, consensusPubkeyToHexAddress, toDay, abbrMessage, abbrAddress,
|
||||
} from '@/libs/utils'
|
||||
import { keybase } from '@/libs/fetch'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
import StakingAddressComponent from './StakingAddressComponent.vue'
|
||||
import StakingCommissionComponent from './StakingCommissionComponent.vue'
|
||||
import StakingRewardComponent from './StakingRewardComponent.vue'
|
||||
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -300,7 +303,7 @@ export default {
|
||||
StakingAddressComponent,
|
||||
StakingCommissionComponent,
|
||||
StakingRewardComponent,
|
||||
OperationDelegateComponent,
|
||||
OperationModal,
|
||||
},
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
|
@ -39,26 +39,28 @@
|
||||
<b-card-title>Assets</b-card-title>
|
||||
<div>
|
||||
<b-button
|
||||
v-b-modal.transfer-window
|
||||
v-b-modal.operation-modal
|
||||
variant="primary"
|
||||
size="sm"
|
||||
class="mr-25"
|
||||
><feather-icon
|
||||
@click="setOperationModalType('Transfer')"
|
||||
>
|
||||
<feather-icon
|
||||
icon="SendIcon"
|
||||
class="d-md-none"
|
||||
/>
|
||||
<span class="d-none d-md-block">Transfer</span>
|
||||
/><small class="d-none d-md-block">Transfer</small>
|
||||
</b-button>
|
||||
<b-button
|
||||
v-b-modal.ibc-transfer-window
|
||||
v-b-modal.operation-modal
|
||||
variant="danger"
|
||||
size="sm"
|
||||
@click="setOperationModalType('IBCTransfer')"
|
||||
><feather-icon
|
||||
icon="SendIcon"
|
||||
class="d-md-none"
|
||||
/>
|
||||
<span class="d-none d-md-block">IBC Transfer
|
||||
</span></b-button>
|
||||
<span class="d-none d-md-block">IBC Transfer</span>
|
||||
</b-button>
|
||||
</div>
|
||||
</b-card-header>
|
||||
<b-card-body class="pl-0 pr-0">
|
||||
@ -160,10 +162,11 @@
|
||||
<b-card-title>Delegation</b-card-title>
|
||||
<div>
|
||||
<b-button
|
||||
v-b-modal.delegate-window
|
||||
v-b-modal.operation-modal
|
||||
variant="primary"
|
||||
size="sm"
|
||||
class="mr-25"
|
||||
@click="setOperationModalType('Delegate')"
|
||||
>
|
||||
<feather-icon
|
||||
icon="LogInIcon"
|
||||
@ -172,9 +175,10 @@
|
||||
</b-button>
|
||||
<b-button
|
||||
v-if="delegations"
|
||||
v-b-modal.withdraw-window
|
||||
v-b-modal.operation-modal
|
||||
variant="primary"
|
||||
size="sm"
|
||||
@click="setOperationModalType('Withdraw')"
|
||||
>
|
||||
<feather-icon
|
||||
icon="ShareIcon"
|
||||
@ -194,29 +198,29 @@
|
||||
size="sm"
|
||||
>
|
||||
<b-button
|
||||
v-b-modal.delegate-window
|
||||
v-b-modal.operation-modal
|
||||
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
|
||||
v-b-tooltip.hover.top="'Delegate'"
|
||||
variant="outline-primary"
|
||||
@click="selectValue(data.value)"
|
||||
@click="selectValue(data.value,'Delegate')"
|
||||
>
|
||||
<feather-icon icon="LogInIcon" />
|
||||
</b-button>
|
||||
<b-button
|
||||
v-b-modal.redelegate-window
|
||||
v-b-modal.operation-modal
|
||||
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
|
||||
v-b-tooltip.hover.top="'Redelegate'"
|
||||
variant="outline-primary"
|
||||
@click="selectValue(data.value)"
|
||||
@click="selectValue(data.value,'Redelegate')"
|
||||
>
|
||||
<feather-icon icon="ShuffleIcon" />
|
||||
</b-button>
|
||||
<b-button
|
||||
v-b-modal.unbond-window
|
||||
v-b-modal.operation-modal
|
||||
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
|
||||
v-b-tooltip.hover.top="'Unbond'"
|
||||
variant="outline-primary"
|
||||
@click="selectValue(data.value)"
|
||||
@click="selectValue(data.value,'Unbond')"
|
||||
>
|
||||
<feather-icon icon="LogOutIcon" />
|
||||
</b-button>
|
||||
@ -374,20 +378,10 @@
|
||||
<vue-qr :text="address" />
|
||||
</b-popover>
|
||||
|
||||
<operation-transfer-component :address="address" />
|
||||
<operation-transfer-2-component :address="address" />
|
||||
<operation-withdraw-component :address="address" />
|
||||
<operation-unbond-component
|
||||
<operation-modal
|
||||
:type="operationModalType"
|
||||
:address="address"
|
||||
:validator-address.sync="selectedValidator"
|
||||
/>
|
||||
<operation-delegate-component
|
||||
:address="address"
|
||||
:validator-address.sync="selectedValidator"
|
||||
/>
|
||||
<operation-redelegate-component
|
||||
:address="address"
|
||||
:validator-address.sync="selectedValidator"
|
||||
:validator-address="selectedValidator"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -410,13 +404,8 @@ import {
|
||||
} from '@/libs/utils'
|
||||
import { sha256 } from '@cosmjs/crypto'
|
||||
import { toHex } from '@cosmjs/encoding'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||
import OperationTransferComponent from './OperationTransferComponent.vue'
|
||||
import OperationWithdrawComponent from './OperationWithdrawComponent.vue'
|
||||
import OperationUnbondComponent from './OperationUnbondComponent.vue'
|
||||
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
||||
import OperationRedelegateComponent from './OperationRedelegateComponent.vue'
|
||||
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
||||
import ChartComponentDoughnut from './ChartComponentDoughnut.vue'
|
||||
|
||||
export default {
|
||||
@ -442,13 +431,8 @@ export default {
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
ToastificationContent,
|
||||
ObjectFieldComponent,
|
||||
OperationTransferComponent,
|
||||
OperationWithdrawComponent,
|
||||
OperationDelegateComponent,
|
||||
OperationRedelegateComponent,
|
||||
OperationUnbondComponent,
|
||||
OperationTransfer2Component,
|
||||
ChartComponentDoughnut,
|
||||
OperationModal,
|
||||
},
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
@ -472,6 +456,7 @@ export default {
|
||||
quotes: {},
|
||||
transactions: [],
|
||||
stakingParameters: {},
|
||||
operationModalType: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -662,8 +647,12 @@ export default {
|
||||
this.transactions = res
|
||||
})
|
||||
},
|
||||
selectValue(v) {
|
||||
selectValue(v, type) {
|
||||
this.selectedValidator = v
|
||||
this.setOperationModalType(type)
|
||||
},
|
||||
setOperationModalType(type) {
|
||||
this.operationModalType = type
|
||||
},
|
||||
formatHash: abbrAddress,
|
||||
formatDenom(v) {
|
||||
|
@ -153,15 +153,15 @@
|
||||
/>
|
||||
<b-dropdown-item
|
||||
v-if="balances[acc.addr]"
|
||||
v-b-modal.transfer-window
|
||||
@click="transfer(acc.addr)"
|
||||
v-b-modal.operation-modal
|
||||
@click="transfer('Transfer',acc.addr)"
|
||||
>
|
||||
<feather-icon icon="SendIcon" /> Transfer
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
v-if="balances[acc.addr]"
|
||||
v-b-modal.ibc-transfer-window
|
||||
@click="transfer(acc.addr)"
|
||||
v-b-modal.operation-modal
|
||||
@click="transfer('IBCTransfer',acc.addr)"
|
||||
>
|
||||
<feather-icon icon="SendIcon" /> IBC Transfer
|
||||
</b-dropdown-item>
|
||||
@ -265,10 +265,10 @@
|
||||
Connect Wallet
|
||||
</b-card>
|
||||
</router-link>
|
||||
<operation-transfer-component
|
||||
:address.sync="selectedAddress"
|
||||
<operation-modal
|
||||
:type="operationModalType"
|
||||
:address="selectedAddress"
|
||||
/>
|
||||
<operation-transfer-2-component :address="selectedAddress" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -287,8 +287,7 @@ import {
|
||||
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
||||
import AppCollapse from '@core/components/app-collapse/AppCollapse.vue'
|
||||
import AppCollapseItem from '@core/components/app-collapse/AppCollapseItem.vue'
|
||||
import OperationTransferComponent from './OperationTransferComponent.vue'
|
||||
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
import ChartComponentDoughnut from './ChartComponentDoughnut.vue'
|
||||
import EchartScatter from './components/charts/EchartScatter.vue'
|
||||
|
||||
@ -309,14 +308,13 @@ export default {
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
VBTooltip,
|
||||
FeatherIcon,
|
||||
OperationTransferComponent,
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
ToastificationContent,
|
||||
OperationTransfer2Component,
|
||||
ChartComponentDoughnut,
|
||||
AppCollapse,
|
||||
AppCollapseItem,
|
||||
EchartScatter,
|
||||
OperationModal,
|
||||
},
|
||||
directives: {
|
||||
'b-tooltip': VBTooltip,
|
||||
@ -335,6 +333,7 @@ export default {
|
||||
delegations: {},
|
||||
ibcDenom: {},
|
||||
quotes: {},
|
||||
operationModalType: '',
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
@ -533,7 +532,8 @@ export default {
|
||||
this.currency2 = c
|
||||
this.currency = getUserCurrencySign()
|
||||
},
|
||||
transfer(addr) {
|
||||
transfer(type, addr) {
|
||||
this.operationModalType = type
|
||||
this.selectedAddress = addr
|
||||
},
|
||||
completeAdd() {
|
||||
|
@ -42,29 +42,29 @@
|
||||
size="sm"
|
||||
>
|
||||
<b-button
|
||||
v-b-modal.delegate-window
|
||||
v-b-modal.operation-modal
|
||||
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
|
||||
v-b-tooltip.hover.top="'Delegate'"
|
||||
variant="outline-primary"
|
||||
@click="selectValue(data.item)"
|
||||
@click="selectValue('Delegate',data.item)"
|
||||
>
|
||||
<feather-icon icon="LogInIcon" />
|
||||
</b-button>
|
||||
<b-button
|
||||
v-b-modal.redelegate-window
|
||||
v-b-modal.operation-modal
|
||||
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
|
||||
v-b-tooltip.hover.top="'Redelegate'"
|
||||
variant="outline-primary"
|
||||
@click="selectValue(data.item)"
|
||||
@click="selectValue('Redelegate',data.item)"
|
||||
>
|
||||
<feather-icon icon="ShuffleIcon" />
|
||||
</b-button>
|
||||
<b-button
|
||||
v-b-modal.unbond-window
|
||||
v-b-modal.operation-modal
|
||||
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
|
||||
v-b-tooltip.hover.top="'Unbond'"
|
||||
variant="outline-primary"
|
||||
@click="selectValue(data.item)"
|
||||
@click="selectValue('Unbond',data.item)"
|
||||
>
|
||||
<feather-icon icon="LogOutIcon" />
|
||||
</b-button>
|
||||
@ -74,18 +74,10 @@
|
||||
</b-card>
|
||||
|
||||
<!--- not completed--->
|
||||
<operation-withdraw-component :address="address" />
|
||||
<operation-unbond-component
|
||||
<operation-modal
|
||||
:type="operationModalType"
|
||||
:address="address"
|
||||
:validator-address.sync="selectedValidator"
|
||||
/>
|
||||
<operation-delegate-component
|
||||
:address="address"
|
||||
:validator-address.sync="selectedValidator"
|
||||
/>
|
||||
<operation-redelegate-component
|
||||
:address="address"
|
||||
:validator-address.sync="selectedValidator"
|
||||
:validator-address="selectedValidator"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -99,11 +91,7 @@ import {
|
||||
formatToken, getCachedValidators, getLocalAccounts, getLocalChains, tokenFormatter,
|
||||
} from '@/libs/utils'
|
||||
import FeatherIcon from '@/@core/components/feather-icon/FeatherIcon.vue'
|
||||
|
||||
import OperationWithdrawComponent from './OperationWithdrawComponent.vue'
|
||||
import OperationUnbondComponent from './OperationUnbondComponent.vue'
|
||||
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
||||
import OperationRedelegateComponent from './OperationRedelegateComponent.vue'
|
||||
import OperationModal from '@/views/components/OperationModal/index.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -113,11 +101,7 @@ export default {
|
||||
BTable,
|
||||
BCard,
|
||||
FeatherIcon,
|
||||
|
||||
OperationWithdrawComponent,
|
||||
OperationDelegateComponent,
|
||||
OperationRedelegateComponent,
|
||||
OperationUnbondComponent,
|
||||
OperationModal,
|
||||
},
|
||||
directives: {
|
||||
'b-tooltip': VBTooltip,
|
||||
@ -153,6 +137,7 @@ export default {
|
||||
accounts: [],
|
||||
delegations: [],
|
||||
rewards: {},
|
||||
operationModalType: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -200,7 +185,8 @@ export default {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
selectValue(v) {
|
||||
selectValue(type, v) {
|
||||
this.operationModalType = type
|
||||
this.address = v.delegator_address
|
||||
this.selectedValidator = v.validator.validator
|
||||
return v
|
||||
|
214
src/views/components/OperationModal/TransactionResult.vue
Normal file
214
src/views/components/OperationModal/TransactionResult.vue
Normal file
@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="false"
|
||||
class="board "
|
||||
>
|
||||
<div class="data">
|
||||
<div class="board-row">
|
||||
<div class="key">
|
||||
AMOUNT
|
||||
</div>
|
||||
<div class="value">
|
||||
1,233,000 USDT
|
||||
</div>
|
||||
</div>
|
||||
<div class="board-row">
|
||||
<div class="key">
|
||||
BRIDGE FEE
|
||||
</div>
|
||||
<div class="value">
|
||||
3,000 USDT
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sum">
|
||||
<div class="key">
|
||||
TRANSFER AMOUNT
|
||||
</div>
|
||||
<div class="value">
|
||||
1,213,000 USDT
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
v-if="succeed"
|
||||
class="result-text mt-1 text-success"
|
||||
>
|
||||
Congratulations! Transfer completed successfully.
|
||||
</p>
|
||||
<p
|
||||
v-else-if="error"
|
||||
class="result-text mt-1 text-danger"
|
||||
>
|
||||
{{ error }}
|
||||
</p>
|
||||
<p
|
||||
v-else
|
||||
class="result-text mt-1 text-primary"
|
||||
>
|
||||
Processing...
|
||||
</p>
|
||||
|
||||
<div class="status">
|
||||
<!-- <b-progress
|
||||
:value="100"
|
||||
:variant="progressColor"
|
||||
:animated="isLoading"
|
||||
/> -->
|
||||
<b-progress :animated="isLoading">
|
||||
<b-progress-bar
|
||||
variant="success"
|
||||
:value="progresBar[0]"
|
||||
/>
|
||||
<b-progress-bar
|
||||
variant="danger"
|
||||
:value="progresBar[1]"
|
||||
/>
|
||||
<b-progress-bar
|
||||
variant="info"
|
||||
:value="progresBar[2]"
|
||||
/>
|
||||
</b-progress>
|
||||
<div class="status-text">
|
||||
<span v-if="hash">SUBMITED</span>
|
||||
<span v-if="succeed">COMPLETED</span>
|
||||
<span v-if="error">FAILED</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="link">
|
||||
<router-link
|
||||
to="/"
|
||||
>
|
||||
View details
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BProgress, BProgressBar } from 'bootstrap-vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BProgress,
|
||||
BProgressBar,
|
||||
},
|
||||
props: {
|
||||
hash: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
succeed: false,
|
||||
error: '',
|
||||
checkTimes: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
progresBar() {
|
||||
// success: [100, 0, 0]
|
||||
// fail: [50, 50, 0]
|
||||
// pending: [0, 0, 100]
|
||||
if (!this.hash) {
|
||||
return [0, 0, 100]
|
||||
}
|
||||
if (this.succeed) {
|
||||
return [100, 0, 0]
|
||||
}
|
||||
return [50, 0, 50]
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.timer = setInterval(this.trace, 6000)
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.timer)
|
||||
},
|
||||
methods: {
|
||||
trace() {
|
||||
if (this.hash) {
|
||||
this.error = null
|
||||
this.$http.getTxs(this.hash).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.succeed = true
|
||||
clearInterval(this.timer)
|
||||
window.location.reload()
|
||||
} else if (res.code !== 3) { // code 3 is tx unconfirmed(not founded).
|
||||
this.error = res.raw_log
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
}, () => {
|
||||
// error statement
|
||||
this.checkTimes += 1
|
||||
if (this.checkTimes > 5) {
|
||||
clearInterval(this.timer)
|
||||
this.error = 'Timeout'
|
||||
}
|
||||
}).catch(e => {
|
||||
this.error = e
|
||||
clearInterval(this.timer)
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.board {
|
||||
background: #f8f8f8;
|
||||
border-radius: 8px;
|
||||
padding: 0 12px;
|
||||
margin: 35px 0;
|
||||
.data {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #607d8b;
|
||||
}
|
||||
.board-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 16px;
|
||||
line-height: 34px;
|
||||
.key {
|
||||
color: #666;
|
||||
}
|
||||
.value {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.sum {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding: 15px 0;
|
||||
}
|
||||
}
|
||||
.result-text {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
.status {
|
||||
margin-top: 30px;
|
||||
.status-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.link {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
a {
|
||||
text-decoration: underline;
|
||||
color: var(--purple)
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
240
src/views/components/OperationModal/components/Delegate.vue
Normal file
240
src/views/components/OperationModal/components/Delegate.vue
Normal file
@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Delegator"
|
||||
label-for="Delegator"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Delegator"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="selectedAddress"
|
||||
readonly
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Validator"
|
||||
>
|
||||
<b-form-group
|
||||
label="Validator"
|
||||
label-for="validator"
|
||||
>
|
||||
<v-select
|
||||
v-model="selectedValidator"
|
||||
:options="valOptions"
|
||||
:reduce="val => val.value"
|
||||
placeholder="Select a validator"
|
||||
:readonly="validatorAddress"
|
||||
:selectable="(v) => v.value"
|
||||
/>
|
||||
</b-form-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Available Token"
|
||||
label-for="Token"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Token"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="token"
|
||||
text-field="label"
|
||||
>
|
||||
<b-form-select-option
|
||||
v-for="x in balanceOptions"
|
||||
:key="x.denom"
|
||||
:value="x.denom"
|
||||
>
|
||||
{{ format(x) }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Amount"
|
||||
label-for="Amount"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|regex:^([0-9\.]+)$"
|
||||
name="amount"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-form-input
|
||||
id="Amount"
|
||||
v-model="amount"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a number"
|
||||
type="number"
|
||||
/>
|
||||
<b-input-group-append is-text>
|
||||
{{ printDenom() }}
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BFormInput, BFormGroup, BFormSelect, BFormSelectOption,
|
||||
BInputGroupAppend,
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, formatTokenDenom, getUnitAmount,
|
||||
} from '@/libs/utils'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
BFormSelect,
|
||||
BFormSelectOption,
|
||||
vSelect,
|
||||
BInputGroupAppend,
|
||||
|
||||
ValidationProvider,
|
||||
},
|
||||
props: {
|
||||
validatorAddress: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
balance: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedAddress: this.address,
|
||||
availableAddress: [],
|
||||
validators: [],
|
||||
unbundValidators: [],
|
||||
selectedValidator: this.validatorAddress,
|
||||
token: '',
|
||||
amount: null,
|
||||
selectedChain: '',
|
||||
IBCDenom: {},
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
valOptions() {
|
||||
let options = []
|
||||
const vals = this.validators.map(x => ({ value: x.operator_address, label: `${x.description.moniker} (${Number(x.commission.rate) * 100}%)` }))
|
||||
if (vals.length > 0) {
|
||||
options.push({ value: null, label: '=== ACTIVE VALIDATORS ===' })
|
||||
options = options.concat(vals)
|
||||
}
|
||||
const unbunded = this.unbundValidators.map(x => ({ value: x.operator_address, label: `* ${x.description.moniker} (${Number(x.commission.rate) * 100}%)` }))
|
||||
if (unbunded.length > 0) {
|
||||
options.push({ value: null, label: '=== INACTIVE VALIDATORS ===', disabled: true })
|
||||
options = options.concat(unbunded)
|
||||
}
|
||||
return options
|
||||
},
|
||||
balanceOptions() {
|
||||
return this.setupBalance()
|
||||
},
|
||||
msg() {
|
||||
return [{
|
||||
typeUrl: '/cosmos.staking.v1beta1.MsgDelegate',
|
||||
value: {
|
||||
delegatorAddress: this.selectedAddress,
|
||||
validatorAddress: this.selectedValidator,
|
||||
amount: {
|
||||
amount: getUnitAmount(this.amount, this.token),
|
||||
denom: this.token,
|
||||
},
|
||||
},
|
||||
}]
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Delegate Token',
|
||||
historyName: 'delegate',
|
||||
})
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.$http.getValidatorList().then(v => {
|
||||
this.validators = v
|
||||
})
|
||||
this.$http.getValidatorUnbondedList().then(v => {
|
||||
this.unbundValidators = v
|
||||
})
|
||||
},
|
||||
setupBalance() {
|
||||
if (this.balance && this.balance.length > 0) {
|
||||
this.token = this.balance[0].denom
|
||||
return this.balance
|
||||
}
|
||||
return []
|
||||
},
|
||||
printDenom() {
|
||||
return formatTokenDenom(this.token)
|
||||
},
|
||||
format(v) {
|
||||
return formatToken(v, this.IBCDenom, 6)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
194
src/views/components/OperationModal/components/GovDeposit.vue
Normal file
194
src/views/components/OperationModal/components/GovDeposit.vue
Normal file
@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<h4>{{ proposalId }}. {{ proposalTitle }}</h4>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Depositor"
|
||||
label-for="Voter"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Voter"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="address"
|
||||
readonly
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Available Token"
|
||||
label-for="Token"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Token"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="token"
|
||||
>
|
||||
<b-form-select-option
|
||||
v-for="item in balanceOptions"
|
||||
:key="item.denom"
|
||||
:value="item.denom"
|
||||
>
|
||||
{{ format(item) }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Amount"
|
||||
label-for="Amount"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|regex:^([0-9\.]+)$"
|
||||
name="amount"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
id="Amount"
|
||||
v-model="amount"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a number"
|
||||
type="number"
|
||||
/>
|
||||
<b-input-group-append is-text>
|
||||
{{ printDenom() }}
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BFormInput, BFormGroup, BFormSelect,
|
||||
BInputGroupAppend, BFormSelectOption,
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, formatTokenDenom, getUnitAmount,
|
||||
} from '@/libs/utils'
|
||||
|
||||
export default {
|
||||
name: 'DepositDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
BFormSelect,
|
||||
BInputGroupAppend,
|
||||
BFormSelectOption,
|
||||
ValidationProvider,
|
||||
},
|
||||
props: {
|
||||
proposalId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
proposalTitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
balance: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
token: null,
|
||||
amount: '',
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
msg() {
|
||||
return [{
|
||||
typeUrl: '/cosmos.gov.v1beta1.MsgDeposit',
|
||||
value: {
|
||||
depositor: this.address,
|
||||
proposalId: String(this.proposalId),
|
||||
amount: [
|
||||
{
|
||||
amount: getUnitAmount(this.amount, this.token),
|
||||
denom: this.token,
|
||||
},
|
||||
],
|
||||
},
|
||||
}]
|
||||
},
|
||||
balanceOptions() {
|
||||
return this.setupBalance()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Deposit',
|
||||
historyName: 'deposit',
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
printDenom() {
|
||||
return formatTokenDenom(this.token)
|
||||
},
|
||||
format(v) {
|
||||
return formatToken(v)
|
||||
},
|
||||
setupBalance() {
|
||||
if (this.balance && this.balance.length > 0) {
|
||||
this.token = this.balance[0].denom
|
||||
return this.balance
|
||||
}
|
||||
return []
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@core/scss/vue/libs/vue-select.scss';
|
||||
</style>
|
307
src/views/components/OperationModal/components/IBCTransfer.vue
Normal file
307
src/views/components/OperationModal/components/IBCTransfer.vue
Normal file
@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Sender"
|
||||
label-for="Account"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
:value="address"
|
||||
readonly
|
||||
/>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Available Token"
|
||||
label-for="Token"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Token"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="token"
|
||||
@change="tokenChange"
|
||||
>
|
||||
<template #first>
|
||||
<b-form-select-option
|
||||
value=""
|
||||
>
|
||||
-- Please select a token --
|
||||
</b-form-select-option>
|
||||
</template>
|
||||
<b-form-select-option
|
||||
v-for="item in balance"
|
||||
:key="item.denom"
|
||||
:value="item.denom"
|
||||
>
|
||||
{{ format(item) }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Amount"
|
||||
label-for="Amount"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|regex:^([0-9\.]+)$"
|
||||
name="amount"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
id="Amount"
|
||||
v-model="amount"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a number"
|
||||
type="number"
|
||||
/>
|
||||
<b-input-group-append is-text>
|
||||
{{ printDenom() }}
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
:label="`Destination: ${targetChainId}`"
|
||||
label-for="destination"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="destination"
|
||||
>
|
||||
<v-select
|
||||
v-model="destination"
|
||||
name="destination"
|
||||
:options="destinationOptions"
|
||||
placeholder="Select a channel"
|
||||
@input="onChannelChange()"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Recipient"
|
||||
label-for="Recipient"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="recipient"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
id="Recipient"
|
||||
v-model="recipient"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a destination address"
|
||||
/>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BInputGroupAppend, BFormInput, BFormGroup, BFormSelect, BFormSelectOption,
|
||||
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, formatTokenDenom, getUnitAmount,
|
||||
} from '@/libs/utils'
|
||||
import vSelect from 'vue-select'
|
||||
import { coin } from '@cosmjs/amino'
|
||||
import dayjs from 'dayjs'
|
||||
import { toHex } from '@cosmjs/encoding'
|
||||
import { sha256 } from '@cosmjs/crypto'
|
||||
|
||||
export default {
|
||||
name: 'TransforDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BInputGroupAppend,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
BFormSelect,
|
||||
BFormSelectOption,
|
||||
vSelect,
|
||||
|
||||
ValidationProvider,
|
||||
},
|
||||
props: {
|
||||
address: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
balance: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
targetChainId: '',
|
||||
token: '',
|
||||
amount: null,
|
||||
recipient: null,
|
||||
IBCDenom: {},
|
||||
paths: {},
|
||||
destination: {},
|
||||
channels: [],
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
destinationOptions() {
|
||||
if (!this.token && this.token === '') return []
|
||||
const options = this.channels.map(x => ({ port_id: x.port_id, channel_id: x.channel_id, label: `${x.chain_id ? x.chain_id : ''} ${x.port_id}/${x.channel_id}` }))
|
||||
if (this.token.startsWith('ibc/')) {
|
||||
const query = this.paths[this.token]
|
||||
return query ? options.filter(x => x.channel_id === query.channel_id) : options
|
||||
}
|
||||
return options
|
||||
},
|
||||
|
||||
msg() {
|
||||
const timeout = dayjs().add(4, 'hour')
|
||||
return [
|
||||
{
|
||||
typeUrl: '/ibc.applications.transfer.v1.MsgTransfer',
|
||||
value: {
|
||||
sourcePort: this.destination.port_id,
|
||||
sourceChannel: this.destination.channel_id,
|
||||
token: coin(Number(getUnitAmount(this.amount, this.token)), this.token),
|
||||
sender: this.address,
|
||||
receiver: this.recipient,
|
||||
timeoutTimestamp: String(timeout.utc().valueOf() * 1000000),
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
balanceOptions() {
|
||||
return this.setupBalance()
|
||||
},
|
||||
selectedChain() {
|
||||
return this.$store.state.chains.selected
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'IBC Transfer Tokens',
|
||||
historyName: 'transfer',
|
||||
})
|
||||
this.setActionName()
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.destination = null
|
||||
this.channels = []
|
||||
this.token = ''
|
||||
this.targetChainId = ''
|
||||
if (this.address) {
|
||||
this.$http.getAllIBCDenoms(this.selectedChain).then(x => {
|
||||
x.denom_traces.forEach(trace => {
|
||||
const hash = toHex(sha256(new TextEncoder().encode(`${trace.path}/${trace.base_denom}`)))
|
||||
const ibcDenom = `ibc/${hash.toUpperCase()}`
|
||||
// add base_denom to cache
|
||||
this.$set(this.IBCDenom, ibcDenom, trace.base_denom)
|
||||
// store channel/part for ibc denoms
|
||||
const path = trace.path.split('/')
|
||||
if (path.length >= 2) {
|
||||
this.paths[ibcDenom] = {
|
||||
channel_id: path[path.length - 1],
|
||||
port_id: path[path.length - 2],
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.$http.getIBCChannels(this.selectedChain, null).then(ret => {
|
||||
const chans = ret.channels.filter(x => x.state === 'STATE_OPEN').map(x => ({ channel_id: x.channel_id, port_id: x.port_id }))
|
||||
this.$set(this, 'channels', chans)
|
||||
})
|
||||
}
|
||||
},
|
||||
setupBalance() {
|
||||
if (this.balance && this.balance.length > 0) {
|
||||
this.token = this.balance[0].denom
|
||||
return this.balance
|
||||
}
|
||||
return []
|
||||
},
|
||||
tokenChange() {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
this.destination = this.destinationOptions[0]
|
||||
this.recipient = null
|
||||
this.setActionName()
|
||||
this.onChannelChange()
|
||||
},
|
||||
|
||||
setActionName() {
|
||||
this.$emit('update', {
|
||||
actionName: this.token.startsWith('ibc') ? 'Withdraw' : 'Deposit',
|
||||
})
|
||||
},
|
||||
|
||||
format(v) {
|
||||
return formatToken(v, this.IBCDenom)
|
||||
},
|
||||
printDenom() {
|
||||
return formatTokenDenom(this.IBCDenom[this.token] || this.token)
|
||||
},
|
||||
onChannelChange() {
|
||||
this.$http.getIBCChannelClientState(this.destination.channel_id, this.destination.port_id, this.selectedChain).then(cs => {
|
||||
this.targetChainId = cs.identified_client_state.client_state.chain_id
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import '@core/scss/vue/libs/vue-select.scss';
|
||||
</style>
|
239
src/views/components/OperationModal/components/Redelegate.vue
Normal file
239
src/views/components/OperationModal/components/Redelegate.vue
Normal file
@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Delegator"
|
||||
label-for="Account"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Delegator"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="address"
|
||||
readonly
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="From Validator"
|
||||
label-for="validator"
|
||||
>
|
||||
<v-select
|
||||
:value="validatorAddress"
|
||||
:options="valOptions"
|
||||
:reduce="val => val.value"
|
||||
placeholder="Select a validator"
|
||||
:disabled="true"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Current Delegation"
|
||||
label-for="Token"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Token"
|
||||
>
|
||||
<v-select
|
||||
v-model="token"
|
||||
:options="tokenOptions"
|
||||
:reduce="token => token.value"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="To Validator"
|
||||
label-for="validator"
|
||||
>
|
||||
<v-select
|
||||
v-model="toValidator"
|
||||
:options="valOptions"
|
||||
:reduce="val => val.value"
|
||||
placeholder="Select a validator"
|
||||
:selectable="(v) => v.value"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Amount"
|
||||
label-for="Amount"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|regex:^([0-9\.]+)$"
|
||||
name="amount"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-form-input
|
||||
id="Amount"
|
||||
v-model="amount"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a number"
|
||||
type="number"
|
||||
/>
|
||||
<b-input-group-append is-text>
|
||||
{{ printDenom() }}
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BFormInput, BFormGroup,
|
||||
BInputGroupAppend,
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, formatTokenDenom, getUnitAmount,
|
||||
} from '@/libs/utils'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
export default {
|
||||
name: 'Redelegate',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
vSelect,
|
||||
BInputGroupAppend,
|
||||
ValidationProvider,
|
||||
},
|
||||
props: {
|
||||
validatorAddress: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedAddress: this.address,
|
||||
unbundValidators: [],
|
||||
validators: [],
|
||||
toValidator: null,
|
||||
token: '',
|
||||
amount: null,
|
||||
delegations: [],
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
valOptions() {
|
||||
let options = []
|
||||
const vals = this.validators.map(x => ({ value: x.operator_address, label: `${x.description.moniker} (${Number(x.commission.rate) * 100}%)` }))
|
||||
if (vals.length > 0) {
|
||||
options.push({ value: null, label: '=== ACTIVE VALIDATORS ===' })
|
||||
options = options.concat(vals)
|
||||
}
|
||||
const unbunded = this.unbundValidators.map(x => ({ value: x.operator_address, label: `* ${x.description.moniker} (${Number(x.commission.rate) * 100}%)` }))
|
||||
if (unbunded.length > 0) {
|
||||
options.push({ value: null, label: '=== INACTIVE VALIDATORS ===', disabled: true })
|
||||
options = options.concat(unbunded)
|
||||
}
|
||||
return options
|
||||
},
|
||||
tokenOptions() {
|
||||
if (!this.delegations) return []
|
||||
return this.delegations.filter(x => x.delegation.validator_address === this.validatorAddress).map(x => ({ value: x.balance.denom, label: formatToken(x.balance) }))
|
||||
},
|
||||
msg() {
|
||||
return [{
|
||||
typeUrl: '/cosmos.staking.v1beta1.MsgBeginRedelegate',
|
||||
value: {
|
||||
delegatorAddress: this.address,
|
||||
validatorSrcAddress: this.validatorAddress,
|
||||
validatorDstAddress: this.toValidator,
|
||||
amount: {
|
||||
amount: getUnitAmount(this.amount, this.token),
|
||||
denom: this.token,
|
||||
},
|
||||
},
|
||||
}]
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Redelegate Token',
|
||||
historyName: 'redelegate',
|
||||
})
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.$http.getValidatorList().then(v => {
|
||||
this.validators = v
|
||||
})
|
||||
this.$http.getValidatorUnbondedList().then(v => {
|
||||
this.unbundValidators = v
|
||||
})
|
||||
this.$http.getStakingDelegations(this.address).then(res => {
|
||||
this.delegations = res.delegation_responses
|
||||
this.delegations.forEach(x => {
|
||||
if (x.delegation.validator_address === this.validatorAddress) {
|
||||
this.token = x.balance.denom
|
||||
this.$emit('update', {
|
||||
feeDenom: x.balance.denom,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
format(v) {
|
||||
return formatToken(v)
|
||||
},
|
||||
printDenom() {
|
||||
return formatTokenDenom(this.token)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import '@core/scss/vue/libs/vue-select.scss';
|
||||
</style>
|
204
src/views/components/OperationModal/components/Transfer.vue
Normal file
204
src/views/components/OperationModal/components/Transfer.vue
Normal file
@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Sender"
|
||||
label-for="sender"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
|
||||
<b-form-input
|
||||
name="sender"
|
||||
:value="address"
|
||||
readonly
|
||||
/>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Recipient"
|
||||
label-for="Recipient"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="recipient"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
id="Recipient"
|
||||
v-model="recipient"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
/>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Available Token"
|
||||
label-for="Token"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Token"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="token"
|
||||
>
|
||||
<b-form-select-option
|
||||
v-for="item in balanceOptions"
|
||||
:key="item.denom"
|
||||
:value="item.denom"
|
||||
>
|
||||
{{ format(item) }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Amount"
|
||||
label-for="Amount"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|regex:^([0-9\.]+)$"
|
||||
name="amount"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
id="Amount"
|
||||
v-model="amount"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a number"
|
||||
type="number"
|
||||
/>
|
||||
<b-input-group-append is-text>
|
||||
{{ printDenom() }}
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BInputGroupAppend, BFormInput, BFormGroup, BFormSelect, BFormSelectOption,
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, formatTokenDenom, getUnitAmount,
|
||||
} from '@/libs/utils'
|
||||
|
||||
export default {
|
||||
name: 'TransforDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BInputGroupAppend,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
BFormSelect,
|
||||
BFormSelectOption,
|
||||
ValidationProvider,
|
||||
|
||||
},
|
||||
props: {
|
||||
address: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
balance: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
token: '',
|
||||
amount: null,
|
||||
recipient: '',
|
||||
IBCDenom: {},
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
msg() {
|
||||
return [
|
||||
{
|
||||
typeUrl: '/cosmos.bank.v1beta1.MsgSend',
|
||||
value: {
|
||||
fromAddress: this.address,
|
||||
toAddress: this.recipient,
|
||||
amount: [
|
||||
{
|
||||
amount: getUnitAmount(this.amount, this.token),
|
||||
denom: this.token,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
balanceOptions() {
|
||||
return this.setupBalance()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Transfer Tokens',
|
||||
historyName: 'send',
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
setupBalance() {
|
||||
if (this.balance && this.balance.length > 0) {
|
||||
this.token = this.balance[0].denom
|
||||
return this.balance
|
||||
}
|
||||
return []
|
||||
},
|
||||
format(v) {
|
||||
return formatToken(v, this.IBCDenom)
|
||||
},
|
||||
printDenom() {
|
||||
return formatTokenDenom(this.IBCDenom[this.token] || this.token)
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
197
src/views/components/OperationModal/components/Unbond.vue
Normal file
197
src/views/components/OperationModal/components/Unbond.vue
Normal file
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Delegator"
|
||||
label-for="Account"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="address"
|
||||
readonly
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Validator"
|
||||
label-for="validator"
|
||||
>
|
||||
<v-select
|
||||
:value="validatorAddress"
|
||||
:options="valOptions"
|
||||
:reduce="val => val.value"
|
||||
placeholder="Select a validator"
|
||||
:disabled="true"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Current Delegation"
|
||||
label-for="Token"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Token"
|
||||
>
|
||||
<v-select
|
||||
v-model="token"
|
||||
:options="tokenOptions"
|
||||
:reduce="token => token.value"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Amount"
|
||||
label-for="Amount"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|regex:^([0-9\.]+)$"
|
||||
name="amount"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-form-input
|
||||
id="Amount"
|
||||
v-model="amount"
|
||||
:state="errors.length > 0 ? false:null"
|
||||
placeholder="Input a number"
|
||||
type="number"
|
||||
/>
|
||||
<b-input-group-append is-text>
|
||||
{{ printDenom() }}
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BFormInput, BFormGroup, BInputGroupAppend,
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, formatTokenDenom, getUnitAmount,
|
||||
} from '@/libs/utils'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
export default {
|
||||
name: 'UnbondDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
vSelect,
|
||||
BInputGroupAppend,
|
||||
ValidationProvider,
|
||||
},
|
||||
props: {
|
||||
validatorAddress: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
validators: [],
|
||||
token: '',
|
||||
amount: null,
|
||||
delegations: [],
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
valOptions() {
|
||||
return this.validators.map(x => ({ value: x.operator_address, label: `${x.description.moniker} (${Number(x.commission.rate) * 100}%)` }))
|
||||
},
|
||||
tokenOptions() {
|
||||
if (!this.delegations) return []
|
||||
return this.delegations.filter(x => x.delegation.validator_address === this.validatorAddress).map(x => ({ value: x.balance.denom, label: formatToken(x.balance) }))
|
||||
},
|
||||
msg() {
|
||||
return [{
|
||||
typeUrl: '/cosmos.staking.v1beta1.MsgUndelegate',
|
||||
value: {
|
||||
delegatorAddress: this.address,
|
||||
validatorAddress: this.validatorAddress,
|
||||
amount: {
|
||||
amount: getUnitAmount(this.amount, this.token),
|
||||
denom: this.token,
|
||||
},
|
||||
},
|
||||
}]
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Unbond Token',
|
||||
historyName: 'unbond',
|
||||
})
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadData() {
|
||||
if (this.address) {
|
||||
this.$http.getValidatorList().then(v => {
|
||||
this.validators = v
|
||||
})
|
||||
}
|
||||
this.$http.getStakingDelegations(this.address).then(res => {
|
||||
this.delegations = res.delegation_responses
|
||||
this.delegations.forEach(x => {
|
||||
if (x.delegation.validator_address === this.validatorAddress) {
|
||||
this.token = x.balance.denom
|
||||
this.$emit('update', {
|
||||
feeDenom: x.balance.denom,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
printDenom() {
|
||||
return formatTokenDenom(this.token)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import '@core/scss/vue/libs/vue-select.scss';
|
||||
</style>
|
166
src/views/components/OperationModal/components/Vote.vue
Normal file
166
src/views/components/OperationModal/components/Vote.vue
Normal file
@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<h4>{{ proposalId }}. {{ proposalTitle }}</h4>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Voter"
|
||||
label-for="Account"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="Voter"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="address"
|
||||
readonly
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Option"
|
||||
label-for="option"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
rules="required"
|
||||
name="option"
|
||||
>
|
||||
<div class="demo-inline-spacing">
|
||||
|
||||
<b-form-radio
|
||||
v-model="option"
|
||||
name="option"
|
||||
value="1"
|
||||
class="custom-control-success"
|
||||
>
|
||||
Yes
|
||||
</b-form-radio>
|
||||
<b-form-radio
|
||||
v-model="option"
|
||||
name="option"
|
||||
value="3"
|
||||
class="custom-control-warning"
|
||||
>
|
||||
No
|
||||
</b-form-radio>
|
||||
<b-form-radio
|
||||
v-model="option"
|
||||
name="option"
|
||||
value="4"
|
||||
class="custom-control-danger"
|
||||
>
|
||||
No With Veto
|
||||
</b-form-radio>
|
||||
<b-form-radio
|
||||
v-model="option"
|
||||
name="option"
|
||||
value="2"
|
||||
class="custom-control-secondary"
|
||||
>
|
||||
Abstain
|
||||
</b-form-radio>
|
||||
</div>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider } from 'vee-validate'
|
||||
import {
|
||||
BRow, BCol, BFormGroup, BFormInput,
|
||||
BFormRadio,
|
||||
} from 'bootstrap-vue'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken,
|
||||
} from '@/libs/utils'
|
||||
|
||||
export default {
|
||||
name: 'VoteDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BFormGroup,
|
||||
BFormRadio,
|
||||
ValidationProvider,
|
||||
BFormInput,
|
||||
},
|
||||
props: {
|
||||
proposalId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
proposalTitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
option: null,
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
msg() {
|
||||
return [{
|
||||
typeUrl: '/cosmos.gov.v1beta1.MsgVote',
|
||||
value: {
|
||||
voter: this.address,
|
||||
proposalId: this.proposalId,
|
||||
option: Number(this.option),
|
||||
},
|
||||
}]
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Vote',
|
||||
historyName: 'vote',
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
||||
format(v) {
|
||||
return formatToken(v)
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@core/scss/vue/libs/vue-select.scss';
|
||||
</style>
|
80
src/views/components/OperationModal/components/Withdraw.vue
Normal file
80
src/views/components/OperationModal/components/Withdraw.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Sender"
|
||||
label-for="Account"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
:value="address"
|
||||
readonly
|
||||
/>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
BRow, BCol, BInputGroup, BFormInput, BFormGroup,
|
||||
} from 'bootstrap-vue'
|
||||
|
||||
export default {
|
||||
name: 'WithdrawDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
},
|
||||
props: {
|
||||
address: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
account: [],
|
||||
balance: [],
|
||||
delegations: [],
|
||||
feeDenom: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
msg() {
|
||||
const txMsgs = []
|
||||
this.delegations.forEach(i => {
|
||||
txMsgs.push({
|
||||
typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward',
|
||||
value: {
|
||||
delegatorAddress: this.address,
|
||||
validatorAddress: i.delegation.validator_address,
|
||||
},
|
||||
})
|
||||
})
|
||||
return txMsgs
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Withdraw Rewards',
|
||||
historyName: 'withdraw',
|
||||
})
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadData() {
|
||||
this.$http.getStakingDelegations(this.address).then(res => {
|
||||
this.delegations = res.delegation_responses
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-form-group
|
||||
label="Sender"
|
||||
label-for="Account"
|
||||
>
|
||||
<b-input-group class="mb-25">
|
||||
<b-form-input
|
||||
:value="address"
|
||||
readonly
|
||||
/>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
} from 'bootstrap-vue'
|
||||
|
||||
export default {
|
||||
name: 'WithdrawCommissionDialogue',
|
||||
components: {
|
||||
BRow,
|
||||
BCol,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
|
||||
},
|
||||
props: {
|
||||
address: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
validatorAddress: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
msg() {
|
||||
return [
|
||||
{
|
||||
typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward',
|
||||
value: {
|
||||
delegatorAddress: this.address,
|
||||
validatorAddress: this.validatorAddress,
|
||||
},
|
||||
},
|
||||
{
|
||||
typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission',
|
||||
value: {
|
||||
validatorAddress: this.validatorAddress,
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update', {
|
||||
modalTitle: 'Withdraw Validator Commission',
|
||||
historyName: 'withdraw',
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
431
src/views/components/OperationModal/index.vue
Normal file
431
src/views/components/OperationModal/index.vue
Normal file
@ -0,0 +1,431 @@
|
||||
<template>
|
||||
<b-modal
|
||||
:id="modalId"
|
||||
centered
|
||||
size="md"
|
||||
:title="modalTitle"
|
||||
:ok-title="actionName"
|
||||
scrollable
|
||||
:hide-header-close="!showResult"
|
||||
:hide-footer="showResult"
|
||||
modal-class="custom-transaction-modal"
|
||||
:ok-disabled="isOwner"
|
||||
@hidden="resetModal"
|
||||
@ok="handleOk"
|
||||
@show="initialize"
|
||||
>
|
||||
<b-overlay
|
||||
:show="isOwner"
|
||||
rounded="sm"
|
||||
>
|
||||
<template #overlay>
|
||||
<div class="text-center">
|
||||
<b-avatar
|
||||
icon="stopwatch"
|
||||
font-scale="3"
|
||||
animation="cylon"
|
||||
/>
|
||||
<p id="cancel-label">
|
||||
{{ blockingMsg }}
|
||||
</p>
|
||||
<b-button
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
variant="outline-primary"
|
||||
to="/wallet/import"
|
||||
>
|
||||
Connect Wallet
|
||||
</b-button>
|
||||
</div>
|
||||
</template>
|
||||
<validation-observer
|
||||
v-if="!showResult"
|
||||
ref="simpleRules"
|
||||
>
|
||||
<b-form>
|
||||
<component
|
||||
:is="type"
|
||||
ref="component"
|
||||
:address="selectedAddress"
|
||||
:validator-address="validatorAddress"
|
||||
:balance="balance"
|
||||
:proposal-id="proposalId"
|
||||
:proposal-title="proposalTitle"
|
||||
@update="componentUpdate"
|
||||
/>
|
||||
<b-row>
|
||||
<b-col cols="12">
|
||||
<b-form-group>
|
||||
<b-form-checkbox
|
||||
v-model="advance"
|
||||
name="advance"
|
||||
value="true"
|
||||
>
|
||||
<small>Advanced</small>
|
||||
</b-form-checkbox>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-if="advance">
|
||||
<b-col cols="12">
|
||||
<b-form-group
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-form-input v-model="fee" />
|
||||
<b-input-group-append>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
:options="feeDenoms"
|
||||
value-field="denom"
|
||||
text-field="denom"
|
||||
/>
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
<b-col cols="12">
|
||||
<b-form-group
|
||||
label="Gas"
|
||||
label-for="gas"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
name="gas"
|
||||
>
|
||||
<b-form-input
|
||||
id="gas"
|
||||
v-model="gas"
|
||||
type="number"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
<b-col cols="12">
|
||||
<b-form-group
|
||||
label="Memo"
|
||||
label-for="Memo"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
name="memo"
|
||||
>
|
||||
<b-form-input
|
||||
id="Memo"
|
||||
v-model="memo"
|
||||
max="2"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-if="advance">
|
||||
<b-col>
|
||||
<wallet-input-vue v-model="wallet" />
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form>
|
||||
{{ error }}
|
||||
</validation-observer>
|
||||
|
||||
<TransactionResult
|
||||
v-else
|
||||
:hash="txHash"
|
||||
/>
|
||||
</b-overlay>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationProvider, ValidationObserver } from 'vee-validate'
|
||||
import {
|
||||
BAvatar, BModal, BRow, BCol, BInputGroup, BFormInput, BFormGroup, BFormSelect, BFormSelectOption,
|
||||
BForm, BButton, BInputGroupAppend, BFormCheckbox, BOverlay,
|
||||
} from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
extractAccountNumberAndSequence, getLocalAccounts, setLocalTxHistory, sign, timeIn,
|
||||
} from '@/libs/utils'
|
||||
import vSelect from 'vue-select'
|
||||
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
||||
|
||||
import WalletInputVue from '../WalletInput.vue'
|
||||
import Delegate from './components/Delegate.vue'
|
||||
import Redelegate from './components/Redelegate.vue'
|
||||
import Withdraw from './components/Withdraw.vue'
|
||||
import Unbond from './components/Unbond.vue'
|
||||
import Transfer from './components/Transfer.vue'
|
||||
import IBCTransfer from './components/IBCTransfer.vue'
|
||||
import Vote from './components/Vote.vue'
|
||||
import WithdrawCommission from './components/WithdrawCommission.vue'
|
||||
import GovDeposit from './components/GovDeposit.vue'
|
||||
import TransactionResult from './TransactionResult.vue'
|
||||
|
||||
export default {
|
||||
name: 'DelegateDialogue',
|
||||
components: {
|
||||
BAvatar,
|
||||
BModal,
|
||||
BRow,
|
||||
BCol,
|
||||
BForm,
|
||||
BInputGroup,
|
||||
BFormInput,
|
||||
BFormGroup,
|
||||
BFormSelect,
|
||||
BFormSelectOption,
|
||||
BFormCheckbox,
|
||||
vSelect,
|
||||
BButton,
|
||||
BInputGroupAppend,
|
||||
BOverlay,
|
||||
WalletInputVue,
|
||||
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
ToastificationContent,
|
||||
Delegate,
|
||||
Redelegate,
|
||||
Withdraw,
|
||||
Unbond,
|
||||
Transfer,
|
||||
IBCTransfer,
|
||||
Vote,
|
||||
WithdrawCommission,
|
||||
GovDeposit,
|
||||
TransactionResult,
|
||||
},
|
||||
directives: {
|
||||
Ripple,
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
modalId: {
|
||||
type: String,
|
||||
default: 'operation-modal',
|
||||
},
|
||||
validatorAddress: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
proposalId: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
proposalTitle: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalTitle: '',
|
||||
historyName: '',
|
||||
selectedValidator: null,
|
||||
selectedChain: null,
|
||||
token: '',
|
||||
chainId: '',
|
||||
balance: [],
|
||||
IBCDenom: {},
|
||||
error: null,
|
||||
sequence: 1,
|
||||
accountNumber: 0,
|
||||
advance: false,
|
||||
fee: '900',
|
||||
feeDenom: '',
|
||||
wallet: 'ledgerUSB',
|
||||
gas: '250000',
|
||||
memo: '',
|
||||
blockingMsg: this.address ? 'You are not the owner' : 'No available account found.',
|
||||
actionName: 'Send',
|
||||
showResult: false,
|
||||
txHash: '',
|
||||
|
||||
required,
|
||||
password,
|
||||
email,
|
||||
min,
|
||||
integer,
|
||||
url,
|
||||
alpha,
|
||||
between,
|
||||
digits,
|
||||
length,
|
||||
alphaDash,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
feeDenoms() {
|
||||
if (!this.balance) return []
|
||||
return this.balance.filter(item => !item.denom.startsWith('ibc'))
|
||||
},
|
||||
accounts() {
|
||||
const accounts = getLocalAccounts()
|
||||
const selectedWallet = this.$store.state.chains.defaultWallet
|
||||
return accounts[selectedWallet]
|
||||
},
|
||||
isOwner() {
|
||||
if (this.accounts) {
|
||||
this.updateWallet(this.accounts.device)
|
||||
if (this.accounts.address.findIndex(x => x.addr === this.selectedAddress) > -1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
selectedAddress() {
|
||||
if (this.address) {
|
||||
return this.address
|
||||
}
|
||||
const chain = this.$store.state.chains.selected.chain_name
|
||||
const selectedAddress = this.accounts.address.find(x => x.chain === chain)
|
||||
return selectedAddress?.addr
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initialize() {
|
||||
this.$http.getLatestBlock().then(ret => {
|
||||
this.chainId = ret.block.header.chain_id
|
||||
const notSynced = timeIn(ret.block.header.time, 10, 'm')
|
||||
if (notSynced) {
|
||||
this.error = 'Client is not synced or blockchain is halted'
|
||||
} else {
|
||||
this.error = null
|
||||
}
|
||||
})
|
||||
this.$http.getAuthAccount(this.selectedAddress).then(ret => {
|
||||
const account = extractAccountNumberAndSequence(ret)
|
||||
this.accountNumber = account.accountNumber
|
||||
this.sequence = account.sequence
|
||||
})
|
||||
this.$http.getBankBalances(this.selectedAddress).then(res => {
|
||||
if (res && res.length > 0) {
|
||||
this.balance = res.reverse()
|
||||
const token = this.balance.find(i => !i.denom.startsWith('ibc'))
|
||||
this.token = token.denom
|
||||
if (token) this.feeDenom = token.denom
|
||||
}
|
||||
})
|
||||
this.fee = this.$store.state.chains.selected?.min_tx_fee || '1000'
|
||||
this.feeDenom = this.$store.state.chains.selected?.assets[0]?.base || ''
|
||||
},
|
||||
componentUpdate(obj) {
|
||||
Object.keys(obj).forEach(key => {
|
||||
this[key] = obj[key]
|
||||
})
|
||||
},
|
||||
handleOk(bvModalEvt) {
|
||||
bvModalEvt.preventDefault()
|
||||
this.$refs.simpleRules.validate().then(ok => {
|
||||
if (ok) {
|
||||
this.sendTx().then(ret => {
|
||||
console.log(ret)
|
||||
this.error = ret
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
resetModal() {
|
||||
this.feeDenom = ''
|
||||
this.error = null
|
||||
this.showResult = false
|
||||
},
|
||||
async sendTx() {
|
||||
const txMsgs = this.$refs.component.msg
|
||||
if (txMsgs.length === 0) {
|
||||
this.error = 'No delegation found'
|
||||
return ''
|
||||
}
|
||||
if (!this.accountNumber) {
|
||||
this.error = 'Account number should not be empty!'
|
||||
return ''
|
||||
}
|
||||
|
||||
const txFee = {
|
||||
amount: [
|
||||
{
|
||||
amount: this.fee,
|
||||
denom: this.feeDenom,
|
||||
},
|
||||
],
|
||||
gas: this.gas,
|
||||
}
|
||||
|
||||
const signerData = {
|
||||
accountNumber: this.accountNumber,
|
||||
sequence: this.sequence,
|
||||
chainId: this.chainId,
|
||||
}
|
||||
|
||||
sign(
|
||||
this.wallet,
|
||||
this.chainId,
|
||||
this.selectedAddress,
|
||||
txMsgs,
|
||||
txFee,
|
||||
this.memo,
|
||||
signerData,
|
||||
).then(bodyBytes => {
|
||||
this.showResult = true
|
||||
this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => {
|
||||
this.txHash = res.tx_response.txhash
|
||||
setLocalTxHistory({
|
||||
chain: this.$store.state.chains.selected,
|
||||
op: this.historyName,
|
||||
hash: res.tx_response.txhash,
|
||||
time: new Date(),
|
||||
})
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
this.error = e
|
||||
})
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
|
||||
this.error = e
|
||||
})
|
||||
return ''
|
||||
},
|
||||
updateWallet(v) {
|
||||
console.log('device', v)
|
||||
if (v && v !== 'address') {
|
||||
this.wallet = v
|
||||
}
|
||||
this.wallet = 'keplr'
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import '@core/scss/vue/libs/vue-select.scss';
|
||||
.custom-transaction-modal {
|
||||
.modal-header {
|
||||
.modal-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
.close {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user