Skip to content

Commit

Permalink
Fabo/1199 improve jank at start (#1216)
Browse files Browse the repository at this point in the history
* added native menu for versions

* remove about from view

* changelog

* fixed tests

* linted and simplified

* remove more about code

* show correct voting power

* changelog

* extracted keybase and throttle updates to localstorage

* changelog

* fixed wallet tests

* fixed tests

* fixed tests

* added throttle tests

* removed check if state has loaded, as we are filtering mutations

* updated snapshots

* skip loading validators at start

* linted

* fixed check for validators test

* add in cart delegates to cache

* fix moniker not showing

* fix tests

* fixed page bond test

* add test for restoring committed delegations

* handle issue with staking e2e tests

* fixed current atoms in pagebond not being updated right away

* changelog

* fixed cache not restoring cart

* increased coverage

* fix showing undefined for bonding denom

* fix staked indicator

* changelog

* fix wrong error showing on pagebond

* changelog

* removed querying for delegations after staking and relying on optimistic update

* fixed bad test on pagebond

* readded updating validators after staking

* fixed back pagebond snapshot
  • Loading branch information
faboweb authored and fedekunze committed Sep 4, 2018
1 parent a045903 commit 9fe51d8
Show file tree
Hide file tree
Showing 27 changed files with 364 additions and 237 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

* use correct set of seed nodes @ƒaboweb
* validator page showed incorrect voting power @faboweb
* improves poor performance at start by throttling the updates of the cached store @faboweb
* Run lint test in CI. @NodeGuy
* current atoms in PageBond still showed old atoms right after staking @ƒaboweb
* fix showing undefined for bonding denom in staking sucess message @faboweb
* fix not showing a lock (I have stake with this one) on a validator if stake is less then 1 @faboweb
* fix showing wrong error on pagebond validation @okwme

## [0.10.1] - 2018-08-29

Expand Down
1 change: 0 additions & 1 deletion app/networks

This file was deleted.

1 change: 1 addition & 0 deletions app/networks
Submodule networks added at 07c6bb
2 changes: 1 addition & 1 deletion app/src/renderer/components/staking/LiDelegate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
.li-delegate__value.status
span {{ delegateType }}
template(v-if="userCanDelegate")
.li-delegate__value.checkbox(v-if="yourVotes > 0")
.li-delegate__value.checkbox(v-if="committedDelegations[delegate.id]")
i.material-icons lock
.li-delegate__value.checkbox#remove-from-cart(v-else-if="inCart" @click='rm(delegate)')
i.material-icons check_box
Expand Down
8 changes: 4 additions & 4 deletions app/src/renderer/components/staking/PageBond.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ tm-page.page-bond(title="Staking")
:class="bondGroupClass(delta(d.atoms, d.oldAtoms))")
.bond-group__fields
.bond-bar
label.bond-bar__label(v-if="!d.delegate.revoked") {{ d.delegate.moniker }}
label.bond-bar__label.revoked(v-if="d.delegate.revoked") {{ d.delegate.moniker }}
label.bond-bar__label(v-if="!d.delegate.revoked") {{ d.delegate.description.moniker }}
label.bond-bar__label.revoked(v-if="d.delegate.revoked") {{ d.delegate.description.moniker }}
label.bond-bar__revoked(v-if="d.delegate.revoked") REVOKED
.bond-bar__input
.bond-bar-old__outer
Expand Down Expand Up @@ -72,7 +72,7 @@ tm-page.page-bond(title="Staking")

tm-form-msg(:name="bondingDenom + 's'" type="required"
v-if="!$v.fields.delegates.$each[index].atoms.required")
tm-form-msg(name="bondingDenom + 's'" type="numeric"
tm-form-msg(:name="bondingDenom + 's'" type="numeric"
v-if="!$v.fields.delegates.$each[index].atoms.numeric")

.bond-group.bond-group--unbonding(
Expand Down Expand Up @@ -232,7 +232,7 @@ export default {
await this.$store.dispatch("submitDelegation", this.fields.delegates)
this.$store.commit("notify", {
title: "Successful Staking!",
body: `You have successfully staked your ${this.denom}s.`
body: `You have successfully staked your ${this.bondingDenom}s.`
})
this.$router.push("/staking")
} catch (err) {
Expand Down
4 changes: 3 additions & 1 deletion app/src/renderer/components/staking/PageStaking.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export default {
"config",
"user",
"connected",
"bondingDenom"
"bondingDenom",
"keybase"
]),
address() {
return this.user.address
Expand All @@ -93,6 +94,7 @@ export default {
v.small_moniker = v.description.moniker.toLowerCase()
v.percent_of_vote = num.percent(v.voting_power / this.vpTotal)
v.your_votes = this.num.prettyInt(this.committedDelegations[v.id])
v.keybase = this.keybase[v.description.identity]
return v
})
},
Expand Down
7 changes: 5 additions & 2 deletions app/src/renderer/components/staking/PageValidator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ export default {
TmDataError
},
computed: {
...mapGetters(["delegates", "config"]),
...mapGetters(["delegates", "config", "keybase"]),
validator() {
return this.delegates.delegates.find(
let validator = this.delegates.delegates.find(
v => this.$route.params.validator === v.owner
)
if (validator)
validator.keybase = this.keybase[validator.description.identity]
return validator
},
selfBond() {
parseFloat(this.validator.tokens) -
Expand Down
1 change: 1 addition & 0 deletions app/src/renderer/vuex/getters.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const committedDelegations = state => state.delegation.committedDelegates
export const delegates = state => state.delegates
export const shoppingCart = state => state.delegation.delegates
export const validators = state => state.validators.validators
export const keybase = state => state.keybase.identities

// govern
export const proposals = state => state.proposals
Expand Down
37 changes: 1 addition & 36 deletions app/src/renderer/vuex/modules/delegates.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import axios from "axios"

export default ({ node }) => {
const emptyState = {
delegates: [],
Expand Down Expand Up @@ -38,16 +36,6 @@ export default ({ node }) => {
}

state.delegates.push(delegate)
},
setKeybaseIdentity(
state,
{ validatorOwner, avatarUrl, profileUrl, userName }
) {
let validator = state.delegates.find(v => v.owner === validatorOwner)
if (!validator.keybase) validator.keybase = {}
validator.keybase.avatarUrl = avatarUrl
validator.keybase.profileUrl = profileUrl
validator.keybase.userName = userName
}
}

Expand All @@ -73,32 +61,9 @@ export default ({ node }) => {

commit("setDelegates", candidates)
commit("setDelegateLoading", false)
dispatch("updateValidatorAvatars")
dispatch("getKeybaseIdentities", candidates)

return state.delegates
},
async updateValidatorAvatars({ state, commit }) {
return Promise.all(
state.delegates.map(async validator => {
if (validator.description.identity && !validator.keybase) {
let urlPrefix =
"https://keybase.io/_/api/1.0/user/lookup.json?key_suffix="
let fullUrl = urlPrefix + validator.description.identity
let json = await axios.get(fullUrl)
if (json.data.status.name === "OK") {
let user = json.data.them[0]
if (user && user.pictures && user.pictures.primary) {
commit("setKeybaseIdentity", {
validatorOwner: validator.owner,
avatarUrl: user.pictures.primary.url,
userName: user.basics.username,
profileUrl: "https://keybase.io/" + user.basics.username
})
}
}
}
})
)
}
}

Expand Down
35 changes: 26 additions & 9 deletions app/src/renderer/vuex/modules/delegation.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,23 @@ export default ({ node }) => {
begin_unbondings: unbond
})

// usually I would just query the new state through the LCD but at this point we still get the old shares
dispatch("updateDelegates").then(() => {
for (let delegation of delegations) {
commit("setCommittedDelegation", {
candidateId: delegation.delegate.owner,
value: delegation.atoms
})
}
})
// (optimistic update) we update the atoms of the user before we get the new values from chain
let atomsDiff = delegations
// compare old and new delegations and diff against old atoms
.map(
delegation =>
state.committedDelegates[delegation.delegate.owner] -
delegation.atoms
)
.reduce((sum, diff) => sum + diff, 0)
commit("setAtoms", rootState.user.atoms + atomsDiff)

// we optimistically update the committed delegations
updateCommittedDelegations(delegations, commit)
// TODO usually I would just query the new state through the LCD and update the state with the result, but at this point we still get the old shares
dispatch("updateDelegates").then(() =>
updateCommittedDelegations(delegations, commit)
)
}
}

Expand All @@ -165,3 +173,12 @@ export default ({ node }) => {
actions
}
}

function updateCommittedDelegations(delegations, commit) {
for (let delegation of delegations) {
commit("setCommittedDelegation", {
candidateId: delegation.delegate.owner,
value: delegation.atoms
})
}
}
3 changes: 2 additions & 1 deletion app/src/renderer/vuex/modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export default opts => ({
themes: require("./themes.js").default(opts),
user: require("./user.js").default(opts),
validators: require("./validators.js").default(opts),
wallet: require("./wallet.js").default(opts)
wallet: require("./wallet.js").default(opts),
keybase: require("./keybase.js").default(opts)
})
60 changes: 60 additions & 0 deletions app/src/renderer/vuex/modules/keybase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import axios from "axios"

export default ({}) => {
const emptyState = {
identities: {},
loading: false
}
const state = JSON.parse(JSON.stringify(emptyState))

const mutations = {
setKeybaseIdentities(state, identities) {
identities.forEach(identity => {
state.identities[identity.keybaseId] = identity
})
}
}

const actions = {
async getKeybaseIdentity({ state }, keybaseId) {
if (!/.{16}/.test(keybaseId)) return // the keybase id is not correct
if (state.identities[keybaseId]) return // we already have this identity

let urlPrefix =
"https://keybase.io/_/api/1.0/user/lookup.json?key_suffix="
let fullUrl = urlPrefix + keybaseId
let json = await axios.get(fullUrl)
if (json.data.status.name === "OK") {
let user = json.data.them[0]
if (user && user.pictures && user.pictures.primary) {
return {
keybaseId,
avatarUrl: user.pictures.primary.url,
userName: user.basics.username,
profileUrl: "https://keybase.io/" + user.basics.username
}
}
}
},
async getKeybaseIdentities({ dispatch, commit }, validators) {
return Promise.all(
validators.map(async validator => {
if (validator.description.identity) {
return dispatch(
"getKeybaseIdentity",
validator.description.identity
)
}
})
).then(identities => {
commit("setKeybaseIdentities", identities.filter(x => !!x))
})
}
}

return {
state,
actions,
mutations
}
}
6 changes: 5 additions & 1 deletion app/src/renderer/vuex/modules/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ export default function({ node }) {
rootState.wallet.zoneIds.unshift(header.chain_id)
}

await dispatch("maybeUpdateValidators", header)
// updating the header is done even while the user is not logged in
// to prevent errors popping up from the LCD before the user is signed on, we skip updating validators before
// TODO identify why rest calls fail at this point
if (rootState.user.signedIn)
await dispatch("maybeUpdateValidators", header)
},
async reconnect({ commit }) {
if (state.stopConnecting) return
Expand Down
2 changes: 1 addition & 1 deletion app/src/renderer/vuex/modules/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default ({ node }) => {
let { address } = await node.getKey(account)
state.address = address

commit("loadPersistedState", { password })
dispatch("loadPersistedState", { password })
commit("setModalSession", false)
dispatch("initializeWallet", address)
dispatch("loadErrorCollection", account)
Expand Down
35 changes: 8 additions & 27 deletions app/src/renderer/vuex/modules/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,6 @@ export default ({ node }) => {
},
setDenoms(state, denoms) {
state.denoms = denoms
},
setTransactionTime(state, { blockHeight, blockMetaInfo }) {
state.history = state.history.map(t => {
if (t.height === blockHeight) {
// console.log("blockMetaInfo", blockMetaInfo)
t.time = blockMetaInfo && blockMetaInfo.header.time
}
return t
})
}
}

Expand Down Expand Up @@ -99,30 +90,20 @@ export default ({ node }) => {
if (!res) return

const uniqueTransactions = uniqBy(res, "hash")
commit("setWalletHistory", uniqueTransactions)

await dispatch("enrichTransactions", uniqueTransactions)
commit("setWalletHistory", uniqueTransactions)

commit("setHistoryLoading", false)
},
async enrichTransactions({ dispatch }, transactions) {
let blockHeights = []
transactions.forEach(t => {
if (!blockHeights.find(h => h === t.height)) {
blockHeights.push(t.height)
}
})
await Promise.all(
blockHeights.map(h => dispatch("queryTransactionTime", h))
transactions = await Promise.all(
transactions.map(async t => {
let blockMetaInfo = await dispatch("queryBlockInfo", t.height)
t.time = blockMetaInfo && blockMetaInfo.header.time
return t
})
)
},
async queryTransactionTime({ commit, dispatch }, blockHeight) {
let blockMetaInfo = await dispatch("queryBlockInfo", blockHeight)
// console.log(
// "received blockMetaInfo at height " + blockHeight,
// blockMetaInfo
// )
commit("setTransactionTime", { blockHeight, blockMetaInfo })
return transactions
},
async loadDenoms({ commit }) {
// read genesis.json to get default denoms
Expand Down
Loading

0 comments on commit 9fe51d8

Please sign in to comment.