/
get_block_by_number.go
147 lines (126 loc) · 3.37 KB
/
get_block_by_number.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
package eth
import (
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/lmittmann/w3/core"
)
// BlockByNumber requests the block with full transactions with the given
// number.
func BlockByNumber(number *big.Int) interface {
core.CallFactoryReturns[types.Block]
core.CallFactoryReturnsRAW[RPCBlock]
} {
return &blockByNumberFactory{number: number}
}
type blockByNumberFactory struct {
// args
number *big.Int
// returns
result json.RawMessage
returns *types.Block
resultRAW *RPCBlock
returnsRAW *RPCBlock
}
func (f *blockByNumberFactory) Returns(block *types.Block) core.Caller {
f.returns = block
return f
}
func (f *blockByNumberFactory) ReturnsRAW(block *RPCBlock) core.Caller {
f.returnsRAW = block
return f
}
// CreateRequest implements the core.RequestCreator interface.
func (f *blockByNumberFactory) CreateRequest() (rpc.BatchElem, error) {
if f.returns != nil {
return rpc.BatchElem{
Method: "eth_getBlockByNumber",
Args: []any{toBlockNumberArg(f.number), true},
Result: &f.result,
}, nil
}
return rpc.BatchElem{
Method: "eth_getBlockByNumber",
Args: []any{toBlockNumberArg(f.number), true},
Result: &f.resultRAW,
}, nil
}
// HandleResponse implements the core.ResponseHandler interface.
func (f *blockByNumberFactory) HandleResponse(elem rpc.BatchElem) error {
if err := elem.Error; err != nil {
return err
}
if f.returns != nil && len(f.result) <= 4 || f.returnsRAW != nil && f.resultRAW == nil {
return errNotFound
}
if f.returns != nil {
var head *types.Header
var body rpcBlock
if err := json.Unmarshal(f.result, &head); err != nil {
return err
}
if err := json.Unmarshal(f.result, &body); err != nil {
return err
}
block := types.NewBlockWithHeader(head).WithBody(body.Transactions, nil)
*f.returns = *block
} else {
*f.returnsRAW = *f.resultRAW
}
return nil
}
// HeaderByNumber requests the header with the given number.
func HeaderByNumber(number *big.Int) interface {
core.CallFactoryReturns[types.Header]
core.CallFactoryReturnsRAW[RPCHeader]
} {
return &headerByNumberFactory{number: number}
}
type headerByNumberFactory struct {
// args
number *big.Int
// returns
result *types.Header
returns *types.Header
resultRAW *RPCHeader
returnsRAW *RPCHeader
}
func (f *headerByNumberFactory) Returns(header *types.Header) core.Caller {
f.returns = header
return f
}
func (f *headerByNumberFactory) ReturnsRAW(header *RPCHeader) core.Caller {
f.returnsRAW = header
return f
}
// CreateRequest implements the core.RequestCreator interface.
func (f *headerByNumberFactory) CreateRequest() (rpc.BatchElem, error) {
if f.returns != nil {
return rpc.BatchElem{
Method: "eth_getBlockByNumber",
Args: []any{toBlockNumberArg(f.number), false},
Result: &f.result,
}, nil
}
return rpc.BatchElem{
Method: "eth_getBlockByNumber",
Args: []any{toBlockNumberArg(f.number), false},
Result: &f.resultRAW,
}, nil
}
// HandleResponse implements the core.ResponseHandler interface.
func (f *headerByNumberFactory) HandleResponse(elem rpc.BatchElem) error {
if err := elem.Error; err != nil {
return err
}
if f.returns != nil && f.result == nil || f.returnsRAW != nil && f.resultRAW == nil {
return errNotFound
}
if f.returns != nil {
*f.returns = *f.result
} else {
*f.returnsRAW = *f.resultRAW
}
return nil
}