You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

685 lines
15 KiB

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