import $ from 'jquery' import _ from 'lodash' import URI from 'urijs' import humps from 'humps' import numeral from 'numeral' import socket, { subscribeChannel } from '../socket' import { createStore, connectElements } from '../lib/redux_helpers.js' import { updateAllCalculatedUsdValues } from '../lib/currency.js' import { loadTokenBalanceDropdown } from '../lib/token_balance_dropdown' export const initialState = { channelDisconnected: false, addressHash: null, filter: null, balance: null, transactionCount: null, validationCount: null } export function reducer (state = initialState, action) { switch (action.type) { case 'PAGE_LOAD': case 'ELEMENTS_LOAD': { return Object.assign({}, state, _.omit(action, 'type')) } case 'CHANNEL_DISCONNECTED': { if (state.beyondPageOne) return state return Object.assign({}, state, { channelDisconnected: true }) } case 'RECEIVED_NEW_BLOCK': { if (state.channelDisconnected) return state const validationCount = state.validationCount + 1 return Object.assign({}, state, { validationCount }) } case 'RECEIVED_NEW_TRANSACTION': { if (state.channelDisconnected) return state const transactionCount = (action.msg.fromAddressHash === state.addressHash) ? state.transactionCount + 1 : state.transactionCount return Object.assign({}, state, { transactionCount }) } case 'RECEIVED_UPDATED_BALANCE': { return Object.assign({}, state, { balance: action.msg.balance }) } default: return state } } const elements = { '[data-selector="channel-disconnected-message"]': { render ($el, state) { if (state.channelDisconnected) $el.show() } }, '[data-selector="balance-card"]': { load ($el) { return { balance: $el.html() } }, render ($el, state, oldState) { if (oldState.balance === state.balance) return $el.empty().append(state.balance) loadTokenBalanceDropdown() updateAllCalculatedUsdValues() } }, '[data-selector="transaction-count"]': { load ($el) { return { transactionCount: numeral($el.text()).value() } }, render ($el, state, oldState) { if (oldState.transactionCount === state.transactionCount) return $el.empty().append(numeral(state.transactionCount).format()) } }, '[data-selector="validation-count"]': { load ($el) { return { validationCount: numeral($el.text()).value() } }, render ($el, state, oldState) { if (oldState.validationCount === state.validationCount) return $el.empty().append(numeral(state.validationCount).format()) } } } const $addressDetailsPage = $('[data-page="address-details"]') if ($addressDetailsPage.length) { const store = createStore(reducer) const addressHash = $addressDetailsPage[0].dataset.pageAddressHash const { filter, blockNumber } = humps.camelizeKeys(URI(window.location).query(true)) store.dispatch({ type: 'PAGE_LOAD', addressHash, filter, beyondPageOne: !!blockNumber }) connectElements({ store, elements }) const addressChannel = subscribeChannel(`addresses:${addressHash}`) addressChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) addressChannel.on('balance', (msg) => store.dispatch({ type: 'RECEIVED_UPDATED_BALANCE', msg: humps.camelizeKeys(msg) })) addressChannel.on('transaction', (msg) => { store.dispatch({ type: 'RECEIVED_NEW_TRANSACTION', msg: humps.camelizeKeys(msg) }) }) const blocksChannel = socket.channel(`blocks:${addressHash}`, {}) blocksChannel.join() blocksChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) blocksChannel.on('new_block', (msg) => store.dispatch({ type: 'RECEIVED_NEW_BLOCK', msg: humps.camelizeKeys(msg) })) }