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