Skip to content

Commit

Permalink
Fabo/better handling of sequence in ActionModal (#3364)
Browse files Browse the repository at this point in the history
* show loading when sequence number is missing + fix some tests

* changelog

* security updates

* log failed tx submissions client side

* fix test for error tracking

* changelog

* fix typo

* fix undefined inside sentry messages

* Update src/ActionModal/components/ActionModal.vue

* removed sequence loading again

* snap

Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com>
  • Loading branch information
faboweb and Bitcoinera authored Jan 8, 2020
1 parent 925ac1a commit 9dad3b1
Show file tree
Hide file tree
Showing 8 changed files with 430 additions and 416 deletions.
2 changes: 2 additions & 0 deletions changes/fabo_fix-sequence-issue
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Fixed] [#3364](https://github.com/cosmos/lunie/pull/3364) Improve handling of sequence querying in ActionModal @faboweb
[Added] [#3364](https://github.com/cosmos/lunie/pull/3364) Track failing transactions clientside in Sentry @faboweb
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"moment": "^2.24.0",
"no-scroll": "^2.1.1",
"register-service-worker": "^1.6.2",
"serialize-javascript": ">=2.1.1",
"subscriptions-transport-ws": "0.9.16",
"timezone-mock": "^1.0.8",
"vue": "^2.6.10",
Expand Down Expand Up @@ -131,4 +132,4 @@
"handlebars": ">=4.5.3",
"serialize-javascript": ">=2.1.1"
}
}
}
89 changes: 49 additions & 40 deletions src/ActionModal/components/ActionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<i class="material-icons">close</i>
</div>
<div class="action-modal-header">
<span class="action-modal-title">{{
requiresSignIn ? `Sign in required` : title
}}</span>
<span class="action-modal-title">
{{ requiresSignIn ? `Sign in required` : title }}
</span>
<Steps
v-if="
[defaultStep, feeStep, signStep].includes(step) &&
Expand Down Expand Up @@ -63,9 +63,9 @@
field-id="gasPrice"
field-label="Gas Price"
>
<span class="input-suffix">{{
network.stakingDenom | viewDenom
}}</span>
<span class="input-suffix">
{{ network.stakingDenom | viewDenom }}
</span>
<TmField
id="gas-price"
v-model="gasPrice"
Expand Down Expand Up @@ -120,7 +120,7 @@
/>
</TmFormGroup>
<HardwareState
v-if="selectedSignMethod === SIGN_METHODS.LEDGER"
v-else-if="selectedSignMethod === SIGN_METHODS.LEDGER"
:icon="session.browserWithLedgerSupport ? 'usb' : 'info'"
:loading="!!sending"
>
Expand All @@ -138,7 +138,7 @@
</div>
</HardwareState>
<HardwareState
v-if="selectedSignMethod === SIGN_METHODS.EXTENSION"
v-else-if="selectedSignMethod === SIGN_METHODS.EXTENSION"
:icon="session.browserWithLedgerSupport ? 'laptop' : 'info'"
:loading="!!sending"
>
Expand Down Expand Up @@ -187,9 +187,7 @@
</div>
<div v-else-if="step === inclusionStep" class="action-modal-form">
<TmDataMsg icon="hourglass_empty" :spin="true">
<div slot="title">
Sent and confirming
</div>
<div slot="title">Sent and confirming</div>
<div slot="subtitle">
Waiting for confirmation from {{ networkId }}.
</div>
Expand All @@ -200,9 +198,7 @@
class="action-modal-form success-step"
>
<TmDataMsg icon="check" :success="true">
<div slot="title">
{{ notifyMessage.title }}
</div>
<div slot="title">{{ notifyMessage.title }}</div>
<div slot="subtitle">
{{ notifyMessage.body }}
<br />
Expand Down Expand Up @@ -294,6 +290,7 @@ import { between, requiredIf } from "vuelidate/lib/validators"
import { track } from "scripts/google-analytics"
import { UserTransactionAdded } from "src/gql"
import config from "src/../config"
import * as Sentry from "@sentry/browser"
import ActionManager from "../utils/ActionManager"
Expand Down Expand Up @@ -469,6 +466,22 @@ export default {
},
prettyIncludedHeight() {
return prettyInt(this.includedHeight)
},
// TODO lets slice this monstrocity
context() {
return {
url: this.network.api_url,
networkId: this.network.id,
chainId: this.network.chain_id,
connected: this.connected,
userAddress: this.session.address,
rewards: this.rewards,
totalRewards: this.overview.totalRewards,
delegations: this.delegations,
bondDenom: this.network.stakingDenom,
isExtensionAccount: this.isExtensionAccount,
account: this.overview.accountInformation
}
}
},
watch: {
Expand All @@ -480,15 +493,18 @@ export default {
this.selectedSignMethod = signMethods[0].value
}
}
},
context: {
immediate: true,
handler(context) {
this.actionManager.setContext(context)
}
}
},
created() {
this.$apollo.skipAll = true
},
updated: function() {
// TODO do we need to set the context on every update of the component?
const context = this.createContext()
this.actionManager.setContext(context)
if (
(this.title === "Withdraw" || this.step === "fees") &&
this.$refs.next
Expand All @@ -497,21 +513,6 @@ export default {
}
},
methods: {
createContext() {
return {
url: this.network.api_url, // state.connection.externals.node.url,
networkId: this.network.id, // state.connection.lastHeader.chain_id,
chainId: this.network.chain_id, // state.connection.lastHeader.chain_id,
connected: this.connected,
userAddress: this.session.address,
rewards: this.rewards, // state.distribution.rewards,
totalRewards: this.overview.totalRewards, // getters.totalRewards,
delegations: this.delegations, // state.delegates.delegates,
bondDenom: this.network.stakingDenom, // getters.bondDenom,
isExtensionAccount: this.isExtensionAccount,
account: this.overview.accountInformation
}
},
confirmModalOpen() {
let confirmResult = false
if (this.session.currrentModalOpen) {
Expand Down Expand Up @@ -618,7 +619,7 @@ export default {
this.gasEstimate = await this.actionManager.simulate(memo)
} else {
this.gasEstimate = await this.actionManager.simulateTxAPI(
this.createContext(),
this.context,
type,
properties,
memo
Expand Down Expand Up @@ -656,8 +657,9 @@ export default {
if (!this.useTxService) {
hashResult = await this.actionManager.send(memo, feeProperties)
} else {
await this.$apollo.queries.overview.refetch()
hashResult = await this.actionManager.sendTxAPI(
this.createContext(),
this.context,
type,
memo,
properties,
Expand All @@ -668,8 +670,8 @@ export default {
const { hash } = hashResult
this.txHash = hash
this.step = inclusionStep
} catch ({ message }) {
this.onSendingFailed(message)
} catch (error) {
this.onSendingFailed(error)
}
},
onTxIncluded() {
Expand All @@ -683,10 +685,17 @@ export default {
this.$emit(`txIncluded`)
this.$apollo.queries.overview.refetch()
},
onSendingFailed(message) {
onSendingFailed(error) {
Sentry.withScope(scope => {
scope.setExtra("signMethod", this.selectedSignMethod)
scope.setExtra("transactionData", this.transactionData)
scope.setExtra("gasEstimate", this.gasEstimate)
scope.setExtra("gasPrice", this.gasPrice)
Sentry.captureException(error)
})
this.step = signStep
this.submissionError = `${this.submissionErrorPrefix}: ${message}.`
this.trackEvent(`event`, `failed-submit`, this.title, message)
this.submissionError = `${this.submissionErrorPrefix}: ${error.message}.`
this.trackEvent(`event`, `failed-submit`, this.title, error.message)
this.$apollo.queries.overview.refetch()
},
async connectLedger() {
Expand Down Expand Up @@ -842,7 +851,7 @@ export default {
this.onTxIncluded()
} else {
/* istanbul ignore next */
this.onSendingFailed(log)
this.onSendingFailed(new Error(log))
}
}
this.txHash = null
Expand Down
2 changes: 1 addition & 1 deletion src/ActionModal/utils/ActionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export default class ActionManager {
if (result.success) {
return { hash: result.hash }
} else {
throw Error("Broadcast was not successfull: " + result.error)
throw Error("Broadcast was not successful: " + result.error)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ let mockSend = jest.fn(() => ({
}))
let mockSetContext = jest.fn()

jest.mock("src/../config.js", () => ({
default_gas_price: 2.5e-8,
graphqlHost: "http://localhost:4000"
}))

jest.mock(`src/ActionModal/utils/ActionManager.js`, () => {
return jest.fn(() => {
return {
Expand All @@ -28,6 +33,11 @@ jest.mock(`src/ActionModal/utils/ActionManager.js`, () => {
})
})

// TODO move into global mock to not duplicate everywhere
jest.mock("@sentry/browser", () => ({
withScope: () => {}
}))

describe(`ActionModal`, () => {
let wrapper, $store, $apollo

Expand Down Expand Up @@ -132,7 +142,12 @@ describe(`ActionModal`, () => {
},
stubs: ["router-link"]
})
wrapper.setData({ network, overview })
const context = {
account: {
sequence: 0
}
}
wrapper.setData({ network, overview, context })
wrapper.vm.open()
})

Expand Down Expand Up @@ -167,10 +182,10 @@ describe(`ActionModal`, () => {
}
await ActionModal.methods.submit.call(self)
expect(self.onSendingFailed).toHaveBeenCalledWith(
"some kind of error message"
new Error("some kind of error message")
)

ActionModal.methods.onSendingFailed.call(self, "some kind of error message")
ActionModal.methods.onSendingFailed.call(self, new Error("some kind of error message"))
expect(self.submissionError).toEqual(`PREFIX: some kind of error message.`)
})

Expand Down Expand Up @@ -618,7 +633,12 @@ describe(`ActionModal`, () => {
isValidInput: jest.fn(() => true),
selectedSignMethod: `local`,
step: `details`,
validateChangeStep: jest.fn(() => {})
validateChangeStep: jest.fn(() => {}),
context: {
account: {
sequence: 0
}
}
}
})

Expand Down
Loading

0 comments on commit 9dad3b1

Please sign in to comment.