diff --git a/PENDING.md b/PENDING.md index 58c86027e5..cb841b3238 100644 --- a/PENDING.md +++ b/PENDING.md @@ -6,3 +6,4 @@ - [\#2301](https://github.com/cosmos/voyager/issues/2301) throttle requests for keybase identities @faboweb - [\#2272](https://github.com/cosmos/voyager/issues/2272) fixed showing uatoms instead of atoms @faboweb +- [\#2289](https://github.com/cosmos/voyager/pull/2289) reduced amount of requests to full node @fedekunze diff --git a/app/src/renderer/components/common/TmBalance.vue b/app/src/renderer/components/common/TmBalance.vue index 2e6825b8a4..caf3c1b7d2 100644 --- a/app/src/renderer/components/common/TmBalance.vue +++ b/app/src/renderer/components/common/TmBalance.vue @@ -53,6 +53,7 @@ export default { `connected`, `session`, `liquidAtoms`, + `lastHeader`, `totalAtoms`, `bondDenom`, `distribution` @@ -67,6 +68,18 @@ export default { ) } }, + watch: { + lastHeader: { + immediate: true, + handler(newHeader) { + const waitTenBlocks = Number(newHeader.height) % 10 === 0 + if (this.session.signedIn && waitTenBlocks) { + this.$store.dispatch(`getTotalRewards`) + this.$store.dispatch(`queryWalletBalances`) + } + } + } + }, methods: { onWithdrawal() { this.$refs.modalWithdrawAllRewards.open() diff --git a/app/src/renderer/components/staking/ModalWithdrawAllRewards.vue b/app/src/renderer/components/staking/ModalWithdrawAllRewards.vue index b8f1df28b8..b0ca6889cd 100644 --- a/app/src/renderer/components/staking/ModalWithdrawAllRewards.vue +++ b/app/src/renderer/components/staking/ModalWithdrawAllRewards.vue @@ -41,12 +41,26 @@ export default { num }), computed: { - ...mapGetters([`bondDenom`, `distribution`]), + ...mapGetters([`bondDenom`, `distribution`, `lastHeader`, `session`]), totalRewards({ bondDenom, distribution } = this) { const rewards = distribution.totalRewards[bondDenom] return (rewards && atoms(rewards)) || 0 } }, + watch: { + lastHeader: { + immediate: true, + handler() { + if ( + this.session.signedIn && + this.$refs.actionModal && + this.$refs.actionModal.show + ) { + this.$store.dispatch(`getTotalRewards`) + } + } + } + }, methods: { open() { this.$refs.actionModal.open() diff --git a/app/src/renderer/components/staking/PageValidator.vue b/app/src/renderer/components/staking/PageValidator.vue index be7e19df61..a8d3b21118 100644 --- a/app/src/renderer/components/staking/PageValidator.vue +++ b/app/src/renderer/components/staking/PageValidator.vue @@ -173,7 +173,6 @@ diff --git a/app/src/renderer/components/staking/TableValidators.vue b/app/src/renderer/components/staking/TableValidators.vue index 33841f84de..1e48b714a6 100644 --- a/app/src/renderer/components/staking/TableValidators.vue +++ b/app/src/renderer/components/staking/TableValidators.vue @@ -139,13 +139,6 @@ export default { watch: { address: function() { this.session.address && this.$store.dispatch(`updateDelegates`) - }, - validators: function(validators) { - if (!validators || validators.length === 0 || !this.session.signedIn) { - return - } - - this.$store.dispatch(`getRewardsFromAllValidators`, this.yourValidators) } }, mounted() { diff --git a/app/src/renderer/components/wallet/PageTransactions.vue b/app/src/renderer/components/wallet/PageTransactions.vue index e3be4df6ad..6ab7fb89c9 100644 --- a/app/src/renderer/components/wallet/PageTransactions.vue +++ b/app/src/renderer/components/wallet/PageTransactions.vue @@ -62,8 +62,7 @@ export default { `session`, `bondDenom`, `delegation`, - `delegates`, - `lastHeader` + `delegates` ]), orderedTransactions() { return orderBy( @@ -79,14 +78,6 @@ export default { return this.orderedTransactions.length === 0 } }, - watch: { - lastHeader: { - immediate: true, - handler() { - this.refreshTransactions() - } - } - }, mounted() { this.refreshTransactions() }, diff --git a/app/src/renderer/components/wallet/PageWallet.vue b/app/src/renderer/components/wallet/PageWallet.vue index 1d4d213079..a35e157183 100644 --- a/app/src/renderer/components/wallet/PageWallet.vue +++ b/app/src/renderer/components/wallet/PageWallet.vue @@ -65,16 +65,6 @@ export default { ) } }, - watch: { - lastHeader: { - immediate: true, - handler() { - if (this.session.signedIn) { - this.queryWalletBalances() - } - } - } - }, async mounted() { this.updateDelegates() await this.queryWalletBalances() diff --git a/app/src/renderer/vuex/modules/connection.js b/app/src/renderer/vuex/modules/connection.js index a215676c50..f64e62ee68 100644 --- a/app/src/renderer/vuex/modules/connection.js +++ b/app/src/renderer/vuex/modules/connection.js @@ -4,7 +4,7 @@ import config from "../../../config" const NODE_HALTED_TIMEOUT = config.node_halted_timeout -export default function({ node }) { +export default function ({ node }) { // get tendermint RPC client from basecoin client const state = { @@ -98,10 +98,6 @@ export default function({ node }) { }, ({ header }) => { dispatch(`setLastHeader`, header) - - if (rootState.session.signedIn) { - dispatch(`getTotalRewards`) - } } ) if (rootState.session.signedIn) { diff --git a/app/src/renderer/vuex/modules/delegation.js b/app/src/renderer/vuex/modules/delegation.js index 3afd81c2aa..85f63c27d2 100644 --- a/app/src/renderer/vuex/modules/delegation.js +++ b/app/src/renderer/vuex/modules/delegation.js @@ -42,7 +42,7 @@ export default ({ node }) => { setUnbondingDelegations(state, unbondingDelegations) { state.unbondingDelegations = unbondingDelegations ? unbondingDelegations - // building a dict from the array and taking out the validators with no undelegations + // building a dict from the array and taking out the validators with no undelegations .reduce( (dict, { validator_address, entries }) => ({ ...dict, @@ -137,7 +137,7 @@ export default ({ node }) => { async updateDelegates({ dispatch, rootState }) { const candidates = await dispatch(`getDelegates`) - if(rootState.session.signedIn) { + if (rootState.session.signedIn) { dispatch(`getBondedDelegates`, candidates) } }, @@ -178,6 +178,7 @@ export default ({ node }) => { value: state.committedDelegates[validator_address] + Number(amount) }) + await dispatch(`getAllTxs`) // load delegates after delegation to get new atom distribution on validators dispatch(`updateDelegates`) }, @@ -201,6 +202,7 @@ export default ({ node }) => { password, submitType }) + await dispatch(`getAllTxs`) }, async submitRedelegation( { @@ -223,6 +225,8 @@ export default ({ node }) => { password, submitType }) + + await dispatch(`getAllTxs`) } } diff --git a/app/src/renderer/vuex/modules/distribution.js b/app/src/renderer/vuex/modules/distribution.js index 7b1caa2dbe..4d08bb7fa2 100644 --- a/app/src/renderer/vuex/modules/distribution.js +++ b/app/src/renderer/vuex/modules/distribution.js @@ -97,6 +97,7 @@ export default ({ node }) => { }) await dispatch(`getTotalRewards`) await dispatch(`queryWalletBalances`) + await dispatch(`getAllTxs`) }, async getRewardsFromAllValidators({ state, dispatch }, validators) { state.loading = true diff --git a/app/src/renderer/vuex/modules/governance/deposits.js b/app/src/renderer/vuex/modules/governance/deposits.js index 6f7155f78e..452ac0359b 100644 --- a/app/src/renderer/vuex/modules/governance/deposits.js +++ b/app/src/renderer/vuex/modules/governance/deposits.js @@ -61,6 +61,7 @@ export default ({ node }) => { await dispatch(`getProposalDeposits`, proposal_id) await dispatch(`getProposal`, proposal_id) + await dispatch(`getAllTxs`) } } return { diff --git a/app/src/renderer/vuex/modules/governance/proposals.js b/app/src/renderer/vuex/modules/governance/proposals.js index 3db3813c1c..fcd6a1fbdf 100644 --- a/app/src/renderer/vuex/modules/governance/proposals.js +++ b/app/src/renderer/vuex/modules/governance/proposals.js @@ -105,7 +105,7 @@ export default ({ node }) => { }) const latestId = Object.keys(state.proposals).reduce((latest, id) => { - return latest > Number(id) ? latest : Number(id) + return latest > Number(id) ? latest : Number(id) }, 0) commit(`setProposal`, { proposal_id: String(latestId + 1), @@ -115,6 +115,7 @@ export default ({ node }) => { }) await dispatch(`getProposals`) + await dispatch(`getAllTxs`) } } return { diff --git a/app/src/renderer/vuex/modules/governance/votes.js b/app/src/renderer/vuex/modules/governance/votes.js index ab4e06656d..065de6fe2a 100644 --- a/app/src/renderer/vuex/modules/governance/votes.js +++ b/app/src/renderer/vuex/modules/governance/votes.js @@ -46,6 +46,7 @@ export default ({ node }) => { }) await dispatch(`getProposalVotes`, proposal_id) await dispatch(`getProposal`, proposal_id) + await dispatch(`getAllTxs`) } } return { diff --git a/app/src/renderer/vuex/modules/wallet.js b/app/src/renderer/vuex/modules/wallet.js index 6c3c722987..896e3ab48f 100644 --- a/app/src/renderer/vuex/modules/wallet.js +++ b/app/src/renderer/vuex/modules/wallet.js @@ -103,6 +103,7 @@ export default ({ node }) => { denom, amount: oldBalance.amount - amount }) + await dispatch(`getAllTxs`) }, queryWalletStateAfterHeight({ rootState, dispatch }, height) { return new Promise(resolve => { diff --git a/test/unit/specs/components/common/TmBalance.spec.js b/test/unit/specs/components/common/TmBalance.spec.js index d35d67e8f2..3b7ceb2dad 100644 --- a/test/unit/specs/components/common/TmBalance.spec.js +++ b/test/unit/specs/components/common/TmBalance.spec.js @@ -19,8 +19,10 @@ describe(`TmBalance`, () => { totalRewards: { stake: 1000450000000 } - } - } + }, + lastHeader: { height: `10` } + }, + dispatch: jest.fn() } wrapper = shallowMount(TmBalance, { @@ -51,4 +53,43 @@ describe(`TmBalance`, () => { TmBalance.methods.onWithdrawal.call({ $refs }) expect($refs.modalWithdrawAllRewards.open).toHaveBeenCalled() }) + + describe(`update balance and total rewards on new blocks`, () => { + describe(`shouldn't update`, () => { + it(`if user is not signed in `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: false } + const newHeader = { height: `10` } + TmBalance.watch.lastHeader.handler.call( + { session, $store }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith(`getTotalRewards`) + expect($store.dispatch).not.toHaveBeenCalledWith(`queryWalletBalances`) + }) + + it(`if hasn't waited for 10 blocks `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const newHeader = { height: `12` } + TmBalance.watch.lastHeader.handler.call( + { session, $store }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith(`getTotalRewards`) + expect($store.dispatch).not.toHaveBeenCalledWith(`queryWalletBalances`) + }) + }) + + describe(`should update balance and rewards `, () => { + it(`if user is signed in and wait for 10 blocks`, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const newHeader = { height: `10` } + TmBalance.watch.lastHeader.handler.call( + { session, $store }, + newHeader) + expect($store.dispatch).toHaveBeenCalledWith(`getTotalRewards`) + expect($store.dispatch).toHaveBeenCalledWith(`queryWalletBalances`) + }) + }) + }) }) diff --git a/test/unit/specs/components/staking/ModalWithdrawAllRewards.spec.js b/test/unit/specs/components/staking/ModalWithdrawAllRewards.spec.js index 397cd27205..bd203d3efd 100644 --- a/test/unit/specs/components/staking/ModalWithdrawAllRewards.spec.js +++ b/test/unit/specs/components/staking/ModalWithdrawAllRewards.spec.js @@ -12,7 +12,9 @@ describe(`ModalWithdrawAllRewards`, () => { dispatch: jest.fn(), getters: { bondDenom: `stake`, - distribution: { totalRewards: { stake: 10000000 } } + distribution: { totalRewards: { stake: 10000000 } }, + lastHeader: { height: `10` }, + session: { signedIn: true } } } wrapper = shallowMount(ModalWithdrawAllRewards, { @@ -58,4 +60,42 @@ describe(`ModalWithdrawAllRewards`, () => { ) }) }) + + describe(`update total rewards on new blocks`, () => { + describe(`shouldn't update total `, () => { + it(`if user is not signed in `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: false } + const $refs = { actionModal: { show: true } } + ModalWithdrawAllRewards.watch.lastHeader.handler.call( + { session, $store, $refs }) + expect($store.dispatch).not.toHaveBeenCalledWith(`getTotalRewards`) + }) + + it(`if user is not on watching the modal `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + let $refs = {} + ModalWithdrawAllRewards.watch.lastHeader.handler.call( + { session, $store, $refs }) + expect($store.dispatch).not.toHaveBeenCalledWith(`getTotalRewards`) + + $refs = { actionModal: { show: false } } + ModalWithdrawAllRewards.watch.lastHeader.handler.call( + { session, $store, $refs }) + expect($store.dispatch).not.toHaveBeenCalledWith(`getTotalRewards`) + }) + }) + + describe(`should update total rewards `, () => { + it(`if user is signed in and is watching the modal `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const $refs = { actionModal: { show: true } } + ModalWithdrawAllRewards.watch.lastHeader.handler.call( + { session, $store, $refs }) + expect($store.dispatch).toHaveBeenCalledWith(`getTotalRewards`) + }) + }) + }) }) diff --git a/test/unit/specs/components/staking/PageValidator.spec.js b/test/unit/specs/components/staking/PageValidator.spec.js index fb58997d24..ccc6f3ae30 100644 --- a/test/unit/specs/components/staking/PageValidator.spec.js +++ b/test/unit/specs/components/staking/PageValidator.spec.js @@ -51,12 +51,12 @@ const getters = { globalPower: 4200, loaded: true }, - + delegation: { loaded: true }, committedDelegations: { [validator.operator_address]: 0 }, lastHeader: { - height: 500 + height: `500` }, distribution: { rewards: { @@ -214,12 +214,13 @@ describe(`PageValidator`, () => { }) describe(`rewards`, () => { - let bondDenom, validator, session + let bondDenom, validator, session, lastHeader beforeEach(() => { bondDenom = `stake` validator = { operator_address: `cosmos1address` } session = { signedIn: true } + lastHeader = { height: `20` } }) it(`gets rewards from validator if it has some`, () => { const distribution = { @@ -230,7 +231,7 @@ describe(`PageValidator`, () => { } } const rewardsString = PageValidator.computed.rewards.call( - { session, bondDenom, distribution, validator } + { session, bondDenom, distribution, validator, lastHeader } ) expect(rewardsString).toBe(`100.000000 stake`) }) @@ -243,8 +244,9 @@ describe(`PageValidator`, () => { } } } + const rewardsString = PageValidator.computed.rewards.call( - { session, bondDenom, distribution, validator } + { session, bondDenom, distribution, validator, lastHeader } ) expect(rewardsString).toBe(`0.000000 stake`) }) @@ -252,33 +254,142 @@ describe(`PageValidator`, () => { it(`when user doesn't have any delegations`, () => { const distribution = { rewards: {} } const rewardsString = PageValidator.computed.rewards.call( - { session, bondDenom, distribution, validator } + { session, bondDenom, distribution, validator, lastHeader } ) expect(rewardsString).toBeNull() }) }) - it(`doesn't call user rewards if not signed in`, () => { - const session = { signedIn: false } + it(`should only call user rewards if bond is more then 0`, () => { const $store = { dispatch: jest.fn() } + const myBond = 1 const $route = { params: { validator: `cosmos1address` } } - PageValidator.mounted.call({ session, $store, $route }) - expect($store.dispatch).not.toHaveBeenCalledWith( + PageValidator.watch[`myBond`].handler.call( + { $store, $route }, myBond + ) + expect($store.dispatch).toHaveBeenCalledWith( `getRewardsFromValidator`, $route.params.validator ) }) - it(`updates rewards if block hasn't updated`, () => { + it(`shouldn't call user rewards if bond is 0`, () => { const $store = { dispatch: jest.fn() } - const session = { signedIn: false } + const myBond = 0 const $route = { params: { validator: `cosmos1address` } } - PageValidator.watch.lastHeader.handler.call({ session, $store, $route }) + PageValidator.watch[`myBond`].handler.call( + { $store, $route }, myBond + ) expect($store.dispatch).not.toHaveBeenCalledWith( `getRewardsFromValidator`, $route.params.validator ) }) + + describe(`update rewards on new blocks`, () => { + describe(`shouldn't update`, () => { + it(`if user is not signed in `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: false } + const $route = { + params: { validator: `cosmos1address` }, + name: `validator` + } + const myBond = 1 + const newHeader = { height: `20` } + const delegation = { loaded: true } + PageValidator.watch.lastHeader.handler.call( + { session, $store, $route, myBond, delegation }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromValidator`, + $route.params.validator + ) + }) + + it(`if hasn't waited for 20 blocks `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const $route = { + params: { validator: `cosmos1address` }, + name: `validator` + } + const myBond = 1 + const newHeader = { height: `30` } + const delegation = { loaded: true } + PageValidator.watch.lastHeader.handler.call( + { session, $store, $route, myBond, delegation }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromValidator`, + $route.params.validator + ) + }) + + it(`if user is not watching page validator`, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const $route = { + params: { validator: `cosmos1address` }, + name: `my-delegations` + } + const myBond = 1 + const newHeader = { height: `20` } + const delegation = { loaded: true } + PageValidator.watch.lastHeader.handler.call( + { session, $store, $route, myBond, delegation }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromValidator`, + $route.params.validator + ) + }) + + it(`if user doesn't have any delegations `, () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const $route = { + params: { validator: `cosmos1address` }, + name: `validator` + } + const myBond = 0 + const newHeader = { height: `30` } + const delegation = { loaded: true } + PageValidator.watch.lastHeader.handler.call( + { session, $store, $route, myBond, delegation }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromValidator`, + $route.params.validator + ) + }) + }) + + describe(`should update rewards `, () => { + it( + `if waited for 20 blocks, ` + + `user has signed in, ` + + `has delegations and is watching the validator page`, + () => { + const $store = { dispatch: jest.fn() } + const session = { signedIn: true } + const $route = { + params: { validator: `cosmos1address` }, + name: `validator` + } + const myBond = 1 + const newHeader = { height: `20` } + const delegation = { loaded: true } + PageValidator.watch.lastHeader.handler.call( + { session, $store, $route, myBond, delegation }, + newHeader) + expect($store.dispatch).toHaveBeenCalledWith( + `getRewardsFromValidator`, + $route.params.validator + ) + }) + }) + }) }) describe(`delegationTargetOptions`, () => { diff --git a/test/unit/specs/components/staking/TabMyDelegations.spec.js b/test/unit/specs/components/staking/TabMyDelegations.spec.js index a017da58e9..4ebb237cb2 100644 --- a/test/unit/specs/components/staking/TabMyDelegations.spec.js +++ b/test/unit/specs/components/staking/TabMyDelegations.spec.js @@ -3,24 +3,6 @@ import TabMyDelegations from "renderer/components/staking/TabMyDelegations" import validators from "../../store/json/validators.js" import { stakingTxs } from "../../store/json/txs" -const getters = { - transactions: { - staking: [] - }, - delegates: { - delegates: validators - }, - delegation: { - unbondingDelegations: { - }, - loaded: true - }, - committedDelegations: {}, - connected: true, - bondDenom: `uatom`, - session: { signedIn: true } -} - // TODO: remove this dirty addition: the real cleanup will be done in a separate PR // the problem is mock VS real implementation have different keys: shares in mock, shares_amount in SDK // const unbondingTransactions = lcdClientMock.state.txs.slice(5).map(t => { @@ -29,6 +11,27 @@ const getters = { // }) describe(`Component: TabMyDelegations`, () => { + + const getters = { + transactions: { + staking: [] + }, + delegates: { + delegates: validators + }, + delegation: { + unbondingDelegations: { + }, + loaded: true + }, + committedDelegations: { + }, + connected: true, + bondDenom: `uatom`, + session: { signedIn: true }, + lastHeader: { height: `20` } + } + describe(`view`, () => { let wrapper, $store @@ -41,7 +44,10 @@ describe(`Component: TabMyDelegations`, () => { wrapper = shallowMount(TabMyDelegations, { mocks: { - $store + $store, + $route: { + path: `/staking/my-delegations` + } }, stubs: [`router-link`] }) @@ -122,17 +128,77 @@ describe(`Component: TabMyDelegations`, () => { ).toHaveLength(1) }) - it(`yourValidators`, () => { - expect( - TabMyDelegations.computed.yourValidators({ - committedDelegations: { - [validators[0].operator_address]: 1, - [validators[2].operator_address]: 2 - }, - delegates: { delegates: validators } + describe(`yourValidators`, () => { + it(`should return validators if signed in`, () => { + expect( + TabMyDelegations.computed.yourValidators({ + committedDelegations: { + [validators[0].operator_address]: 1, + [validators[2].operator_address]: 2 + }, + delegates: { delegates: validators }, + session: { signedIn: true } + }) + ).toEqual([validators[0], validators[2]]) + }) + + it(`should return false if not signed in`, () => { + expect( + TabMyDelegations.computed.yourValidators({ + committedDelegations: { + [validators[0].operator_address]: 1, + [validators[2].operator_address]: 2 + }, + delegates: { delegates: validators }, + session: { signedIn: false } + }) + ).toBe(false) + }) + }) + + describe(`update rewards on new blocks`, () => { + describe(`shouldn't update`, () => { + it(`if hasn't waited for 20 blocks `, () => { + const $store = { dispatch: jest.fn() } + const yourValidators = [{}] + const newHeader = { height: `30` } + TabMyDelegations.watch.lastHeader.handler.call( + { $store, yourValidators }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromAllValidators`, + yourValidators + ) }) - ).toEqual([validators[0], validators[2]]) + + it(`if user doesn't have any delegations `, () => { + const $store = { dispatch: jest.fn() } + const yourValidators = [] + const newHeader = { height: `40` } + TabMyDelegations.watch.lastHeader.handler.call( + { $store, yourValidators }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromAllValidators`, + yourValidators + ) + }) + + describe(`should update rewards `, () => { + it(`if has waited for 20 blocks and has delegations`, () => { + const $store = { dispatch: jest.fn() } + const yourValidators = [{}] + const newHeader = { height: `40` } + TabMyDelegations.watch.lastHeader.handler.call( + { $store, yourValidators }, + newHeader) + expect($store.dispatch).toHaveBeenCalledWith( + `getRewardsFromAllValidators`, + yourValidators + ) + }) + }) + }) }) }) - }) diff --git a/test/unit/specs/components/staking/TabValidators.spec.js b/test/unit/specs/components/staking/TabValidators.spec.js index 82590725b2..7cc6fa6849 100644 --- a/test/unit/specs/components/staking/TabValidators.spec.js +++ b/test/unit/specs/components/staking/TabValidators.spec.js @@ -1,22 +1,24 @@ import { shallowMount } from "@vue/test-utils" import TabValidators from "renderer/components/staking/TabValidators" - -// we don't show data of a validator in this component so we just provide stubs here -const delegates = new Array(3).fill({}) +import validators from "../../store/json/validators.js" describe(`TabValidators`, () => { let wrapper, $store const getters = { delegates: { - delegates, + delegates: validators, loading: false, loaded: true }, + committedDelegations: { + [validators[0].operator_address]: 42 + }, session: { signedIn: true }, - connected: true + connected: true, + lastHeader: { height: 20 } } beforeEach(async () => { @@ -41,14 +43,18 @@ describe(`TabValidators`, () => { dispatch: jest.fn(), getters: { delegates: { - delegates, + delegates: validators, loading: false, loaded: false }, + committedDelegations: { + [validators[0].operator_address]: 42 + }, session: { signedIn: true }, - connected: false + connected: false, + lastHeader: { height: 20 } } } @@ -66,14 +72,18 @@ describe(`TabValidators`, () => { dispatch: jest.fn(), getters: { delegates: { - delegates, + delegates: validators, loading: true, loaded: false }, + committedDelegations: { + [validators[0].operator_address]: 42 + }, session: { signedIn: true }, - connected: true + connected: true, + lastHeader: { height: 20 } } } @@ -95,10 +105,14 @@ describe(`TabValidators`, () => { loading: false, loaded: true }, + committedDelegations: { + [validators[0].operator_address]: 42 + }, session: { signedIn: true }, - connected: true + connected: true, + lastHeader: { height: 20 } } } @@ -130,4 +144,77 @@ describe(`TabValidators`, () => { }, true) expect(dispatch).toHaveBeenCalledWith(`updateDelegates`) }) + + describe(`yourValidators`, () => { + it(`should return validators if signed in`, () => { + expect( + TabValidators.computed.yourValidators({ + committedDelegations: { + [validators[0].operator_address]: 1, + [validators[2].operator_address]: 2 + }, + delegates: { delegates: validators }, + session: { signedIn: true } + }) + ).toEqual([validators[0], validators[2]]) + }) + + it(`should return false if not signed in`, () => { + expect( + TabValidators.computed.yourValidators({ + committedDelegations: { + [validators[0].operator_address]: 1, + [validators[2].operator_address]: 2 + }, + delegates: { delegates: validators }, + session: { signedIn: false } + }) + ).toBe(false) + }) + }) + + describe(`update rewards on new blocks`, () => { + describe(`shouldn't update`, () => { + it(`if hasn't waited for 20 blocks `, () => { + const $store = { dispatch: jest.fn() } + const yourValidators = [{}] + const newHeader = { height: `30` } + TabValidators.watch.lastHeader.handler.call( + { $store, yourValidators }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromAllValidators`, + yourValidators + ) + }) + + it(`if user doesn't have any delegations `, () => { + const $store = { dispatch: jest.fn() } + const yourValidators = [] + const newHeader = { height: `40` } + TabValidators.watch.lastHeader.handler.call( + { $store, yourValidators }, + newHeader) + expect($store.dispatch).not.toHaveBeenCalledWith( + `getRewardsFromAllValidators`, + yourValidators + ) + }) + + describe(`should update rewards `, () => { + it(`if has waited for 20 blocks and has delegations`, () => { + const $store = { dispatch: jest.fn() } + const yourValidators = [{}] + const newHeader = { height: `40` } + TabValidators.watch.lastHeader.handler.call( + { $store, yourValidators }, + newHeader) + expect($store.dispatch).toHaveBeenCalledWith( + `getRewardsFromAllValidators`, + yourValidators + ) + }) + }) + }) + }) }) diff --git a/test/unit/specs/components/staking/TableValidators.spec.js b/test/unit/specs/components/staking/TableValidators.spec.js index 5352a625da..6f5950e95e 100644 --- a/test/unit/specs/components/staking/TableValidators.spec.js +++ b/test/unit/specs/components/staking/TableValidators.spec.js @@ -101,49 +101,6 @@ describe(`TableValidators`, () => { expect($store.dispatch).not.toHaveBeenCalledWith(`updateDelegates`) }) - it(`updates if there are existing validators`, () => { - const session = { signedIn: true } - const yourValidators = { - cosmosvaladdr15ky9du8a2wlstz6fpx3p4mqpjyrm5ctgurrg7n: 2 - } - TableValidators.watch.validators.call({ - session, $store, yourValidators - }, validators) - expect($store.dispatch.mock.calls[2]).toEqual( - [ - `getRewardsFromAllValidators`, - { cosmosvaladdr15ky9du8a2wlstz6fpx3p4mqpjyrm5ctgurrg7n: 2 } - ] - ) - }) - - it(`doesn't update rewards if user hasn't signed in`, () => { - const validators = [] - const session = { signedIn: false } - TableValidators.watch.validators.call({ $store, session }, validators) - expect($store.dispatch).not.toHaveBeenCalledWith( - `getRewardsFromAllValidators` - ) - }) - - it(`doesn't update rewards if validator set is empty`, () => { - const validators = [] - const session = { signedIn: true } - TableValidators.watch.validators.call({ $store, session }, validators) - expect($store.dispatch).not.toHaveBeenCalledWith( - `getRewardsFromAllValidators` - ) - }) - - it(`doesn't update rewards if validator set is undefined`, () => { - const validators = undefined - const session = { signedIn: true } - TableValidators.watch.validators.call({ $store, session }, validators) - expect($store.dispatch).not.toHaveBeenCalledWith( - `getRewardsFromAllValidators` - ) - }) - it(`should filter the validators for your delegations`, () => { const session = { signedIn: true } expect( diff --git a/test/unit/specs/components/wallet/PageTransactions.spec.js b/test/unit/specs/components/wallet/PageTransactions.spec.js index 59d5a9d30d..5d95db0e6a 100644 --- a/test/unit/specs/components/wallet/PageTransactions.spec.js +++ b/test/unit/specs/components/wallet/PageTransactions.spec.js @@ -316,10 +316,4 @@ describe(`PageTransactions`, () => { 1 ]) }) - - it(`updates transactions every block`, () => { - const refreshTransactions = jest.fn() - PageTransactions.watch.lastHeader.handler.call({ refreshTransactions }) - expect(refreshTransactions).toHaveBeenCalled() - }) }) diff --git a/test/unit/specs/components/wallet/PageWallet.spec.js b/test/unit/specs/components/wallet/PageWallet.spec.js index bcd24b09de..02fc2c0422 100644 --- a/test/unit/specs/components/wallet/PageWallet.spec.js +++ b/test/unit/specs/components/wallet/PageWallet.spec.js @@ -13,7 +13,7 @@ describe(`PageWallet`, () => { balances: lcdClientMock.state.accounts[lcdClientMock.addresses[0]].coins, externals: { config: { faucet: `yo` } }, }, - lastHeader: ``, + lastHeader: { height: `20` }, connected: true, session: { signedIn: true } } @@ -127,21 +127,4 @@ describe(`PageWallet`, () => { }) expect(wrapper.exists(`tm-data-loading`)).toBe(true) }) - - describe(`updates balances every block`, () => { - it(`should not update if the user hasn't signed in`, () => { - const queryWalletBalances = jest.fn() - const session = { signedIn: false } - PageWallet.watch.lastHeader.handler.call({ session, queryWalletBalances }) - expect(queryWalletBalances).not.toHaveBeenCalled() - }) - - it(`should update if the user has signed in`, () => { - const queryWalletBalances = jest.fn() - const session = { signedIn: true } - PageWallet.watch.lastHeader.handler.call({ session, queryWalletBalances }) - expect(queryWalletBalances).toHaveBeenCalled() - }) - }) - }) diff --git a/test/unit/specs/store/__snapshots__/delegation.spec.js.snap b/test/unit/specs/store/__snapshots__/delegation.spec.js.snap deleted file mode 100644 index 96ad63c5e2..0000000000 --- a/test/unit/specs/store/__snapshots__/delegation.spec.js.snap +++ /dev/null @@ -1,47 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Module: Delegations submits delegation transaction 1`] = ` -Array [ - Array [ - "sendTx", - Object { - "delegation": Object { - "amount": "undefined", - "denom": "STAKE", - }, - "delegator_address": "cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9", - "password": undefined, - "submitType": undefined, - "to": "cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9", - "type": "postDelegation", - "validator_address": undefined, - }, - ], - Array [ - "updateDelegates", - ], -] -`; - -exports[`Module: Delegations submits undelegation transaction 1`] = ` -Array [ - Array [ - "sendTx", - Object { - "delegation": Object { - "amount": "undefined", - "denom": "STAKE", - }, - "delegator_address": "cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9", - "password": undefined, - "submitType": undefined, - "to": "cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9", - "type": "postDelegation", - "validator_address": undefined, - }, - ], - Array [ - "updateDelegates", - ], -] -`; diff --git a/test/unit/specs/store/delegation.spec.js b/test/unit/specs/store/delegation.spec.js index ee539122cb..cde825076b 100644 --- a/test/unit/specs/store/delegation.spec.js +++ b/test/unit/specs/store/delegation.spec.js @@ -192,37 +192,65 @@ describe(`Module: Delegations`, () => { { stakingTransactions } ) - expect(dispatch.mock.calls).toMatchSnapshot() + expect(dispatch).toHaveBeenCalledWith(`getAllTxs`) }) it(`submits undelegation transaction`, async () => { - const stakingTransactions = {} - stakingTransactions.delegations = [ + const validator = lcdClientMock.state.candidates[0] + const amount = 10 + const password = `` + const submitType = `ledger` + const dispatch = jest.fn() + + await actions.submitUnbondingDelegation( { - validator: lcdClientMock.state.candidates[0], - atoms: -113 + rootState: mockRootState, + state, + dispatch }, - { - validator: lcdClientMock.state.candidates[1], - atoms: -356 - } - ] + { validator, amount, password, submitType } + ) + + expect(dispatch).toHaveBeenCalledWith(`sendTx`, { + type: `postUnbondingDelegation`, + to: `cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9`, + delegator_address: `cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9`, + validator_address: validator.operator_address, + shares: `10.0000000000`, + password, + submitType + }) + expect(dispatch).toHaveBeenCalledWith(`getAllTxs`) + }) + + it(`submits redelegation transaction`, async () => { + const validatorSrc = lcdClientMock.state.candidates[0] + const validatorDst = lcdClientMock.state.candidates[1] + const amount = 10 + const password = `` + const submitType = `ledger` const dispatch = jest.fn() - await actions.submitDelegation( + await actions.submitRedelegation( { rootState: mockRootState, - getters: { - liquidAtoms: 1000 - }, state, - dispatch, - commit: () => {} + dispatch }, - { stakingTransactions } + { validatorSrc, validatorDst, amount, password, submitType } ) - expect(dispatch.mock.calls).toMatchSnapshot() + expect(dispatch).toHaveBeenCalledWith(`sendTx`, { + type: `postRedelegation`, + to: `cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9`, + delegator_address: `cosmos15ky9du8a2wlstz6fpx3p4mqpjyrm5ctpesxxn9`, + validator_src_address: validatorSrc.operator_address, + validator_dst_address: validatorDst.operator_address, + shares: `10.0000000000`, + password, + submitType + }) + expect(dispatch).toHaveBeenCalledWith(`getAllTxs`) }) describe(`queries the delegated atoms on reconnection`, () => { @@ -339,7 +367,7 @@ describe(`Module: Delegations`, () => { getters: { liquidAtoms: 1000 }, - dispatch: () => {}, + dispatch: () => { }, commit }, { @@ -389,6 +417,7 @@ describe(`Module: Delegations`, () => { ) jest.runAllTimers() expect(dispatch).toHaveBeenCalledWith(`updateDelegates`) + expect(dispatch).toHaveBeenCalledWith(`getAllTxs`) }) it(`should store an error if failed to load delegations`, async () => { @@ -442,11 +471,13 @@ describe(`Module: Delegations`, () => { const dispatch = jest.fn(() => []) - await actions.updateDelegates({ dispatch, rootState: { - session: { - signedIn: true + await actions.updateDelegates({ + dispatch, rootState: { + session: { + signedIn: true + } } - } }) + }) expect(dispatch).toHaveBeenCalledWith(`getDelegates`) expect(dispatch).toHaveBeenCalledWith(`getBondedDelegates`, [])