diff --git a/changes/ana_emoney-format-rewards b/changes/ana_emoney-format-rewards
new file mode 100644
index 0000000000..952173c053
--- /dev/null
+++ b/changes/ana_emoney-format-rewards
@@ -0,0 +1 @@
+[Added] [#3559](https://github.com/cosmos/lunie/pull/3559) Now rewards for multidenom networks are displayed in TmBalance and staking denom is especified in validators' components @Bitcoinera
\ No newline at end of file
diff --git a/src/ActionModal/components/ActionModal.vue b/src/ActionModal/components/ActionModal.vue
index 07155f8cba..d415b51d78 100644
--- a/src/ActionModal/components/ActionModal.vue
+++ b/src/ActionModal/components/ActionModal.vue
@@ -936,7 +936,7 @@ export default {
.action-modal-footer .tm-form-group .tm-form-group__field {
display: flex;
align-items: center;
- justify-items: space-between;
+ justify-content: flex-end;
}
.action-modal-footer .tm-form-group .tm-form-group__field .tertiary {
diff --git a/src/components/common/TmBalance.vue b/src/components/common/TmBalance.vue
index cd1f03218e..4e16bbe77c 100644
--- a/src/components/common/TmBalance.vue
+++ b/src/components/common/TmBalance.vue
@@ -34,39 +34,76 @@
-
@@ -136,6 +173,7 @@ export default {
selectedTokenFiatValue: `Tokens Total Fiat Value`,
selectedFiatCurrency: `EUR`, // EUR is our default fiat currency
showTutorial: false,
+ rewards: [],
cosmosTokensTutorial: {
fullguide: `https://lunie.io/guides/how-to-get-tokens/`,
background: `red`,
@@ -183,19 +221,10 @@ export default {
readyToWithdraw() {
return this.overview.totalRewards > 0
},
- formattedBalances() {
- return this.balances
- .filter(balance => !balance.denom.includes(this.stakingDenom))
- .map(
- balance =>
- (balance = {
- denom: balance.denom
- .charAt(0)
- .toLowerCase()
- .concat(balance.denom.slice(-3)),
- amount: parseFloat(balance.amount).toFixed(2)
- })
- )
+ filteredMultiDenomBalances() {
+ return this.balances.filter(
+ balance => !balance.denom.includes(this.stakingDenom)
+ )
},
concatBalances() {
let balancesArray = []
@@ -233,6 +262,17 @@ export default {
} else {
return [this.stakingDenom]
}
+ },
+ isMultiDenomNetwork() {
+ if (this.balances && this.balances.length > 0) {
+ return this.balances.find(
+ balance => balance.denom !== this.stakingDenom
+ )
+ ? true
+ : false
+ } else {
+ return false
+ }
}
},
methods: {
@@ -247,6 +287,17 @@ export default {
},
hideTutorial() {
this.showTutorial = false
+ },
+ calculateTotalRewardsDenom(denom) {
+ if (this.overview.rewards && this.overview.rewards.length > 0) {
+ let rewardsAccumulator = 0
+ this.overview.rewards
+ .filter(reward => reward.denom === denom)
+ .forEach(reward => {
+ rewardsAccumulator += parseFloat(reward.amount)
+ })
+ return rewardsAccumulator
+ }
}
},
apollo: {
@@ -257,6 +308,10 @@ export default {
totalRewards
liquidStake
totalStake
+ rewards {
+ amount
+ denom
+ }
}
}
`,
@@ -310,7 +365,8 @@ export default {
}
return {
...data.overview,
- totalRewards: Number(data.overview.totalRewards)
+ totalRewards: Number(data.overview.totalRewards),
+ rewards: data.overview.rewards
}
},
/* istanbul ignore next */
@@ -408,7 +464,6 @@ export default {
.values-container {
position: relative;
- padding: 1rem 2rem;
}
.values-container h2 {
@@ -430,29 +485,9 @@ export default {
padding-right: 2.5rem;
}
-.tokens-div {
- position: absolute;
- right: 1.25rem;
- top: 3.5rem;
-}
-
-.tokens-div > .col {
- margin-right: 1rem;
-}
-
-.token-denom {
- font-size: 12px;
- float: left;
-}
-
-.token-balance {
- font-weight: bold;
-}
-
-.currency-selector.tm-form-group {
- position: absolute;
- right: 1.25rem;
- top: -0.7rem;
+p.rewards {
+ color: var(--success);
+ font-size: var(--s);
}
.rewards h2 {
@@ -460,17 +495,29 @@ export default {
font-size: var(--m);
}
+.rewards.multi-denom h2 {
+ font-size: 12px;
+}
+
.available-atoms h2 {
font-size: var(--m);
line-height: 20px;
}
.upper-header {
+ padding: 0 2rem;
display: flex;
align-items: center;
justify-content: space-between;
}
+.lower-header {
+ padding: 2rem;
+ align-items: normal;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
.button-container {
display: flex;
align-items: center;
@@ -478,6 +525,7 @@ export default {
width: 100%;
border-bottom: 1px solid var(--bc-dim);
border-top: 1px solid var(--bc-dim);
+ margin-top: 1rem;
margin-bottom: 2rem;
}
@@ -490,8 +538,8 @@ export default {
flex-direction: row;
}
-.small-container {
- padding-top: 1rem;
+.row div {
+ white-space: nowrap;
}
.open-tutorial {
@@ -535,85 +583,61 @@ export default {
flex-direction: column-reverse;
}
- .values-container {
- flex-direction: column;
- width: 100%;
- }
-
.values-container .total-atoms__value {
font-size: 28px;
font-weight: 500;
line-height: 32px;
}
- .available-atoms,
- .rewards {
- padding: 0;
- }
-
.total-atoms {
padding: 1rem 0;
text-align: center;
}
- .tutorial-button {
- margin: 0 auto 1rem auto;
- }
-
- .scroll {
- display: flex;
- width: 90vw;
- overflow-x: auto;
- /* Make it smooth scrolling on iOS devices */
- -webkit-overflow-scrolling: touch;
- }
-
- .scroll-item {
- width: 100%;
- }
-
- /* This doesn't work */
- /* .scroll > .scroll-item {
- flex: 0 0 auto;
- } */
-
- .scroll > .row > div {
- margin-right: 3rem;
+ .single-denom-rewards {
+ justify-content: center;
+ text-align: center;
}
- .tokens-div {
- position: inherit;
- margin: 0;
- top: 0;
+ .single-denom-rewards .rewards {
+ padding-right: 0;
}
- .token-denom {
- float: none;
+ .single-denom-rewards .available-atoms {
+ padding-right: 4rem;
}
- .currency-selector.tm-form-group {
- width: 40px;
- right: 2.5rem;
+ .tutorial-button {
+ margin: 0 auto 1rem auto;
}
.button-container {
width: 100%;
padding: 1rem;
border-top: 1px solid var(--bc);
+ margin-top: 0rem;
}
.button-container button {
width: 50%;
}
- .small-container {
- display: flex;
- justify-content: space-evenly;
- padding: 1rem 0;
- text-align: center;
- }
.tutorial-container {
padding-right: 1rem;
}
}
+
+@media screen and (max-width: 1023px) {
+ .scroll {
+ display: flex;
+ width: 100vw;
+ overflow-x: auto;
+ /* Make it smooth scrolling on iOS devices */
+ -webkit-overflow-scrolling: touch;
+ }
+
+ .scroll-item {
+ width: 100%;
+ }
+}
diff --git a/src/components/staking/LiValidator.vue b/src/components/staking/LiValidator.vue
index edd797badf..56d19af4b4 100644
--- a/src/components/staking/LiValidator.vue
+++ b/src/components/staking/LiValidator.vue
@@ -42,8 +42,18 @@
{{ delegation.amount | bigFigureOrShortDecimals }}
-
- +{{ rewards.amount | bigFigureOrShortDecimals }}
+
+ +{{
+ filterStakingDenomReward() | bigFigureOrShortDecimals
+ }}
@@ -85,26 +95,39 @@ export default {
type: Object,
required: true
},
+ /* istanbul ignore next */
delegation: {
type: Object,
default: () => ({})
},
+ /* istanbul ignore next */
rewards: {
- type: Object,
+ type: Array,
default: () => ({})
},
index: {
type: Number,
required: true
},
+ /* istanbul ignore next */
showOnMobile: {
type: String,
- /* istanbul ignore next */
default: () => "returns"
+ },
+ stakingDenom: {
+ type: String,
+ default: ""
}
},
methods: {
- bigFigureOrPercent
+ bigFigureOrPercent,
+ bigFigureOrShortDecimals,
+ filterStakingDenomReward() {
+ const stakingDenomRewards = this.rewards.filter(
+ reward => reward.denom === this.stakingDenom
+ )
+ return stakingDenomRewards[0].amount
+ }
}
}
diff --git a/src/components/staking/PageValidator.vue b/src/components/staking/PageValidator.vue
index 835aa21fab..ddcbe69a61 100644
--- a/src/components/staking/PageValidator.vue
+++ b/src/components/staking/PageValidator.vue
@@ -61,7 +61,7 @@
{{ delegation.amount | fullDecimals }}
- +{{ rewards.amount | fullDecimals | noBlanks }}
+ +{{ filterStakingDenomReward() | noBlanks }}
@@ -259,6 +259,8 @@ export default {
error: false,
loaded: false,
showTutorial: false,
+ isMostRelevantRewardSelected: false,
+ mostRelevantReward: ``,
cosmosStakingTutorial: {
fullguide: `https://lunie.io/guides/how-cosmos-staking-works/`,
background: `blue`,
@@ -314,17 +316,21 @@ export default {
},
methods: {
shortDecimals,
+ fullDecimals,
atoms,
percent,
fromNow,
noBlanks,
moment,
+ /* istanbul ignore next */
onDelegation() {
this.$refs.delegationModal.open()
},
+ /* istanbul ignore next */
onUndelegation() {
this.$refs.undelegationModal.open()
},
+ /* istanbul ignore next */
isBlankField(field, alternateFilter) {
return field ? alternateFilter(field) : noBlanks(field)
},
@@ -336,6 +342,14 @@ export default {
},
handleIntercom() {
this.$store.dispatch(`displayMessenger`)
+ },
+ filterStakingDenomReward() {
+ if (this.rewards && this.rewards.length > 0) {
+ const stakingDenomRewards = this.rewards.filter(
+ reward => reward.denom === this.stakingDenom
+ )
+ return stakingDenomRewards[0].amount
+ }
}
},
apollo: {
@@ -355,18 +369,19 @@ export default {
}
}
`,
+ /* istanbul ignore next */
skip() {
- /* istanbul ignore next */
return !this.userAddress
},
+ /* istanbul ignore next */
variables() {
- /* istanbul ignore next */
return {
networkId: this.network,
delegatorAddress: this.userAddress,
operatorAddress: this.$route.params.validator
}
},
+ /* istanbul ignore next */
update(result) {
if (!result.delegation) {
return {
@@ -393,57 +408,79 @@ export default {
operatorAddress: $operatorAddress
) {
amount
+ denom
}
}
`,
+ /* istanbul ignore next */
skip() {
- /* istanbul ignore next */
return !this.userAddress
},
+ /* istanbul ignore next */
variables() {
- /* istanbul ignore next */
return {
networkId: this.network,
delegatorAddress: this.userAddress,
operatorAddress: this.$route.params.validator
}
},
+ /* istanbul ignore next */
update(result) {
- /* istanbul ignore next */
return result.rewards && result.rewards.length > 0
- ? result.rewards[0]
+ ? result.rewards
: { amount: 0 }
}
},
validator: {
query: ValidatorProfile,
+ /* istanbul ignore next */
variables() {
- /* istanbul ignore next */
return {
networkId: this.network,
operatorAddress: this.$route.params.validator
}
},
+ /* istanbul ignore next */
update(result) {
if (!result.validator) return {}
- /* istanbul ignore next */
this.loaded = true
- /* istanbul ignore next */
return {
...result.validator,
statusDetailed: getStatusText(result.validator.statusDetailed)
}
}
},
+ stakingDenom: {
+ query: gql`
+ query Network($networkId: String!) {
+ network(id: $networkId) {
+ id
+ stakingDenom
+ }
+ }
+ `,
+ /* istanbul ignore next */
+ variables() {
+ return {
+ networkId: this.network
+ }
+ },
+ /* istanbul ignore next */
+ update(data) {
+ if (!data.network) return ""
+ return data.network.stakingDenom
+ }
+ },
$subscribe: {
blockAdded: {
+ /* istanbul ignore next */
variables() {
- /* istanbul ignore next */
return {
networkId: this.network
}
},
+ /* istanbul ignore next */
query() {
return gql`
subscription($networkId: String!) {
@@ -454,26 +491,26 @@ export default {
}
`
},
+ /* istanbul ignore next */
result() {
- /* istanbul ignore next */
this.$apollo.queries.rewards.refetch()
}
},
userTransactionAdded: {
+ /* istanbul ignore next */
variables() {
- /* istanbul ignore next */
return {
networkId: this.network,
address: this.userAddress
}
},
+ /* istanbul ignore next */
skip() {
- /* istanbul ignore next */
return !this.userAddress
},
query: UserTransactionAdded,
+ /* istanbul ignore next */
result({ data }) {
- /* istanbul ignore next */
if (data.userTransactionAdded.success) {
this.$apollo.queries.delegation.refetch()
}
@@ -620,10 +657,12 @@ span {
border-color: var(--success);
}
-.validator-status-detailed {
+.validator-status-detailed,
+.no-img-info {
display: block;
- margin-top: 0.4rem;
+ margin-top: 1rem;
font-size: 0.8rem;
+ color: var(--dim);
}
@media screen and (max-width: 425px) {
diff --git a/src/components/staking/TableValidators.vue b/src/components/staking/TableValidators.vue
index abb36d3895..8ae7d8ed46 100644
--- a/src/components/staking/TableValidators.vue
+++ b/src/components/staking/TableValidators.vue
@@ -21,6 +21,7 @@
:delegation="getDelegation(validator)"
:rewards="getRewards(validator)"
:show-on-mobile="showOnMobile"
+ :staking-denom="stakingDenom"
/>
@@ -60,7 +61,8 @@ export default {
property: `expectedReturns`,
order: `desc`
},
- showing: 15
+ showing: 15,
+ stakingDenom: ""
}),
computed: {
...mapGetters([`address`, `network`]),
@@ -123,9 +125,15 @@ export default {
)
},
getRewards({ operatorAddress }) {
- return this.rewards.find(
- ({ validator }) => validator.operatorAddress === operatorAddress
- )
+ if (this.rewards) {
+ return (
+ this.rewards
+ /* istanbul ignore next */
+ .filter(
+ ({ validator }) => validator.operatorAddress === operatorAddress
+ )
+ )
+ }
}
},
apollo: {
@@ -137,29 +145,56 @@ export default {
operatorAddress
}
amount
+ denom
}
}
`,
+ /* istanbul ignore next */
skip() {
return !this.address
},
+ /* istanbul ignore next */
variables() {
return {
networkId: this.network,
delegatorAddress: this.address
}
},
+ /* istanbul ignore next */
update: result => {
return result.rewards || []
}
},
+ stakingDenom: {
+ query: gql`
+ query Network($networkId: String!) {
+ network(id: $networkId) {
+ id
+ stakingDenom
+ }
+ }
+ `,
+ /* istanbul ignore next */
+ variables() {
+ return {
+ networkId: this.network
+ }
+ },
+ /* istanbul ignore next */
+ update(data) {
+ if (!data.network) return ""
+ return data.network.stakingDenom
+ }
+ },
$subscribe: {
blockAdded: {
+ /* istanbul ignore next */
variables() {
return {
networkId: this.network
}
},
+ /* istanbul ignore next */
query() {
return gql`
subscription($networkId: String!) {
@@ -170,8 +205,8 @@ export default {
}
`
},
+ /* istanbul ignore next */
result() {
- /* istanbul ignore next */
this.$apollo.queries.rewards.refetch()
}
}
diff --git a/src/styles/table.css b/src/styles/table.css
index 96e06579c3..569ab20276 100644
--- a/src/styles/table.css
+++ b/src/styles/table.css
@@ -137,10 +137,6 @@
padding: 0;
}
- .data-table__row__info {
- max-width: calc(100vw - 6rem);
- }
-
.data-table th:nth-child(4) {
width: 20%;
}
diff --git a/tests/unit/specs/components/common/TmBalance.spec.js b/tests/unit/specs/components/common/TmBalance.spec.js
index 489980c07c..d3ea696e86 100644
--- a/tests/unit/specs/components/common/TmBalance.spec.js
+++ b/tests/unit/specs/components/common/TmBalance.spec.js
@@ -40,7 +40,21 @@ describe(`TmBalance`, () => {
overview: {
totalStake: 3210,
liquidStake: 1230,
- totalRewards: 1000.45
+ totalRewards: 1000.45,
+ rewards: [
+ {
+ amount: 1,
+ denom: `TOKEN1`
+ },
+ {
+ amount: 2,
+ denom: `TOKEN1`
+ },
+ {
+ amount: 1.5,
+ denom: `TOKEN1`
+ }
+ ]
}
})
})
@@ -154,6 +168,22 @@ describe(`TmBalance`, () => {
])
})
+ it(`should return true if rewards contain multiple denoms`, () => {
+ wrapper.setData({
+ balances: [
+ {
+ amount: 1,
+ denom: `TOKEN1`
+ },
+ {
+ amount: 2,
+ denom: `utoken2`
+ }
+ ]
+ })
+ expect(wrapper.vm.isMultiDenomNetwork).toBe(true)
+ })
+
it(`should show How To Get Tokens tutorial`, () => {
wrapper.setData({
showTutorial: false
@@ -169,4 +199,9 @@ describe(`TmBalance`, () => {
wrapper.vm.hideTutorial()
expect(wrapper.vm.showTutorial).toBe(false)
})
+
+ it(`should calculate the total rewards amount for each denom when rewards contain multiple denoms`, () => {
+ const totalDenomRewards = wrapper.vm.calculateTotalRewardsDenom(`TOKEN1`)
+ expect(totalDenomRewards).toBe(4.5)
+ })
})
diff --git a/tests/unit/specs/components/common/__snapshots__/TmBalance.spec.js.snap b/tests/unit/specs/components/common/__snapshots__/TmBalance.spec.js.snap
index 860e7952c6..966f5cf694 100644
--- a/tests/unit/specs/components/common/__snapshots__/TmBalance.spec.js.snap
+++ b/tests/unit/specs/components/common/__snapshots__/TmBalance.spec.js.snap
@@ -41,14 +41,18 @@ exports[`TmBalance do not show available atoms when the user has none in the fir
class="scroll"
>
-
-
@@ -122,38 +126,48 @@ exports[`TmBalance show the balance header when signed in 1`] = `
class="scroll"
>
-
-
diff --git a/tests/unit/specs/components/staking/LiValidator.spec.js b/tests/unit/specs/components/staking/LiValidator.spec.js
index 192e756429..b2e6681cc9 100644
--- a/tests/unit/specs/components/staking/LiValidator.spec.js
+++ b/tests/unit/specs/components/staking/LiValidator.spec.js
@@ -1,4 +1,5 @@
import { shallowMount, createLocalVue } from "@vue/test-utils"
+import { toMicroDenom } from "scripts/common"
import VueApollo from "vue-apollo"
import LiValidator from "src/components/staking/LiValidator"
@@ -65,6 +66,12 @@ describe(`LiValidator`, () => {
localVue,
propsData: {
validator,
+ rewards: [
+ {
+ amount: 1,
+ denom: `token1`
+ }
+ ],
index,
showOnMobile: "returns"
},
@@ -92,4 +99,30 @@ describe(`LiValidator`, () => {
})
expect(wrapper.find("avatar-stub").exists())
})
+
+ it(`should filter the staking denom reward`, () => {
+ const rewards = [
+ {
+ amount: 1,
+ denom: `TOKEN1`
+ },
+ {
+ amount: 2,
+ denom: `TOKEN2`
+ },
+ {
+ amount: 3,
+ denom: `TOKEN3`
+ }
+ ]
+ const self = {
+ stakingDenom: `TOKEN1`,
+ rewards: rewards,
+ toMicroDenom
+ }
+ const stakingDenomReward = LiValidator.methods.filterStakingDenomReward.call(
+ self
+ )
+ expect(stakingDenomReward).toEqual(1)
+ })
})
diff --git a/tests/unit/specs/components/staking/PageValidator.spec.js b/tests/unit/specs/components/staking/PageValidator.spec.js
index 7474614070..bed94d61d7 100644
--- a/tests/unit/specs/components/staking/PageValidator.spec.js
+++ b/tests/unit/specs/components/staking/PageValidator.spec.js
@@ -1,4 +1,5 @@
import PageValidator from "staking/PageValidator"
+import { toMicroDenom } from "scripts/common"
import { shallowMount, createLocalVue } from "@vue/test-utils"
const validator = {
@@ -124,6 +125,31 @@ describe(`PageValidator`, () => {
PageValidator.methods.handleIntercom.call(self)
expect(self.$store.dispatch).toHaveBeenCalledWith("displayMessenger")
})
+ it(`should filter the staking denom reward`, () => {
+ const rewards = [
+ {
+ amount: 1,
+ denom: `TOKEN1`
+ },
+ {
+ amount: 2,
+ denom: `TOKEN2`
+ },
+ {
+ amount: 3,
+ denom: `TOKEN3`
+ }
+ ]
+ const self = {
+ stakingDenom: `TOKEN1`,
+ rewards: rewards,
+ toMicroDenom
+ }
+ const stakingDenomReward = PageValidator.methods.filterStakingDenomReward.call(
+ self
+ )
+ expect(stakingDenomReward).toEqual(1)
+ })
})
describe(`isBlankField method`, () => {
diff --git a/tests/unit/specs/components/staking/TableValidators.spec.js b/tests/unit/specs/components/staking/TableValidators.spec.js
index 1a20ed4b46..7f94c0f309 100644
--- a/tests/unit/specs/components/staking/TableValidators.spec.js
+++ b/tests/unit/specs/components/staking/TableValidators.spec.js
@@ -48,10 +48,6 @@ describe(`TableValidators`, () => {
expect(wrapper.element).toMatchSnapshot()
})
- it(`should add smallName property to validators`, () => {
- expect(wrapper.vm.showingValidators[0].smallName).toBe(`cosmos1a`)
- })
-
it(`should sort the delegates by selected property`, () => {
wrapper.vm.sort.property = `operatorAddress`
wrapper.vm.sort.order = `desc`
diff --git a/tests/unit/specs/components/staking/__snapshots__/TableValidators.spec.js.snap b/tests/unit/specs/components/staking/__snapshots__/TableValidators.spec.js.snap
index e8a4989afb..7a5d89bdf4 100644
--- a/tests/unit/specs/components/staking/__snapshots__/TableValidators.spec.js.snap
+++ b/tests/unit/specs/components/staking/__snapshots__/TableValidators.spec.js.snap
@@ -20,106 +20,121 @@ exports[`TableValidators shows a validator table 1`] = `