on master help sign in
Merge pull request #99 from pkova/master
58b8e51Fang
src/bridge/Bridge.js+13−2
@@ -87,7 +87,8 @@ class Bridge extends React.Component {
87 pointCursor: Maybe.Nothing(),
87 pointCursor: Maybe.Nothing(),
88 pointCache: {},
88 pointCache: {},
89 // txn
89 // txn
90− txnHashCursor: Maybe.Nothing()
90+ txnHashCursor: Maybe.Nothing(),
91+ txnConfirmations: {}
91 }
92 }
92
93
93 this.pushRoute = this.pushRoute.bind(this)
94 this.pushRoute = this.pushRoute.bind(this)
@@ -102,6 +103,7 @@ class Bridge extends React.Component {
102 this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
103 this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
103 this.setPointCursor = this.setPointCursor.bind(this)
104 this.setPointCursor = this.setPointCursor.bind(this)
104 this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
105 this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
106+ this.setTxnConfirmations = this.setTxnConfirmations.bind(this)
105 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this)
107 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this)
106 this.addToPointCache = this.addToPointCache.bind(this)
108 this.addToPointCache = this.addToPointCache.bind(this)
107 }
109 }
@@ -241,6 +243,12 @@ class Bridge extends React.Component {
241 this.setState({ txnHashCursor })
243 this.setState({ txnHashCursor })
242 }
244 }
243
245
246+ setTxnConfirmations(txnHash, txnConfirmations) {
247+ this.setState((prevState, _) =>
248+ ({txnConfirmations: { ...prevState.txnConfirmations,
249+ [txnHash]: txnConfirmations}}))
250+ }
251+
244 render() {
252 render() {
245 const {
253 const {
246 routeCrumbs,
254 routeCrumbs,
@@ -255,6 +263,7 @@ class Bridge extends React.Component {
255 pointCursor,
263 pointCursor,
256 pointCache,
264 pointCache,
257 txnHashCursor,
265 txnHashCursor,
266+ txnConfirmations,
258 web3,
267 web3,
259 contracts
268 contracts
260 } = this.state
269 } = this.state
@@ -307,7 +316,9 @@ class Bridge extends React.Component {
307 setNetworkSeedCache= { this.setNetworkSeedCache }
316 setNetworkSeedCache= { this.setNetworkSeedCache }
308 // txn
317 // txn
309 setTxnHashCursor={ this.setTxnHashCursor }
318 setTxnHashCursor={ this.setTxnHashCursor }
310− txnHashCursor={ txnHashCursor } />
319+ txnHashCursor={ txnHashCursor }
320+ setTxnConfirmations={ this.setTxnConfirmations }
321+ txnConfirmations={ txnConfirmations } />
311
322
312 <div className={'push'} />
323 <div className={'push'} />
313
324
src/bridge/components/StatelessTransaction.js+1−1
@@ -88,7 +88,7 @@ class StatelessTransaction extends React.Component {
88
88
89 submit(){
89 submit(){
90 const { props, state } = this
90 const { props, state } = this
91− sendSignedTransaction(props.web3.value, state.stx)
91+ sendSignedTransaction(props.web3.value, state.stx, props.setTxnConfirmations)
92 .then(sent => {
92 .then(sent => {
93 props.setTxnHashCursor(sent)
93 props.setTxnHashCursor(sent)
94 props.popRoute()
94 props.popRoute()
src/bridge/lib/txn.js+5−1
@@ -138,7 +138,7 @@ const signTransaction = async config => {
138 setStx(Just(stx))
138 setStx(Just(stx))
139}
139}
140
140
141−const sendSignedTransaction = (web3, stx) => {
141+const sendSignedTransaction = (web3, stx, confirmationCb) => {
142 const txn = stx.matchWith({
142 const txn = stx.matchWith({
143 Just: (tx) => tx.value,
143 Just: (tx) => tx.value,
144 Nothing: () => {
144 Nothing: () => {
@@ -156,6 +156,10 @@ const sendSignedTransaction = (web3, stx) => {
156 .on('receipt', txn => {
156 .on('receipt', txn => {
157 resolve(Just(Ok(txn.transactionHash)))
157 resolve(Just(Ok(txn.transactionHash)))
158 })
158 })
159+ .on('confirmation', (confirmationNum, txn) => {
160+ confirmationCb(txn.transactionHash, confirmationNum + 1)
161+ resolve(Just(Ok(txn.transactionHash)))
162+ })
159 .on('error', err => {
163 .on('error', err => {
160 reject(Just(Error(err.message)))
164 reject(Just(Error(err.message)))
161 })
165 })
src/bridge/views/AcceptTransfer.js+1
@@ -126,6 +126,7 @@ class AcceptTransfer extends React.Component {
126 walletHdPath={props.walletHdPath}
126 walletHdPath={props.walletHdPath}
127 networkType={props.networkType}
127 networkType={props.networkType}
128 setTxnHashCursor={props.setTxnHashCursor}
128 setTxnHashCursor={props.setTxnHashCursor}
129+ setTxnConfirmations={props.setTxnConfirmations}
129 popRoute={props.popRoute}
130 popRoute={props.popRoute}
130 pushRoute={props.pushRoute}
131 pushRoute={props.pushRoute}
131 // Other
132 // Other
src/bridge/views/CancelTransfer.js+1
@@ -87,6 +87,7 @@ class CancelTransfer extends React.Component {
87 walletHdPath={props.walletHdPath}
87 walletHdPath={props.walletHdPath}
88 networkType={props.networkType}
88 networkType={props.networkType}
89 setTxnHashCursor={props.setTxnHashCursor}
89 setTxnHashCursor={props.setTxnHashCursor}
90+ setTxnConfirmations={props.setTxnConfirmations}
90 popRoute={props.popRoute}
91 popRoute={props.popRoute}
91 pushRoute={props.pushRoute}
92 pushRoute={props.pushRoute}
92 // Other
93 // Other
src/bridge/views/CreateGalaxy.js+1
@@ -212,6 +212,7 @@ class CreateGalaxy extends React.Component {
212 walletHdPath={props.walletHdPath}
212 walletHdPath={props.walletHdPath}
213 networkType={props.networkType}
213 networkType={props.networkType}
214 setTxnHashCursor={props.setTxnHashCursor}
214 setTxnHashCursor={props.setTxnHashCursor}
215+ setTxnConfirmations={props.setTxnConfirmations}
215 popRoute={props.popRoute}
216 popRoute={props.popRoute}
216 pushRoute={props.pushRoute}
217 pushRoute={props.pushRoute}
217 // Other
218 // Other
src/bridge/views/IssueChild.js+1
@@ -303,6 +303,7 @@ class IssueChild extends React.Component {
303 walletHdPath={props.walletHdPath}
303 walletHdPath={props.walletHdPath}
304 networkType={props.networkType}
304 networkType={props.networkType}
305 setTxnHashCursor={props.setTxnHashCursor}
305 setTxnHashCursor={props.setTxnHashCursor}
306+ setTxnConfirmations={props.setTxnConfirmations}
306 popRoute={props.popRoute}
307 popRoute={props.popRoute}
307 pushRoute={props.pushRoute}
308 pushRoute={props.pushRoute}
308 // Other
309 // Other
src/bridge/views/SentTransaction.js+91−44
@@ -1,3 +1,4 @@
1+import Maybe from 'folktale/maybe'
1import React from 'react'
2import React from 'react'
2import { Row, Col, H1, H3, P, Warning, Anchor } from '../components/Base'
3import { Row, Col, H1, H3, P, Warning, Anchor } from '../components/Base'
3import { Button } from '../components/Base'
4import { Button } from '../components/Base'
@@ -6,55 +7,100 @@ import { ROUTE_NAMES } from '../lib/router'
6import { BRIDGE_ERROR, renderTxnError } from '../lib/error'
7import { BRIDGE_ERROR, renderTxnError } from '../lib/error'
7import { NETWORK_NAMES } from '../lib/network'
8import { NETWORK_NAMES } from '../lib/network'
8
9
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>
35
10
36− return (
11+class Success extends React.Component {
37− <Row>
12+
38− <Col>
13+ constructor(props) {
39− <H1>{ 'Your Transaction was Sent' }</H1>
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+ : ''
40
56
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+
41− <P>
80+ <P>
42− {
81+ {
43− `We sent your transaction to the chain. It can take some time to
82+ `We sent your transaction to the chain. It can take some time to
44 execute, especially if the network is busy. ${esmessage}`
83 execute, especially if the network is busy. ${esmessage}`
45− }
84+ }
46− </P>
85+ </P>
47
86
48− <H3>{ 'Transaction Hash' }</H3>
87+ <H3>{ 'Transaction Hash' }</H3>
49− <P>
88+ <P>
50− { props.hash }
89+ { hash }
51− </P>
90+ </P>
52
91
92+ <H3>{ 'Transaction Status' }</H3>
93+ <P>
94+ { status }
95+ </P>
96+ <P>
53− { esanchor }
97+ { esanchor }
98+ </P>
54
99
55− </Col>
100+ </Col>
56− </Row>
101+ </Row>
57− )
102+ )
103+ }
58}
104}
59
105
60const Failure = (props) =>
106const Failure = (props) =>
@@ -76,7 +122,7 @@ const Failure = (props) =>
76 </Row>
122 </Row>
77
123
78const SentTransaction = (props) => {
124const SentTransaction = (props) => {
79− const { web3, txnHashCursor, networkType, popRoute, pushRoute } = props
125+ const { web3, txnHashCursor, networkType, popRoute, pushRoute, txnConfirmations} = props
80 const { setPointCursor, pointCursor } = props
126 const { setPointCursor, pointCursor } = props
81
127
82 const promptKeyfile = props.routeData && props.routeData.promptKeyfile
128 const promptKeyfile = props.routeData && props.routeData.promptKeyfile
@@ -97,6 +143,7 @@ const SentTransaction = (props) => {
97 <Success
143 <Success
98 hash={ hash.value }
144 hash={ hash.value }
99 networkType={ networkType }
145 networkType={ networkType }
146+ txnConfirmations={ txnConfirmations }
100 />
147 />
101 })
148 })
102
149
src/bridge/views/SetKeys.js+1
@@ -194,6 +194,7 @@ class SetKeys extends React.Component {
194 walletHdPath={props.walletHdPath}
194 walletHdPath={props.walletHdPath}
195 networkType={props.networkType}
195 networkType={props.networkType}
196 setTxnHashCursor={props.setTxnHashCursor}
196 setTxnHashCursor={props.setTxnHashCursor}
197+ setTxnConfirmations={props.setTxnConfirmations}
197 popRoute={props.popRoute}
198 popRoute={props.popRoute}
198 pushRoute={props.pushRoute}
199 pushRoute={props.pushRoute}
199 // Tx
200 // Tx
src/bridge/views/SetProxy.js+1
@@ -162,6 +162,7 @@ class SetProxy extends React.Component {
162 walletHdPath={props.walletHdPath}
162 walletHdPath={props.walletHdPath}
163 networkType={props.networkType}
163 networkType={props.networkType}
164 setTxnHashCursor={props.setTxnHashCursor}
164 setTxnHashCursor={props.setTxnHashCursor}
165+ setTxnConfirmations={props.setTxnConfirmations}
165 popRoute={props.popRoute}
166 popRoute={props.popRoute}
166 pushRoute={props.pushRoute}
167 pushRoute={props.pushRoute}
167 // Other
168 // Other
src/bridge/views/Transfer.js+1
@@ -132,6 +132,7 @@ class Transfer extends React.Component {
132 walletHdPath={props.walletHdPath}
132 walletHdPath={props.walletHdPath}
133 networkType={props.networkType}
133 networkType={props.networkType}
134 setTxnHashCursor={props.setTxnHashCursor}
134 setTxnHashCursor={props.setTxnHashCursor}
135+ setTxnConfirmations={props.setTxnConfirmations}
135 popRoute={props.popRoute}
136 popRoute={props.popRoute}
136 pushRoute={props.pushRoute}
137 pushRoute={props.pushRoute}
137 // Checks
138 // Checks