mirror of
https://github.com/arnaucube/goBlockchainDataAnalysis.git
synced 2026-02-07 11:46:38 +01:00
Sankey data generated in backend, not yet showed correctly in frontend
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@
|
|||||||
|
|
||||||
/*.conf
|
/*.conf
|
||||||
/*.json
|
/*.json
|
||||||
|
*.mp4
|
||||||
|
|||||||
63
README.md
63
README.md
@@ -1,11 +1,70 @@
|
|||||||
# goBlockchainDataAnalysis
|
# goBlockchainDataAnalysis
|
||||||
blockchain data analysis, written in Go
|
blockchain data analysis, written in Go
|
||||||
|
|
||||||
|
### Install
|
||||||
|
1. Nodejs & NPM https://nodejs.org/
|
||||||
|
2. MongoDB https://www.mongodb.com/
|
||||||
|
3. Faircoin wallet https://download.faircoin.world/
|
||||||
|
4. goBlockchainDataAnalysis https://github.com/arnaucode/goBlockchainDataAnalysis
|
||||||
|
|
||||||
|
### Configure
|
||||||
|
- Wallet /home/user/.faircoin2/faircoin.conf:
|
||||||
|
```
|
||||||
|
rpcuser=usernamerpc
|
||||||
|
rpcpassword=password
|
||||||
|
rpcport=3021
|
||||||
|
rpcworkqueue=2000
|
||||||
|
server=1
|
||||||
|
rpcbind=127.0.0.1
|
||||||
|
rpcallowip=127.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
## Run
|
- goBlockchainDataAnalysis/config.json:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"user": "usernamerpc",
|
||||||
|
"pass": "password",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"port": "3021",
|
||||||
|
"genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046",
|
||||||
|
"genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- First run explorer
|
### Run
|
||||||
|
|
||||||
|
1. Start MongoDB
|
||||||
|
```
|
||||||
|
sudo service mongod start
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Start wallet
|
||||||
|
```
|
||||||
|
./faircoind -txindex -reindex-chainstate
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run explorer, to fill the database
|
||||||
```
|
```
|
||||||
./goBlockchainDataAnalysis -explore
|
./goBlockchainDataAnalysis -explore
|
||||||
```
|
```
|
||||||
|
|
||||||
|
3.1. The next runs, once the database have data, can just run:
|
||||||
|
```
|
||||||
|
./goBlockchainDataAnalysis
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run the webserver, in the /web directory
|
||||||
|
```
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
Webapp will run on 127.0.0.1:8080
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Additional info
|
||||||
|
- Backend
|
||||||
|
- Go lang https://golang.org/
|
||||||
|
- MongoDB https://www.mongodb.com/
|
||||||
|
- Frontend
|
||||||
|
- AngularJS https://angularjs.org/
|
||||||
|
- Angular-Bootstrap-Material https://tilwinjoy.github.io/angular-bootstrap-material
|
||||||
|
|||||||
BIN
goBlockchainDataAbalysis.gif
Normal file
BIN
goBlockchainDataAbalysis.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 MiB |
BIN
goBlockchainDataAnalysis01.png
Normal file
BIN
goBlockchainDataAnalysis01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 298 KiB |
BIN
goBlockchainDataAnalysis02.png
Normal file
BIN
goBlockchainDataAnalysis02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 298 KiB |
@@ -28,7 +28,7 @@ type EdgeModel struct {
|
|||||||
Txid string `json:"txid"`
|
Txid string `json:"txid"`
|
||||||
From string `json:"from"`
|
From string `json:"from"`
|
||||||
To string `json:"to"`
|
To string `json:"to"`
|
||||||
Label float64 `json:"label"`
|
Label float64 `json:"label"` //the value of transaction
|
||||||
Arrows string `json:"arrows"`
|
Arrows string `json:"arrows"`
|
||||||
BlockHeight int64 `json:"blockheight"`
|
BlockHeight int64 `json:"blockheight"`
|
||||||
}
|
}
|
||||||
@@ -36,3 +36,20 @@ type NetworkModel struct {
|
|||||||
Nodes []NodeModel `json:"nodes"`
|
Nodes []NodeModel `json:"nodes"`
|
||||||
Edges []EdgeModel `json:"edges"`
|
Edges []EdgeModel `json:"edges"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SankeyNodeModel struct {
|
||||||
|
//StringNode string `json:"stringnode"`
|
||||||
|
Node int `json:"node"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
type SankeyLinkModel struct {
|
||||||
|
//StringSource string `json:"stringsource"`
|
||||||
|
Source int `json:"source"`
|
||||||
|
//StringTarget string `json:"stringtarget"`
|
||||||
|
Target int `json:"target"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
}
|
||||||
|
type SankeyModel struct {
|
||||||
|
Nodes []SankeyNodeModel `json:"nodes"`
|
||||||
|
Links []SankeyLinkModel `json:"links"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ var routes = Routes{
|
|||||||
"/address/network/{address}",
|
"/address/network/{address}",
|
||||||
AddressNetwork,
|
AddressNetwork,
|
||||||
},
|
},
|
||||||
|
Route{
|
||||||
|
"AddressSankey",
|
||||||
|
"GET",
|
||||||
|
"/address/sankey/{address}",
|
||||||
|
AddressSankey,
|
||||||
|
},
|
||||||
Route{
|
Route{
|
||||||
"NetworkMap",
|
"NetworkMap",
|
||||||
"Get",
|
"Get",
|
||||||
@@ -99,6 +105,45 @@ func AddressNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintln(w, string(jNetwork))
|
fmt.Fprintln(w, string(jNetwork))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func AddressSankey(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ipFilter(w, r)
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
address := vars["address"]
|
||||||
|
if address == "undefined" {
|
||||||
|
fmt.Fprintln(w, "not valid address")
|
||||||
|
} else {
|
||||||
|
network := addressTree(address)
|
||||||
|
var sankey SankeyModel
|
||||||
|
|
||||||
|
fmt.Println("network generated")
|
||||||
|
mapNodeK := make(map[string]int)
|
||||||
|
for k, n := range network.Nodes {
|
||||||
|
var sankeyNode SankeyNodeModel
|
||||||
|
//sankeyNode.StringNode = n.Id
|
||||||
|
sankeyNode.Node = k
|
||||||
|
sankeyNode.Name = n.Id
|
||||||
|
sankey.Nodes = append(sankey.Nodes, sankeyNode)
|
||||||
|
mapNodeK[n.Id] = k
|
||||||
|
}
|
||||||
|
for _, e := range network.Edges {
|
||||||
|
var sankeyLink SankeyLinkModel
|
||||||
|
//sankeyLink.StringSource = e.From
|
||||||
|
sankeyLink.Source = mapNodeK[e.From]
|
||||||
|
//sankeyLink.StringTarget = e.To
|
||||||
|
sankeyLink.Target = mapNodeK[e.To]
|
||||||
|
sankeyLink.Value = e.Label
|
||||||
|
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 NetworkMap(w http.ResponseWriter, r *http.Request) {
|
func NetworkMap(w http.ResponseWriter, r *http.Request) {
|
||||||
ipFilter(w, r)
|
ipFilter(w, r)
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
"angular-route": "^1.6.1",
|
"angular-route": "^1.6.1",
|
||||||
"angular-chart.js": "^1.1.1",
|
"angular-chart.js": "^1.1.1",
|
||||||
"vis": "^4.18.1",
|
"vis": "^4.18.1",
|
||||||
"mui": "^0.9.20",
|
|
||||||
"angular-bootstrap-material": "abm#^0.1.4",
|
"angular-bootstrap-material": "abm#^0.1.4",
|
||||||
"angular-bootstrap": "^2.5.0",
|
"angular-bootstrap": "^2.5.0",
|
||||||
"angular-messages": "^1.6.5",
|
"angular-messages": "^1.6.5",
|
||||||
"components-font-awesome": "^4.7.0"
|
"components-font-awesome": "^4.7.0",
|
||||||
|
"sankeyjs": "^1.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,10 @@
|
|||||||
<script src="bower_components/chart.js/dist/Chart.min.js"></script>
|
<script src="bower_components/chart.js/dist/Chart.min.js"></script>
|
||||||
<script src="bower_components/angular-chart.js/dist/angular-chart.min.js"></script>
|
<script src="bower_components/angular-chart.js/dist/angular-chart.min.js"></script>
|
||||||
|
|
||||||
|
<!-- d3js -->
|
||||||
|
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8" type="text/javascript"></script>
|
||||||
|
<script src="bower_components/sankeyjs/dist/d3.sankey.js" charset="utf-8" type="text/javascript"></script>
|
||||||
|
<script src="bower_components/sankeyjs/dist/d3.sankey.directive.js" charset="utf-8" type="text/javascript"></script>
|
||||||
|
|
||||||
<!-- visjs -->
|
<!-- visjs -->
|
||||||
<script type="text/javascript" src="bower_components/vis/dist/vis.min.js"></script>
|
<script type="text/javascript" src="bower_components/vis/dist/vis.min.js"></script>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="panel-heading c_blueGrey300">
|
<div class="panel-heading c_blueGrey300">
|
||||||
<h3 class="panel-title">Network</h3>
|
<h3 class="panel-title">Address history Network Map</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div id="mynetwork" style="height:800px;"></div>
|
<div id="mynetwork" style="height:800px;"></div>
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-2">
|
||||||
|
<div class="panel-heading c_blueGrey300">
|
||||||
|
<h3 class="panel-title">All addresses</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body" style="max-height: 500px;overflow-y: scroll;">
|
||||||
|
<div class="form-group label-floating">
|
||||||
|
<input ng-model="filterAddress" abmFormControl class="form-control" placeholder="Filter" type="text">
|
||||||
|
</div>
|
||||||
|
<div ng-click="getAddressSankey(node)" class="list-group-item" ng-repeat="node in addresses | filter: filterAddress">
|
||||||
|
<div class="row-content">
|
||||||
|
<p class="list-group-item-text">{{node.id}}</p>
|
||||||
|
|
||||||
|
<!--<p class="list-group-item-text">Maecenas sed diam eget risus varius blandit.</p>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-10">
|
||||||
<div class="panel-heading c_blueGrey300">
|
<div class="panel-heading c_blueGrey300">
|
||||||
<h3 class="panel-title">Sankey</h3>
|
<h3 class="panel-title">Sankey</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
<ng-sankey id="sankeyChart" options="options" data="data"></ng-sankey>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('app.sankey', ['ngRoute'])
|
angular.module('app.sankey', ['ngRoute', 'ngSankey'])
|
||||||
|
|
||||||
.config(['$routeProvider', function($routeProvider) {
|
.config(['$routeProvider', function($routeProvider) {
|
||||||
$routeProvider.when('/sankey', {
|
$routeProvider.when('/sankey', {
|
||||||
@@ -11,5 +11,42 @@ angular.module('app.sankey', ['ngRoute'])
|
|||||||
|
|
||||||
.controller('SankeyCtrl', function($scope, $http, $routeParams) {
|
.controller('SankeyCtrl', function($scope, $http, $routeParams) {
|
||||||
|
|
||||||
|
$scope.options = {
|
||||||
|
chart: '#sankeyChart',
|
||||||
|
width: 960,
|
||||||
|
height: 500,
|
||||||
|
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 + 'alladdresses')
|
||||||
|
.then(function(data, status, headers, config) {
|
||||||
|
console.log('data success');
|
||||||
|
console.log(data);
|
||||||
|
$scope.addresses = data.data;
|
||||||
|
}, function(data, status, headers, config) {
|
||||||
|
console.log('data error');
|
||||||
|
});
|
||||||
|
$scope.getAddressSankey = function(address) {
|
||||||
|
console.log(address);
|
||||||
|
$http.get(urlapi + 'address/sankey/' + address.id)
|
||||||
|
.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);
|
||||||
|
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