OSDN Git Service

b0c25e4cefb8d4b345f6927d6624f4d0451a8e3d
[bytom/bytom-electron.git] / src / features / core / reducers.js
1 import { combineReducers } from 'redux'
2 import { testnetUrl } from 'utility/environment'
3 import moment from 'moment'
4 import { DeltaSampler } from 'utility/time'
5
6 const LONG_TIME_FORMAT = 'YYYY-MM-DD, h:mm:ss a'
7
8 const coreConfigReducer = (key, state, defaultState, action) => {
9   if (action.type == 'UPDATE_CORE_INFO') {
10     return action.param[key] || defaultState
11   }
12
13   return state || defaultState
14 }
15
16 const buildConfigReducer = (key, state, defaultState, action) => {
17   // if (action.type == 'UPDATE_CORE_INFO') {
18         // return action.param.buildConfig[key] || defaultState
19   // }
20
21   return state || defaultState
22 }
23
24 const configKnown = (state = false, action) => {
25   if (action.type == 'UPDATE_CORE_INFO') {
26     return true
27   }
28   return state
29 }
30
31 export const configured = (state, action) =>
32   coreConfigReducer('isConfigured', state, false, action)
33 export const configuredAt = (state, action) => {
34   let value = coreConfigReducer('configuredAt', state, '', action)
35   if (action.type == 'UPDATE_CORE_INFO' && value != '') {
36     value = moment(value).format(LONG_TIME_FORMAT)
37   }
38   return value
39 }
40
41 export const mockhsm = (state, action) =>
42   buildConfigReducer('isMockhsm', state, false, action)
43 export const localhostAuth = (state, action) =>
44   buildConfigReducer('isLocalhostAuth', state, false, action)
45 export const reset = (state, action) =>
46   buildConfigReducer('isReset', state, false, action)
47 export const httpOk = (state, action) =>
48   buildConfigReducer('isHttpOk', state, false, action)
49 export const blockHeight = (state, action) =>
50   coreConfigReducer('blockHeight', state, 0, action)
51 export const generatorBlockHeight = (state, action) => {
52   if (action.type == 'UPDATE_CORE_INFO') {
53     if (action.param.generatorBlockHeight == 0) return '???'
54   }
55
56   return coreConfigReducer('generatorBlockHeight', state, 0, action)
57 }
58 export const signer = (state, action) =>
59   coreConfigReducer('isSigner', state, false, action)
60 export const generator = (state, action) =>
61   coreConfigReducer('isGenerator', state, false, action)
62 export const generatorUrl = (state, action) =>
63   coreConfigReducer('generatorUrl', state, false, action)
64 export const generatorAccessToken = (state, action) =>
65   coreConfigReducer('generatorAccessToken', state, false, action)
66 export const blockchainId = (state, action) =>
67   coreConfigReducer('blockchainId', state, 0, action)
68 export const crosscoreRpcVersion = (state, action) =>
69   coreConfigReducer('crosscoreRpcVersion', state, 0, action)
70
71 export const coreType = (state = '', action) => {
72   if (action.type == 'UPDATE_CORE_INFO') {
73     if (action.param.isGenerator) return 'Generator'
74     if (action.param.isSigner) return 'Signer'
75     return 'Participant'
76   }
77   return state
78 }
79
80 export const replicationLag = (state = null, action) => {
81   if (action.type == 'UPDATE_CORE_INFO') {
82     if (action.param.generatorBlockHeight == 0) {
83       return null
84     }
85     return action.param.generatorBlockHeight - action.param.blockHeight
86   }
87
88   return state
89 }
90
91 let syncSamplers = null
92 const resetSyncSamplers = () => {
93   syncSamplers = {
94     snapshot: new DeltaSampler({sampleTtl: 10 * 1000}),
95     replicationLag: new DeltaSampler({sampleTtl: 10 * 1000}),
96   }
97 }
98
99 export const syncEstimates = (state = {}, action) => {
100   switch (action.type) {
101     case 'UPDATE_CORE_INFO': {
102       if (!syncSamplers) {
103         resetSyncSamplers()
104       }
105
106       const {
107         snapshot,
108         generatorBlockHeight,
109         blockHeight,
110       } = action.param
111
112       const estimates = {}
113
114       if (snapshot && snapshot.inProgress) {
115         const speed = syncSamplers.snapshot.sample(snapshot.downloaded)
116
117         if (speed != 0) {
118           estimates.snapshot = (snapshot.size - snapshot.downloaded) / speed
119         }
120       } else if (generatorBlockHeight > 0) {
121         const replicationLag = generatorBlockHeight - blockHeight
122         const speed = syncSamplers.replicationLag.sample(replicationLag)
123         if (speed != 0) {
124           const duration = -1 * replicationLag / speed
125           if (duration > 0) {
126             estimates.replicationLag = duration
127           }
128         }
129       }
130
131       return estimates
132     }
133
134     case 'CORE_DISCONNECT':
135       resetSyncSamplers()
136       return {}
137
138     default:
139       return state
140   }
141 }
142
143 export const replicationLagClass = (state = null, action) => {
144   if (action.type == 'UPDATE_CORE_INFO') {
145     if (action.param.generatorBlockHeight == 0) {
146       return 'red'
147     } else {
148       let lag = action.param.generatorBlockHeight - action.param.blockHeight
149       if (lag < 5) {
150         return 'green'
151       } else if (lag < 10) {
152         return 'yellow'
153       } else {
154         return 'red'
155       }
156     }
157   }
158
159   return state
160 }
161
162 export const onTestnet = (state = false, action) => {
163   if (action.type == 'UPDATE_CORE_INFO') {
164     return (action.param.generatorUrl || '').indexOf(testnetUrl) >= 0
165   }
166
167   return state
168 }
169
170 export const requireClientToken = (state = false, action) => {
171   if (action.type == 'ERROR' && action.payload.status == 401) return true
172
173   return state
174 }
175
176 export const clientToken = (state = '', action) => {
177   if      (action.type == 'SET_CLIENT_TOKEN') return action.token
178   else if (action.type == 'ERROR' &&
179            action.payload.status == 401)      return ''
180
181   return state
182 }
183
184 export const validToken = (state = false, action) => {
185   if      (action.type == 'SET_CLIENT_TOKEN') return false
186   else if (action.type == 'USER_LOG_IN')      return true
187   else if (action.type == 'ERROR' &&
188            action.payload.status == 401)      return false
189
190   return state
191 }
192
193 export const connected = (state = true, action) => {
194   if      (action.type == 'UPDATE_CORE_INFO') return true
195   else if (action.type == 'CORE_DISCONNECT')  return false
196
197   return state
198 }
199
200 export const btmAmountUnit = (state = 'BTM' , action) => {
201   if (action.type == 'UPDATE_BTM_AMOUNT_UNIT') {
202     return action.param
203   }
204   return state
205 }
206
207 const defaultLang = window.navigator.language.startsWith('zh') ? 'zh' : 'en'
208 const lang = (state = defaultLang, action) => {
209   if (action.type === 'UPDATE_CORE_LANGUAGE') {
210     return action.lang || ''
211   }
212   return state
213 }
214
215 const mingStatus = (state = false, action) => {
216   if (action.type == 'UPDATE_CORE_INFO') {
217     return action.param.data.mining
218   }
219   return state
220 }
221
222 const coreData = (state = null, action) => {
223   if (action.type == 'UPDATE_CORE_INFO') {
224     return action.param.data || null
225   }
226   return state
227 }
228
229 const accountInit = (state = false, action) => {
230   if (action.type == 'CREATE_REGISTER_ACCOUNT') {
231     return true
232   }
233   return state
234 }
235
236 const snapshot = (state = null, action) => {
237   if (action.type == 'UPDATE_CORE_INFO') {
238     return action.param.snapshot || null // snapshot may be undefined, which Redux doesn't like.
239   }
240   return state
241 }
242
243 const version = (state, action) => coreConfigReducer('version', state, 'N/A', action)
244
245
246 export default combineReducers({
247   accountInit,
248   blockchainId,
249   blockHeight,
250   connected,
251   clientToken,
252   configKnown,
253   configured,
254   configuredAt,
255   coreType,
256   coreData,
257   generator,
258   generatorAccessToken,
259   generatorBlockHeight,
260   generatorUrl,
261   localhostAuth,
262   mockhsm,
263   mingStatus,
264   crosscoreRpcVersion,
265   onTestnet,
266   httpOk,
267   replicationLag,
268   replicationLagClass,
269   requireClientToken,
270   reset,
271   signer,
272   snapshot,
273   syncEstimates,
274   validToken,
275   version,
276   lang,
277   btmAmountUnit
278 })