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		"BlockSankey",
 75		"GET",
 76		"/block/{height}/sankey",
 77		BlockSankey,
 78	},
 79	Route{
 80		"TxSankey",
 81		"GET",
 82		"/tx/{txid}/sankey",
 83		TxSankey,
 84	},
 85	Route{
 86		"AddressSankey",
 87		"GET",
 88		"/address/sankey/{address}",
 89		AddressSankey,
 90	},
 91	Route{
 92		"NetworkMap",
 93		"Get",
 94		"/map",
 95		NetworkMap,
 96	},
 97	Route{
 98		"GetTotalHourAnalysis",
 99		"Get",
100		"/totalhouranalysis",
101		GetTotalHourAnalysis,
102	},
103	Route{
104		"GetLast24HourAnalysis",
105		"Get",
106		"/last24hour",
107		GetLast24HourAnalysis,
108	},
109	Route{
110		"GetLast7DayAnalysis",
111		"Get",
112		"/last7day",
113		GetLast7DayAnalysis,
114	},
115	Route{
116		"GetLast7DayHourAnalysis",
117		"Get",
118		"/last7dayhour",
119		GetLast7DayHourAnalysis,
120	},
121	Route{
122		"GetAddressTimeChart",
123		"GET",
124		"/addresstimechart/{hash}",
125		GetAddressTimeChart,
126	},
127}
128
129//ROUTES
130
131func Index(w http.ResponseWriter, r *http.Request) {
132	fmt.Fprintln(w, "ask for recommendations in /r")
133	//http.FileServer(http.Dir("./web"))
134}
135
136/*
137func NewUser(w http.ResponseWriter, r *http.Request) {
138	ipFilter(w, r)
139	decoder := json.NewDecoder(r.Body)
140	var newUser UserModel
141	err := decoder.Decode(&newUser)
142	check(err)
143	defer r.Body.Close()
144
145	saveUser(userCollection, newUser)
146
147	fmt.Println(newUser)
148	fmt.Fprintln(w, "new user added: ", newUser.ID)
149}
150*/
151func Stats(w http.ResponseWriter, r *http.Request) {
152	ipFilter(w, r)
153
154	stats := getStats()
155
156	jsonResp, err := json.Marshal(stats)
157	check(err)
158
159	fmt.Fprintln(w, string(jsonResp))
160}
161func AllAddresses(w http.ResponseWriter, r *http.Request) {
162	ipFilter(w, r)
163
164	nodes := []NodeModel{}
165	iter := nodeCollection.Find(bson.M{"type": "address"}).Limit(10000).Iter()
166	err := iter.All(&nodes)
167
168	//convert []resp struct to json
169	jsonNodes, err := json.Marshal(nodes)
170	check(err)
171
172	fmt.Fprintln(w, string(jsonNodes))
173}
174func GetLastAddr(w http.ResponseWriter, r *http.Request) {
175	ipFilter(w, r)
176
177	addresses := []AddressModel{}
178	err := addressCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&addresses)
179	check(err)
180
181	//convert []resp struct to json
182	jsonResp, err := json.Marshal(addresses)
183	check(err)
184
185	fmt.Fprintln(w, string(jsonResp))
186}
187func GetLastTx(w http.ResponseWriter, r *http.Request) {
188	ipFilter(w, r)
189
190	txs := []TxModel{}
191	err := txCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&txs)
192	check(err)
193
194	//convert []resp struct to json
195	jsonData, err := json.Marshal(txs)
196	check(err)
197
198	fmt.Fprintln(w, string(jsonData))
199}
200func Block(w http.ResponseWriter, r *http.Request) {
201	ipFilter(w, r)
202
203	vars := mux.Vars(r)
204	var heightString string
205	heightString = vars["height"]
206	height, err := strconv.ParseInt(heightString, 10, 64)
207	if err != nil {
208		fmt.Fprintln(w, "not valid height")
209	} else {
210		block := BlockModel{}
211		err := blockCollection.Find(bson.M{"height": height}).One(&block)
212
213		txs := []TxModel{}
214		err = txCollection.Find(bson.M{"blockheight": heightString}).All(&txs)
215		block.Txs = txs
216
217		//convert []resp struct to json
218		jsonResp, err := json.Marshal(block)
219		check(err)
220
221		fmt.Fprintln(w, string(jsonResp))
222	}
223}
224func Tx(w http.ResponseWriter, r *http.Request) {
225	ipFilter(w, r)
226
227	vars := mux.Vars(r)
228	txid := vars["txid"]
229	if txid == "undefined" {
230		fmt.Fprintln(w, "not valid txid")
231	} else {
232		tx := TxModel{}
233		err := txCollection.Find(bson.M{"txid": txid}).One(&tx)
234
235		//convert []resp struct to json
236		jsonResp, err := json.Marshal(tx)
237		check(err)
238
239		fmt.Fprintln(w, string(jsonResp))
240	}
241}
242func Address(w http.ResponseWriter, r *http.Request) {
243	ipFilter(w, r)
244
245	vars := mux.Vars(r)
246	hash := vars["hash"]
247	if hash == "undefined" {
248		fmt.Fprintln(w, "not valid hash")
249	} else {
250		address := AddressModel{}
251		err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
252
253		txs := []TxModel{}
254		err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"vin.address": hash}, bson.M{"vout.address": hash}}}).All(&txs)
255		address.Txs = txs
256
257		for _, tx := range address.Txs {
258			blocks := []BlockModel{}
259			err = blockCollection.Find(bson.M{"hash": tx.BlockHash}).All(&blocks)
260			for _, block := range blocks {
261				address.Blocks = append(address.Blocks, block)
262			}
263		}
264
265		//convert []resp struct to json
266		jsonResp, err := json.Marshal(address)
267		check(err)
268
269		fmt.Fprintln(w, string(jsonResp))
270	}
271}
272func AddressNetwork(w http.ResponseWriter, r *http.Request) {
273	ipFilter(w, r)
274
275	vars := mux.Vars(r)
276	address := vars["address"]
277	if address == "undefined" {
278		fmt.Fprintln(w, "not valid address")
279	} else {
280		network := addressTree(address)
281		network.Nodes[0].Shape = "triangle"
282
283		//convert []resp struct to json
284		jNetwork, err := json.Marshal(network)
285		check(err)
286
287		fmt.Fprintln(w, string(jNetwork))
288	}
289}
290func BlockSankey(w http.ResponseWriter, r *http.Request) {
291	ipFilter(w, r)
292	vars := mux.Vars(r)
293	var heightString string
294	heightString = vars["height"]
295	height, err := strconv.ParseInt(heightString, 10, 64)
296	if err != nil {
297		fmt.Fprintln(w, "not valid height")
298	} else {
299		block := BlockModel{}
300		err := blockCollection.Find(bson.M{"height": height}).One(&block)
301
302		txs := []TxModel{}
303		err = txCollection.Find(bson.M{"blockheight": heightString}).All(&txs)
304		block.Txs = txs
305
306		var nodesCount int
307		mapNodeK := make(map[string]int)
308		var sankey SankeyModel
309		for _, tx := range block.Txs {
310			var sankeyNodeA SankeyNodeModel
311			sankeyNodeA.Node = nodesCount
312			mapNodeK["tx"] = nodesCount
313			nodesCount++
314			sankeyNodeA.Name = "tx"
315			sankey.Nodes = append(sankey.Nodes, sankeyNodeA)
316
317			for _, vin := range tx.Vin {
318				var sankeyNode SankeyNodeModel
319				sankeyNode.Node = nodesCount
320				mapNodeK[vin.Address] = nodesCount
321				nodesCount++
322				sankeyNode.Name = vin.Address
323				sankey.Nodes = append(sankey.Nodes, sankeyNode)
324
325				var sankeyLink SankeyLinkModel
326				sankeyLink.Source = mapNodeK[vin.Address]
327				sankeyLink.Target = mapNodeK["tx"]
328				sankeyLink.Value = vin.Amount
329				fmt.Println(sankeyLink)
330				sankey.Links = append(sankey.Links, sankeyLink)
331				fmt.Println(sankey.Links)
332			}
333
334			for _, vout := range tx.Vout {
335				var sankeyNode SankeyNodeModel
336				sankeyNode.Node = nodesCount
337				mapNodeK[vout.Address] = nodesCount
338				nodesCount++
339				sankeyNode.Name = vout.Address
340				sankey.Nodes = append(sankey.Nodes, sankeyNode)
341
342				var sankeyLink SankeyLinkModel
343				sankeyLink.Source = mapNodeK["tx"]
344				sankeyLink.Target = mapNodeK[vout.Address]
345				sankeyLink.Value = vout.Value
346				fmt.Println(sankeyLink)
347				sankey.Links = append(sankey.Links, sankeyLink)
348			}
349
350		}
351
352		fmt.Println("Sankey generated")
353		fmt.Println(sankey)
354
355		//convert []resp struct to json
356		jsonSankey, err := json.Marshal(sankey)
357		check(err)
358
359		fmt.Fprintln(w, string(jsonSankey))
360	}
361}
362func TxSankey(w http.ResponseWriter, r *http.Request) {
363	ipFilter(w, r)
364	vars := mux.Vars(r)
365	txid := vars["txid"]
366	if txid == "undefined" {
367		fmt.Fprintln(w, "not valid height")
368	} else {
369
370		tx := TxModel{}
371		err := txCollection.Find(bson.M{"txid": txid}).One(&tx)
372
373		var nodesCount int
374		mapNodeK := make(map[string]int)
375		var sankey SankeyModel
376		var sankeyNodeA SankeyNodeModel
377		sankeyNodeA.Node = nodesCount
378		mapNodeK["tx"] = nodesCount
379		nodesCount++
380		sankeyNodeA.Name = "tx"
381		sankey.Nodes = append(sankey.Nodes, sankeyNodeA)
382
383		fmt.Println(tx.Vin)
384		for _, vin := range tx.Vin {
385			var sankeyNode SankeyNodeModel
386			sankeyNode.Node = nodesCount
387			mapNodeK[vin.Address] = nodesCount
388			nodesCount++
389			sankeyNode.Name = vin.Address
390			sankey.Nodes = append(sankey.Nodes, sankeyNode)
391
392			var sankeyLink SankeyLinkModel
393			sankeyLink.Source = mapNodeK[vin.Address]
394			sankeyLink.Target = mapNodeK["tx"]
395			sankeyLink.Value = vin.Amount
396			sankey.Links = append(sankey.Links, sankeyLink)
397		}
398
399		for _, vout := range tx.Vout {
400			var sankeyNode SankeyNodeModel
401			sankeyNode.Node = nodesCount
402			mapNodeK[vout.Address] = nodesCount
403			nodesCount++
404			sankeyNode.Name = vout.Address
405			sankey.Nodes = append(sankey.Nodes, sankeyNode)
406
407			var sankeyLink SankeyLinkModel
408			sankeyLink.Source = mapNodeK["tx"]
409			sankeyLink.Target = mapNodeK[vout.Address]
410			sankeyLink.Value = vout.Value
411			sankey.Links = append(sankey.Links, sankeyLink)
412		}
413
414		fmt.Println("Sankey generated")
415
416		//convert []resp struct to json
417		jsonSankey, err := json.Marshal(sankey)
418		check(err)
419
420		fmt.Fprintln(w, string(jsonSankey))
421	}
422}
423func AddressSankey(w http.ResponseWriter, r *http.Request) {
424	ipFilter(w, r)
425	vars := mux.Vars(r)
426	address := vars["address"]
427	if address == "undefined" {
428		fmt.Fprintln(w, "not valid address")
429	} else {
430		network := addressTree(address)
431		var sankey SankeyModel
432
433		fmt.Println("network generated")
434		mapNodeK := make(map[string]int)
435		for k, n := range network.Nodes {
436			var sankeyNode SankeyNodeModel
437			//sankeyNode.StringNode = n.Id
438			sankeyNode.Node = k
439			sankeyNode.Name = n.Id
440			sankey.Nodes = append(sankey.Nodes, sankeyNode)
441			mapNodeK[n.Id] = k
442		}
443		for _, e := range network.Edges {
444			var sankeyLink SankeyLinkModel
445			//sankeyLink.StringSource = e.From
446			sankeyLink.Source = mapNodeK[e.From]
447			//sankeyLink.StringTarget = e.To
448			sankeyLink.Target = mapNodeK[e.To]
449			sankeyLink.Value = e.Label
450			sankey.Links = append(sankey.Links, sankeyLink)
451		}
452		fmt.Println("Sankey generated")
453
454		//convert []resp struct to json
455		jsonSankey, err := json.Marshal(sankey)
456		check(err)
457
458		fmt.Fprintln(w, string(jsonSankey))
459	}
460}
461func NetworkMap(w http.ResponseWriter, r *http.Request) {
462	ipFilter(w, r)
463
464	nodes, err := getAllNodes()
465	check(err)
466	edges, err := getAllEdges()
467	check(err)
468
469	var network NetworkModel
470	network.Nodes = nodes
471	network.Edges = edges
472
473	//convert []resp struct to json
474	jNetwork, err := json.Marshal(network)
475	check(err)
476
477	fmt.Fprintln(w, string(jNetwork))
478}
479
480func GetTotalHourAnalysis(w http.ResponseWriter, r *http.Request) {
481	ipFilter(w, r)
482
483	hourAnalysis := []ChartCountModel{}
484	iter := hourCountCollection.Find(bson.M{}).Limit(10000).Iter()
485	err := iter.All(&hourAnalysis)
486
487	//sort by hour
488	sort.Slice(hourAnalysis, func(i, j int) bool {
489		return hourAnalysis[i].Elem < hourAnalysis[j].Elem
490	})
491
492	var resp ChartAnalysisResp
493	for _, d := range hourAnalysis {
494		resp.Labels = append(resp.Labels, strconv.Itoa(d.Elem))
495		resp.Data = append(resp.Data, d.Count)
496	}
497
498	//convert []resp struct to json
499	jsonResp, err := json.Marshal(resp)
500	check(err)
501	fmt.Fprintln(w, string(jsonResp))
502}
503
504func GetLast24HourAnalysis(w http.ResponseWriter, r *http.Request) {
505	ipFilter(w, r)
506
507	fromDate := time.Now().AddDate(0, 0, -1)
508	toDate := time.Now()
509
510	txs := []TxModel{}
511	err := txCollection.Find(bson.M{
512		"datet": bson.M{
513			"$gt": fromDate,
514			"$lt": toDate,
515		},
516	}).Sort("-$natural").All(&txs)
517	check(err)
518
519	//generate map with 24 hours
520	hourFrequencies := map24hours()
521	for _, tx := range txs {
522		hourFrequencies[tx.Date.Hour]++
523	}
524	var hourCount []ChartCountModel
525	for hour, frequency := range hourFrequencies {
526		hourCount = append(hourCount, ChartCountModel{hour, frequency})
527	}
528	//sort by hour
529	sort.Slice(hourCount, func(i, j int) bool {
530		return hourCount[i].Elem < hourCount[j].Elem
531	})
532
533	var resp ChartAnalysisResp
534	for _, d := range hourCount {
535		resp.Labels = append(resp.Labels, strconv.Itoa(d.Elem))
536		resp.Data = append(resp.Data, d.Count)
537	}
538
539	//convert []resp struct to json
540	jsonResp, err := json.Marshal(resp)
541	check(err)
542	fmt.Fprintln(w, string(jsonResp))
543}
544func GetLast7DayAnalysis(w http.ResponseWriter, r *http.Request) {
545	ipFilter(w, r)
546
547	fromDate := time.Now().AddDate(0, 0, -7)
548	toDate := time.Now()
549
550	txs := []TxModel{}
551	err := txCollection.Find(bson.M{
552		"datet": bson.M{
553			"$gt": fromDate,
554			"$lt": toDate,
555		},
556	}).Sort("-$natural").All(&txs)
557	check(err)
558
559	//generate map with 24 hours
560	//hourFrequencies := map24hours()
561	dayFrequencies := make(map[int]int)
562	for _, tx := range txs {
563		dayFrequencies[tx.Date.Day]++
564	}
565	var dayCount []ChartCountModel
566	for day, frequency := range dayFrequencies {
567		dayCount = append(dayCount, ChartCountModel{day, frequency})
568	}
569	//sort by hour
570	sort.Slice(dayCount, func(i, j int) bool {
571		return dayCount[i].Elem < dayCount[j].Elem
572	})
573
574	var resp ChartAnalysisResp
575	for _, d := range dayCount {
576		resp.Labels = append(resp.Labels, strconv.Itoa(d.Elem))
577		resp.Data = append(resp.Data, d.Count)
578	}
579
580	//convert []resp struct to json
581	jsonResp, err := json.Marshal(resp)
582	check(err)
583	fmt.Fprintln(w, string(jsonResp))
584}
585
586func GetLast7DayHourAnalysis(w http.ResponseWriter, r *http.Request) {
587	ipFilter(w, r)
588
589	var resp ChartSeriesAnalysisResp
590
591	for i := 0; i < 7; i++ {
592		fromDate := time.Now().AddDate(0, 0, -i-1)
593		toDate := time.Now().AddDate(0, 0, -i)
594		txs := []TxModel{}
595		err := txCollection.Find(bson.M{
596			"datet": bson.M{
597				"$gt": fromDate,
598				"$lt": toDate,
599			},
600		}).Sort("-$natural").All(&txs)
601		check(err)
602
603		//generate map with 24 hours
604		hourFrequencies := map24hours()
605		for _, tx := range txs {
606			hourFrequencies[tx.Date.Hour]++
607		}
608		var hourCount []ChartCountModel
609		for hour, frequency := range hourFrequencies {
610			hourCount = append(hourCount, ChartCountModel{hour, frequency})
611		}
612		//sort by hour
613		sort.Slice(hourCount, func(i, j int) bool {
614			return hourCount[i].Elem < hourCount[j].Elem
615		})
616		var dayData []int
617		for _, d := range hourCount {
618			dayData = append(dayData, d.Count)
619		}
620		if len(txs) > 0 {
621			resp.Series = append(resp.Series, txs[0].Date.Day)
622			resp.Data = append(resp.Data, dayData)
623		}
624	}
625	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"}
626	resp.Labels = hourLabels
627
628	//convert []resp struct to json
629	jsonResp, err := json.Marshal(resp)
630	check(err)
631	fmt.Fprintln(w, string(jsonResp))
632}
633func GetAddressTimeChart(w http.ResponseWriter, r *http.Request) {
634	ipFilter(w, r)
635
636	vars := mux.Vars(r)
637	hash := vars["hash"]
638	if hash == "undefined" {
639		fmt.Fprintln(w, "not valid hash")
640	} else {
641		address := AddressModel{}
642		err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
643
644		txs := []TxModel{}
645		err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"vin.address": hash}, bson.M{"vout.address": hash}}}).All(&txs)
646		address.Txs = txs
647
648		for _, tx := range address.Txs {
649			blocks := []BlockModel{}
650			err = blockCollection.Find(bson.M{"hash": tx.BlockHash}).All(&blocks)
651			for _, block := range blocks {
652				address.Blocks = append(address.Blocks, block)
653			}
654		}
655
656		count := make(map[time.Time]float64)
657		for _, tx := range txs {
658			var val float64
659			for _, vin := range tx.Vin {
660				val = val + vin.Amount
661			}
662			count[tx.DateT] = val
663		}
664		var dateSorted []time.Time
665		for t, _ := range count {
666			dateSorted = append(dateSorted, t)
667		}
668		sort.Slice(dateSorted, func(i, j int) bool {
669			//return dateSorted[i] < dateSorted[j]
670			return dateBeforeThan(dateSorted[i], dateSorted[j])
671		})
672
673		var resp ChartAnalysisRespFloat64
674		for _, t := range dateSorted {
675			resp.Labels = append(resp.Labels, t.String())
676			resp.Data = append(resp.Data, count[t])
677		}
678
679		//convert []resp struct to json
680		jsonResp, err := json.Marshal(resp)
681		check(err)
682
683		fmt.Fprintln(w, string(jsonResp))
684	}
685}