/
rewards.go
151 lines (136 loc) · 4.41 KB
/
rewards.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package storagereader
import (
"context"
"fmt"
"github.com/spacemeshos/explorer-backend/utils"
"go.mongodb.org/mongo-driver/mongo"
"strings"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/spacemeshos/explorer-backend/model"
)
// CountRewards returns the number of rewards matching the query.
func (s *Reader) CountRewards(ctx context.Context, query *bson.D, opts ...*options.CountOptions) (int64, error) {
count, err := s.db.Collection("rewards").CountDocuments(ctx, query, opts...)
if err != nil {
return 0, fmt.Errorf("error count transactions: %w", err)
}
return count, nil
}
// GetRewards returns the rewards matching the query.
func (s *Reader) GetRewards(ctx context.Context, query *bson.D, opts ...*options.FindOptions) ([]*model.Reward, error) {
cursor, err := s.db.Collection("rewards").Find(ctx, query, opts...)
if err != nil {
return nil, fmt.Errorf("error get rewards: %w", err)
}
var rewards []*model.Reward
if err = cursor.All(ctx, &rewards); err != nil {
return nil, fmt.Errorf("error decode rewards: %w", err)
}
return rewards, nil
}
// GetReward returns the reward matching the query.
func (s *Reader) GetReward(ctx context.Context, rewardID string) (*model.Reward, error) {
id, err := primitive.ObjectIDFromHex(strings.ToLower(rewardID))
if err != nil {
return nil, fmt.Errorf("error create objectID from string `%s`: %w", rewardID, err)
}
cursor, err := s.db.Collection("rewards").Find(ctx, &bson.D{{Key: "_id", Value: id}})
if err != nil {
return nil, fmt.Errorf("error get reward `%s`: %w", rewardID, err)
}
if !cursor.Next(ctx) {
return nil, nil
}
var reward *model.Reward
if err = cursor.Decode(&reward); err != nil {
return nil, fmt.Errorf("error decode reward `%s`: %w", rewardID, err)
}
return reward, nil
}
// CountCoinbaseRewards returns the number of rewards for given coinbase address.
func (s *Reader) CountCoinbaseRewards(ctx context.Context, coinbase string) (total, count int64, err error) {
matchStage := bson.D{{Key: "$match", Value: bson.D{{Key: "coinbase", Value: coinbase}}}}
groupStage := bson.D{
{Key: "$group", Value: bson.D{
{Key: "_id", Value: ""},
{Key: "total", Value: bson.D{
{Key: "$sum", Value: "$total"},
}},
{Key: "layerReward", Value: bson.D{
{Key: "$sum", Value: "$layerReward"},
}},
{Key: "count", Value: bson.D{
{Key: "$sum", Value: 1},
}},
}},
}
cursor, err := s.db.Collection("rewards").Aggregate(ctx, mongo.Pipeline{
matchStage,
groupStage,
})
if err != nil {
return 0, 0, fmt.Errorf("error get coinbase rewards: %w", err)
}
if !cursor.Next(ctx) {
return 0, 0, nil
}
doc := cursor.Current
return utils.GetAsInt64(doc.Lookup("total")), utils.GetAsInt64(doc.Lookup("count")), nil
}
// GetTotalRewards returns the total number of rewards.
func (s *Reader) GetTotalRewards(ctx context.Context, filter *bson.D) (total, count int64, err error) {
groupStage := bson.D{
{Key: "$group", Value: bson.D{
{Key: "_id", Value: ""},
{Key: "total", Value: bson.D{
{Key: "$sum", Value: "$total"},
}},
{Key: "count", Value: bson.D{
{Key: "$sum", Value: 1},
}},
}},
}
pipeline := bson.A{
groupStage,
}
if filter != nil {
pipeline = append(bson.A{
bson.D{{Key: "$match", Value: *filter}},
}, pipeline...)
}
cursor, err := s.db.Collection("rewards").Aggregate(ctx, pipeline)
if err != nil {
return 0, 0, fmt.Errorf("error get total rewards: %w", err)
}
if !cursor.Next(ctx) {
return 0, 0, nil
}
doc := cursor.Current
return utils.GetAsInt64(doc.Lookup("total")), utils.GetAsInt64(doc.Lookup("count")), nil
}
// GetLatestReward returns the latest reward for given coinbase
func (s *Reader) GetLatestReward(ctx context.Context, coinbase string) (*model.Reward, error) {
matchStage := bson.D{{Key: "$match", Value: bson.D{{Key: "coinbase", Value: coinbase}}}}
groupStage := bson.D{
{Key: "$group", Value: bson.D{
{Key: "_id", Value: ""},
{Key: "layer", Value: bson.D{
{Key: "$max", Value: "$layer"},
}},
}},
}
cursor, err := s.db.Collection("rewards").Aggregate(ctx, mongo.Pipeline{matchStage, groupStage})
if err != nil {
return nil, fmt.Errorf("error occured while getting latest reward: %w", err)
}
if !cursor.Next(ctx) {
return nil, nil
}
var reward *model.Reward
if err = cursor.Decode(&reward); err != nil {
return nil, fmt.Errorf("error decode reward: %w", err)
}
return reward, nil
}