-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathoptions.go
More file actions
297 lines (267 loc) · 8.05 KB
/
options.go
File metadata and controls
297 lines (267 loc) · 8.05 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
package main
import (
"errors"
"strings"
"time"
)
// Option is a function that configures the application
type Option func(*options) error
type options struct {
listenAddr string
tlsCert string
tlsKey string
seiWSEndpoint string
seiHTTPEndpoint string
allowedOrigins map[string]bool
allowedMethods map[string]bool
blockedMethods map[string]bool
maxRequestSize int64
rateLimitPerIP float64
rateLimitBurst int
httpOnlyMethods map[string]bool
maxWSConnections int
wsReadTimeout time.Duration
wsWriteTimeout time.Duration
httpTimeout time.Duration
wsPingInterval time.Duration
wsMaxMessageSize int64
maxConcurrentBatch int
connectionMaxAge time.Duration
cache Cache
memcachedServers []string
cacheTTL time.Duration
cacheableMethods map[string]MethodCache
}
func newOptions(opt ...Option) (*options, error) {
opts := &options{
listenAddr: "localhost:8555",
seiWSEndpoint: "ws://localhost:8546",
seiHTTPEndpoint: "http://localhost:8545",
blockedMethods: map[string]bool{
"admin_addPeer": true, "admin_removePeer": true, "admin_startRPC": true,
"admin_stopRPC": true, "admin_startWS": true, "admin_stopWS": true,
"miner_start": true, "miner_stop": true, "personal_unlockAccount": true,
"personal_sendTransaction": true, "personal_sign": true, "debug_setHead": true,
"debug_gcStats": true, "debug_memStats": true, "debug_cpuProfile": true,
"debug_startCPUProfile": true, "debug_stopCPUProfile": true,
"debug_writeBlockProfile": true, "debug_writeMemProfile": true,
"debug_setBlockProfileRate": true, "debug_setGCPercent": true,
"debug_setMutexProfileFraction": true,
},
maxRequestSize: 1 << 20,
rateLimitPerIP: 100,
rateLimitBurst: 200,
httpOnlyMethods: map[string]bool{
"debug_traceTransaction": true, "debug_traceCall": true,
"debug_traceBlockByNumber": true, "debug_traceBlockByHash": true,
"trace_block": true, "trace_transaction": true, "trace_call": true,
"trace_replayTransaction": true, "trace_replayBlockTransactions": true,
"eth_getLogs": true,
},
maxWSConnections: 20,
wsReadTimeout: 60 * time.Second,
wsWriteTimeout: 10 * time.Second,
httpTimeout: 60 * time.Second,
wsPingInterval: 15 * time.Second,
wsMaxMessageSize: 4 << 20,
maxConcurrentBatch: 50,
connectionMaxAge: 5 * time.Minute,
cache: NoopCache{},
cacheTTL: 5 * time.Second,
cacheableMethods: map[string]MethodCache{
"eth_getBlockByHash": {TTL: 24 * time.Hour}, "eth_getBlockByNumber": {TTL: 5 * time.Second},
"eth_getBlockTransactionCountByHash": {TTL: 24 * time.Hour}, "eth_getBlockTransactionCountByNumber": {TTL: 5 * time.Second},
"eth_getTransactionByHash": {TTL: 24 * time.Hour}, "eth_getTransactionReceipt": {TTL: 24 * time.Hour},
"eth_getCode": {TTL: 1 * time.Hour}, "eth_chainId": {TTL: 1 * time.Hour},
"net_version": {TTL: 1 * time.Hour}, "web3_clientVersion": {TTL: 1 * time.Hour},
"eth_blockNumber": {TTL: 1 * time.Second}, "eth_gasPrice": {TTL: 3 * time.Second},
"eth_feeHistory": {TTL: 3 * time.Second}, "eth_getBalance": {TTL: 2 * time.Second},
"eth_getStorageAt": {TTL: 2 * time.Second}, "eth_getTransactionCount": {TTL: 2 * time.Second},
"eth_call": {TTL: 2 * time.Second}, "eth_estimateGas": {TTL: 2 * time.Second},
},
}
for _, apply := range opt {
if err := apply(opts); err != nil {
return nil, err
}
}
return opts, nil
}
// WithListenAddr sets the address to listen on
func WithListenAddr(addr string) Option {
return func(o *options) error {
o.listenAddr = addr
return nil
}
}
// WithTLS sets TLS certificate and key paths
func WithTLS(certPath, keyPath string) Option {
return func(o *options) error {
o.tlsCert = certPath
o.tlsKey = keyPath
return nil
}
}
// WithSeiWSEndpoint sets the Sei WebSocket endpoint
func WithSeiWSEndpoint(endpoint string) Option {
return func(o *options) error {
o.seiWSEndpoint = endpoint
return nil
}
}
// WithSeiHTTPEndpoint sets the Sei HTTP endpoint
func WithSeiHTTPEndpoint(endpoint string) Option {
return func(o *options) error {
o.seiHTTPEndpoint = endpoint
return nil
}
}
// WithAllowedOrigins sets the allowed CORS origins
func WithAllowedOrigins(origins []string) Option {
return func(o *options) error {
if o.allowedOrigins == nil {
o.allowedOrigins = make(map[string]bool)
}
for _, origin := range origins {
if origin == "" {
return errors.New("empty origin")
}
o.allowedOrigins[strings.ToLower(origin)] = true
}
return nil
}
}
// WithAllowedMethods sets the allowed RPC methods (whitelist)
func WithAllowedMethods(methods []string) Option {
return func(o *options) error {
o.allowedMethods = make(map[string]bool)
for _, m := range methods {
o.allowedMethods[m] = true
}
return nil
}
}
// WithBlockedMethods adds methods to the blocklist
func WithBlockedMethods(methods []string) Option {
return func(o *options) error {
if o.blockedMethods == nil {
o.blockedMethods = make(map[string]bool)
}
for _, m := range methods {
o.blockedMethods[m] = true
}
return nil
}
}
// WithMaxRequestSize sets the maximum request body size
func WithMaxRequestSize(size int64) Option {
return func(o *options) error {
o.maxRequestSize = size
return nil
}
}
// WithRateLimit sets the per-IP rate limit
func WithRateLimit(rps float64, burst int) Option {
return func(o *options) error {
o.rateLimitPerIP = rps
o.rateLimitBurst = burst
return nil
}
}
// WithHTTPOnlyMethods sets methods that should only use HTTP
func WithHTTPOnlyMethods(methods []string) Option {
return func(o *options) error {
o.httpOnlyMethods = make(map[string]bool)
for _, m := range methods {
o.httpOnlyMethods[m] = true
}
return nil
}
}
// WithMaxWSConnections sets the maximum WebSocket pool size
func WithMaxWSConnections(max int) Option {
return func(o *options) error {
o.maxWSConnections = max
return nil
}
}
// WithWSReadTimeout sets the WebSocket read operation timeout
func WithWSReadTimeout(timeout time.Duration) Option {
return func(o *options) error {
o.wsReadTimeout = timeout
return nil
}
}
// WithWSWriteTimeout sets the WebSocket write operation timeout
func WithWSWriteTimeout(timeout time.Duration) Option {
return func(o *options) error {
o.wsWriteTimeout = timeout
return nil
}
}
// WithHTTPTimeout sets the HTTP client timeout
func WithHTTPTimeout(timeout time.Duration) Option {
return func(o *options) error {
o.httpTimeout = timeout
return nil
}
}
// WithWSPingInterval sets the WebSocket ping interval
func WithWSPingInterval(interval time.Duration) Option {
return func(o *options) error {
o.wsPingInterval = interval
return nil
}
}
// WithWSMaxMessageSize sets the maximum WebSocket message size
func WithWSMaxMessageSize(size int64) Option {
return func(o *options) error {
o.wsMaxMessageSize = size
return nil
}
}
// WithMaxConcurrentBatch sets the maximum concurrent batch requests
func WithMaxConcurrentBatch(max int) Option {
return func(o *options) error {
o.maxConcurrentBatch = max
return nil
}
}
// WithConnectionMaxAge sets the maximum connection age
func WithConnectionMaxAge(age time.Duration) Option {
return func(o *options) error {
o.connectionMaxAge = age
return nil
}
}
// WithMemcachedServers sets the memcached server addresses
func WithMemcachedServers(servers []string) Option {
return func(o *options) error {
o.memcachedServers = servers
return nil
}
}
// WithCache sets the JSON RPC response cache.
func WithCache(cache Cache) Option {
return func(o *options) error {
o.cache = cache
return nil
}
}
// WithCacheTTL sets the default cache TTL
func WithCacheTTL(ttl time.Duration) Option {
return func(o *options) error {
o.cacheTTL = ttl
return nil
}
}
// WithCacheableMethod adds a cacheable method configuration
func WithCacheableMethod(method string, ttl time.Duration, keyIncludesID bool) Option {
return func(o *options) error {
if o.cacheableMethods == nil {
o.cacheableMethods = make(map[string]MethodCache)
}
o.cacheableMethods[method] = MethodCache{TTL: ttl, KeyIncludesID: keyIncludesID}
return nil
}
}