diff --git a/DevelopmentNotes.md b/DevelopmentNotes.md new file mode 100644 index 0000000..ae5a691 --- /dev/null +++ b/DevelopmentNotes.md @@ -0,0 +1,35 @@ +# Development Notes + +## ToDo list + +- Backend + - Network Address generation avoiding infinite relation loops + - Sankey Address generation without loops +- Frontend + - After Sankey visualization, go to Network Address visualization and render without Sankey dots +- Both + - Tx/day + - Tx volume + - Block size + - Blockchain size + +other +- To get tx/hours of last 24 hours + Search for TxModel with DateF > last24h + Count for each hour +- To get tx/day of last month + Search TxModel with DateF > last month + Count each day +- Add counter with total blocks, total tx, total address + +- store date hour, day, etc: + ```Go + type DateModel struct { + Hour string `json:"hour"` + Day string `json:"day"` + Month string `json:"month"` + Amount float64 `json:"amount"` + BlockHash string `json:"blockhash"` + BlockHeight string `json:"blockheight"` + } +``` diff --git a/README.md b/README.md index 665d217..9ba7e82 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,9 @@ blockchain data analysis, written in Go #### Not finished - ToDo list -- Backend - - Network Address generation avoiding infinite relation loops - - Sankey Address generation without loops -- Frontend - - After Sankey visualization, go to Network Address visualization and render without Sankey dots -- Both - - Tx/day - - Tx volume - - Block size - - Blockchain size +To Do list in DevelopmentNotes.md https://github.com/arnaucode/goBlockchainDataAnalysis/blob/master/DevelopmentNotes.md + +## Instructions ### Install 1. Nodejs & NPM https://nodejs.org/ --> to get npm packages for the web @@ -22,7 +15,7 @@ blockchain data analysis, written in Go ### Configure - Wallet /home/user/.faircoin2/faircoin.conf: ``` -rpcuser=usernamerpc +rpcuser=faircoinrpc rpcpassword=password rpcport=3021 rpcworkqueue=2000 @@ -34,12 +27,26 @@ rpcallowip=127.0.0.1 - goBlockchainDataAnalysis/config.json: ```json { - "user": "usernamerpc", + "user": "faircoinrpc", "pass": "password", "host": "127.0.0.1", "port": "3021", - "genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046", - "genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7" + "genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046", + "genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7", + "startFromBlock": 160, + "server": { + "serverIP": "127.0.0.1", + "serverPort": "3014", + "webServerPort": "8080", + "allowedIPs": [ + "127.0.0.1" + ], + "blockedIPs": [] + }, + "mongodb": { + "ip": "127.0.0.1", + "database": "goBlockchainDataAnalysis" + } } ``` @@ -87,18 +94,19 @@ Webapp will run on 127.0.0.1:8080 ### Some screenshots +Some screenshots can be old, and can contain errors. -![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/goBlockchainDataAnalysis00.png "goBlockchainDataAnalysis") +![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/screenshots/goBlockchainDataAnalysis00.png "goBlockchainDataAnalysis") -![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/goBlockchainDataAnalysis06.gif "goBlockchainDataAnalysis") +![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/screenshots/goBlockchainDataAnalysis06.gif "goBlockchainDataAnalysis") -![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/goBlockchainDataAnalysis05.png "goBlockchainDataAnalysis") +![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/screenshots/goBlockchainDataAnalysis05.png "goBlockchainDataAnalysis") -![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/goBlockchainDataAnalysis01.png "goBlockchainDataAnalysis") +![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/screenshots/goBlockchainDataAnalysis01.png "goBlockchainDataAnalysis") -![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/goBlockchainDataAnalysis02.png "goBlockchainDataAnalysis") +![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/screenshots/goBlockchainDataAnalysis02.png "goBlockchainDataAnalysis") -![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/goBlockchainDataAnalysis04.png "goBlockchainDataAnalysis") +![goBlockchainDataAnalysis](https://raw.githubusercontent.com/arnaucode/goBlockchainDataAnalysis/master/screenshots/goBlockchainDataAnalysis04.png "goBlockchainDataAnalysis") diff --git a/dateAnalysis.go b/dateAnalysis.go index 484a86b..f137441 100644 --- a/dateAnalysis.go +++ b/dateAnalysis.go @@ -24,8 +24,8 @@ func timeToDate(blockTime int64) string { func hourAnalysis(e EdgeModel, blockTime int64) { //fmt.Println(blockTime) date := timeToDate(blockTime) - date_hour := strings.Split(date, " ")[1] - hour := strings.Split(date_hour, ":")[0] + dateHour := strings.Split(date, " ")[1] + hour := strings.Split(dateHour, ":")[0] hourCount := HourCountModel{} err := hourCountCollection.Find(bson.M{"hour": hour}).One(&hourCount) diff --git a/exploreBlockchain.go b/exploreBlockchain.go index 69873db..d86f20b 100644 --- a/exploreBlockchain.go +++ b/exploreBlockchain.go @@ -10,14 +10,14 @@ import ( func explore(client *btcrpcclient.Client, blockHash string) { var realBlocks int - var nOrigin NodeModel + /*var nOrigin NodeModel nOrigin.Id = "origin" nOrigin.Label = "origin" nOrigin.Title = "origin" nOrigin.Group = "origin" nOrigin.Value = 1 nOrigin.Shape = "dot" - saveNode(nodeCollection, nOrigin) + saveNode(nodeCollection, nOrigin)*/ for blockHash != "" { //generate hash from string @@ -27,6 +27,17 @@ func explore(client *btcrpcclient.Client, blockHash string) { check(err) if block.Height > config.StartFromBlock { + var newBlock BlockModel + newBlock.Hash = block.Hash + newBlock.Confirmations = block.Confirmations + newBlock.Size = block.Size + newBlock.Height = block.Height + //newBlock.Amount = block.Amount + //newBlock.Fee = block.Fee + newBlock.PreviousHash = block.PreviousHash + newBlock.NextHash = block.NextHash + newBlock.Time = block.Time + for k, txHash := range block.Tx { if k > 0 { realBlocks++ @@ -39,25 +50,24 @@ func explore(client *btcrpcclient.Client, blockHash string) { th, err := chainhash.NewHashFromStr(txHash) check(err) - tx, err := client.GetRawTransactionVerbose(th) + blockTx, err := client.GetRawTransactionVerbose(th) check(err) //save Tx - var nTx NodeModel - nTx.Id = txHash - nTx.Label = txHash - nTx.Title = txHash - nTx.Group = strconv.FormatInt(block.Height, 10) - nTx.Value = 1 - nTx.Shape = "square" - nTx.Type = "tx" - saveNode(nodeCollection, nTx) + var nodeTx NodeModel + nodeTx.Id = txHash + nodeTx.Label = txHash + nodeTx.Title = txHash + nodeTx.Group = strconv.FormatInt(block.Height, 10) + nodeTx.Value = 1 + nodeTx.Shape = "square" + nodeTx.Type = "tx" + saveNode(nodeCollection, nodeTx) var originAddresses []string var outputAddresses []string var outputAmount []float64 - for _, Vo := range tx.Vout { - //if Vo.Value > 0 { + for _, Vo := range blockTx.Vout { for _, outputAddr := range Vo.ScriptPubKey.Addresses { outputAddresses = append(outputAddresses, outputAddr) outputAmount = append(outputAmount, Vo.Value) @@ -70,17 +80,36 @@ func explore(client *btcrpcclient.Client, blockHash string) { n2.Shape = "dot" n2.Type = "address" saveNode(nodeCollection, n2) + + //Address + var addr AddressModel + addr.Hash = outputAddr + addr.InBittrex = false + saveAddress(addr) } - //} } - for _, Vi := range tx.Vin { + for _, Vi := range blockTx.Vin { th, err := chainhash.NewHashFromStr(Vi.Txid) check(err) txVi, err := client.GetRawTransactionVerbose(th) check(err) if len(txVi.Vout[Vi.Vout].ScriptPubKey.Addresses) > 0 { + //add tx to newBlock + newBlock.Tx = append(newBlock.Tx, blockTx.Txid) + + //Tx save + var newTx TxModel + newTx.Hex = blockTx.Hex + newTx.Txid = blockTx.Txid + newTx.Hash = blockTx.Hash + newTx.BlockHash = block.Hash + newTx.BlockHeight = strconv.FormatInt(block.Height, 10) + newTx.Time = blockTx.Time for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses { originAddresses = append(originAddresses, originAddr) + + newTx.From = originAddr + var n1 NodeModel n1.Id = originAddr n1.Label = originAddr @@ -91,12 +120,18 @@ func explore(client *btcrpcclient.Client, blockHash string) { n1.Type = "address" saveNode(nodeCollection, n1) + //Address + var addr AddressModel + addr.Hash = originAddr + addr.InBittrex = false + saveAddress(addr) + for k, outputAddr := range outputAddresses { var eIn EdgeModel eIn.From = originAddr eIn.To = txHash eIn.Label = txVi.Vout[Vi.Vout].Value - eIn.Txid = tx.Txid + eIn.Txid = blockTx.Txid eIn.Arrows = "to" eIn.BlockHeight = block.Height saveEdge(edgeCollection, eIn) @@ -105,7 +140,7 @@ func explore(client *btcrpcclient.Client, blockHash string) { eOut.From = txHash eOut.To = outputAddr eOut.Label = outputAmount[k] - eOut.Txid = tx.Txid + eOut.Txid = blockTx.Txid eOut.Arrows = "to" eOut.BlockHeight = block.Height saveEdge(edgeCollection, eOut) @@ -113,9 +148,13 @@ func explore(client *btcrpcclient.Client, blockHash string) { //date analysis //dateAnalysis(e, tx.Time) //hour analysis - hourAnalysis(eIn, tx.Time) + hourAnalysis(eIn, blockTx.Time) + + newTx.To = outputAddr + } } + saveTx(newTx) } else { originAddresses = append(originAddresses, "origin") } @@ -127,6 +166,7 @@ func explore(client *btcrpcclient.Client, blockHash string) { fmt.Println(len(outputAddresses)) } } + saveBlock(newBlock) } //set the next block blockHash = block.NextHash diff --git a/goBlockchainDataAnalysis b/goBlockchainDataAnalysis index 2921e3c..6f5fc08 100755 Binary files a/goBlockchainDataAnalysis and b/goBlockchainDataAnalysis differ diff --git a/ipFilter.go b/ipFilter.go index 67b513a..8a6ea60 100644 --- a/ipFilter.go +++ b/ipFilter.go @@ -11,13 +11,13 @@ func ipFilter(w http.ResponseWriter, r *http.Request) { var err error fmt.Println(r.RemoteAddr) reqIP := strings.Split(r.RemoteAddr, ":")[0] - for _, ip := range serverConfig.BlockedIPs { + for _, ip := range config.Server.BlockedIPs { if reqIP == ip { err = errors.New("ip not allowed to post images") } } - for _, ip := range serverConfig.AllowedIPs { + for _, ip := range config.Server.AllowedIPs { if reqIP != ip { err = errors.New("ip not allowed to post images") } diff --git a/main.go b/main.go index 944f1fd..d00eac7 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "log" "net/http" "os" + "time" mgo "gopkg.in/mgo.v2" @@ -13,6 +14,8 @@ import ( ) var blockCollection *mgo.Collection +var txCollection *mgo.Collection +var addressCollection *mgo.Collection var nodeCollection *mgo.Collection var edgeCollection *mgo.Collection var dateCountCollection *mgo.Collection @@ -24,10 +27,12 @@ func main() { readConfig("config.json") //connect with mongodb - readMongodbConfig("./mongodbConfig.json") + //readMongodbConfig("./mongodbConfig.json") session, err := getSession() check(err) blockCollection = getCollection(session, "blocks") + txCollection = getCollection(session, "txs") + addressCollection = getCollection(session, "address") nodeCollection = getCollection(session, "nodes") edgeCollection = getCollection(session, "edges") dateCountCollection = getCollection(session, "dateCounts") @@ -57,7 +62,10 @@ func main() { log.Printf("%s: %s", label, amount) } color.Blue("starting to explore blockchain") + start := time.Now() explore(client, config.GenesisBlock) + log.Println("blockchain exploration finished, time:") + log.Println(time.Since(start)) // Get the current block count. blockCount, err := client.GetBlockCount() @@ -71,22 +79,22 @@ func main() { go webserver() //http server start - readServerConfig("./serverConfig.json") + //readServerConfig("./serverConfig.json") log.Println("server running") log.Print("port: ") - log.Println(serverConfig.ServerPort) + log.Println(config.Server.ServerPort) router := NewRouter() headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Access-Control-Allow-Origin"}) originsOk := handlers.AllowedOrigins([]string{"*"}) methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"}) - log.Fatal(http.ListenAndServe(":"+serverConfig.ServerPort, handlers.CORS(originsOk, headersOk, methodsOk)(router))) + log.Fatal(http.ListenAndServe(":"+config.Server.ServerPort, handlers.CORS(originsOk, headersOk, methodsOk)(router))) //log.Fatal(http.ListenAndServe(":"+serverConfig.ServerPort, router)) } func webserver() { - log.Println("webserver in port " + serverConfig.WebServerPort) + log.Println("webserver in port " + config.Server.WebServerPort) http.Handle("/", http.FileServer(http.Dir("./web"))) - http.ListenAndServe(":"+serverConfig.WebServerPort, nil) + http.ListenAndServe(":"+config.Server.WebServerPort, nil) } diff --git a/mongoModels.go b/mongoModels.go index 6a85803..d13107d 100644 --- a/mongoModels.go +++ b/mongoModels.go @@ -1,18 +1,44 @@ package main +type AddressModel struct { + Hash string `json:"hash"` + Amount float64 `json:"amount"` + InBittrex bool `json:"inbittrex"` +} +type DateModel struct { + Hour string `json:"hour"` + Day string `json:"day"` + Month string `json:"month"` + Amount float64 `json:"amount"` + BlockHash string `json:"blockhash"` + BlockHeight string `json:"blockheight"` +} type TxModel struct { - Txid string - From string - To string - Amount float64 + Hex string `json:"hex"` + Txid string `json:"txid"` + Hash string `json:"hash"` + From string `json:"from"` //hash of address + To string `json:"to"` //hash of address + Amount float64 `json:"amount"` + BlockHash string `json:"blockhash"` + BlockHeight string `json:"blockheight"` + Time int64 `json:"time"` + DateF string `json:"datef"` //date formated + Date DateModel } type BlockModel struct { - Hash string - Height int64 - Confirmations uint64 - Amount float64 - Fee float64 - Tx []TxModel + Hash string `json:"hash"` + Confirmations uint64 `json:"confirmations"` + Size int32 `json:"size"` + Height int64 `json:"height"` + //Amount float64 `json:"amount"` + //Fee float64 `json:"fee"` + Tx []string `json:"txid"` //txid of the TxModel + PreviousHash string `json:"previoushash"` + NextHash string `json:"nexthash"` + Time int64 `json:"time"` + DateF string `json:"datef"` //date formated + Date DateModel } type NodeModel struct { diff --git a/mongoOperations.go b/mongoOperations.go index 86796e4..42009df 100644 --- a/mongoOperations.go +++ b/mongoOperations.go @@ -1,34 +1,14 @@ package main import ( - "encoding/json" - "fmt" - "io/ioutil" "log" mgo "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) -//MongoConfig stores the configuration of mongodb to connect -type MongoConfig struct { - IP string `json:"ip"` - Database string `json:"database"` -} - -var mongoConfig MongoConfig - -func readMongodbConfig(path string) { - file, e := ioutil.ReadFile(path) - if e != nil { - fmt.Println("error:", e) - } - content := string(file) - json.Unmarshal([]byte(content), &mongoConfig) -} - func getSession() (*mgo.Session, error) { - session, err := mgo.Dial("mongodb://" + mongoConfig.IP) + session, err := mgo.Dial("mongodb://" + config.Mongodb.IP) if err != nil { panic(err) } @@ -44,9 +24,11 @@ func getSession() (*mgo.Session, error) { } func getCollection(session *mgo.Session, collection string) *mgo.Collection { - c := session.DB(mongoConfig.Database).C(collection) + c := session.DB(config.Mongodb.Database).C(collection) return c } + +/* func saveBlock(c *mgo.Collection, block BlockModel) { //first, check if the item already exists result := BlockModel{} @@ -63,6 +45,7 @@ func saveBlock(c *mgo.Collection, block BlockModel) { } } +*/ func getAllNodes() ([]NodeModel, error) { result := []NodeModel{} @@ -126,3 +109,34 @@ func edgeInEdges(edges []EdgeModel, edge EdgeModel) bool { } return false } +func saveAddress(address AddressModel) { + + result := AddressModel{} + err := addressCollection.Find(bson.M{"hash": address.Hash}).One(&result) + if err != nil { + //address not found, so let's add a new entry + err = addressCollection.Insert(address) + check(err) + } +} +func saveTx(tx TxModel) { + + result := TxModel{} + err := txCollection.Find(bson.M{"txid": tx.Txid}).One(&result) + if err != nil { + //tx not found, so let's add a new entry + err = txCollection.Insert(tx) + check(err) + } +} + +func saveBlock(block BlockModel) { + + result := BlockModel{} + err := blockCollection.Find(bson.M{"hash": block.Hash}).One(&result) + if err != nil { + //block not found, so let's add a new entry + err = blockCollection.Insert(block) + check(err) + } +} diff --git a/readConfig.go b/readConfig.go index f55021c..1ff0d89 100644 --- a/readConfig.go +++ b/readConfig.go @@ -5,14 +5,32 @@ import ( "io/ioutil" ) +//MongoConfig stores the configuration of mongodb to connect +type MongoConfig struct { + IP string `json:"ip"` + Database string `json:"database"` +} + +//ServerConfig reads the server configuration +type ServerConfig struct { + ServerIP string `json:"serverIP"` + ServerPort string `json:"serverPort"` + WebServerPort string `json:"webserverPort"` + AllowedIPs []string `json:"allowedIPs"` + BlockedIPs []string `json:"blockedIPs"` +} + +//Config reads the config type Config struct { - User string `json:"user"` - Pass string `json:"pass"` - Host string `json:"host"` - Port string `json:"port"` - GenesisTx string `json:"genesisTx"` - GenesisBlock string `json:"genesisBlock"` - StartFromBlock int64 `json:"startFromBlock"` + User string `json:"user"` + Pass string `json:"pass"` + Host string `json:"host"` + Port string `json:"port"` + GenesisTx string `json:"genesisTx"` + GenesisBlock string `json:"genesisBlock"` + StartFromBlock int64 `json:"startFromBlock"` + Server ServerConfig `json:"server"` + Mongodb MongoConfig `json:"mongodb"` } var config Config @@ -23,3 +41,27 @@ func readConfig(path string) { content := string(file) json.Unmarshal([]byte(content), &config) } + +/* +var mongoConfig MongoConfig + +func readMongodbConfig(path string) { + file, e := ioutil.ReadFile(path) + if e != nil { + fmt.Println("error:", e) + } + content := string(file) + json.Unmarshal([]byte(content), &mongoConfig) +} + +var serverConfig ServerConfig + +func readServerConfig(path string) { + file, err := ioutil.ReadFile(path) + if err != nil { + fmt.Println("error: ", err) + } + content := string(file) + json.Unmarshal([]byte(content), &serverConfig) +} +*/ diff --git a/goBlockchainDataAnalysis00.png b/screenshots/goBlockchainDataAnalysis00.png similarity index 100% rename from goBlockchainDataAnalysis00.png rename to screenshots/goBlockchainDataAnalysis00.png diff --git a/goBlockchainDataAnalysis01.png b/screenshots/goBlockchainDataAnalysis01.png similarity index 100% rename from goBlockchainDataAnalysis01.png rename to screenshots/goBlockchainDataAnalysis01.png diff --git a/goBlockchainDataAnalysis02.png b/screenshots/goBlockchainDataAnalysis02.png similarity index 100% rename from goBlockchainDataAnalysis02.png rename to screenshots/goBlockchainDataAnalysis02.png diff --git a/goBlockchainDataAnalysis04.png b/screenshots/goBlockchainDataAnalysis04.png similarity index 100% rename from goBlockchainDataAnalysis04.png rename to screenshots/goBlockchainDataAnalysis04.png diff --git a/goBlockchainDataAnalysis05.png b/screenshots/goBlockchainDataAnalysis05.png similarity index 100% rename from goBlockchainDataAnalysis05.png rename to screenshots/goBlockchainDataAnalysis05.png diff --git a/goBlockchainDataAnalysis06.gif b/screenshots/goBlockchainDataAnalysis06.gif similarity index 100% rename from goBlockchainDataAnalysis06.gif rename to screenshots/goBlockchainDataAnalysis06.gif diff --git a/serverConfig.go b/serverConfig.go index 490f597..36a332e 100644 --- a/serverConfig.go +++ b/serverConfig.go @@ -1,9 +1,6 @@ package main import ( - "encoding/json" - "fmt" - "io/ioutil" "log" "net/http" "time" @@ -18,26 +15,6 @@ type Route struct { HandlerFunc http.HandlerFunc } -//server config -type ServerConfig struct { - ServerIP string `json:"serverIP"` - ServerPort string `json:"serverPort"` - WebServerPort string `json:"webserverPort"` - AllowedIPs []string `json:"allowedIPs"` - BlockedIPs []string `json:"blockedIPs"` -} - -var serverConfig ServerConfig - -func readServerConfig(path string) { - file, err := ioutil.ReadFile(path) - if err != nil { - fmt.Println("error: ", err) - } - content := string(file) - json.Unmarshal([]byte(content), &serverConfig) -} - func Logger(inner http.Handler, name string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() diff --git a/serverRoutes.go b/serverRoutes.go index 34a0dbe..45ba319 100644 --- a/serverRoutes.go +++ b/serverRoutes.go @@ -102,25 +102,25 @@ func AllAddresses(w http.ResponseWriter, r *http.Request) { func GetLastAddr(w http.ResponseWriter, r *http.Request) { ipFilter(w, r) - nodes := []NodeModel{} - err := nodeCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&nodes) + addresses := []AddressModel{} + err := addressCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&addresses) check(err) //convert []resp struct to json - jNodes, err := json.Marshal(nodes) + jsonResp, err := json.Marshal(addresses) check(err) - fmt.Fprintln(w, string(jNodes)) + fmt.Fprintln(w, string(jsonResp)) } func GetLastTx(w http.ResponseWriter, r *http.Request) { ipFilter(w, r) - edges := []EdgeModel{} - err := edgeCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&edges) + txs := []TxModel{} + err := txCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&txs) check(err) //convert []resp struct to json - jsonData, err := json.Marshal(edges) + jsonData, err := json.Marshal(txs) check(err) fmt.Fprintln(w, string(jsonData)) diff --git a/web/views/main/main.html b/web/views/main/main.html index 72d2aaf..951e38c 100644 --- a/web/views/main/main.html +++ b/web/views/main/main.html @@ -5,9 +5,9 @@

Last addresses used

-
+
-

{{node.id}}

+

{{address.hash}}