on master help sign in
Merge pull request #99 from pkova/master

Add transaction status indicator to SentTransaction

commit58b8e511259f8d2b33505a47b46b76ad34b7acd7 authorFang <Fang-@users.noreply.github.com> dateTue 16 Apr 2019, 21:25 (8 years ago) parentdb5943c8de9bc3
11 files changed+117−48
src/bridge/Bridge.js+13−2 src/bridge/components/StatelessTransaction.js+1−1 src/bridge/lib/txn.js+5−1 src/bridge/views/AcceptTransfer.js+1 src/bridge/views/CancelTransfer.js+1 src/bridge/views/CreateGalaxy.js+1 src/bridge/views/IssueChild.js+1 src/bridge/views/SentTransaction.js+91−44 src/bridge/views/SetKeys.js+1 src/bridge/views/SetProxy.js+1 src/bridge/views/Transfer.js+1
src/bridge/Bridge.js+13−2
@@ -87,7 +87,8 @@ class Bridge extends React.Component {
8787 pointCursor: Maybe.Nothing(),
8888 pointCache: {},
8989 // txn
90− txnHashCursor: Maybe.Nothing()
90+ txnHashCursor: Maybe.Nothing(),
91+ txnConfirmations: {}
9192 }
9293
9394 this.pushRoute = this.pushRoute.bind(this)
@@ -102,6 +103,7 @@ class Bridge extends React.Component {
102103 this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
103104 this.setPointCursor = this.setPointCursor.bind(this)
104105 this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
106+ this.setTxnConfirmations = this.setTxnConfirmations.bind(this)
105107 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this)
106108 this.addToPointCache = this.addToPointCache.bind(this)
107109 }
@@ -241,6 +243,12 @@ class Bridge extends React.Component {
241243 this.setState({ txnHashCursor })
242244 }
243245
246+ setTxnConfirmations(txnHash, txnConfirmations) {
247+ this.setState((prevState, _) =>
248+ ({txnConfirmations: { ...prevState.txnConfirmations,
249+ [txnHash]: txnConfirmations}}))
250+ }
251+
244252 render() {
245253 const {
246254 routeCrumbs,
@@ -255,6 +263,7 @@ class Bridge extends React.Component {
255263 pointCursor,
256264 pointCache,
257265 txnHashCursor,
266+ txnConfirmations,
258267 web3,
259268 contracts
260269 } = this.state
@@ -307,7 +316,9 @@ class Bridge extends React.Component {
307316 setNetworkSeedCache= { this.setNetworkSeedCache }
308317 // txn
309318 setTxnHashCursor={ this.setTxnHashCursor }
310− txnHashCursor={ txnHashCursor } />
319+ txnHashCursor={ txnHashCursor }
320+ setTxnConfirmations={ this.setTxnConfirmations }
321+ txnConfirmations={ txnConfirmations } />
311322
312323 <div className={'push'} />
313324
src/bridge/components/StatelessTransaction.js+1−1
@@ -88,7 +88,7 @@ class StatelessTransaction extends React.Component {
8888
8989 submit(){
9090 const { props, state } = this
91− sendSignedTransaction(props.web3.value, state.stx)
91+ sendSignedTransaction(props.web3.value, state.stx, props.setTxnConfirmations)
9292 .then(sent => {
9393 props.setTxnHashCursor(sent)
9494 props.popRoute()
src/bridge/lib/txn.js+5−1
@@ -138,7 +138,7 @@ const signTransaction = async config => {
138138 setStx(Just(stx))
139139}
140140
141−const sendSignedTransaction = (web3, stx) => {
141+const sendSignedTransaction = (web3, stx, confirmationCb) => {
142142 const txn = stx.matchWith({
143143 Just: (tx) => tx.value,
144144 Nothing: () => {
@@ -156,6 +156,10 @@ const sendSignedTransaction = (web3, stx) => {
156156 .on('receipt', txn => {
157157 resolve(Just(Ok(txn.transactionHash)))
158158 })
159+ .on('confirmation', (confirmationNum, txn) => {
160+ confirmationCb(txn.transactionHash, confirmationNum + 1)
161+ resolve(Just(Ok(txn.transactionHash)))
162+ })
159163 .on('error', err => {
160164 reject(Just(Error(err.message)))
161165 })
src/bridge/views/AcceptTransfer.js+1
@@ -126,6 +126,7 @@ class AcceptTransfer extends React.Component {
126126 walletHdPath={props.walletHdPath}
127127 networkType={props.networkType}
128128 setTxnHashCursor={props.setTxnHashCursor}
129+ setTxnConfirmations={props.setTxnConfirmations}
129130 popRoute={props.popRoute}
130131 pushRoute={props.pushRoute}
131132 // Other
src/bridge/views/CancelTransfer.js+1
@@ -87,6 +87,7 @@ class CancelTransfer extends React.Component {
8787 walletHdPath={props.walletHdPath}
8888 networkType={props.networkType}
8989 setTxnHashCursor={props.setTxnHashCursor}
90+ setTxnConfirmations={props.setTxnConfirmations}
9091 popRoute={props.popRoute}
9192 pushRoute={props.pushRoute}
9293 // Other
src/bridge/views/CreateGalaxy.js+1
@@ -212,6 +212,7 @@ class CreateGalaxy extends React.Component {
212212 walletHdPath={props.walletHdPath}
213213 networkType={props.networkType}
214214 setTxnHashCursor={props.setTxnHashCursor}
215+ setTxnConfirmations={props.setTxnConfirmations}
215216 popRoute={props.popRoute}
216217 pushRoute={props.pushRoute}
217218 // Other
src/bridge/views/IssueChild.js+1
@@ -303,6 +303,7 @@ class IssueChild extends React.Component {
303303 walletHdPath={props.walletHdPath}
304304 networkType={props.networkType}
305305 setTxnHashCursor={props.setTxnHashCursor}
306+ setTxnConfirmations={props.setTxnConfirmations}
306307 popRoute={props.popRoute}
307308 pushRoute={props.pushRoute}
308309 // Other
src/bridge/views/SentTransaction.js+91−44
@@ -1,3 +1,4 @@
1+import Maybe from 'folktale/maybe'
12import React from 'react'
23import { Row, Col, H1, H3, P, Warning, Anchor } from '../components/Base'
34import { Button } from '../components/Base'
@@ -6,55 +7,100 @@ import { ROUTE_NAMES } from '../lib/router'
67import { BRIDGE_ERROR, renderTxnError } from '../lib/error'
78import { NETWORK_NAMES } from '../lib/network'
89
9−const Success = (props) => {
10−
11− const esvisible =
12− props.networkType === NETWORK_NAMES.ROPSTEN ||
13− props.networkType === NETWORK_NAMES.MAINNET
14−
15− const esdomain =
16− props.networkType === NETWORK_NAMES.ROPSTEN
17− ? "ropsten.etherscan.io"
18− : "etherscan.io"
19−
20− const esmessage =
21− esvisible === true
22− ? "If you’d like to keep track of it, click the Etherscan link below."
23− : ''
24−
25− const esanchor =
26− esvisible === false
27− ? <div />
28− : <Anchor
29− className={'mb-4 mt-1'}
30− prop-size={'sm'}
31− target={'_blank'}
32− href={`https://${esdomain}/tx/${props.hash}`}>
33− {'View on Etherscan ↗'}
34− </Anchor>
3510
36− return (
37− <Row>
38− <Col>
39− <H1>{ 'Your Transaction was Sent' }</H1>
11+class Success extends React.Component {
12+
13+ constructor(props) {
14+ super(props)
15+
16+ this.state = {
17+ pending: '.',
18+ interval: null
19+ }
20+ }
21+
22+ componentDidMount() {
23+ const nextDot = {'.': '..',
24+ '..': '...',
25+ '...': '.'}
26+
27+ const interval = setInterval(() => {
28+ this.setState(({ pending }) => ({pending: nextDot[pending]}))
29+ }, 1000)
30+ this.setState({interval: interval})
31+ }
32+
33+ componentWillUnmount() {
34+ clearInterval(this.state.interval)
35+ }
36+
37+ render() {
38+
39+ const { props, state } = this
40+ const { networkType, hash, txnConfirmations } = props
41+ const { pending } = state
42+
43+ const esvisible =
44+ networkType === NETWORK_NAMES.ROPSTEN ||
45+ networkType === NETWORK_NAMES.MAINNET
46+
47+ const esdomain =
48+ networkType === NETWORK_NAMES.ROPSTEN
49+ ? "ropsten.etherscan.io"
50+ : "etherscan.io"
51+
52+ const esmessage =
53+ esvisible === true
54+ ? "If you’d like to keep track of it, click the Etherscan link below."
55+ : ''
4056
41− <P>
42− {
43− `We sent your transaction to the chain. It can take some time to
57+ const esanchor =
58+ esvisible === false
59+ ? null
60+ : <Anchor
61+ className={'mb-4 mt-1'}
62+ prop-size={'sm'}
63+ target={'_blank'}
64+ href={`https://${esdomain}/tx/${hash}`}>
65+ {'View on Etherscan ↗'}
66+ </Anchor>
67+
68+ const confirmations = Maybe.fromNullable(txnConfirmations[hash]).getOrElse(0)
69+
70+ const requiredConfirmations = 1
71+
72+ const status = confirmations < requiredConfirmations ?
73+ `Pending${pending}` : `Confirmed! (x${confirmations} confirmations)!`
74+
75+ return (
76+ <Row>
77+ <Col>
78+ <H1>{ 'Your Transaction was Sent' }</H1>
79+
80+ <P>
81+ {
82+ `We sent your transaction to the chain. It can take some time to
4483 execute, especially if the network is busy. ${esmessage}`
45− }
46− </P>
84+ }
85+ </P>
4786
48− <H3>{ 'Transaction Hash' }</H3>
49− <P>
50− { props.hash }
51− </P>
87+ <H3>{ 'Transaction Hash' }</H3>
88+ <P>
89+ { hash }
90+ </P>
5291
53− { esanchor }
92+ <H3>{ 'Transaction Status' }</H3>
93+ <P>
94+ { status }
95+ </P>
96+ <P>
97+ { esanchor }
98+ </P>
5499
55− </Col>
56− </Row>
57− )
100+ </Col>
101+ </Row>
102+ )
103+ }
58104}
59105
60106const Failure = (props) =>
@@ -76,7 +122,7 @@ const Failure = (props) =>
76122 </Row>
77123
78124const SentTransaction = (props) => {
79− const { web3, txnHashCursor, networkType, popRoute, pushRoute } = props
125+ const { web3, txnHashCursor, networkType, popRoute, pushRoute, txnConfirmations} = props
80126 const { setPointCursor, pointCursor } = props
81127
82128 const promptKeyfile = props.routeData && props.routeData.promptKeyfile
@@ -97,6 +143,7 @@ const SentTransaction = (props) => {
97143 <Success
98144 hash={ hash.value }
99145 networkType={ networkType }
146+ txnConfirmations={ txnConfirmations }
100147 />
101148 })
102149
src/bridge/views/SetKeys.js+1
@@ -194,6 +194,7 @@ class SetKeys extends React.Component {
194194 walletHdPath={props.walletHdPath}
195195 networkType={props.networkType}
196196 setTxnHashCursor={props.setTxnHashCursor}
197+ setTxnConfirmations={props.setTxnConfirmations}
197198 popRoute={props.popRoute}
198199 pushRoute={props.pushRoute}
199200 // Tx
src/bridge/views/SetProxy.js+1
@@ -162,6 +162,7 @@ class SetProxy extends React.Component {
162162 walletHdPath={props.walletHdPath}
163163 networkType={props.networkType}
164164 setTxnHashCursor={props.setTxnHashCursor}
165+ setTxnConfirmations={props.setTxnConfirmations}
165166 popRoute={props.popRoute}
166167 pushRoute={props.pushRoute}
167168 // Other
src/bridge/views/Transfer.js+1
@@ -132,6 +132,7 @@ class Transfer extends React.Component {
132132 walletHdPath={props.walletHdPath}
133133 networkType={props.networkType}
134134 setTxnHashCursor={props.setTxnHashCursor}
135+ setTxnConfirmations={props.setTxnConfirmations}
135136 popRoute={props.popRoute}
136137 pushRoute={props.pushRoute}
137138 // Checks