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}