|
|
@ -2,16 +2,21 @@ import $ from 'jquery' |
|
|
|
import omit from 'lodash/omit' |
|
|
|
import omit from 'lodash/omit' |
|
|
|
import URI from 'urijs' |
|
|
|
import URI from 'urijs' |
|
|
|
import humps from 'humps' |
|
|
|
import humps from 'humps' |
|
|
|
|
|
|
|
import numeral from 'numeral' |
|
|
|
import { subscribeChannel } from '../../socket' |
|
|
|
import { subscribeChannel } from '../../socket' |
|
|
|
import { connectElements } from '../../lib/redux_helpers.js' |
|
|
|
import { connectElements } from '../../lib/redux_helpers.js' |
|
|
|
import { createAsyncLoadStore } from '../../lib/async_listing_load' |
|
|
|
import { createAsyncLoadStore } from '../../lib/async_listing_load' |
|
|
|
|
|
|
|
import { batchChannel } from '../../lib/utils' |
|
|
|
import '../address' |
|
|
|
import '../address' |
|
|
|
import { isFiltered } from './utils' |
|
|
|
import { isFiltered } from './utils' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const BATCH_THRESHOLD = 6 |
|
|
|
|
|
|
|
|
|
|
|
export const initialState = { |
|
|
|
export const initialState = { |
|
|
|
addressHash: null, |
|
|
|
addressHash: null, |
|
|
|
channelDisconnected: false, |
|
|
|
channelDisconnected: false, |
|
|
|
filter: null |
|
|
|
filter: null, |
|
|
|
|
|
|
|
transactionsBatch: [] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function reducer (state, action) { |
|
|
|
export function reducer (state, action) { |
|
|
@ -36,11 +41,46 @@ export function reducer (state, action) { |
|
|
|
|
|
|
|
|
|
|
|
return Object.assign({}, state, { items: [action.msg.transactionHtml, ...state.items] }) |
|
|
|
return Object.assign({}, state, { items: [action.msg.transactionHtml, ...state.items] }) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
case 'RECEIVED_NEW_TRANSACTION_BATCH': { |
|
|
|
|
|
|
|
if (state.channelDisconnected || state.beyondPageOne) return state |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const transactionCount = state.transactionCount + action.msgs.length |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!state.transactionsBatch.length && action.msgs.length < BATCH_THRESHOLD) { |
|
|
|
|
|
|
|
return Object.assign({}, state, { |
|
|
|
|
|
|
|
items: [ |
|
|
|
|
|
|
|
...action.msgs.map(msg => msg.transactionHtml).reverse(), |
|
|
|
|
|
|
|
...state.items |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
transactionCount |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return Object.assign({}, state, { |
|
|
|
|
|
|
|
transactionsBatch: [ |
|
|
|
|
|
|
|
...action.msgs.reverse(), |
|
|
|
|
|
|
|
...state.transactionsBatch |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
transactionCount |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
case 'RECEIVED_NEW_REWARD': { |
|
|
|
case 'RECEIVED_NEW_REWARD': { |
|
|
|
if (state.channelDisconnected) return state |
|
|
|
if (state.channelDisconnected) return state |
|
|
|
|
|
|
|
|
|
|
|
return Object.assign({}, state, { items: [action.msg.rewardHtml, ...state.items] }) |
|
|
|
return Object.assign({}, state, { items: [action.msg.rewardHtml, ...state.items] }) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
case 'TRANSACTION_BATCH_EXPANDED': { |
|
|
|
|
|
|
|
return Object.assign({}, state, { |
|
|
|
|
|
|
|
transactionsBatch: [] |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case 'TRANSACTIONS_FETCHED': |
|
|
|
|
|
|
|
return Object.assign({}, state, { items: [...action.msg.items] }) |
|
|
|
|
|
|
|
case 'TRANSACTIONS_FETCH_ERROR': { |
|
|
|
|
|
|
|
const $channelBatching = $('[data-selector="channel-batching-message"]') |
|
|
|
|
|
|
|
$channelBatching.show() |
|
|
|
|
|
|
|
return state |
|
|
|
|
|
|
|
} |
|
|
|
default: |
|
|
|
default: |
|
|
|
return state |
|
|
|
return state |
|
|
|
} |
|
|
|
} |
|
|
@ -66,6 +106,14 @@ const elements = { |
|
|
|
|
|
|
|
|
|
|
|
return $el.show() |
|
|
|
return $el.show() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
'[data-selector="channel-batching-count"]': { |
|
|
|
|
|
|
|
render ($el, state, _oldState) { |
|
|
|
|
|
|
|
const $channelBatching = $('[data-selector="channel-batching-message"]') |
|
|
|
|
|
|
|
if (!state.transactionsBatch.length) return $channelBatching.hide() |
|
|
|
|
|
|
|
$channelBatching.show() |
|
|
|
|
|
|
|
$el[0].innerHTML = numeral(state.transactionsBatch.length).format() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -85,18 +133,18 @@ if ($('[data-page="address-transactions"]').length) { |
|
|
|
|
|
|
|
|
|
|
|
const addressChannel = subscribeChannel(`addresses:${addressHash}`) |
|
|
|
const addressChannel = subscribeChannel(`addresses:${addressHash}`) |
|
|
|
addressChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) |
|
|
|
addressChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) |
|
|
|
addressChannel.on('transaction', (msg) => { |
|
|
|
addressChannel.on('transaction', batchChannel((msgs) => |
|
|
|
store.dispatch({ |
|
|
|
store.dispatch({ |
|
|
|
type: 'RECEIVED_NEW_TRANSACTION', |
|
|
|
type: 'RECEIVED_NEW_TRANSACTION_BATCH', |
|
|
|
msg: humps.camelizeKeys(msg) |
|
|
|
msgs: humps.camelizeKeys(msgs) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
)) |
|
|
|
addressChannel.on('pending_transaction', (msg) => { |
|
|
|
addressChannel.on('pending_transaction', batchChannel((msgs) => |
|
|
|
store.dispatch({ |
|
|
|
store.dispatch({ |
|
|
|
type: 'RECEIVED_NEW_TRANSACTION', |
|
|
|
type: 'RECEIVED_NEW_TRANSACTION_BATCH', |
|
|
|
msg: humps.camelizeKeys(msg) |
|
|
|
msgs: humps.camelizeKeys(msgs) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
)) |
|
|
|
|
|
|
|
|
|
|
|
const rewardsChannel = subscribeChannel(`rewards:${addressHash}`) |
|
|
|
const rewardsChannel = subscribeChannel(`rewards:${addressHash}`) |
|
|
|
rewardsChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) |
|
|
|
rewardsChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' })) |
|
|
@ -106,4 +154,24 @@ if ($('[data-page="address-transactions"]').length) { |
|
|
|
msg: humps.camelizeKeys(msg) |
|
|
|
msg: humps.camelizeKeys(msg) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const $txReloadButton = $('[data-selector="reload-transactions-button"]') |
|
|
|
|
|
|
|
const $channelBatching = $('[data-selector="channel-batching-message"]') |
|
|
|
|
|
|
|
$txReloadButton.on('click', (event) => { |
|
|
|
|
|
|
|
event.preventDefault() |
|
|
|
|
|
|
|
loadTransactions(store) |
|
|
|
|
|
|
|
$channelBatching.hide() |
|
|
|
|
|
|
|
store.dispatch({ |
|
|
|
|
|
|
|
type: 'TRANSACTION_BATCH_EXPANDED' |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function loadTransactions (store) { |
|
|
|
|
|
|
|
const path = $('[class="card-body"]')[1].dataset.asyncListing |
|
|
|
|
|
|
|
store.dispatch({ type: 'START_TRANSACTIONS_FETCH' }) |
|
|
|
|
|
|
|
$.getJSON(path, { type: 'JSON' }) |
|
|
|
|
|
|
|
.done(response => store.dispatch({ type: 'TRANSACTIONS_FETCHED', msg: humps.camelizeKeys(response) })) |
|
|
|
|
|
|
|
.fail(() => store.dispatch({ type: 'TRANSACTIONS_FETCH_ERROR' })) |
|
|
|
|
|
|
|
.always(() => store.dispatch({ type: 'FINISH_TRANSACTIONS_FETCH' })) |
|
|
|
} |
|
|
|
} |
|
|
|