github.com/gagliardetto/solana-go@v1.11.0/rpc/client-with-ratelimit2.go (about)

     1  package rpc
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net/http"
     7  
     8  	"github.com/gagliardetto/solana-go/rpc/jsonrpc"
     9  	"golang.org/x/time/rate"
    10  )
    11  
    12  var _ JSONRPCClient = &clientWithLimiter{}
    13  
    14  type clientWithLimiter struct {
    15  	rpcClient jsonrpc.RPCClient
    16  	limiter   *rate.Limiter
    17  }
    18  
    19  // NewWithLimiter creates a new rate-limitted Solana RPC client.
    20  // Example: NewWithLimiter(URL, rate.Every(time.Second), 1)
    21  func NewWithLimiter(
    22  	rpcEndpoint string,
    23  	every rate.Limit, // time frame
    24  	b int, // number of requests per time frame
    25  ) JSONRPCClient {
    26  	opts := &jsonrpc.RPCClientOpts{
    27  		HTTPClient: newHTTP(),
    28  	}
    29  
    30  	rpcClient := jsonrpc.NewClientWithOpts(rpcEndpoint, opts)
    31  	rater := rate.NewLimiter(every, b)
    32  
    33  	return &clientWithLimiter{
    34  		rpcClient: rpcClient,
    35  		limiter:   rater,
    36  	}
    37  }
    38  
    39  func (wr *clientWithLimiter) CallForInto(ctx context.Context, out interface{}, method string, params []interface{}) error {
    40  	err := wr.limiter.Wait(ctx)
    41  	if err != nil {
    42  		return err
    43  	}
    44  	return wr.rpcClient.CallForInto(ctx, &out, method, params)
    45  }
    46  
    47  func (wr *clientWithLimiter) CallWithCallback(
    48  	ctx context.Context,
    49  	method string,
    50  	params []interface{},
    51  	callback func(*http.Request, *http.Response) error,
    52  ) error {
    53  	err := wr.limiter.Wait(ctx)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	return wr.rpcClient.CallWithCallback(ctx, method, params, callback)
    58  }
    59  
    60  func (wr *clientWithLimiter) CallBatch(
    61  	ctx context.Context,
    62  	requests jsonrpc.RPCRequests,
    63  ) (jsonrpc.RPCResponses, error) {
    64  	err := wr.limiter.Wait(ctx)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	return wr.rpcClient.CallBatch(ctx, requests)
    69  }
    70  
    71  // Close closes clientWithLimiter.
    72  func (cl *clientWithLimiter) Close() error {
    73  	if c, ok := cl.rpcClient.(io.Closer); ok {
    74  		return c.Close()
    75  	}
    76  	return nil
    77  }