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