• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lmittmann / w3 / 7496150241

12 Jan 2024 12:19AM UTC coverage: 77.601%. Remained the same
7496150241

Pull #99

github

web-flow
build(deps): bump github.com/ethereum/go-ethereum in /examples

Bumps [github.com/ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) from 1.13.8 to 1.13.10.
- [Release notes](https://github.com/ethereum/go-ethereum/releases)
- [Commits](https://github.com/ethereum/go-ethereum/compare/v1.13.8...v1.13.10)

---
updated-dependencies:
- dependency-name: github.com/ethereum/go-ethereum
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #99: build(deps): bump github.com/ethereum/go-ethereum from 1.13.8 to 1.13.10 in /examples

1805 of 2326 relevant lines covered (77.6%)

1420.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.21
/client.go
1
/*
2
Package w3 implements a blazing fast and modular Ethereum JSON RPC client with
3
first-class ABI support.
4
*/
5
package w3
6

7
import (
8
        "context"
9
        "fmt"
10
        "reflect"
11
        "strings"
12

13
        "github.com/ethereum/go-ethereum/rpc"
14
        "github.com/lmittmann/w3/w3types"
15
        "golang.org/x/time/rate"
16
)
17

18
// Client represents a connection to an RPC endpoint.
19
type Client struct {
20
        client *rpc.Client
21

22
        // rate limiter
23
        rl         *rate.Limiter
24
        rlCostFunc func(method string) (cost int)
25
}
26

27
// NewClient returns a new Client given an rpc.Client client.
28
func NewClient(client *rpc.Client, opts ...Option) *Client {
8✔
29
        c := &Client{
8✔
30
                client: client,
8✔
31
        }
8✔
32
        for _, opt := range opts {
8✔
33
                if opt == nil {
×
34
                        continue
×
35
                }
36
                opt(c)
×
37
        }
38
        return c
8✔
39
}
40

41
// Dial returns a new Client connected to the URL rawurl. An error is returned
42
// if the connection establishment fails.
43
//
44
// The supported URL schemes are "http", "https", "ws" and "wss". If rawurl is a
45
// file name with no URL scheme, a local IPC socket connection is established.
46
func Dial(rawurl string, opts ...Option) (*Client, error) {
8✔
47
        client, err := rpc.Dial(rawurl)
8✔
48
        if err != nil {
8✔
49
                return nil, err
×
50
        }
×
51
        return NewClient(client, opts...), nil
8✔
52
}
53

54
// MustDial is like [Dial] but panics if the connection establishment fails.
55
func MustDial(rawurl string, opts ...Option) *Client {
×
56
        client, err := Dial(rawurl, opts...)
×
57
        if err != nil {
×
58
                panic(fmt.Sprintf("w3: %s", err))
×
59
        }
60
        return client
×
61
}
62

63
// Close closes the RPC connection and cancels any in-flight requests.
64
//
65
// Close implements the [io.Closer] interface.
66
func (c *Client) Close() error {
×
67
        c.client.Close()
×
68
        return nil
×
69
}
×
70

71
// CallCtx creates the final RPC request, sends it, and handles the RPC
72
// response.
73
//
74
// An error is returned if RPC request creation, networking, or RPC response
75
// handling fails.
76
func (c *Client) CallCtx(ctx context.Context, calls ...w3types.Caller) error {
8✔
77
        // no requests = nothing to do
8✔
78
        if len(calls) <= 0 {
8✔
79
                return nil
×
80
        }
×
81

82
        // create requests
83
        batchElems := make([]rpc.BatchElem, len(calls))
8✔
84
        var err error
8✔
85
        for i, req := range calls {
20✔
86
                batchElems[i], err = req.CreateRequest()
12✔
87
                if err != nil {
14✔
88
                        return err
2✔
89
                }
2✔
90
        }
91

92
        // invoke rate limiter
93
        if err := c.rateLimit(ctx, batchElems); err != nil {
6✔
94
                return err
×
95
        }
×
96

97
        // do requests
98
        if len(batchElems) > 1 {
10✔
99
                // batch requests if >1 request
4✔
100
                err = c.client.BatchCallContext(ctx, batchElems)
4✔
101
                if err != nil {
4✔
102
                        return err
×
103
                }
×
104
        } else {
2✔
105
                // non-batch requests if 1 request
2✔
106
                batchElem := batchElems[0]
2✔
107
                err = c.client.CallContext(ctx, batchElem.Result, batchElem.Method, batchElem.Args...)
2✔
108
                if err != nil {
2✔
109
                        switch reflect.TypeOf(err).String() {
×
110
                        case "*rpc.jsonError":
×
111
                                batchElems[0].Error = err
×
112
                        default:
×
113
                                return err
×
114
                        }
115
                }
116
        }
117

118
        // handle responses
119
        var callErrs CallErrors
6✔
120
        for i, req := range calls {
16✔
121
                err = req.HandleResponse(batchElems[i])
10✔
122
                if err != nil {
16✔
123
                        if callErrs == nil {
11✔
124
                                callErrs = make(CallErrors, len(calls))
5✔
125
                        }
5✔
126
                        callErrs[i] = err
6✔
127
                }
128
        }
129
        if len(callErrs) > 0 {
11✔
130
                return callErrs
5✔
131
        }
5✔
132
        return nil
1✔
133
}
134

135
// Call is like [Client.CallCtx] with ctx equal to context.Background().
136
func (c *Client) Call(calls ...w3types.Caller) error {
8✔
137
        return c.CallCtx(context.Background(), calls...)
8✔
138
}
8✔
139

140
func (c *Client) rateLimit(ctx context.Context, batchElems []rpc.BatchElem) error {
6✔
141
        if c.rl == nil {
12✔
142
                return nil
6✔
143
        }
6✔
144

145
        if c.rlCostFunc == nil {
×
146
                // limit requests
×
147
                return c.rl.Wait(ctx)
×
148
        }
×
149

150
        // limit requests based on Compute Units (CUs)
151
        var cost int
×
152
        for _, batchElem := range batchElems {
×
153
                cost += c.rlCostFunc(batchElem.Method)
×
154
        }
×
155
        return c.rl.WaitN(ctx, cost)
×
156
}
157

158
// CallErrors is an error type that contains the errors of multiple calls. The
159
// length of the error slice is equal to the number of calls. Each error at a
160
// given index corresponds to the call at the same index. An error is nil if the
161
// corresponding call was successful.
162
type CallErrors []error
163

164
func (e CallErrors) Error() string {
8✔
165
        if len(e) == 1 && e[0] != nil {
10✔
166
                return fmt.Sprintf("w3: call failed: %s", e[0])
2✔
167
        }
2✔
168

169
        var errors []string
6✔
170
        for i, err := range e {
18✔
171
                if err == nil {
16✔
172
                        continue
4✔
173
                }
174
                errors = append(errors, fmt.Sprintf("call[%d]: %s", i, err))
8✔
175
        }
176

177
        var plr string
6✔
178
        if len(errors) > 1 {
8✔
179
                plr = "s"
2✔
180
        }
2✔
181
        return fmt.Sprintf("w3: %d call%s failed:\n%s", len(errors), plr, strings.Join(errors, "\n"))
6✔
182
}
183

184
func (e CallErrors) Is(target error) bool {
1✔
185
        _, ok := target.(CallErrors)
1✔
186
        return ok
1✔
187
}
1✔
188

189
// An Option configures a Client.
190
type Option func(*Client)
191

192
// WithRateLimiter sets the rate limiter for the client. Set the optional argument
193
// costFunc to nil to limit the number of requests. Supply a costFunc to limit
194
// the the number of requests based on individual RPC calls for advanced rate
195
// limiting by Compute Units (CUs).
196
func WithRateLimiter(rl *rate.Limiter, costFunc func(method string) (cost int)) Option {
×
197
        return func(c *Client) {
×
198
                c.rl = rl
×
199
                c.rlCostFunc = costFunc
×
200
        }
×
201
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc