arnaucube
arnaucube/goBlockchainDataAnalysisPublic Self-hosted repository
goBlockchainDataAnalysis/serverRoutes.go
serverRoutes.goRaw
  1package main
  2
  3import (
  4	"encoding/json"
  5	"fmt"
  6	"net/http"
  7	"sort"
  8	"strconv"
  9	"time"
 10
 11	"gopkg.in/mgo.v2/bson"
 12
 13	"github.com/gorilla/mux"
 14)
 15
 16type Routes []Route
 17
 18var routes = Routes{
 19	Route{
 20		"Index",
 21		"GET",
 22		"/",
 23		Index,
 24	},
 25	Route{
 26		"Stats",
 27		"Get",
 28		"/stats",
 29		Stats,
 30	},
 31	Route{
 32		"AllAddresses",
 33		"Get",
 34		"/alladdresses",
 35		AllAddresses,
 36	},
 37	Route{
 38		"GetLastAddr",
 39		"Get",
 40		"/lastaddr",
 41		GetLastAddr,
 42	},
 43	Route{
 44		"GetLastTx",
 45		"Get",
 46		"/lasttx",
 47		GetLastTx,
 48	},
 49	Route{
 50		"Block",
 51		"GET",
 52		"/block/{height}",
 53		Block,
 54	},
 55	Route{
 56		"Tx",
 57		"GET",
 58		"/tx/{txid}",
 59		Tx,
 60	},
 61	Route{
 62		"Address",
 63		"GET",
 64		"/address/{hash}",
 65		Address,
 66	},
 67	Route{
 68		"AddressNetwork",
 69		"GET",
 70		"/address/network/{address}",
 71		AddressNetwork,
 72	},
 73	Route{
 74		"AddressSankey",
 75		"GET",
 76		"/address/sankey/{address}",
 77		AddressSankey,
 78	},
 79	Route{
 80		"NetworkMap",
 81		"Get",
 82		"/map",
 83		NetworkMap,
 84	},
 85	Route{
 86		"GetTotalHourAnalysis",
 87		"Get",
 88		"/totalhouranalysis",
 89		GetTotalHourAnalysis,
 90	},
 91	Route{
 92		"GetLast24HourAnalysis",
 93		"Get",
 94		"/last24hour",
 95		GetLast24HourAnalysis,
 96	},
 97	Route{
 98		"GetLast7DayAnalysis",
 99		"Get",
100		"/last7day",
101		GetLast7DayAnalysis,
102	},
103	Route{
104		"GetLast7DayHourAnalysis",
105		"Get",
106		"/last7dayhour",
107		GetLast7DayHourAnalysis,
108	},
109	Route{
110		"GetAddressTimeChart",
111		"GET",
112		"/addresstimechart/{hash}",
113		GetAddressTimeChart,
114	},
115}
116
117//ROUTES
118
119func Index(w http.ResponseWriter, r *http.Request) {
120	fmt.Fprintln(w, "ask for recommendations in /r")
121	//http.FileServer(http.Dir("./web"))
122}
123
124/*
125func NewUser(w http.ResponseWriter, r *http.Request) {
126	ipFilter(w, r)
127	decoder := json.NewDecoder(r.Body)
128	var newUser UserModel
129	err := decoder.Decode(&newUser)
130	check(err)
131	defer r.Body.Close()
132
133	saveUser(userCollection, newUser)
134
135	fmt.Println(newUser)
136	fmt.Fprintln(w, "new user added: ", newUser.ID)
137}
138*/
139func Stats(w http.ResponseWriter, r *http.Request) {
140	ipFilter(w, r)
141
142	stats := getStats()
143
144	jsonResp, err := json.Marshal(stats)
145	check(err)
146
147	fmt.Fprintln(w, string(jsonResp))
148}
149func AllAddresses(w http.ResponseWriter, r *http.Request) {
150	ipFilter(w, r)
151
152	nodes := []NodeModel{}
153	iter := nodeCollection.Find(bson.M{"type": "address"}).Limit(10000).Iter()
154	err := iter.All(&nodes)
155
156	//convert []resp struct to json
157	jsonNodes, err := json.Marshal(nodes)
158	check(err)
159
160	fmt.Fprintln(w, string(jsonNodes))
161}
162func GetLastAddr(w http.ResponseWriter, r *http.Request) {
163	ipFilter(w, r)
164
165	addresses := []AddressModel{}
166	err := addressCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&addresses)
167	check(err)
168
169	//convert []resp struct to json
170	jsonResp, err := json.Marshal(addresses)
171	check(err)
172
173	fmt.Fprintln(w, string(jsonResp))
174}
175func GetLastTx(w http.ResponseWriter, r *http.Request) {
176	ipFilter(w, r)
177
178	txs := []TxModel{}
179	err := txCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&txs)
180	check(err)
181
182	//convert []resp struct to json
183	jsonData, err := json.Marshal(txs)
184	check(err)
185
186	fmt.Fprintln(w, string(jsonData))
187}
188func Block(w http.ResponseWriter, r *http.Request) {
189	ipFilter(w, r)
190
191	vars := mux.Vars(r)
192	var heightString string
193	heightString = vars["height"]
194	height, err := strconv.ParseInt(heightString, 10, 64)
195	if err != nil {
196		fmt.Fprintln(w, "not valid height")
197	} else {
198		block := BlockModel{}
199		err := blockCollection.Find(bson.M{"height": height}).One(&block)
200
201		txs := []TxModel{}
202		err = txCollection.Find(bson.M{"blockheight": heightString}).All(&txs)
203		block.Txs = txs
204
205		//convert []resp struct to json
206		jsonResp, err := json.Marshal(block)
207		check(err)
208
209		fmt.Fprintln(w, string(jsonResp))
210	}
211}
212func Tx(w http.ResponseWriter, r *http.Request) {
213	ipFilter(w, r)
214
215	vars := mux.Vars(r)
216	txid := vars["txid"]
217	if txid == "undefined" {
218		fmt.Fprintln(w, "not valid txid")
219	} else {
220		tx := TxModel{}
221		err := txCollection.Find(bson.M{"txid": txid}).One(&tx)
222
223		//convert []resp struct to json
224		jsonResp, err := json.Marshal(tx)
225		check(err)
226
227		fmt.Fprintln(w, string(jsonResp))
228	}
229}
230func Address(w http.ResponseWriter, r *http.Request) {
231	ipFilter(w, r)
232
233	vars := mux.Vars(r)
234	hash := vars["hash"]
235	if hash == "undefined" {
236		fmt.Fprintln(w, "not valid hash")
237	} else {
238		address := AddressModel{}
239		err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
240
241		txs := []TxModel{}
242		err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"vin.address": hash}, bson.M{"vout.address": hash}}}).All(&txs)
243		address.Txs = txs
244
245		for _, tx := range address.Txs {
246			blocks := []BlockModel{}
247			err = blockCollection.Find(bson.M{"hash": tx.BlockHash}).All(&blocks)
248			for _, block := range blocks {
249				address.Blocks = append(address.Blocks, block)
250			}
251		}
252
253		//convert []resp struct to json
254		jsonResp, err := json.Marshal(address)
255		check(err)
256
257		fmt.Fprintln(w, string(jsonResp))
258	}
259}
260func AddressNetwork(w http.ResponseWriter, r *http.Request) {
261	ipFilter(w, r)
262
263	vars := mux.Vars(r)
264	address := vars["address"]
265	if address == "undefined" {
266		fmt.Fprintln(w, "not valid address")
267	} else {
268		network := addressTree(address)
269		network.Nodes[0].Shape = "triangle"
270
271		//convert []resp struct to json
272		jNetwork, err := json.Marshal(network)
273		check(err)
274
275		fmt.Fprintln(w, string(jNetwork))
276	}
277}
278func AddressSankey(w http.ResponseWriter, r *http.Request) {
279	ipFilter(w, r)
280	vars := mux.Vars(r)
281	address := vars["address"]
282	if address == "undefined" {
283		fmt.Fprintln(w, "not valid address")
284	} else {
285		network := addressTree(address)
286		var sankey SankeyModel
287
288		fmt.Println("network generated")
289		mapNodeK := make(map[string]int)
290		for k, n := range network.Nodes {
291			var sankeyNode SankeyNodeModel
292			//sankeyNode.StringNode = n.Id
293			sankeyNode.Node = k
294			sankeyNode.Name = n.Id
295			sankey.Nodes = append(sankey.Nodes, sankeyNode)
296			mapNodeK[n.Id] = k
297		}
298		for _, e := range network.Edges {
299			var sankeyLink SankeyLinkModel
300			//sankeyLink.StringSource = e.From
301			sankeyLink.Source = mapNodeK[e.From]
302			//sankeyLink.StringTarget = e.To
303			sankeyLink.Target = mapNodeK[e.To]
304			sankeyLink.Value = e.Label
305			sankey.Links = append(sankey.Links, sankeyLink)
306		}
307		fmt.Println("Sankey generated")
308
309		//convert []resp struct to json
310		jsonSankey, err := json.Marshal(sankey)
311		check(err)
312
313		fmt.Fprintln(w, string(jsonSankey))
314	}
315}
316func NetworkMap(w http.ResponseWriter, r *http.Request) {
317	ipFilter(w, r)
318
319	nodes, err := getAllNodes()
320	check(err)
321	edges, err := getAllEdges()
322	check(err)
323
324	var network NetworkModel
325	network.Nodes = nodes
326	network.Edges = edges
327
328	//convert []resp struct to json
329	jNetwork, err := json.Marshal(network)
330	check(err)
331
332	fmt.Fprintln(w, string(jNetwork))
333}
334
335func GetTotalHourAnalysis(w http.ResponseWriter, r *http.Request) {
336	ipFilter(w, r)
337
338	hourAnalysis := []ChartCountModel{}
339	iter := hourCountCollection.Find(bson.M{}).Limit(10000).Iter()
340	err := iter.All(&hourAnalysis)
341
342	//sort by hour
343	sort.Slice(hourAnalysis, func(i, j int) bool {
344		return hourAnalysis[i].Elem < hourAnalysis[j].Elem
345	})
346
347	var resp ChartAnalysisResp
348	for _, d := range hourAnalysis {
349		resp.Labels = append(resp.Labels, strconv.Itoa(d.Elem))
350		resp.Data = append(resp.Data, d.Count)
351	}
352
353	//convert []resp struct to json
354	jsonResp, err := json.Marshal(resp)
355	check(err)
356	fmt.Fprintln(w, string(jsonResp))
357}
358
359func GetLast24HourAnalysis(w http.ResponseWriter, r *http.Request) {
360	ipFilter(w, r)
361
362	fromDate := time.Now().AddDate(0, 0, -1)
363	toDate := time.Now()
364
365	txs := []TxModel{}
366	err := txCollection.Find(bson.M{
367		"datet": bson.M{
368			"$gt": fromDate,
369			"$lt": toDate,
370		},
371	}).Sort("-$natural").All(&txs)
372	check(err)
373
374	//generate map with 24 hours
375	hourFrequencies := map24hours()
376	for _, tx := range txs {
377		hourFrequencies[tx.Date.Hour]++
378	}
379	var hourCount []ChartCountModel
380	for hour, frequency := range hourFrequencies {
381		hourCount = append(hourCount, ChartCountModel{hour, frequency})
382	}
383	//sort by hour
384	sort.Slice(hourCount, func(i, j int) bool {
385		return hourCount[i].Elem < hourCount[j].Elem
386	})
387
388	var resp ChartAnalysisResp
389	for _, d := range hourCount {
390		resp.Labels = append(resp.Labels, strconv.Itoa(d.Elem))
391		resp.Data = append(resp.Data, d.Count)
392	}
393
394	//convert []resp struct to json
395	jsonResp, err := json.Marshal(resp)
396	check(err)
397	fmt.Fprintln(w, string(jsonResp))
398}
399func GetLast7DayAnalysis(w http.ResponseWriter, r *http.Request) {
400	ipFilter(w, r)
401
402	fromDate := time.Now().AddDate(0, 0, -7)
403	toDate := time.Now()
404
405	txs := []TxModel{}
406	err := txCollection.Find(bson.M{
407		"datet": bson.M{
408			"$gt": fromDate,
409			"$lt": toDate,
410		},
411	}).Sort("-$natural").All(&txs)
412	check(err)
413
414	//generate map with 24 hours
415	//hourFrequencies := map24hours()
416	dayFrequencies := make(map[int]int)
417	for _, tx := range txs {
418		dayFrequencies[tx.Date.Day]++
419	}
420	var dayCount []ChartCountModel
421	for day, frequency := range dayFrequencies {
422		dayCount = append(dayCount, ChartCountModel{day, frequency})
423	}
424	//sort by hour
425	sort.Slice(dayCount, func(i, j int) bool {
426		return dayCount[i].Elem < dayCount[j].Elem
427	})
428
429	var resp ChartAnalysisResp
430	for _, d := range dayCount {
431		resp.Labels = append(resp.Labels, strconv.Itoa(d.Elem))
432		resp.Data = append(resp.Data, d.Count)
433	}
434
435	//convert []resp struct to json
436	jsonResp, err := json.Marshal(resp)
437	check(err)
438	fmt.Fprintln(w, string(jsonResp))
439}
440
441func GetLast7DayHourAnalysis(w http.ResponseWriter, r *http.Request) {
442	ipFilter(w, r)
443
444	var resp ChartSeriesAnalysisResp
445
446	for i := 0; i < 7; i++ {
447		fromDate := time.Now().AddDate(0, 0, -i-1)
448		toDate := time.Now().AddDate(0, 0, -i)
449		txs := []TxModel{}
450		err := txCollection.Find(bson.M{
451			"datet": bson.M{
452				"$gt": fromDate,
453				"$lt": toDate,
454			},
455		}).Sort("-$natural").All(&txs)
456		check(err)
457
458		//generate map with 24 hours
459		hourFrequencies := map24hours()
460		for _, tx := range txs {
461			hourFrequencies[tx.Date.Hour]++
462		}
463		var hourCount []ChartCountModel
464		for hour, frequency := range hourFrequencies {
465			hourCount = append(hourCount, ChartCountModel{hour, frequency})
466		}
467		//sort by hour
468		sort.Slice(hourCount, func(i, j int) bool {
469			return hourCount[i].Elem < hourCount[j].Elem
470		})
471		var dayData []int
472		for _, d := range hourCount {
473			dayData = append(dayData, d.Count)
474		}
475		if len(txs) > 0 {
476			resp.Series = append(resp.Series, txs[0].Date.Day)
477			resp.Data = append(resp.Data, dayData)
478		}
479	}
480	hourLabels := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"}
481	resp.Labels = hourLabels
482
483	//convert []resp struct to json
484	jsonResp, err := json.Marshal(resp)
485	check(err)
486	fmt.Fprintln(w, string(jsonResp))
487}
488func GetAddressTimeChart(w http.ResponseWriter, r *http.Request) {
489	ipFilter(w, r)
490
491	vars := mux.Vars(r)
492	hash := vars["hash"]
493	if hash == "undefined" {
494		fmt.Fprintln(w, "not valid hash")
495	} else {
496		address := AddressModel{}
497		err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
498
499		txs := []TxModel{}
500		err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"vin.address": hash}, bson.M{"vout.address": hash}}}).All(&txs)
501		address.Txs = txs
502
503		for _, tx := range address.Txs {
504			blocks := []BlockModel{}
505			err = blockCollection.Find(bson.M{"hash": tx.BlockHash}).All(&blocks)
506			for _, block := range blocks {
507				address.Blocks = append(address.Blocks, block)
508			}
509		}
510
511		count := make(map[time.Time]float64)
512		for _, tx := range txs {
513			var val float64
514			for _, vin := range tx.Vin {
515				val = val + vin.Amount
516			}
517			count[tx.DateT] = val
518		}
519		var dateSorted []time.Time
520		for t, _ := range count {
521			dateSorted = append(dateSorted, t)
522		}
523		sort.Slice(dateSorted, func(i, j int) bool {
524			//return dateSorted[i] < dateSorted[j]
525			return dateBeforeThan(dateSorted[i], dateSorted[j])
526		})
527
528		var resp ChartAnalysisRespFloat64
529		for _, t := range dateSorted {
530			resp.Labels = append(resp.Labels, t.String())
531			resp.Data = append(resp.Data, count[t])
532		}
533
534		//convert []resp struct to json
535		jsonResp, err := json.Marshal(resp)
536		check(err)
537
538		fmt.Fprintln(w, string(jsonResp))
539	}
540}