/
list_table.go
128 lines (106 loc) · 3.78 KB
/
list_table.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
// Copyright 2020 dfuse Platform Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package server
import (
"fmt"
"net/http"
"net/url"
"strconv"
zsw "github.com/zhongshuwen/zswchain-go"
"github.com/dfuse-io/derr"
"github.com/zhongshuwen/historyexp/statedb"
"github.com/dfuse-io/logging"
"github.com/dfuse-io/validator"
"go.uber.org/zap"
)
func (srv *EOSServer) listTableRowsHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
zlog := logging.Logger(ctx, zlog)
errors := validateGetTableRequest(r)
if len(errors) > 0 {
writeError(ctx, w, derr.RequestValidationError(ctx, errors))
return
}
request := extractGetTableRequest(r)
zlog.Debug("extracted request", zap.Reflect("request", request))
actualBlockNum, lastWrittenBlock, upToBlock, speculativeWrites, err := srv.prepareRead(ctx, request.BlockNum, request.IrreversibleOnly)
if err != nil {
writeError(ctx, w, fmt.Errorf("prepare read failed: %w", err))
return
}
tablet := statedb.NewContractStateTablet(request.Account, request.Table, request.Scope)
rows, serializationInfo, err := srv.readContractStateTable(
ctx,
tablet,
actualBlockNum,
request.ToJSON,
speculativeWrites,
)
if err != nil {
writeError(ctx, w, fmt.Errorf("read rows failed: %w", err))
return
}
var abi *zsw.ABI
if serializationInfo != nil && request.WithABI {
abi = serializationInfo.abi
}
response := &getTableRowsResponse{
commonStateResponse: newCommonGetResponse(upToBlock, lastWrittenBlock),
readTableResponse: &readTableResponse{
ABI: abi,
Rows: []*tableRow{},
},
}
keyConverter := getKeyConverterForType(request.KeyType)
for _, row := range rows {
tableRow, err := toTableRow(row.(*statedb.ContractStateRow), keyConverter, serializationInfo, request.WithBlockNum)
if err != nil {
writeError(ctx, w, fmt.Errorf("creating table row failed: %w", err))
return
}
response.Rows = append(response.Rows, tableRow)
}
zlog.Debug("streaming response", zap.Int("row_count", len(response.readTableResponse.Rows)), zap.Reflect("common_response", response.commonStateResponse))
streamResponse(ctx, w, response)
}
type listTableRowsRequest struct {
*readRequestCommon
IrreversibleOnly bool `json:"irreversible_only"`
Account string `json:"account"`
Table string `json:"table"`
Scope string `json:"scope"`
}
func validateGetTableRequest(r *http.Request) url.Values {
errors := validator.ValidateQueryParams(r, withCommonValidationRules(validator.Rules{
"account": []string{"required", "fluxdb.eos.name"},
"table": []string{"required", "fluxdb.eos.name"},
"scope": []string{"fluxdb.eos.extendedName"},
"irreversible_only": []string{"bool"},
}))
// Let's ensure the scope param is at least present (but can be the empty string)
if _, ok := r.Form["scope"]; !ok {
errors["scope"] = []string{"The scope field is required"}
}
return errors
}
func extractGetTableRequest(r *http.Request) *listTableRowsRequest {
irreversibleOnly, _ := strconv.ParseBool(r.FormValue("irreversible_only"))
return &listTableRowsRequest{
readRequestCommon: extractReadRequestCommon(r),
Table: r.FormValue("table"),
Account: r.FormValue("account"),
Scope: r.FormValue("scope"),
IrreversibleOnly: irreversibleOnly,
}
}