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.

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