How to get the transactionHash by blockNumber?
I entered block.transactions.0.transactionHash but that didn't catch it (empty string). How can i get the transactionHash?
func GetBlockTransactions(number int) string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
var hashHeaders []models.Block
defer cancel()
options := options.Find().SetProjection(bson.M{"block.transactions.0.transactionHash": 1})
options.SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
fmt.Println(err)
}
//reading from the db in an optimal way
defer results.Close(ctx)
for results.Next(ctx) {
var singleHashHeader models.Block
if err = results.Decode(&singleHashHeader); err != nil {
fmt.Println(err)
}
hashHeaders = append(hashHeaders, singleHashHeader)
}
fmt.Println("%v", hashHeaders[0].Transactions.TransactionHash)
return string(hashHeaders[0].Transactions.TransactionHash)
}
Edit:
My structs look like this (edited):
type BlockHeader struct {
HashHeader string `json:"hashHeader,omitempty"`
BlockNumber string `json:"blockNumber,omitempty"`
TimestampSeconds string `json:"timestampSeconds,omitempty"`
HashHeaderPrev string `json:"hashHeaderPrev,omitempty"`
RewardBlock string `json:"rewardBlock,omitempty"`
MerkleRoot string `json:"merkleRoot,omitempty"`
MiningNonce int `json:"miningNonce,omitempty"`
ExtraNonce string `json:"extraNonce,omitempty"`
}
type Header struct {
Header BlockHeader
}
type CoinbaseTransaction struct {
AddrTo string `json:"addrTo,omitempty"`
Amount string `json:"amount,omitempty"`
}
type BlockTransaction struct {
MasterAddr string `json:"masterAddr,omitempty"`
Nonce string `json:"nonce,omitempty"`
TransactionHash string `json:"transactionHash,omitempty"`
Coinbase []CoinbaseTransaction
}
type Block struct {
Block Header
Transactions []BlockTransaction
}
Current code:
func GetBlockTransactions(number int) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// options := options.Find().
// SetProjection(bson.M{"block.transactions.transactionHash": 1}).
// SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)})
if err != nil {
return "", fmt.Errorf("Find() failed: %w", err)
}
var blocks []models.Block
err = results.All(ctx, &blocks)
if err != nil {
return "", fmt.Errorf("Cursor.All() failed: %w", err)
}
for _, block := range blocks {
fmt.Printf("header: %v", block.Block.Header)
for _, tx := range block.Transactions {
fmt.Printf("transaction: %v", tx)
}
}
fmt.Printf("hash: %v\n", blocks[0].Transactions[0].TransactionHash)
return string(blocks[0].Transactions[0].TransactionHash), nil
}
mongo shell output
Here is the document, block number 15 for example. Here are all the details, included below.
{ "_id" : ObjectId("62caea8923ca1b926b789122"), "block" : { "header" : { "hashHeader" : "6WKsUtRXGWqIMs/VcwT8CAU384Uab8NMOwB7wMoAAAA=", "blockNumber" : "15", "timestampSeconds" : "1530015361", "hashHeaderPrev" : "y4G/O/Oj19 AOZNMF4yPL2xVdl/TQI ErBjhihUAAAA=", "rewardBlock" : "6656333953", "rewardFee" : "1000000", "merkleRoot" : "/gRuLu8UGAG621xvGA7M4rZmWbsMophiQ3xPprTVJkU=", "miningNonce" : NumberLong("2781151944"), "extraNonce" : "16980399104" }, "transactions" : [ { "masterAddr" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", "nonce" : "16", "transactionHash" : "Jp8fU6h9yqh6onymq/lFEJq/XRHPKKbj drmvHOi5gY=", "coinbase" : { "addrTo" : "AQYAHTRijaCHM53dZQqEPhMfpKPzsQfptiItYJ9trThgtHmMxbNh", "amount" : "6657333953" } }, { "fee" : "1000000", "publicKey" : "AAYAs6Tt7 YeX6sEZfTeaKUAMF7RAURH7Khcs2vnTW23LrVBf FCFer87crYcsUx9ureHHugTG J/tKwcYPBgMk6vw==", "signature" : "AAAAAH8Tfjt2e/4J xec8eWlgWXPlPOquRu RZz5yT3hXdVF3uwhvbxasw9oj6 SpAwjy1ICSdlBeefasS970ker/DvBzLX93ryAxHI66 WqZQ9aj7gSVEhqTzylMzDj/I4P34ScaQ7kwRF/6Q3DnA/qiG/q4zc5MmHeU/pBp/ ngEMcM/cFSrCNQE Us7B7Sp2Ws6inix3y SGbrznsBDWdTcxIpq4k/0Od9VIBFA09th/svLZCbH5YGfZ7IboT4NQx7hTnANLNTLo4ztkX2u6B8WkFrJ3LV6VS3C7w7pRuhItlSIl/slVMhYizgCjVpzNb0C8JMtZeqb6sarcqSwarQiX65NVrj6ux7pJtJT08gCc2nxh3HwjhYahzjRoCkIGQbHYqfGkKkAyRIig3wu4K NsoG13UKxIaVy/kJSB5NRMEFVG1Xp2JLj3WqlnTeNnIMAGz7V/srVji8EXtcODjuOL0Qoenhesocl5 dbX0lyMu qhXQuXzcxm dBW4TMSyoI2xSlgCLdqRNuHstOwmAdZ7qnTOKOASp5EsZGj5vPTjnP 9GcLxM5ms MU57A3ciAjDaVpX2AoShLcP9xW/jBI0/ijGZvzA4mRIIkmwCC EOklXH/c0JB832SrhQy/cc3v1kYYITu4pkqFl7EAzzGCEy3yLdrdhzsYSN6tlTOqO57rHzehu/1xJg9LmT5LyixJVzW58DsO0swSeT dZMNR5AZmyWp4aj633YUEi8p9KKmCgEceF4T 54MZJbIQExwX4CFQ1GLJVQiEZdXy/PR3cr6AFUQGwp5ZJ8 gFLDhWGFVuHPH3HxTstyepTSQQUb8JFv4G0nM/INXpWXHvNdEvOEyDUzkfJ11yhbkCrMLak8AumtPnoNnZQXyxaUa4YX5Z8tkmbNRQWtjC/6NGTcHWQ8IKf6MxVjQCdHtqTRzgfRYOh/ /bzRy7p3o0p95Hn4Yxuf3BBshnJJmg2mKoS6sc8V8cA44YpaA9eP9Ce4G3knJ/wxuWRWzZmxC yl43qgofPU5xGWQEf6vtTS0JJ7fv61mFYhM4REt FocXf3bjifP08qrAFZNDejODjycLNXlmBahqp8mqKTvllofbeLrYnYrcCH9KMfXGGL4PZLKnmh bHlolWEn8Y4hxOlVkfRjYvBakfEsAgS MQEtkN4tGqHwT2Taz1014PAbO90O8HFZb5I146Yb4JpL38wpuvfKMBR161MNn7LLO8vOv4aZE2SBySJE6XoYIxfFL KlP4MXqGGm2kWomR2 HtvSCl7dRwfUapLlrE1xcP44HbYsDYM z5z6mWMvxQHj9WDovi7OvdwoIV3kMChSTA9DR8gqOgtDItZ9UrsDjJdhLF7aZ8/D6vyEJGAwRi3NCUYo4mBLPF5EnhXqHnmogwWh vzW37RiyHHnUxwQWDJPc81RMlXnGjIT6/KCXjrvCeYUr2Lj K8OIaNKgiuRsRjC5h/83btOWJ7PMjLMyyg1aklgkam4Hp13bVZo3zIwNsTlOt9jAn QNPPUtzToKaD twG3m GglN/kaeA6/Bmm10qIKAWkPCNP0xkEDKYDIUhxaix sZLYSPRWRi/M3sEc79WwSZVc7sunNYWnHOvPhubDgLfO6AjFpbqYU7g6q06A4 zG85bu0vXxRucZMMO7njrHnW30Xw3vU3oFQlpFEmWBZ8S a53wyXBK fNC6PgBIqyF4qhVk8YJDHpkJW9zBwjytE8nSkTV4wCD qexfrvJvREQESDzT3eT2YfWoqEKWqPknwGK0W6TNXwmv7xMWB8zKS2LThAqotZRH6S9V1zJVbSsSrsO2 Ct8kVXGrioWxZ84Wj3R5tGBghwLbOTBlfP/jxKFbUIyEJ6hUiCFhYI/qoayi3j9Tdh1ChhnhF 4Id32QhzMemQvO/ 2uKxvu3CE5grZmRD93TdNRBz751QI EsoAMLT7Gx6LUqHVLd4q1NnO79hQFr YBunt0KYZolVZoEnMqUhkmyPUkSjadoBKHMD6MEViDcGgaqNs7n 0Z Mr7leOJXwg67hG2MX6M23VAANMagEgPw4ub1fZF1p7rpHGakW8j4apLVVHOibJNj8HNWXtElALQI8ZThlIhkdc/e7mSIlio4jiNYkuuhaXd5I8X67u2GYkqGlPibSf 90u/qQ22iRsIBE63fgbjNxv9KN6CR1XEhWaZA jgWCtcFTo46Ge3ZBbEZ7DWL6ExDM/U4 CHnpw8n7RUKV1GUCCzr9KFqFpxqdzCCdBUct9pu6ejcph 5vKH/Gh6H7MBNGVwlwSuxloBBHS6xfb7ho6UFqzvO1qfNjCH3/50Wc3MhLZxftmTf2VO4/emW1XdfFvH9WaA8968Fhr4WJ tuPWSZ/U88drb2siLavdkhGHPOdXWSuDOvnFr9qIK1TlFpylWkNQrHRsrOscDlCgllbS8v9GOg1Yp2X/KDGFXzZa1elaqJazur43Q6ktyA2RIz9O2l//R3ktU2SME9fB2anh Oiz3 VUyNRjJRNF3oC82NxIEt/cRDvcLI qEB/HVBvv1nXQ728Ri0EXocER2EvDr9C1jiBZu2VOuRjPzeo1QMaCABqQCipJBNgWUXMHvTAvK1GwCxQg8q4gSDkfMyKeSlinoJI8vs8oNicFJlnVembWrCYt/ tn9UD2ygguklwXpwbv WypHg3nagpk2bsi0EAZ3wJaAXwvFxwREsxyvq6SWl2u3o loyuu322NbgQeA /HGYvSaKmb7CjSSBl2EtDpQI77LzYcFZmEtD 8DM3JHza85/g0x4VNL5GzZ6UTLtpd1B/g3XxmNcrqBp/ppJYYDBK9NK79FodDpQlAWlPREkWPsV7X8IkxzG7i6jHxTIiuO0Nyrb1yiPWfa/onjOJVRp4wW4yVOY8vWOkTaz1zNBqR3mZ0RnebHWKr4/0wNM0jV3WaZd096es/D1nrDEQytAnb6ORlbxKAqX/2zHWexMgCCgzuj1jz5NJIkMKQxhtKnHBPTbCz1ZUzfL9tPjzFqAQ99shrusUXdueuLXjoIVFVn gULAx5 uDSIU7ERiqtc5LgVeeyzeA35E/gSHNKqu1v822xGg/70csYT69nMzHHVjwSnaC0/GOs5esFS7S4QkaOMgkS6MZiKdAqYkJ9nJN wqY15JNxbmB0tU7C2XjdKGxV1mRcjtxAdxS9JNYurBPw7l4zviAqXzmL/So/rwJUnaw0L/gha92vgECXu16lqDKuKydGSssFvFuCJpA6IzEEIkvuqV CLcEto35nkwrjBl4YZGM/nRmoI1y/qSvqJx9PNoMkeZZGQsoFtPggXYge53v5pX9I2kZ3hgY9zNXOGdzDqEUlqTVVHYLnBddo3eIfRSz31 IoOvG0QCO/Qvu9rwtuZCIltnhQWfRc4FmWsj9JUs=", "nonce" : "1", "transactionHash" : "vGS9M6aerWCoEj0BqbW5IwZ7jyw4jpECEJ/b1uL5oc0=", "token" : { "symbol" : "RnIxdDI=", "name" : "RnIxdDI=", "owner" : "AAYAPHpYp dc/fVXo8Oi3LnaBPDhCCVEh6/H8mBuuoCbMzffYw1r", "decimals" : "10", "initialBalances" : [ { "address" : "AAYAPHpYp dc/fVXo8Oi3LnaBPDhCCVEh6/H8mBuuoCbMzffYw1r", "amount" : "1000000000000000000" } ] } } ] } }
CodePudding user response:
3 errors in your approach.
First, a find()
on the blocks collection returns complete documents, not just the block documents (being the block
field). So unmarshal results into a value of type that describes the complete documents, e.g.:
type Doc struct {
ID primitive.ObjectID `bson:"_id"`
Block Block `bson:"block"`
}
And the unmarshaling code:
var doc Doc
if err = results.Decode(&doc); err != nil {
fmt.Println(err)
}
hashHeaders = append(hashHeaders, doc.Block)
Second, transactions
is an array, so in Go you must model it with a slice:
type Block struct {
Transactions []BlockTransaction
}
Third, Properties of objects array fields in projections and filters are referred to without indices, so use a projection:
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1})
Also note that you can simply decode results using the Cursor.All()
method like this:
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
fmt.Println(err)
}
Working complete code:
func GetBlockTransactions(number int) string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1}).
SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
fmt.Println(err)
}
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
fmt.Println(err)
}
fmt.Printf("hash: %v\n", docs[0].Block.Transactions[0].TransactionHash)
return string(docs[0].Block.Transactions[0].TransactionHash)
}
Also note that if an error is encountered, subsequent code is likely to fail, so you should return early. You should also return an annotated error.
Like this:
func GetBlockTransactions(number int) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1}).
SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
return "", fmt.Errorf("Find() failed: %w", err)
}
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
return "", fmt.Errorf("Cursor.All() failed: %w", err)
}
fmt.Printf("hash: %v\n", docs[0].Block.Transactions[0].TransactionHash)
return string(docs[0].Block.Transactions[0].TransactionHash), nil
}
Also note that if you're expected exactly one result, a simpler solution is to use Collection.FindOne()
.