implemented sankey of block.txs[] and from tx, in frontend and backend
arnaucode idoctnef@openmailbox.org
Wed, 30 Aug 2017 15:47:20 +0200
7 files changed,
228 insertions(+),
4 deletions(-)
M
DevelopmentNotes.md
→
DevelopmentNotes.md
@@ -30,3 +30,6 @@
- mantain connection with wallet using websockets - num address evolution throught time + +- fix error in exploreBlockchain.go, when getting the tx.Vin +tx 8f04960da36beaa928b9693f7dca4afae5a6122bb6874d409a1156e4c6c55024 has 4 vin, but exploreBlockchain is only getting the first
M
serverRoutes.go
→
serverRoutes.go
@@ -71,6 +71,18 @@ "/address/network/{address}",
AddressNetwork, }, Route{ + "BlockSankey", + "GET", + "/block/{height}/sankey", + BlockSankey, + }, + Route{ + "TxSankey", + "GET", + "/tx/{txid}/sankey", + TxSankey, + }, + Route{ "AddressSankey", "GET", "/address/sankey/{address}",@@ -273,6 +285,139 @@ jNetwork, err := json.Marshal(network)
check(err) fmt.Fprintln(w, string(jNetwork)) + } +} +func BlockSankey(w http.ResponseWriter, r *http.Request) { + ipFilter(w, r) + vars := mux.Vars(r) + var heightString string + heightString = vars["height"] + height, err := strconv.ParseInt(heightString, 10, 64) + if err != nil { + fmt.Fprintln(w, "not valid height") + } else { + block := BlockModel{} + err := blockCollection.Find(bson.M{"height": height}).One(&block) + + txs := []TxModel{} + err = txCollection.Find(bson.M{"blockheight": heightString}).All(&txs) + block.Txs = txs + + var nodesCount int + mapNodeK := make(map[string]int) + var sankey SankeyModel + for _, tx := range block.Txs { + var sankeyNodeA SankeyNodeModel + sankeyNodeA.Node = nodesCount + mapNodeK["tx"] = nodesCount + nodesCount++ + sankeyNodeA.Name = "tx" + sankey.Nodes = append(sankey.Nodes, sankeyNodeA) + + for _, vin := range tx.Vin { + var sankeyNode SankeyNodeModel + sankeyNode.Node = nodesCount + mapNodeK[vin.Address] = nodesCount + nodesCount++ + sankeyNode.Name = vin.Address + sankey.Nodes = append(sankey.Nodes, sankeyNode) + + var sankeyLink SankeyLinkModel + sankeyLink.Source = mapNodeK[vin.Address] + sankeyLink.Target = mapNodeK["tx"] + sankeyLink.Value = vin.Amount + fmt.Println(sankeyLink) + sankey.Links = append(sankey.Links, sankeyLink) + fmt.Println(sankey.Links) + } + + for _, vout := range tx.Vout { + var sankeyNode SankeyNodeModel + sankeyNode.Node = nodesCount + mapNodeK[vout.Address] = nodesCount + nodesCount++ + sankeyNode.Name = vout.Address + sankey.Nodes = append(sankey.Nodes, sankeyNode) + + var sankeyLink SankeyLinkModel + sankeyLink.Source = mapNodeK["tx"] + sankeyLink.Target = mapNodeK[vout.Address] + sankeyLink.Value = vout.Value + fmt.Println(sankeyLink) + sankey.Links = append(sankey.Links, sankeyLink) + } + + } + + fmt.Println("Sankey generated") + fmt.Println(sankey) + + //convert []resp struct to json + jsonSankey, err := json.Marshal(sankey) + check(err) + + fmt.Fprintln(w, string(jsonSankey)) + } +} +func TxSankey(w http.ResponseWriter, r *http.Request) { + ipFilter(w, r) + vars := mux.Vars(r) + txid := vars["txid"] + if txid == "undefined" { + fmt.Fprintln(w, "not valid height") + } else { + + tx := TxModel{} + err := txCollection.Find(bson.M{"txid": txid}).One(&tx) + + var nodesCount int + mapNodeK := make(map[string]int) + var sankey SankeyModel + var sankeyNodeA SankeyNodeModel + sankeyNodeA.Node = nodesCount + mapNodeK["tx"] = nodesCount + nodesCount++ + sankeyNodeA.Name = "tx" + sankey.Nodes = append(sankey.Nodes, sankeyNodeA) + + fmt.Println(tx.Vin) + for _, vin := range tx.Vin { + var sankeyNode SankeyNodeModel + sankeyNode.Node = nodesCount + mapNodeK[vin.Address] = nodesCount + nodesCount++ + sankeyNode.Name = vin.Address + sankey.Nodes = append(sankey.Nodes, sankeyNode) + + var sankeyLink SankeyLinkModel + sankeyLink.Source = mapNodeK[vin.Address] + sankeyLink.Target = mapNodeK["tx"] + sankeyLink.Value = vin.Amount + sankey.Links = append(sankey.Links, sankeyLink) + } + + for _, vout := range tx.Vout { + var sankeyNode SankeyNodeModel + sankeyNode.Node = nodesCount + mapNodeK[vout.Address] = nodesCount + nodesCount++ + sankeyNode.Name = vout.Address + sankey.Nodes = append(sankey.Nodes, sankeyNode) + + var sankeyLink SankeyLinkModel + sankeyLink.Source = mapNodeK["tx"] + sankeyLink.Target = mapNodeK[vout.Address] + sankeyLink.Value = vout.Value + sankey.Links = append(sankey.Links, sankeyLink) + } + + fmt.Println("Sankey generated") + + //convert []resp struct to json + jsonSankey, err := json.Marshal(sankey) + check(err) + + fmt.Fprintln(w, string(jsonSankey)) } } func AddressSankey(w http.ResponseWriter, r *http.Request) {
M
web/views/block/block.html
→
web/views/block/block.html
@@ -15,10 +15,13 @@ </div>
<div class="col-sm-8"> <div class="panel"> <div class="panel-heading c_deepPurpleG300to500"> - <h3 class="panel-title">Block evolution</h3> + <h3 class="panel-title">Block transactions flow</h3> </div> - <div class="panel-body"> - + <div class="panel-body" style="height: 300px;overflow-y: hidden;"> + <div id="sankeyChart"> + <canvas></canvas> + <svg></svg> + </div> </div> </div> </div>
M
web/views/block/block.js
→
web/views/block/block.js
@@ -1,6 +1,6 @@
'use strict'; -angular.module('app.block', ['ngRoute']) +angular.module('app.block', ['ngRoute', 'ngSankey']) .config(['$routeProvider', function($routeProvider) { $routeProvider.when('/block/:height', {@@ -15,6 +15,36 @@ $http.get(urlapi + 'block/' + $routeParams.height)
.then(function(data, status, headers, config) { console.log(data); $scope.block = data.data; + }, function(data, status, headers, config) { + console.log('data error'); + }); + + + //Sankey + $scope.options = { + chart: '#sankeyChart', + width: 700, + height: 280, + margin: {top: 1, right: 1, bottom: 6, left: 1}, + node: {width: 15, padding :10, showValue: false}, + value: {format: ',.0f', unit : ''}, + dynamicLinkColor: true, + trafficInLinks: true + }; + $scope.data={ + nodes: [], + links: [] + }; + $http.get(urlapi + 'block/' + $routeParams.height + '/sankey') + .then(function(data, status, headers, config) { + console.log('data success'); + console.log(data); + $scope.data.nodes = data.data.nodes; + $scope.data.links = data.data.links; + console.log($scope.data); + d3.selectAll("svg > *").remove(); + let chart = new d3.sankeyChart(data.data, $scope.options); + //$scope.data = data.data; }, function(data, status, headers, config) { console.log('data error'); });
M
web/views/tx/tx.html
→
web/views/tx/tx.html
@@ -45,3 +45,18 @@ </div>
</div> </div> </div> +<div class="row"> + <div class="col-sm-12"> + <div class="panel"> + <div class="panel-heading c_deepPurpleG300to500"> + <h3 class="panel-title">Transaction flow</h3> + </div> + <div class="panel-body" style="height: 300px;overflow-y: hidden;"> + <div id="sankeyChart"> + <canvas></canvas> + <svg></svg> + </div> + </div> + </div> + </div> +</div>
M
web/views/tx/tx.js
→
web/views/tx/tx.js
@@ -18,4 +18,32 @@ $scope.tx = data.data;
}, function(data, status, headers, config) { console.log('data error'); }); + //Sankey + $scope.options = { + chart: '#sankeyChart', + width: 1000, + height: 280, + margin: {top: 1, right: 1, bottom: 6, left: 1}, + node: {width: 15, padding :10, showValue: false}, + value: {format: ',.0f', unit : ''}, + dynamicLinkColor: true, + trafficInLinks: true + }; + $scope.data={ + nodes: [], + links: [] + }; + $http.get(urlapi + 'tx/' + $routeParams.txid + '/sankey') + .then(function(data, status, headers, config) { + console.log('data success'); + console.log(data); + $scope.data.nodes = data.data.nodes; + $scope.data.links = data.data.links; + console.log($scope.data); + d3.selectAll("svg > *").remove(); + let chart = new d3.sankeyChart(data.data, $scope.options); + //$scope.data = data.data; + }, function(data, status, headers, config) { + console.log('data error'); + }); });