mirror of
https://github.com/arnaucube/goBlockchainDataAnalysis.git
synced 2026-02-06 19:26:41 +01:00
implemented sankey of block.txs[] and from tx, in frontend and backend
This commit is contained in:
@@ -30,3 +30,6 @@ other
|
|||||||
- mantain connection with wallet using websockets
|
- mantain connection with wallet using websockets
|
||||||
|
|
||||||
- num address evolution throught time
|
- 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
|
||||||
|
|||||||
Binary file not shown.
145
serverRoutes.go
145
serverRoutes.go
@@ -70,6 +70,18 @@ var routes = Routes{
|
|||||||
"/address/network/{address}",
|
"/address/network/{address}",
|
||||||
AddressNetwork,
|
AddressNetwork,
|
||||||
},
|
},
|
||||||
|
Route{
|
||||||
|
"BlockSankey",
|
||||||
|
"GET",
|
||||||
|
"/block/{height}/sankey",
|
||||||
|
BlockSankey,
|
||||||
|
},
|
||||||
|
Route{
|
||||||
|
"TxSankey",
|
||||||
|
"GET",
|
||||||
|
"/tx/{txid}/sankey",
|
||||||
|
TxSankey,
|
||||||
|
},
|
||||||
Route{
|
Route{
|
||||||
"AddressSankey",
|
"AddressSankey",
|
||||||
"GET",
|
"GET",
|
||||||
@@ -275,6 +287,139 @@ func AddressNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintln(w, string(jNetwork))
|
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) {
|
func AddressSankey(w http.ResponseWriter, r *http.Request) {
|
||||||
ipFilter(w, r)
|
ipFilter(w, r)
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|||||||
@@ -15,10 +15,13 @@
|
|||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-heading c_deepPurpleG300to500">
|
<div class="panel-heading c_deepPurpleG300to500">
|
||||||
<h3 class="panel-title">Block evolution</h3>
|
<h3 class="panel-title">Block transactions flow</h3>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('app.block', ['ngRoute'])
|
angular.module('app.block', ['ngRoute', 'ngSankey'])
|
||||||
|
|
||||||
.config(['$routeProvider', function($routeProvider) {
|
.config(['$routeProvider', function($routeProvider) {
|
||||||
$routeProvider.when('/block/:height', {
|
$routeProvider.when('/block/:height', {
|
||||||
@@ -18,4 +18,34 @@ angular.module('app.block', ['ngRoute'])
|
|||||||
}, function(data, status, headers, config) {
|
}, function(data, status, headers, config) {
|
||||||
console.log('data error');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -45,3 +45,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
|||||||
@@ -18,4 +18,32 @@ angular.module('app.tx', ['ngRoute'])
|
|||||||
}, function(data, status, headers, config) {
|
}, function(data, status, headers, config) {
|
||||||
console.log('data error');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user