Skip to content

Commit

Permalink
feat: add max & min balance w/ timestamps to account meta, along with…
Browse files Browse the repository at this point in the history
… last timestamps for change and send blocks
  • Loading branch information
mistakia committed Apr 17, 2024
1 parent 90d652a commit 6de4ecf
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/core/accounts/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const Account = new Record({
representative: false,
last_seen: null,
account_meta: new Map(),
stats: new Map(),
representative_meta: new Map(),
telemetry_history: new List(),
uptime: new List(),
Expand Down
41 changes: 41 additions & 0 deletions src/core/accounts/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export const accountsActions = {
GET_ACCOUNT_PENDING: 'GET_ACCOUNT_PENDING',
GET_ACCOUNT_FULFILLED: 'GET_ACCOUNT_FULFILLED',

GET_ACCOUNT_STATS: 'GET_ACCOUNT_STATS',
GET_ACCOUNT_STATS_FAILED: 'GET_ACCOUNT_STATS_FAILED',
GET_ACCOUNT_STATS_PENDING: 'GET_ACCOUNT_STATS_PENDING',
GET_ACCOUNT_STATS_FULFILLED: 'GET_ACCOUNT_STATS_FULFILLED',

GET_ACCOUNT_OPEN_FAILED: 'GET_ACCOUNT_OPEN_FAILED',
GET_ACCOUNT_OPEN_PENDING: 'GET_ACCOUNT_OPEN_PENDING',
GET_ACCOUNT_OPEN_FULFILLED: 'GET_ACCOUNT_OPEN_FULFILLED',
Expand Down Expand Up @@ -174,6 +179,36 @@ export const accountsActions = {
params,
data
}
}),

getAccountStats: (account) => ({
type: accountsActions.GET_ACCOUNT_STATS,
payload: {
account
}
}),

getAccountStatsFailed: (params, error) => ({
type: accountsActions.GET_ACCOUNT_STATS_FAILED,
payload: {
params,
error
}
}),

getAccountStatsPending: (params) => ({
type: accountsActions.GET_ACCOUNT_STATS_PENDING,
payload: {
params
}
}),

getAccountStatsFulfilled: (params, data) => ({
type: accountsActions.GET_ACCOUNT_STATS_FULFILLED,
payload: {
params,
data
}
})
}

Expand Down Expand Up @@ -206,3 +241,9 @@ export const accountBalanceHistoryRequestActions = {
pending: accountsActions.getAccountBalanceHistoryPending,
fulfilled: accountsActions.getAccountBalanceHistoryFulfilled
}

export const accountStatsRequestActions = {
failed: accountsActions.getAccountStatsFailed,
pending: accountsActions.getAccountStatsPending,
fulfilled: accountsActions.getAccountStatsFulfilled
}
3 changes: 2 additions & 1 deletion src/core/accounts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export {
accountRequestActions,
accountOpenRequestActions,
accountBlocksSummaryRequestActions,
accountBalanceHistoryRequestActions
accountBalanceHistoryRequestActions,
accountStatsRequestActions
} from './actions'
export { accountsReducer } from './reducer'
export { accountSagas } from './sagas'
Expand Down
23 changes: 18 additions & 5 deletions src/core/accounts/reducer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Map, List } from 'immutable'

import { accountsActions } from './actions'
import { createAccount } from './account'
import { createAccount, Account } from './account'

const initialState = new Map({
isLoading: false,
Expand Down Expand Up @@ -50,10 +50,17 @@ export function accountsReducer(state = initialState, { payload, type }) {
})

case accountsActions.GET_ACCOUNT_FULFILLED:
return state.setIn(
['items', payload.params],
createAccount({ ...payload.data, account_is_loading: false })
)
return state.withMutations((state) => {
const existing_account = state
.getIn(['items', payload.params], new Account())
.toJS()
const updated_account = createAccount({
...existing_account,
...payload.data,
account_is_loading: false
})
state.setIn(['items', payload.params], updated_account)
})

case accountsActions.GET_ACCOUNT_OPEN_PENDING:
return state.setIn(
Expand Down Expand Up @@ -126,6 +133,12 @@ export function accountsReducer(state = initialState, { payload, type }) {
)
})

case accountsActions.GET_ACCOUNT_STATS_FULFILLED:
return state.setIn(
['items', payload.params.account, 'stats'],
new Map(payload.data)
)

default:
return state
}
Expand Down
19 changes: 17 additions & 2 deletions src/core/accounts/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
getAccountOpen,
getAccountBlocksSummary,
get_account_balance_history,
get_request_history
get_request_history,
get_account_stats
} from '@core/api'
import { accountsActions } from './actions'

Expand All @@ -32,6 +33,15 @@ export function* loadAccountBalanceHistory({ payload }) {
yield call(get_account_balance_history, { account })
}

export function* loadAccountStats({ payload }) {
const { account } = payload
const request_history = yield select(get_request_history)
if (request_history.has(`GET_ACCOUNT_STATS_${account}`)) {
return
}
yield call(get_account_stats, { account })
}

//= ====================================
// WATCHERS
// -------------------------------------
Expand All @@ -51,12 +61,17 @@ export function* watchGetAccountBalanceHistory() {
)
}

export function* watchGetAccountStats() {
yield takeLatest(accountsActions.GET_ACCOUNT_STATS, loadAccountStats)
}

//= ====================================
// ROOT
// -------------------------------------

export const accountSagas = [
fork(watchGetRepresentatives),
fork(watchGetAccount),
fork(watchGetAccountBalanceHistory)
fork(watchGetAccountBalanceHistory),
fork(watchGetAccountStats)
]
3 changes: 2 additions & 1 deletion src/core/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export {
get_accounts_unconfirmed_summary,
get_blocks_unconfirmed_summary,
get_account_balance_history,
get_price_history
get_price_history,
get_account_stats
} from './sagas'

export { api_reducer } from './reducer'
Expand Down
12 changes: 12 additions & 0 deletions src/core/api/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ export function api_reducer(state = initialState, { payload, type }) {
case nanodb_actions.GET_PRICE_HISTORY_FAILED:
return state.deleteIn(['request_history', 'GET_PRICE_HISTORY'])

case accountsActions.GET_ACCOUNT_STATS_PENDING:
return state.setIn(
['request_history', `GET_ACCOUNT_STATS_${payload.params.account}`],
true
)

case accountsActions.GET_ACCOUNT_STATS_FAILED:
return state.deleteIn([
'request_history',
`GET_ACCOUNT_STATS_${payload.params.account}`
])

default:
return state
}
Expand Down
9 changes: 8 additions & 1 deletion src/core/api/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import {
accountRequestActions,
accountOpenRequestActions,
accountBlocksSummaryRequestActions,
accountBalanceHistoryRequestActions
accountBalanceHistoryRequestActions,
accountStatsRequestActions
} from '@core/accounts/actions'
import { blockRequestActions } from '@core/blocks/actions'
import { dailyRequestActions } from '@core/ledger/actions'
Expand Down Expand Up @@ -157,3 +158,9 @@ export const get_price_history = fetch.bind(
api.get_price_history,
price_history_request_actions
)

export const get_account_stats = fetch.bind(
null,
api.get_account_stats,
accountStatsRequestActions
)
4 changes: 4 additions & 0 deletions src/core/api/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ export const api = {
get_price_history() {
const url = `${API_URL}/nanodb/price_history`
return { url }
},
get_account_stats({ account }) {
const url = `${API_URL}/nanodb/accounts/${account}/stats`
return { url }
}
}

Expand Down
74 changes: 74 additions & 0 deletions src/views/components/account-meta/account-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,31 @@ export default class AccountMeta extends React.Component {
'account_meta',
'modified_timestamp'
])
const last_send_timestamp = account.getIn([
'stats',
'last_send_block_timestamp'
])
const last_change_timestamp = account.getIn([
'stats',
'last_change_block_timestamp'
])
const last_modified_non_epoch = account.getIn([
'stats',
'last_non_epoch_block_timestamp'
])

const max_balance = account.getIn(['stats', 'max_balance'])
const max_balance_timestamp = account.getIn([
'stats',
'max_balance_timestamp'
])

const min_balance = account.getIn(['stats', 'min_balance'])
const min_balance_timestamp = account.getIn([
'stats',
'min_balance_timestamp'
])

const items = [
{
label: 'Funding Account',
Expand Down Expand Up @@ -54,6 +79,22 @@ export default class AccountMeta extends React.Component {
? BigNumber(openBalance).shiftedBy(-30).toFormat()
: '-'
},
{
label: 'Maximum Balance',
value: max_balance
? `${BigNumber(max_balance).shiftedBy(-30).toFormat()} (${dayjs(
max_balance_timestamp * 1000
).format('MMM D, YY h:mm a')})`
: '-'
},
{
label: 'Minimum Balance',
value: min_balance
? `${BigNumber(min_balance).shiftedBy(-30).toFormat()} (${dayjs(
min_balance_timestamp * 1000
).format('MMM D, YY h:mm a')})`
: '-'
},
{
label: 'Receivable Balance',
value: pendingBalance
Expand All @@ -75,6 +116,39 @@ export default class AccountMeta extends React.Component {
'MMM D, YYYY h:mm a'
)} (${timeago.format(modifiedTimestamp * 1000, 'nano_short')} ago)`
: '-'
},
{
label: 'Last Modified (non-epoch)',
value: last_modified_non_epoch
? `${dayjs(last_modified_non_epoch * 1000).format(
'MMM D, YYYY h:mm a'
)} (${timeago.format(
last_modified_non_epoch * 1000,
'nano_short'
)} ago)`
: '-'
},
{
label: 'Last Send',
value: last_send_timestamp
? `${dayjs(last_send_timestamp * 1000).format(
'MMM D, YYYY h:mm a'
)} (${timeago.format(
last_send_timestamp * 1000,
'nano_short'
)} ago)`
: '-'
},
{
label: 'Last Representative Change',
value: last_change_timestamp
? `${dayjs(last_change_timestamp * 1000).format(
'MMM D, YYYY h:mm a'
)} (${timeago.format(
last_change_timestamp * 1000,
'nano_short'
)} ago)`
: '-'
}
]

Expand Down
3 changes: 3 additions & 0 deletions src/views/pages/account/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default function AccountPage({
match,
showNotification,
getAccount,
get_account_stats,
account
}) {
const [value, setValue] = useState(0)
Expand All @@ -68,6 +69,7 @@ export default function AccountPage({
useEffect(() => {
const { address } = match.params
getAccount(`nano_${address}`)
get_account_stats(`nano_${address}`)
}, [match.params.address])

const is_loaded = account.get('account_is_loaded')
Expand Down Expand Up @@ -266,6 +268,7 @@ export default function AccountPage({
AccountPage.propTypes = {
match: PropTypes.object,
getAccount: PropTypes.func,
get_account_stats: PropTypes.func,
account: ImmutablePropTypes.record,
showNotification: PropTypes.func
}
1 change: 1 addition & 0 deletions src/views/pages/account/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const mapStateToProps = createSelector(getAccountById, (account) => ({

const mapDispatchToProps = {
getAccount: accountsActions.getAccount,
get_account_stats: accountsActions.getAccountStats,
showNotification: notificationActions.show
}

Expand Down

0 comments on commit 6de4ecf

Please sign in to comment.