diff --git a/app/components/Wallet/Wallet.js b/app/components/Wallet/Wallet.js
index 75f28121..c565683c 100644
--- a/app/components/Wallet/Wallet.js
+++ b/app/components/Wallet/Wallet.js
@@ -30,7 +30,8 @@ const Wallet = ({
setCurrency,
setWalletCurrencyFilters,
network,
- settingsProps
+ settingsProps,
+ paymentTimeout
}) => {
const fiatAmount = btc.satoshisToFiat(
parseInt(balance.walletBalance, 10) + parseInt(balance.channelBalance, 10),
@@ -112,8 +113,11 @@ const Wallet = ({
{showPayLoadingScreen && (
-
- Sending your transaction...
+
+
+ {paymentTimeout / 1000}
+
+
)}
{showSuccessPayScreen && (
@@ -165,6 +169,7 @@ Wallet.propTypes = {
settingsProps: PropTypes.object.isRequired,
currentCurrencyFilters: PropTypes.array.isRequired,
currencyName: PropTypes.string.isRequired,
+ paymentTimeout: PropTypes.number.isRequired,
setCurrency: PropTypes.func.isRequired,
setWalletCurrencyFilters: PropTypes.func.isRequired
}
diff --git a/app/components/Wallet/Wallet.scss b/app/components/Wallet/Wallet.scss
index 5444818a..8cb8ce1d 100644
--- a/app/components/Wallet/Wallet.scss
+++ b/app/components/Wallet/Wallet.scss
@@ -196,9 +196,14 @@
transition: all 0.25s;
}
+ .spinnerContainer {
+ position: relative;
+ display: inline;
+ }
+
.spinner {
- height: 20px;
- width: 20px;
+ height: 30px;
+ width: 30px;
border: 1px solid rgba(235, 184, 100, 0.1);
border-left-color: rgba(235, 184, 100, 0.4);
-webkit-border-radius: 999px;
@@ -210,6 +215,15 @@
animation: animation-rotate 1000ms linear infinite;
}
+ .timeout {
+ position: absolute;
+ top: 20%;
+ left: 0;
+ font-size: 10px;
+ width: 32px;
+ text-align: center;
+ }
+
.icon {
margin-right: 5px;
}
diff --git a/app/reducers/payment.js b/app/reducers/payment.js
index c07e07ad..25dc379a 100644
--- a/app/reducers/payment.js
+++ b/app/reducers/payment.js
@@ -15,6 +15,10 @@ export const RECEIVE_PAYMENTS = 'RECEIVE_PAYMENTS'
export const SEND_PAYMENT = 'SEND_PAYMENT'
+export const TICK_TIMEOUT = 'TICK_TIMEOUT'
+export const SET_INTERVAL = 'SET_INTERVAL'
+export const RESET_TIMEOUT = 'RESET_TIMEOUT'
+
export const PAYMENT_SUCCESSFULL = 'PAYMENT_SUCCESSFULL'
export const PAYMENT_FAILED = 'PAYMENT_FAILED'
@@ -43,6 +47,25 @@ export function sendPayment() {
}
}
+export function tickTimeout() {
+ return {
+ type: TICK_TIMEOUT
+ }
+}
+
+export function setPaymentInterval(paymentInterval) {
+ return {
+ type: SET_INTERVAL,
+ paymentInterval
+ }
+}
+
+export function resetTimeout() {
+ return {
+ type: RESET_TIMEOUT
+ }
+}
+
export function paymentSuccessfull(payment) {
return {
type: PAYMENT_SUCCESSFULL,
@@ -96,21 +119,30 @@ export const paymentFailed = (event, { error }) => dispatch => {
dispatch(setError(error))
}
-export const payInvoice = paymentRequest => dispatch => {
+export const payInvoice = paymentRequest => (dispatch, getState) => {
dispatch(sendPayment())
ipcRenderer.send('lnd', { msg: 'sendPayment', data: { paymentRequest } })
+ // Set an interval to call tick which will continuously tick down the ticker until the payment goes through or it hits
+ // 0 and throws an error. We also call setPaymentInterval so we are storing the interval. This allows us to clear the
+ // interval in flexible ways whenever we need to
+ const paymentInterval = setInterval(() => tick(dispatch, getState), 1000)
+ dispatch(setPaymentInterval(paymentInterval))
+
// Close the form modal once the payment has been sent
dispatch(setFormType(null))
+}
- // if LND hangs on sending the payment we'll cut it after 10 seconds and return an error
- // setTimeout(() => {
- // const { payment } = getState()
+// Tick checks if the payment is sending and checks the timeout every second. If the payment is still sending and the
+// timeout is above 0 it will continue to tick it down, once we hit 0 we fire an error to the user and reset the reducer
+const tick = (dispatch, getState) => {
+ const { payment } = getState()
- // if (payment.sendingPayment) {
- // dispatch(paymentFailed(null, { error: 'Shoot, we\'re having some trouble sending your payment.' }))
- // }
- // }, 10000)
+ if (payment.sendingPayment && payment.paymentTimeout <= 0) {
+ dispatch(paymentFailed(null, { error: 'Shoot, there was some trouble sending your payment.' }))
+ } else {
+ dispatch(tickTimeout())
+ }
}
// ------------------------------------
@@ -121,9 +153,32 @@ const ACTION_HANDLERS = {
[RECEIVE_PAYMENTS]: (state, { payments }) => ({ ...state, paymentLoading: false, payments }),
[SET_PAYMENT]: (state, { payment }) => ({ ...state, payment }),
+
[SEND_PAYMENT]: state => ({ ...state, sendingPayment: true }),
- [PAYMENT_SUCCESSFULL]: state => ({ ...state, sendingPayment: false }),
- [PAYMENT_FAILED]: state => ({ ...state, sendingPayment: false }),
+
+ [TICK_TIMEOUT]: state => ({ ...state, paymentTimeout: state.paymentTimeout - 1000 }),
+ [SET_INTERVAL]: (state, { paymentInterval }) => ({ ...state, paymentInterval }),
+
+ [PAYMENT_SUCCESSFULL]: state => {
+ clearInterval(state.paymentInterval)
+
+ return {
+ ...state,
+ sendingPayment: false,
+ paymentInterval: null,
+ paymentTimeout: 60000
+ }
+ },
+ [PAYMENT_FAILED]: state => {
+ clearInterval(state.paymentInterval)
+
+ return {
+ ...state,
+ sendingPayment: false,
+ paymentInterval: null,
+ paymentTimeout: 60000
+ }
+ },
[SHOW_SUCCESS_SCREEN]: state => ({ ...state, showSuccessPayScreen: true }),
[HIDE_SUCCESS_SCREEN]: state => ({ ...state, showSuccessPayScreen: false })
@@ -142,6 +197,8 @@ export { paymentSelectors }
const initialState = {
sendingPayment: false,
paymentLoading: false,
+ paymentTimeout: 60000,
+ paymentInterval: null,
payments: [],
payment: null,
showSuccessPayScreen: false
diff --git a/app/routes/activity/containers/ActivityContainer.js b/app/routes/activity/containers/ActivityContainer.js
index 8f188f01..e1a084db 100644
--- a/app/routes/activity/containers/ActivityContainer.js
+++ b/app/routes/activity/containers/ActivityContainer.js
@@ -98,6 +98,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => ({
currentCurrencyFilters: stateProps.currentCurrencyFilters,
currencyName: stateProps.currencyName,
network: stateProps.info.network,
+ paymentTimeout: stateProps.payment.paymentTimeout,
setCurrency: dispatchProps.setCurrency,
setWalletCurrencyFilters: dispatchProps.setWalletCurrencyFilters,
diff --git a/test/unit/reducers/__snapshots__/payment.spec.js.snap b/test/unit/reducers/__snapshots__/payment.spec.js.snap
index e756e959..ee86c143 100644
--- a/test/unit/reducers/__snapshots__/payment.spec.js.snap
+++ b/test/unit/reducers/__snapshots__/payment.spec.js.snap
@@ -3,7 +3,9 @@
exports[`reducers paymentReducer should correctly getPayments 1`] = `
Object {
"payment": null,
+ "paymentInterval": null,
"paymentLoading": true,
+ "paymentTimeout": 60000,
"payments": Array [],
"sendingPayment": false,
"showSuccessPayScreen": false,
@@ -13,7 +15,9 @@ Object {
exports[`reducers paymentReducer should correctly paymentSuccessful 1`] = `
Object {
"payment": null,
+ "paymentInterval": null,
"paymentLoading": false,
+ "paymentTimeout": 60000,
"payments": Array [],
"sendingPayment": false,
"showSuccessPayScreen": false,
@@ -23,7 +27,9 @@ Object {
exports[`reducers paymentReducer should correctly receivePayments 1`] = `
Object {
"payment": null,
+ "paymentInterval": null,
"paymentLoading": false,
+ "paymentTimeout": 60000,
"payments": Array [
1,
2,
@@ -36,7 +42,9 @@ Object {
exports[`reducers paymentReducer should correctly sendPayment 1`] = `
Object {
"payment": "foo",
+ "paymentInterval": null,
"paymentLoading": false,
+ "paymentTimeout": 60000,
"payments": Array [],
"sendingPayment": false,
"showSuccessPayScreen": false,
@@ -46,7 +54,9 @@ Object {
exports[`reducers paymentReducer should handle initial state 1`] = `
Object {
"payment": null,
+ "paymentInterval": null,
"paymentLoading": false,
+ "paymentTimeout": 60000,
"payments": Array [],
"sendingPayment": false,
"showSuccessPayScreen": false,