-
Notifications
You must be signed in to change notification settings - Fork 496
/
effects.go
125 lines (106 loc) · 3.36 KB
/
effects.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
package actions
import (
"context"
"net/http"
horizonContext "github.com/stellar/go/services/horizon/internal/context"
"github.com/stellar/go/services/horizon/internal/db2"
"github.com/stellar/go/services/horizon/internal/db2/history"
"github.com/stellar/go/services/horizon/internal/ledger"
"github.com/stellar/go/services/horizon/internal/resourceadapter"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/render/hal"
"github.com/stellar/go/support/render/problem"
)
// EffectsQuery query struct for effects end-points
type EffectsQuery struct {
AccountID string `schema:"account_id" valid:"accountID,optional"`
OperationID uint64 `schema:"op_id" valid:"-"`
LiquidityPoolID string `schema:"liquidity_pool_id" valid:"sha256,optional"`
TxHash string `schema:"tx_id" valid:"transactionHash,optional"`
LedgerID uint32 `schema:"ledger_id" valid:"-"`
}
// Validate runs extra validations on query parameters
func (qp EffectsQuery) Validate() error {
count, err := countNonEmpty(
qp.AccountID,
qp.OperationID,
qp.LiquidityPoolID,
qp.TxHash,
qp.LedgerID,
)
if err != nil {
return problem.BadRequest
}
if count > 1 {
return problem.MakeInvalidFieldProblem(
"filters",
errors.New("Use a single filter for effects, you can only use one of account_id, op_id, tx_id or ledger_id"),
)
}
return nil
}
type GetEffectsHandler struct {
LedgerState *ledger.State
}
func (handler GetEffectsHandler) GetResourcePage(w HeaderWriter, r *http.Request) ([]hal.Pageable, error) {
pq, err := GetPageQuery(handler.LedgerState, r)
if err != nil {
return nil, err
}
err = validateCursorWithinHistory(handler.LedgerState, pq)
if err != nil {
return nil, err
}
qp := EffectsQuery{}
err = getParams(&qp, r)
if err != nil {
return nil, err
}
historyQ, err := horizonContext.HistoryQFromRequest(r)
if err != nil {
return nil, err
}
records, err := loadEffectRecords(r.Context(), historyQ, qp, pq)
if err != nil {
return nil, errors.Wrap(err, "loading transaction records")
}
ledgers, err := loadEffectLedgers(r.Context(), historyQ, records)
if err != nil {
return nil, errors.Wrap(err, "loading ledgers")
}
var result []hal.Pageable
for _, record := range records {
effect, err := resourceadapter.NewEffect(r.Context(), record, ledgers[record.LedgerSequence()])
if err != nil {
return nil, errors.Wrap(err, "could not create effect")
}
result = append(result, effect)
}
return result, nil
}
func loadEffectRecords(ctx context.Context, hq *history.Q, qp EffectsQuery, pq db2.PageQuery) ([]history.Effect, error) {
switch {
case qp.AccountID != "":
return hq.EffectsForAccount(ctx, qp.AccountID, pq)
case qp.LiquidityPoolID != "":
return hq.EffectsForLiquidityPool(ctx, qp.LiquidityPoolID, pq)
case qp.OperationID > 0:
return hq.EffectsForOperation(ctx, int64(qp.OperationID), pq)
case qp.LedgerID > 0:
return hq.EffectsForLedger(ctx, int32(qp.LedgerID), pq)
case qp.TxHash != "":
return hq.EffectsForTransaction(ctx, qp.TxHash, pq)
default:
return hq.Effects(ctx, pq)
}
}
func loadEffectLedgers(ctx context.Context, hq *history.Q, effects []history.Effect) (map[int32]history.Ledger, error) {
ledgers := &history.LedgerCache{}
for _, e := range effects {
ledgers.Queue(e.LedgerSequence())
}
if err := ledgers.Load(ctx, hq); err != nil {
return nil, err
}
return ledgers.Records, nil
}