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}