mirror of
https://github.com/arnaucube/goBlockchainDataAnalysis.git
synced 2026-02-06 19:26:41 +01:00
added tx page in frontend and backend route. Added address tx chart time analysis
This commit is contained in:
@@ -8,6 +8,9 @@ import (
|
|||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func dateBeforeThan(dateA time.Time, dateB time.Time) bool {
|
||||||
|
return dateA.Before(dateB)
|
||||||
|
}
|
||||||
func map24hours() map[int]int {
|
func map24hours() map[int]int {
|
||||||
h := make(map[int]int)
|
h := make(map[int]int)
|
||||||
for i := 0; i < 24; i++ {
|
for i := 0; i < 24; i++ {
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ type ChartAnalysisResp struct {
|
|||||||
Labels []string `json:"labels"`
|
Labels []string `json:"labels"`
|
||||||
Data []int `json:"data"`
|
Data []int `json:"data"`
|
||||||
}
|
}
|
||||||
|
type ChartAnalysisRespFloat64 struct {
|
||||||
|
Labels []string `json:"labels"`
|
||||||
|
Data []float64 `json:"data"`
|
||||||
|
}
|
||||||
type ChartSeriesAnalysisResp struct {
|
type ChartSeriesAnalysisResp struct {
|
||||||
Labels []string `json:"labels"`
|
Labels []string `json:"labels"`
|
||||||
Data [][]int `json:"data"`
|
Data [][]int `json:"data"`
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ var routes = Routes{
|
|||||||
"/block/{height}",
|
"/block/{height}",
|
||||||
Block,
|
Block,
|
||||||
},
|
},
|
||||||
|
Route{
|
||||||
|
"Tx",
|
||||||
|
"GET",
|
||||||
|
"/tx/{txid}",
|
||||||
|
Tx,
|
||||||
|
},
|
||||||
Route{
|
Route{
|
||||||
"Address",
|
"Address",
|
||||||
"GET",
|
"GET",
|
||||||
@@ -100,6 +106,12 @@ var routes = Routes{
|
|||||||
"/last7dayhour",
|
"/last7dayhour",
|
||||||
GetLast7DayHourAnalysis,
|
GetLast7DayHourAnalysis,
|
||||||
},
|
},
|
||||||
|
Route{
|
||||||
|
"GetAddressTimeChart",
|
||||||
|
"GET",
|
||||||
|
"/addresstimechart/{hash}",
|
||||||
|
GetAddressTimeChart,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//ROUTES
|
//ROUTES
|
||||||
@@ -190,14 +202,6 @@ func Block(w http.ResponseWriter, r *http.Request) {
|
|||||||
err = txCollection.Find(bson.M{"blockheight": heightString}).All(&txs)
|
err = txCollection.Find(bson.M{"blockheight": heightString}).All(&txs)
|
||||||
block.Txs = txs
|
block.Txs = txs
|
||||||
|
|
||||||
/*for _, tx := range address.Txs {
|
|
||||||
blocks := []BlockModel{}
|
|
||||||
err = blockCollection.Find(bson.M{"blockheight": tx.BlockHash}).All(&blocks)
|
|
||||||
for _, block := range blocks {
|
|
||||||
address.Blocks = append(address.Blocks, block)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//convert []resp struct to json
|
//convert []resp struct to json
|
||||||
jsonResp, err := json.Marshal(block)
|
jsonResp, err := json.Marshal(block)
|
||||||
check(err)
|
check(err)
|
||||||
@@ -205,6 +209,24 @@ func Block(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintln(w, string(jsonResp))
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func Tx(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ipFilter(w, r)
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
txid := vars["txid"]
|
||||||
|
if txid == "undefined" {
|
||||||
|
fmt.Fprintln(w, "not valid txid")
|
||||||
|
} else {
|
||||||
|
tx := TxModel{}
|
||||||
|
err := txCollection.Find(bson.M{"txid": txid}).One(&tx)
|
||||||
|
|
||||||
|
//convert []resp struct to json
|
||||||
|
jsonResp, err := json.Marshal(tx)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
|
}
|
||||||
|
}
|
||||||
func Address(w http.ResponseWriter, r *http.Request) {
|
func Address(w http.ResponseWriter, r *http.Request) {
|
||||||
ipFilter(w, r)
|
ipFilter(w, r)
|
||||||
|
|
||||||
@@ -217,7 +239,7 @@ func Address(w http.ResponseWriter, r *http.Request) {
|
|||||||
err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
|
err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
|
||||||
|
|
||||||
txs := []TxModel{}
|
txs := []TxModel{}
|
||||||
err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"from": hash}, bson.M{"to": hash}}}).All(&txs)
|
err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"vin.address": hash}, bson.M{"vout.address": hash}}}).All(&txs)
|
||||||
address.Txs = txs
|
address.Txs = txs
|
||||||
|
|
||||||
for _, tx := range address.Txs {
|
for _, tx := range address.Txs {
|
||||||
@@ -463,3 +485,56 @@ func GetLast7DayHourAnalysis(w http.ResponseWriter, r *http.Request) {
|
|||||||
check(err)
|
check(err)
|
||||||
fmt.Fprintln(w, string(jsonResp))
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
}
|
}
|
||||||
|
func GetAddressTimeChart(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ipFilter(w, r)
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
hash := vars["hash"]
|
||||||
|
if hash == "undefined" {
|
||||||
|
fmt.Fprintln(w, "not valid hash")
|
||||||
|
} else {
|
||||||
|
address := AddressModel{}
|
||||||
|
err := addressCollection.Find(bson.M{"hash": hash}).One(&address)
|
||||||
|
|
||||||
|
txs := []TxModel{}
|
||||||
|
err = txCollection.Find(bson.M{"$or": []bson.M{bson.M{"vin.address": hash}, bson.M{"vout.address": hash}}}).All(&txs)
|
||||||
|
address.Txs = txs
|
||||||
|
|
||||||
|
for _, tx := range address.Txs {
|
||||||
|
blocks := []BlockModel{}
|
||||||
|
err = blockCollection.Find(bson.M{"hash": tx.BlockHash}).All(&blocks)
|
||||||
|
for _, block := range blocks {
|
||||||
|
address.Blocks = append(address.Blocks, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count := make(map[time.Time]float64)
|
||||||
|
for _, tx := range txs {
|
||||||
|
var val float64
|
||||||
|
for _, vin := range tx.Vin {
|
||||||
|
val = val + vin.Amount
|
||||||
|
}
|
||||||
|
count[tx.DateT] = val
|
||||||
|
}
|
||||||
|
var dateSorted []time.Time
|
||||||
|
for t, _ := range count {
|
||||||
|
dateSorted = append(dateSorted, t)
|
||||||
|
}
|
||||||
|
sort.Slice(dateSorted, func(i, j int) bool {
|
||||||
|
//return dateSorted[i] < dateSorted[j]
|
||||||
|
return dateBeforeThan(dateSorted[i], dateSorted[j])
|
||||||
|
})
|
||||||
|
|
||||||
|
var resp ChartAnalysisRespFloat64
|
||||||
|
for _, t := range dateSorted {
|
||||||
|
resp.Labels = append(resp.Labels, t.String())
|
||||||
|
resp.Data = append(resp.Data, count[t])
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert []resp struct to json
|
||||||
|
jsonResp, err := json.Marshal(resp)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ angular.module('webApp', [
|
|||||||
'app.navbar',
|
'app.navbar',
|
||||||
'app.main',
|
'app.main',
|
||||||
'app.block',
|
'app.block',
|
||||||
|
'app.tx',
|
||||||
'app.address',
|
'app.address',
|
||||||
'app.network',
|
'app.network',
|
||||||
'app.addressNetwork',
|
'app.addressNetwork',
|
||||||
|
|||||||
@@ -76,8 +76,9 @@
|
|||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
<script src="views/navbar.js"></script>
|
<script src="views/navbar.js"></script>
|
||||||
<script src="views/main/main.js"></script>
|
<script src="views/main/main.js"></script>
|
||||||
<script src="views/address/address.js"></script>
|
|
||||||
<script src="views/block/block.js"></script>
|
<script src="views/block/block.js"></script>
|
||||||
|
<script src="views/tx/tx.js"></script>
|
||||||
|
<script src="views/address/address.js"></script>
|
||||||
<script src="views/network/network.js"></script>
|
<script src="views/network/network.js"></script>
|
||||||
<script src="views/addressNetwork/addressNetwork.js"></script>
|
<script src="views/addressNetwork/addressNetwork.js"></script>
|
||||||
<script src="views/sankey/sankey.js"></script>
|
<script src="views/sankey/sankey.js"></script>
|
||||||
|
|||||||
@@ -8,20 +8,29 @@
|
|||||||
{{address.amount}}
|
{{address.amount}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panel">
|
||||||
|
<div class="panel-heading c_deepPurpleG300to500">
|
||||||
|
<h3 class="panel-title">Address uses
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<canvas id="line" class="chart chart-line" chart-data="addresstimechart.data" chart-labels="addresstimechart.labels">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<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">Blocks where address appears</h3>
|
<h3 class="panel-title">Blocks where address appears</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body" style="max-height: 300px;overflow-y: scroll;">
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
<a ng-href="#!/block/{{block.height}}" class="list-group-item-text" ng-repeat="block in address.blocks">
|
<a ng-href="#!/block/{{block.height}}" class="list-group-item-text" ng-repeat="block in address.blocks">
|
||||||
Block Height: {{block.height}}
|
Block Height: {{block.height}}
|
||||||
<br> Hash: {{block.hash}}
|
<br> Hash: {{block.hash}}
|
||||||
<br> {{block.datet}}
|
<br> {{block.datet}}
|
||||||
<br> Size: {{block.size}} bytes
|
<br> Size: {{block.size}} bytes
|
||||||
<br>
|
<hr>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,32 +48,36 @@
|
|||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>BlockHeight</th>
|
<th>Txid</th>
|
||||||
<th>From</th>
|
<th>Input</th>
|
||||||
<th>To</th>
|
<th>Output</th>
|
||||||
<th>Amount</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="tx in address.txs">
|
<tr ng-repeat="tx in address.txs">
|
||||||
<td style="max-width:20px; overflow:hidden;">
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
<a ng-href="#!/block/{{tx.blockheight}}" class="list-group-item-text">
|
<a ng-href="#!/tx/{{tx.txid}}" class="list-group-item-text">
|
||||||
{{tx.blockheight}}
|
{{tx.txid}}
|
||||||
</a>
|
</a>
|
||||||
|
<br>
|
||||||
|
{{tx.datet}}
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width:20px; overflow:hidden;">
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
<a ng-href="#!/address/{{tx.from}}" class="list-group-item-text">
|
<table><tbody><tr ng-repeat="vin in tx.vin"><td>
|
||||||
{{tx.from}}
|
<a ng-href="#!/address/{{vin.address}}" class="list-group-item-text">
|
||||||
</a>
|
{{vin.address}}
|
||||||
|
</a>
|
||||||
|
:{{vin.amount}}
|
||||||
|
</td></tr></tbody></table>
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width:20px; overflow:hidden;">
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
<a ng-href="#!/address/{{tx.to}}" class="list-group-item-text">
|
<table><tbody><tr ng-repeat="vout in tx.vout"><td>
|
||||||
{{tx.to}}
|
<a ng-href="#!/address/{{vout.address}}" class="list-group-item-text">
|
||||||
</a>
|
{{vout.address}}
|
||||||
|
</a>
|
||||||
|
:{{vout.value}}
|
||||||
|
</td></tr></tbody></table>
|
||||||
</td>
|
</td>
|
||||||
<td>{{tx.amount}}</td>
|
|
||||||
<td><a ng-href="#!/tx/{{tx.id}}">View</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -18,4 +18,16 @@ angular.module('app.address', ['ngRoute'])
|
|||||||
}, function(data, status, headers, config) {
|
}, function(data, status, headers, config) {
|
||||||
console.log('data error');
|
console.log('data error');
|
||||||
});
|
});
|
||||||
|
$scope.addresstimechart= {
|
||||||
|
data:[],
|
||||||
|
labels: []
|
||||||
|
};
|
||||||
|
$http.get(urlapi + 'addresstimechart/' + $routeParams.hash)
|
||||||
|
.then(function(data, status, headers, config) {
|
||||||
|
console.log(data);
|
||||||
|
$scope.addresstimechart.data = data.data.data;
|
||||||
|
$scope.addresstimechart.labels = data.data.labels;
|
||||||
|
}, function(data, status, headers, config) {
|
||||||
|
console.log('data error');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="tx in block.txs">
|
<tr ng-repeat="tx in block.txs">
|
||||||
<td style="max-width:20px; overflow:hidden;">
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
<a ng-href="#!/address/{{tx.from}}" class="list-group-item-text">
|
<a ng-href="#!/tx/{{tx.txid}}" class="list-group-item-text">
|
||||||
{{tx.txid}}
|
{{tx.txid}}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
47
web/views/tx/tx.html
Normal file
47
web/views/tx/tx.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel">
|
||||||
|
<div class="panel-heading c_deepPurpleG300to500">
|
||||||
|
<h3 class="panel-title">Tx {{tx.txid}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Txid</th>
|
||||||
|
<th>Input</th>
|
||||||
|
<th>Output</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
|
<a ng-href="#!/tx/{{tx.txid}}" class="list-group-item-text">
|
||||||
|
{{tx.txid}}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
|
<table><tbody><tr ng-repeat="vin in tx.vin"><td>
|
||||||
|
<a ng-href="#!/address/{{vin.address}}" class="list-group-item-text">
|
||||||
|
{{vin.address}}
|
||||||
|
</a>
|
||||||
|
:{{vin.amount}}
|
||||||
|
</td></tr></tbody></table>
|
||||||
|
</td>
|
||||||
|
<td style="max-width:20px; overflow:hidden;">
|
||||||
|
<table><tbody><tr ng-repeat="vout in tx.vout"><td>
|
||||||
|
<a ng-href="#!/address/{{vout.address}}" class="list-group-item-text">
|
||||||
|
{{vout.address}}
|
||||||
|
</a>
|
||||||
|
:{{vout.value}}
|
||||||
|
</td></tr></tbody></table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
21
web/views/tx/tx.js
Normal file
21
web/views/tx/tx.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('app.tx', ['ngRoute'])
|
||||||
|
|
||||||
|
.config(['$routeProvider', function($routeProvider) {
|
||||||
|
$routeProvider.when('/tx/:txid', {
|
||||||
|
templateUrl: 'views/tx/tx.html',
|
||||||
|
controller: 'TxCtrl'
|
||||||
|
});
|
||||||
|
}])
|
||||||
|
|
||||||
|
.controller('TxCtrl', function($scope, $http, $routeParams) {
|
||||||
|
$scope.tx = {};
|
||||||
|
$http.get(urlapi + 'tx/' + $routeParams.txid)
|
||||||
|
.then(function(data, status, headers, config) {
|
||||||
|
console.log(data);
|
||||||
|
$scope.tx = data.data;
|
||||||
|
}, function(data, status, headers, config) {
|
||||||
|
console.log('data error');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user