From a6111c3dd5934007f26ae8bf408c738ca9925c84 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Tue, 19 Sep 2017 14:17:36 -0500 Subject: [PATCH] feature(txs): setup getTransactions and hook up to new reducer --- app/lnd/methods/index.js | 5 + app/reducers/index.js | 4 +- app/reducers/ipc.js | 5 +- app/reducers/transaction.js | 93 +++++++++++++++++++ app/routes/activity/components/Activity.js | 3 +- .../activity/containers/ActivityContainer.js | 2 + 6 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 app/reducers/transaction.js diff --git a/app/lnd/methods/index.js b/app/lnd/methods/index.js index a891a453..9b69ec2f 100644 --- a/app/lnd/methods/index.js +++ b/app/lnd/methods/index.js @@ -49,6 +49,11 @@ export default function (lnd, event, msg, data) { ) .catch(error => console.log('channels error: ', error)) break + case 'transactions': + // Data looks like { transactions: [] } + walletController.getTransactions(lnd) + .then(transactionsData => event.sender.send('receiveTransactions', transactionsData)) + .catch(error => console.log('transactions error: ', error)) case 'payments': // Data looks like { payments: [] } paymentsController.listPayments(lnd) diff --git a/app/reducers/index.js b/app/reducers/index.js index c736b6e3..75b0597e 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -11,6 +11,7 @@ import form from './form' import invoice from './invoice' import modal from './modal' import address from './address' +import transaction from './transaction' const rootReducer = combineReducers({ router, @@ -23,7 +24,8 @@ const rootReducer = combineReducers({ form, invoice, modal, - address + address, + transaction }) export default rootReducer diff --git a/app/reducers/ipc.js b/app/reducers/ipc.js index 78988e07..2f035923 100644 --- a/app/reducers/ipc.js +++ b/app/reducers/ipc.js @@ -22,6 +22,7 @@ import { import { receivePayments, paymentSuccessful, sendSuccessful, sendCoinsError } from './payment' import { receiveInvoices, createdInvoice, receiveFormInvoice } from './invoice' import { receiveBalance } from './balance' +import { receiveTransactions } from './transaction' // Import all receiving IPC event handlers and pass them into createIpc const ipc = createIpc({ @@ -58,7 +59,9 @@ const ipc = createIpc({ disconnectSuccess, receiveAddress, - receiveCryptocurrency + receiveCryptocurrency, + + receiveTransactions }) export default ipc diff --git a/app/reducers/transaction.js b/app/reducers/transaction.js new file mode 100644 index 00000000..e671e324 --- /dev/null +++ b/app/reducers/transaction.js @@ -0,0 +1,93 @@ +import { createSelector } from 'reselect' +import { ipcRenderer } from 'electron' +import { btc, usd } from '../utils' +import { setForm, resetForm } from './form' +import { showModal } from './modal' + +// ------------------------------------ +// Constants +// ------------------------------------ +export const GET_TRANSACTIONS = 'GET_TRANSACTIONS' +export const RECEIVE_TRANSACTIONS = 'RECEIVE_TRANSACTIONS' + +export const SEND_TRANSACTION = 'SEND_TRANSACTION' + +export const TRANSACTION_SUCCESSFULL = 'TRANSACTION_SUCCESSFULL' +export const TRANSACTION_FAILED = 'TRANSACTION_FAILED' + +// ------------------------------------ +// Actions +// ------------------------------------ +export function getTransactions() { + return { + type: GET_TRANSACTIONS + } +} + +export function sendTransaction() { + return { + type: SEND_TRANSACTION + } +} + +// Send IPC event for payments +export const fetchTransactions = () => (dispatch) => { + dispatch(getTransactions()) + ipcRenderer.send('lnd', { msg: 'transactions' }) +} + +// Receive IPC event for payments +export const receiveTransactions = (event, { transactions }) => dispatch => dispatch({ type: RECEIVE_TRANSACTIONS, transactions }) + +export const sendCoins = ({ value, addr, currency, rate }) => (dispatch) => { + const amount = currency === 'usd' ? btc.btcToSatoshis(usd.usdToBtc(value, rate)) : btc.btcToSatoshis(value) + dispatch(sendPayment()) + ipcRenderer.send('lnd', { msg: 'sendCoins', data: { amount, addr } }) +} + +// Receive IPC event for successful payment +// TODO: Add payment to state, not a total re-fetch +export const transactionSuccessful = (event, { amount, addr, txid }) => (dispatch) => { + // Get the new list of transactions (TODO dont do an entire new fetch) + fetchTransactions() + // Close the form modal once the payment was succesful + dispatch(setForm({ modalOpen: false })) + // Show successful payment state + dispatch(showModal('SUCCESSFUL_SEND_COINS', { txid, amount, addr })) + // TODO: Add successful on-chain payment to payments list once payments list supports on-chain and LN + // dispatch({ type: PAYMENT_SUCCESSFULL, payment: { amount, addr, txid, pending: true } }) + dispatch({ type: TRANSACTION_SUCCESSFULL }) + // Reset the payment form + dispatch(resetForm()) +} + +export const transactionError = () => (dispatch) => { + dispatch({ type: PAYMENT_FAILED }) +} + + +// ------------------------------------ +// Action Handlers +// ------------------------------------ +const ACTION_HANDLERS = { + [GET_TRANSACTIONS]: state => ({ ...state, transactionLoading: true }), + [SEND_TRANSACTION]: state => ({ ...state, sendingTransaction: true }), + [RECEIVE_TRANSACTIONS]: (state, { transactions }) => ({ ...state, transactionLoading: false, transactions }), + [TRANSACTION_SUCCESSFULL]: state => ({ ...state, sendingTransaction: false }), + [TRANSACTION_FAILED]: state => ({ ...state, sendingTransaction: false }) +} + +// ------------------------------------ +// Reducer +// ------------------------------------ +const initialState = { + sendingtransaction: false, + transactionLoading: false, + transactions: [] +} + +export default function transactionReducer(state = initialState, action) { + const handler = ACTION_HANDLERS[action.type] + + return handler ? handler(state, action) : state +} diff --git a/app/routes/activity/components/Activity.js b/app/routes/activity/components/Activity.js index 85692c8e..be61ab6a 100644 --- a/app/routes/activity/components/Activity.js +++ b/app/routes/activity/components/Activity.js @@ -14,10 +14,11 @@ class Activity extends Component { } componentWillMount() { - const { fetchPayments, fetchInvoices } = this.props + const { fetchPayments, fetchInvoices, fetchTransactions } = this.props fetchPayments() fetchInvoices() + fetchTransactions() } render() { diff --git a/app/routes/activity/containers/ActivityContainer.js b/app/routes/activity/containers/ActivityContainer.js index 1b3cba45..25f0652e 100644 --- a/app/routes/activity/containers/ActivityContainer.js +++ b/app/routes/activity/containers/ActivityContainer.js @@ -11,6 +11,7 @@ import { fetchPayments, paymentSelectors } from '../../../reducers/payment' +import { fetchTransactions } from '../../../reducers/transaction' import Activity from '../components/Activity' const mapDispatchToProps = { @@ -18,6 +19,7 @@ const mapDispatchToProps = { setInvoice, fetchPayments, fetchInvoices, + fetchTransactions, searchInvoices }