mirror of
https://github.com/arnaucube/goBlockchainDataAnalysis.git
synced 2026-02-07 03:36:44 +01:00
implemented getLast24HourAnalysis, to show the Tx/Hour of the last 24 hours
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,6 +15,6 @@
|
|||||||
|
|
||||||
|
|
||||||
/*.conf
|
/*.conf
|
||||||
/*.json
|
config.json
|
||||||
*.mp4
|
*.mp4
|
||||||
logs
|
logs
|
||||||
|
|||||||
@@ -33,3 +33,7 @@ other
|
|||||||
BlockHeight string `json:"blockheight"`
|
BlockHeight string `json:"blockheight"`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- mantain connection with wallet using websockets
|
||||||
|
|
||||||
|
- add 24h to hour analysis, to show also hours with 0 transactions
|
||||||
|
|||||||
22
configEXAMPLE.json
Normal file
22
configEXAMPLE.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"user": "faircoinrpc",
|
||||||
|
"pass": "password",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"port": "3021",
|
||||||
|
"genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046",
|
||||||
|
"genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7",
|
||||||
|
"startFromBlock": 0,
|
||||||
|
"server": {
|
||||||
|
"serverIP": "127.0.0.1",
|
||||||
|
"serverPort": "3014",
|
||||||
|
"webServerPort": "8080",
|
||||||
|
"allowedIPs": [
|
||||||
|
"127.0.0.1"
|
||||||
|
],
|
||||||
|
"blockedIPs": []
|
||||||
|
},
|
||||||
|
"mongodb": {
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"database": "goBlockchainDataAnalysis"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,21 @@ import (
|
|||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func decomposeDate(blockTime int64) (int, int, int, int) {
|
||||||
|
/*i, err := strconv.ParseInt(blockTime, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}*/
|
||||||
|
i := blockTime
|
||||||
|
year := time.Unix(i, 0).Year()
|
||||||
|
month := time.Unix(i, 0).Month()
|
||||||
|
day := time.Unix(i, 0).Day()
|
||||||
|
hour := time.Unix(i, 0).Hour()
|
||||||
|
return year, int(month), day, hour
|
||||||
|
}
|
||||||
|
func unixTimeToTime(blockTime int64) time.Time {
|
||||||
|
return time.Unix(blockTime, 0)
|
||||||
|
}
|
||||||
func timeToDate(blockTime int64) string {
|
func timeToDate(blockTime int64) string {
|
||||||
stringTime := strconv.FormatInt(blockTime, 10)
|
stringTime := strconv.FormatInt(blockTime, 10)
|
||||||
i, err := strconv.ParseInt(stringTime, 10, 64)
|
i, err := strconv.ParseInt(stringTime, 10, 64)
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
newBlock.PreviousHash = block.PreviousHash
|
newBlock.PreviousHash = block.PreviousHash
|
||||||
newBlock.NextHash = block.NextHash
|
newBlock.NextHash = block.NextHash
|
||||||
newBlock.Time = block.Time
|
newBlock.Time = block.Time
|
||||||
|
newBlock.DateT = unixTimeToTime(block.Time)
|
||||||
|
newBlock.Date.Year, newBlock.Date.Month, newBlock.Date.Day, newBlock.Date.Hour = decomposeDate(block.Time)
|
||||||
|
|
||||||
for k, txHash := range block.Tx {
|
for k, txHash := range block.Tx {
|
||||||
if k > 0 {
|
if k > 0 {
|
||||||
@@ -53,7 +55,7 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
blockTx, err := client.GetRawTransactionVerbose(th)
|
blockTx, err := client.GetRawTransactionVerbose(th)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
//save Tx
|
//save Tx Node
|
||||||
var nodeTx NodeModel
|
var nodeTx NodeModel
|
||||||
nodeTx.Id = txHash
|
nodeTx.Id = txHash
|
||||||
nodeTx.Label = txHash
|
nodeTx.Label = txHash
|
||||||
@@ -105,6 +107,8 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
newTx.BlockHash = block.Hash
|
newTx.BlockHash = block.Hash
|
||||||
newTx.BlockHeight = strconv.FormatInt(block.Height, 10)
|
newTx.BlockHeight = strconv.FormatInt(block.Height, 10)
|
||||||
newTx.Time = blockTx.Time
|
newTx.Time = blockTx.Time
|
||||||
|
newTx.DateT = unixTimeToTime(block.Time)
|
||||||
|
newTx.Date.Year, newTx.Date.Month, newTx.Date.Day, newTx.Date.Hour = decomposeDate(block.Time)
|
||||||
for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses {
|
for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses {
|
||||||
originAddresses = append(originAddresses, originAddr)
|
originAddresses = append(originAddresses, originAddr)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,32 +0,0 @@
|
|||||||
# Instructions
|
|
||||||
|
|
||||||
#### Install FairCoin Wallet and configure
|
|
||||||
now, need to configure wallet:
|
|
||||||
.FairCoin/
|
|
||||||
FairCoin.conf
|
|
||||||
|
|
||||||
```
|
|
||||||
rpcuser=usernamerpc
|
|
||||||
rpcpassword=password
|
|
||||||
rpcport=3021
|
|
||||||
rpcworkqueue=2000
|
|
||||||
server=1
|
|
||||||
rpcbind=127.0.0.1
|
|
||||||
rpcallowip=127.0.0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
execute wallet:
|
|
||||||
./faircoind -txindex -reindex-chainstate
|
|
||||||
|
|
||||||
### Configure
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"user": "usernamerpc",
|
|
||||||
"pass": "password",
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": "3021",
|
|
||||||
"genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046",
|
|
||||||
"genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,29 +1,32 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type AddressModel struct {
|
type AddressModel struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Amount float64 `json:"amount"`
|
Amount float64 `json:"amount"`
|
||||||
InBittrex bool `json:"inbittrex"`
|
InBittrex bool `json:"inbittrex"`
|
||||||
}
|
}
|
||||||
type DateModel struct {
|
type DateModel struct {
|
||||||
Hour string `json:"hour"`
|
Hour int `json:"hour"`
|
||||||
Day string `json:"day"`
|
Day int `json:"day"`
|
||||||
Month string `json:"month"`
|
Month int `json:"month"`
|
||||||
Amount float64 `json:"amount"`
|
Year int `json:"year"`
|
||||||
|
/*Amount float64 `json:"amount"`
|
||||||
BlockHash string `json:"blockhash"`
|
BlockHash string `json:"blockhash"`
|
||||||
BlockHeight string `json:"blockheight"`
|
BlockHeight string `json:"blockheight"`*/
|
||||||
}
|
}
|
||||||
type TxModel struct {
|
type TxModel struct {
|
||||||
Hex string `json:"hex"`
|
Hex string `json:"hex"`
|
||||||
Txid string `json:"txid"`
|
Txid string `json:"txid"`
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
From string `json:"from"` //hash of address
|
From string `json:"from"` //hash of address
|
||||||
To string `json:"to"` //hash of address
|
To string `json:"to"` //hash of address
|
||||||
Amount float64 `json:"amount"`
|
Amount float64 `json:"amount"`
|
||||||
BlockHash string `json:"blockhash"`
|
BlockHash string `json:"blockhash"`
|
||||||
BlockHeight string `json:"blockheight"`
|
BlockHeight string `json:"blockheight"`
|
||||||
Time int64 `json:"time"`
|
Time int64 `json:"time"`
|
||||||
DateF string `json:"datef"` //date formated
|
DateT time.Time `json:"datef"` //date formated
|
||||||
Date DateModel
|
Date DateModel
|
||||||
}
|
}
|
||||||
type BlockModel struct {
|
type BlockModel struct {
|
||||||
@@ -33,11 +36,11 @@ type BlockModel struct {
|
|||||||
Height int64 `json:"height"`
|
Height int64 `json:"height"`
|
||||||
//Amount float64 `json:"amount"`
|
//Amount float64 `json:"amount"`
|
||||||
//Fee float64 `json:"fee"`
|
//Fee float64 `json:"fee"`
|
||||||
Tx []string `json:"txid"` //txid of the TxModel
|
Tx []string `json:"txid"` //txid of the TxModel
|
||||||
PreviousHash string `json:"previoushash"`
|
PreviousHash string `json:"previoushash"`
|
||||||
NextHash string `json:"nexthash"`
|
NextHash string `json:"nexthash"`
|
||||||
Time int64 `json:"time"`
|
Time int64 `json:"time"`
|
||||||
DateF string `json:"datef"` //date formated
|
DateT time.Time `json:"datef"` //date formated
|
||||||
Date DateModel
|
Date DateModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
|
||||||
@@ -57,10 +59,16 @@ var routes = Routes{
|
|||||||
NetworkMap,
|
NetworkMap,
|
||||||
},
|
},
|
||||||
Route{
|
Route{
|
||||||
"GetHourAnalysis",
|
"GetTotalHourAnalysis",
|
||||||
"Get",
|
"Get",
|
||||||
"/houranalysis",
|
"/totalhouranalysis",
|
||||||
GetHourAnalysis,
|
GetTotalHourAnalysis,
|
||||||
|
},
|
||||||
|
Route{
|
||||||
|
"GetLast24HourAnalysis",
|
||||||
|
"Get",
|
||||||
|
"/last24hour",
|
||||||
|
GetLast24HourAnalysis,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,44 +207,7 @@ func NetworkMap(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintln(w, string(jNetwork))
|
fmt.Fprintln(w, string(jNetwork))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func GetTotalHourAnalysis(w http.ResponseWriter, r *http.Request) {
|
||||||
func SelectItem(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ipFilter(w, r)
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
userid := vars["userid"]
|
|
||||||
itemid := vars["itemid"]
|
|
||||||
//find item
|
|
||||||
item, err := getItemById(itemid)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(w, "item "+itemid+" not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
//find user
|
|
||||||
user, err := getUserById(userid)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(w, "user "+userid+" not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
//increase TActed in item
|
|
||||||
item.TActed = item.TActed + 1
|
|
||||||
|
|
||||||
//save item
|
|
||||||
item, err = updateItem(item)
|
|
||||||
check(err)
|
|
||||||
fmt.Println(item)
|
|
||||||
|
|
||||||
//add item to []Actions of user
|
|
||||||
user.Actions = append(user.Actions, itemid)
|
|
||||||
|
|
||||||
//save user
|
|
||||||
user, err = updateUser(user)
|
|
||||||
check(err)
|
|
||||||
fmt.Println(user)
|
|
||||||
|
|
||||||
fmt.Fprintln(w, "user: "+userid+", selects item: "+itemid)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func GetHourAnalysis(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ipFilter(w, r)
|
ipFilter(w, r)
|
||||||
|
|
||||||
hourAnalysis := []HourCountModel{}
|
hourAnalysis := []HourCountModel{}
|
||||||
@@ -259,3 +230,43 @@ func GetHourAnalysis(w http.ResponseWriter, r *http.Request) {
|
|||||||
check(err)
|
check(err)
|
||||||
fmt.Fprintln(w, string(jsonResp))
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetLast24HourAnalysis(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ipFilter(w, r)
|
||||||
|
|
||||||
|
fromDate := time.Now().AddDate(0, 0, -1)
|
||||||
|
toDate := time.Now()
|
||||||
|
|
||||||
|
txs := []TxModel{}
|
||||||
|
err := txCollection.Find(bson.M{
|
||||||
|
"datet": bson.M{
|
||||||
|
"$gt": fromDate,
|
||||||
|
"$lt": toDate,
|
||||||
|
},
|
||||||
|
}).Sort("-$natural").All(&txs)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
hourFrequencies := make(map[int]int)
|
||||||
|
for _, tx := range txs {
|
||||||
|
hourFrequencies[tx.Date.Hour]++
|
||||||
|
}
|
||||||
|
var hourCount []HourCountModel
|
||||||
|
for hour, frequency := range hourFrequencies {
|
||||||
|
hourCount = append(hourCount, HourCountModel{strconv.Itoa(hour), frequency})
|
||||||
|
}
|
||||||
|
//sort by hour
|
||||||
|
sort.Slice(hourCount, func(i, j int) bool {
|
||||||
|
return hourCount[i].Hour < hourCount[j].Hour
|
||||||
|
})
|
||||||
|
|
||||||
|
var resp HourAnalysisResp
|
||||||
|
for _, d := range hourCount {
|
||||||
|
resp.Labels = append(resp.Labels, d.Hour)
|
||||||
|
resp.Data = append(resp.Data, d.Count)
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert []resp struct to json
|
||||||
|
jsonResp, err := json.Marshal(resp)
|
||||||
|
check(err)
|
||||||
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
|
}
|
||||||
|
|||||||
BIN
web/img/favicon.png
Normal file
BIN
web/img/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -6,6 +6,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>goBlockchainDataAnalysis</title>
|
<title>goBlockchainDataAnalysis</title>
|
||||||
|
|
||||||
|
<link rel="icon" type="image/png" href="img/favicon.png">
|
||||||
|
|
||||||
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Open+Sans:400,700'>
|
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Open+Sans:400,700'>
|
||||||
<!-- Material Design fonts -->
|
<!-- Material Design fonts -->
|
||||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700">
|
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700">
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-6">
|
||||||
<div class="panel-heading c_blueGrey300">
|
<div class="panel-heading c_blueGrey300">
|
||||||
<h3 class="panel-title">Tx for each Hour</h3>
|
<h3 class="panel-title">All time Tx/Hour</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<canvas id="bar" class="chart chart-bar" chart-data="data" chart-labels="labels">
|
<canvas id="line" class="chart chart-line" chart-data="totalhour.data" chart-labels="totalhour.labels">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="panel-heading c_blueGrey300">
|
||||||
|
<h3 class="panel-title">Last 24 hours Tx/Hour</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<canvas id="line" class="chart chart-line" chart-data="last24hour.data" chart-labels="last24hour.labels">
|
||||||
</canvas>
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,18 +10,35 @@ angular.module('app.dateAnalysis', ['ngRoute', 'chart.js'])
|
|||||||
}])
|
}])
|
||||||
|
|
||||||
.controller('DateAnalysisCtrl', function($scope, $http, $routeParams) {
|
.controller('DateAnalysisCtrl', function($scope, $http, $routeParams) {
|
||||||
$scope.data=[];
|
$scope.totalhour={
|
||||||
$scope.labels=[];
|
data: [],
|
||||||
|
labels: []
|
||||||
|
};
|
||||||
|
|
||||||
$http.get(urlapi + 'houranalysis')
|
$http.get(urlapi + 'totalhouranalysis')
|
||||||
.then(function(data, status, headers, config) {
|
.then(function(data, status, headers, config) {
|
||||||
console.log('data success');
|
console.log('data success');
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
||||||
$scope.data = data.data.data;
|
$scope.totalhour.data = data.data.data;
|
||||||
$scope.labels=data.data.labels;
|
$scope.totalhour.labels=data.data.labels;
|
||||||
}, function(data, status, headers, config) {
|
}, function(data, status, headers, config) {
|
||||||
console.log('data error');
|
console.log('data error');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//date analysis
|
||||||
|
$scope.last24hour= {
|
||||||
|
data:[],
|
||||||
|
labels: []
|
||||||
|
};
|
||||||
|
$http.get(urlapi + 'last24hour')
|
||||||
|
.then(function(data, status, headers, config) {
|
||||||
|
console.log('data success');
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
$scope.last24hour.data = data.data.data;
|
||||||
|
$scope.last24hour.labels = data.data.labels;
|
||||||
|
}, function(data, status, headers, config) {
|
||||||
|
console.log('data error');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<div class="panel-heading c_blueGrey300">
|
<div class="panel-heading c_blueGrey300">
|
||||||
<h3 class="panel-title">Tx/Hour</h3>
|
<h3 class="panel-title">Last 24 hours Tx/Hour</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<canvas id="line" class="chart chart-line" chart-data="data" chart-labels="labels">
|
<canvas id="line" class="chart chart-line" chart-data="data" chart-labels="labels">
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ angular.module('app.main', ['ngRoute'])
|
|||||||
//date analysis
|
//date analysis
|
||||||
$scope.data = [];
|
$scope.data = [];
|
||||||
$scope.labels = [];
|
$scope.labels = [];
|
||||||
$http.get(urlapi + 'houranalysis')
|
$http.get(urlapi + 'last24hour')
|
||||||
.then(function(data, status, headers, config) {
|
.then(function(data, status, headers, config) {
|
||||||
console.log('data success');
|
console.log('data success');
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|||||||
Reference in New Issue
Block a user