From 58ac6426a090b61dc32da4535bf785287b74e7b7 Mon Sep 17 00:00:00 2001
From: pkova
Date: Mon, 8 Apr 2019 22:48:06 +0300
Subject: [PATCH 1/7] Add transaction status indicator to SentTransaction
---
src/bridge/Bridge.js | 15 +++++++--
src/bridge/components/StatelessTransaction.js | 2 +-
src/bridge/lib/txn.js | 6 +++-
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 | 32 +++++++++++++++----
src/bridge/views/SetKeys.js | 1 +
src/bridge/views/SetProxy.js | 1 +
src/bridge/views/Transfer.js | 1 +
11 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/src/bridge/Bridge.js b/src/bridge/Bridge.js
index efcc8b32c..a962d227c 100644
--- a/src/bridge/Bridge.js
+++ b/src/bridge/Bridge.js
@@ -80,7 +80,8 @@ class Bridge extends React.Component {
pointCursor: Maybe.Nothing(),
pointCache: {},
// txn
- txnHashCursor: Maybe.Nothing()
+ txnHashCursor: Maybe.Nothing(),
+ txnConfirmations: {}
}
this.pushRoute = this.pushRoute.bind(this)
@@ -95,6 +96,7 @@ class Bridge extends React.Component {
this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
this.setPointCursor = this.setPointCursor.bind(this)
this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
+ this.setTxnConfirmations = this.setTxnConfirmations.bind(this)
this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this)
this.addToPointCache = this.addToPointCache.bind(this)
}
@@ -234,6 +236,12 @@ class Bridge extends React.Component {
this.setState({ txnHashCursor })
}
+ setTxnConfirmations(txnHash, txnConfirmations) {
+ this.setState((prevState, _) =>
+ ({txnConfirmations: { ...prevState.txnConfirmations,
+ [txnHash]: txnConfirmations}}))
+ }
+
render() {
const {
routeCrumbs,
@@ -248,6 +256,7 @@ class Bridge extends React.Component {
pointCursor,
pointCache,
txnHashCursor,
+ txnConfirmations,
web3,
contracts
} = this.state
@@ -300,7 +309,9 @@ class Bridge extends React.Component {
setNetworkSeedCache= { this.setNetworkSeedCache }
// txn
setTxnHashCursor={ this.setTxnHashCursor }
- txnHashCursor={ txnHashCursor } />
+ txnHashCursor={ txnHashCursor }
+ setTxnConfirmations={ this.setTxnConfirmations }
+ txnConfirmations={ txnConfirmations } />
diff --git a/src/bridge/components/StatelessTransaction.js b/src/bridge/components/StatelessTransaction.js
index 527d3c946..0e1541d27 100644
--- a/src/bridge/components/StatelessTransaction.js
+++ b/src/bridge/components/StatelessTransaction.js
@@ -85,7 +85,7 @@ class StatelessTransaction extends React.Component {
submit(){
const { props, state } = this
- sendSignedTransaction(props.web3.value, state.stx)
+ sendSignedTransaction(props.web3.value, state.stx, props.setTxnConfirmations)
.then(sent => {
props.setTxnHashCursor(sent)
props.popRoute()
diff --git a/src/bridge/lib/txn.js b/src/bridge/lib/txn.js
index 48f3b34d9..1a9cc7da2 100644
--- a/src/bridge/lib/txn.js
+++ b/src/bridge/lib/txn.js
@@ -137,7 +137,7 @@ const signTransaction = async config => {
setStx(Just(stx))
}
-const sendSignedTransaction = (web3, stx) => {
+const sendSignedTransaction = (web3, stx, confirmationCb) => {
const txn = stx.matchWith({
Just: (tx) => tx.value,
Nothing: () => {
@@ -155,6 +155,10 @@ const sendSignedTransaction = (web3, stx) => {
.on('receipt', txn => {
resolve(Just(Ok(txn.transactionHash)))
})
+ .on('confirmation', (confirmationNum, txn) => {
+ confirmationCb(txn.transactionHash, confirmationNum + 1)
+ resolve(Just(Ok(txn.transactionHash)))
+ })
.on('error', err => {
reject(Just(Error(err.message)))
})
diff --git a/src/bridge/views/AcceptTransfer.js b/src/bridge/views/AcceptTransfer.js
index 2e4d423d4..2095397e9 100644
--- a/src/bridge/views/AcceptTransfer.js
+++ b/src/bridge/views/AcceptTransfer.js
@@ -126,6 +126,7 @@ class AcceptTransfer extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Other
diff --git a/src/bridge/views/CancelTransfer.js b/src/bridge/views/CancelTransfer.js
index e005499be..acacd9866 100644
--- a/src/bridge/views/CancelTransfer.js
+++ b/src/bridge/views/CancelTransfer.js
@@ -87,6 +87,7 @@ class CancelTransfer extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Other
diff --git a/src/bridge/views/CreateGalaxy.js b/src/bridge/views/CreateGalaxy.js
index ebc96f613..28d734cd3 100644
--- a/src/bridge/views/CreateGalaxy.js
+++ b/src/bridge/views/CreateGalaxy.js
@@ -212,6 +212,7 @@ class CreateGalaxy extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Other
diff --git a/src/bridge/views/IssueChild.js b/src/bridge/views/IssueChild.js
index b94e5b529..8a5ef3332 100644
--- a/src/bridge/views/IssueChild.js
+++ b/src/bridge/views/IssueChild.js
@@ -303,6 +303,7 @@ class IssueChild extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Other
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index 4a82b334d..4c6de0701 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -1,3 +1,4 @@
+import Maybe from 'folktale/maybe'
import React from 'react'
import { Row, Col, H1, H3, P, Warning, Anchor } from '../components/Base'
import { Button } from '../components/Base'
@@ -6,14 +7,17 @@ import { ROUTE_NAMES } from '../lib/router'
import { BRIDGE_ERROR, renderTxnError } from '../lib/error'
import { NETWORK_NAMES } from '../lib/network'
+
const Success = (props) => {
+ const { networkType, hash, txnConfirmations } = props
+
const esvisible =
- props.networkType === NETWORK_NAMES.ROPSTEN ||
- props.networkType === NETWORK_NAMES.MAINNET
+ networkType === NETWORK_NAMES.ROPSTEN ||
+ networkType === NETWORK_NAMES.MAINNET
const esdomain =
- props.networkType === NETWORK_NAMES.ROPSTEN
+ networkType === NETWORK_NAMES.ROPSTEN
? "ropsten.etherscan.io"
: "etherscan.io"
@@ -29,10 +33,16 @@ const Success = (props) => {
className={'mb-4 mt-1'}
prop-size={'sm'}
target={'_blank'}
- href={`https://${esdomain}/tx/${props.hash}`}>
+ href={`https://${esdomain}/tx/${hash}`}>
{'View on Etherscan ↗'}
+ const confirmations = Maybe.fromNullable(txnConfirmations[hash]).getOrElse(0)
+
+ const requiredConfirmations = 1
+
+ const status = confirmations < requiredConfirmations ? 'Pending...' : `Confirmed x${confirmations}!`
+
return (
@@ -47,10 +57,17 @@ const Success = (props) => {
{ 'Transaction Hash' }
- { props.hash }
+ { hash }
+
+
+ { 'Transaction Status' }
+
+
{ status }
+ { esanchor }
+
+
- { esanchor }
@@ -76,7 +93,7 @@ const Failure = (props) =>
const SentTransaction = (props) => {
- const { web3, txnHashCursor, networkType, popRoute, pushRoute } = props
+ const { web3, txnHashCursor, networkType, popRoute, pushRoute, txnConfirmations} = props
const { setPointCursor, pointCursor } = props
const promptKeyfile = props.routeData && props.routeData.promptKeyfile
@@ -97,6 +114,7 @@ const SentTransaction = (props) => {
})
diff --git a/src/bridge/views/SetKeys.js b/src/bridge/views/SetKeys.js
index 8efe7263d..bea67392f 100644
--- a/src/bridge/views/SetKeys.js
+++ b/src/bridge/views/SetKeys.js
@@ -194,6 +194,7 @@ class SetKeys extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Tx
diff --git a/src/bridge/views/SetProxy.js b/src/bridge/views/SetProxy.js
index 3da633645..37c9ca694 100644
--- a/src/bridge/views/SetProxy.js
+++ b/src/bridge/views/SetProxy.js
@@ -162,6 +162,7 @@ class SetProxy extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Other
diff --git a/src/bridge/views/Transfer.js b/src/bridge/views/Transfer.js
index 03ed0136c..66cb2f3af 100644
--- a/src/bridge/views/Transfer.js
+++ b/src/bridge/views/Transfer.js
@@ -132,6 +132,7 @@ class Transfer extends React.Component {
walletHdPath={props.walletHdPath}
networkType={props.networkType}
setTxnHashCursor={props.setTxnHashCursor}
+ setTxnConfirmations={props.setTxnConfirmations}
popRoute={props.popRoute}
pushRoute={props.pushRoute}
// Checks
From 31aa34911b1a5f57824535a8d294cba8b5ca6c2b Mon Sep 17 00:00:00 2001
From: pkova
Date: Tue, 16 Apr 2019 20:28:56 +0300
Subject: [PATCH 2/7] Animate pending dots
---
src/bridge/views/SentTransaction.js | 128 +++++++++++++++++-----------
1 file changed, 79 insertions(+), 49 deletions(-)
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index 4c6de0701..be8a4c8ff 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -8,70 +8,100 @@ import { BRIDGE_ERROR, renderTxnError } from '../lib/error'
import { NETWORK_NAMES } from '../lib/network'
-const Success = (props) => {
+class Success extends React.Component {
- const { networkType, hash, txnConfirmations } = props
+ constructor(props) {
+ super(props)
- const esvisible =
- networkType === NETWORK_NAMES.ROPSTEN ||
- networkType === NETWORK_NAMES.MAINNET
+ this.state = {
+ pending: '.',
+ interval: null
+ }
+ }
- const esdomain =
- networkType === NETWORK_NAMES.ROPSTEN
- ? "ropsten.etherscan.io"
- : "etherscan.io"
+ componentDidMount() {
+ const nextDot = {'.': '..',
+ '..': '...',
+ '...': '.'}
- const esmessage =
- esvisible === true
- ? "If you’d like to keep track of it, click the Etherscan link below."
- : ''
+ const interval = setInterval(() => {
+ this.setState(({ pending }) => ({pending: nextDot[pending]}))
+ }, 1000)
+ this.setState({interval: interval})
+ }
- const esanchor =
- esvisible === false
- ?
- :
- {'View on Etherscan ↗'}
-
+ componentDidUnmount() {
+ clearInterval(this.state.interval)
+ }
- const confirmations = Maybe.fromNullable(txnConfirmations[hash]).getOrElse(0)
+ render() {
- const requiredConfirmations = 1
+ const { props, state } = this
+ const { networkType, hash, txnConfirmations } = props
+ const { pending } = state
- const status = confirmations < requiredConfirmations ? 'Pending...' : `Confirmed x${confirmations}!`
+ const esvisible =
+ networkType === NETWORK_NAMES.ROPSTEN ||
+ networkType === NETWORK_NAMES.MAINNET
- return (
-
-
- { 'Your Transaction was Sent' }
+ const esdomain =
+ networkType === NETWORK_NAMES.ROPSTEN
+ ? "ropsten.etherscan.io"
+ : "etherscan.io"
-
- {
- `We sent your transaction to the chain. It can take some time to
+ const esmessage =
+ esvisible === true
+ ? "If you’d like to keep track of it, click the Etherscan link below."
+ : ''
+
+ const esanchor =
+ esvisible === false
+ ?
+ :
+ {'View on Etherscan ↗'}
+
+
+ const confirmations = Maybe.fromNullable(txnConfirmations[hash]).getOrElse(0)
+
+ const requiredConfirmations = 1
+
+ const status = confirmations < requiredConfirmations ?
+ `Pending${pending}` : `Confirmed! (x${confirmations} confirmations)!`
+
+ return (
+
+
+ { 'Your Transaction was Sent' }
+
+
+ {
+ `We sent your transaction to the chain. It can take some time to
execute, especially if the network is busy. ${esmessage}`
- }
-
+ }
+
- { 'Transaction Hash' }
-
- { hash }
-
+ { 'Transaction Hash' }
+
+ { hash }
+
- { 'Transaction Status' }
-
-
{ status }
- { esanchor }
-
-
-
+ { 'Transaction Status' }
+
+
{ status }
+ { esanchor }
+
+
+
-
-
- )
+
+
+ )
+ }
}
const Failure = (props) =>
From 765deb1d40945c2f61b5b80411a3bb7977bfb683 Mon Sep 17 00:00:00 2001
From: pkova
Date: Tue, 16 Apr 2019 20:31:16 +0300
Subject: [PATCH 3/7] Dont put divs inside p
---
src/bridge/views/SentTransaction.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index be8a4c8ff..4abe577fb 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -91,8 +91,8 @@ class Success extends React.Component {
{ 'Transaction Status' }
-
{ status }
- { esanchor }
+ { status }
+ { esanchor }
From bf869de152a12c933e29ab1039b7eae857867a34 Mon Sep 17 00:00:00 2001
From: pkova
Date: Tue, 16 Apr 2019 21:13:37 +0300
Subject: [PATCH 4/7] Give status an esanchor their own paragraphs
---
src/bridge/views/SentTransaction.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index 4abe577fb..5f5e2daf6 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -92,6 +92,8 @@ class Success extends React.Component {
{ 'Transaction Status' }
{ status }
+
+
{ esanchor }
From e2a43bbcf53f64ce48b6c47a4f342eb5ac3dbbe6 Mon Sep 17 00:00:00 2001
From: pkova
Date: Tue, 16 Apr 2019 21:35:55 +0300
Subject: [PATCH 5/7] Fix bug in interval clearing on component unmount
---
src/bridge/views/SentTransaction.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index 5f5e2daf6..03d4fc985 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -30,7 +30,7 @@ class Success extends React.Component {
this.setState({interval: interval})
}
- componentDidUnmount() {
+ componentWillUnmount() {
clearInterval(this.state.interval)
}
From d67f269f813cff95acb1f03acba0a704bc52cb9e Mon Sep 17 00:00:00 2001
From: pkova
Date: Tue, 16 Apr 2019 21:36:29 +0300
Subject: [PATCH 6/7] Remove dangling p element
---
src/bridge/views/SentTransaction.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index 03d4fc985..ac7dc54ab 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -96,9 +96,6 @@ class Success extends React.Component {
{ esanchor }
-
-
-
From 8de9bc3d0bc97ddbe123e84412a090202dbd1ec9 Mon Sep 17 00:00:00 2001
From: pkova
Date: Tue, 16 Apr 2019 21:36:41 +0300
Subject: [PATCH 7/7] Return nothing instead of empty div when esvisible ==
false
React complains about having divs inside of p elements otherwise
---
src/bridge/views/SentTransaction.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/bridge/views/SentTransaction.js b/src/bridge/views/SentTransaction.js
index ac7dc54ab..ccd9405d3 100644
--- a/src/bridge/views/SentTransaction.js
+++ b/src/bridge/views/SentTransaction.js
@@ -56,7 +56,7 @@ class Success extends React.Component {
const esanchor =
esvisible === false
- ?
+ ? null
: