-
Notifications
You must be signed in to change notification settings - Fork 33
/
client.go
152 lines (126 loc) · 4.56 KB
/
client.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
148
149
150
151
152
package relapi
import (
"context"
"fmt"
"net/http"
"github.com/dubonzi/otelresty"
"github.com/go-http-utils/headers"
"github.com/go-resty/resty/v2"
"github.com/synapsecns/sanguine/core/metrics"
"github.com/valyala/fastjson"
)
// RelayerClient is the interface for the relayer client.
type RelayerClient interface {
Health(ctx context.Context) (ok bool, err error)
RetryTransaction(ctx context.Context, txhash string) (*GetTxRetryResponse, error)
Withdraw(ctx context.Context, req *WithdrawRequest) (*WithdrawResponse, error)
GetTxHashByNonce(ctx context.Context, req *GetTxByNonceRequest) (*TxHashByNonceResponse, error)
GetQuoteRequestByTXID(ctx context.Context, txid string) (*GetQuoteRequestResponse, error)
GetQuoteRequestByTxHash(ctx context.Context, txhash string) (*GetQuoteRequestResponse, error)
}
type relayerClient struct {
client *resty.Client
}
// NewRelayerClient creates a new RelayerClient.
func NewRelayerClient(handler metrics.Handler, url string) RelayerClient {
client := resty.New()
client.SetBaseURL(url)
client.SetHeader(headers.UserAgent, "relayer-client")
otelresty.TraceClient(client, otelresty.WithTracerProvider(handler.GetTracerProvider()))
return &relayerClient{
client: client,
}
}
// Health checks if the relayer is healthy.
func (r *relayerClient) Health(ctx context.Context) (ok bool, err error) {
resp, err := r.client.R().SetContext(ctx).Get(getHealthRoute)
if err != nil {
return false, fmt.Errorf("failed to check health: %w", err)
}
if resp.StatusCode() != http.StatusOK {
return false, fmt.Errorf("unexpected status code: %d", resp.StatusCode())
}
ok = fastjson.GetString(resp.Body(), "status") == "ok"
return ok, nil
}
func (r *relayerClient) RetryTransaction(ctx context.Context, txhash string) (*GetTxRetryResponse, error) {
var res GetTxRetryResponse
resp, err := r.client.R().SetContext(ctx).
SetQueryParam("hash", txhash).
SetResult(&res).
Get(getRetryRoute)
if err != nil {
return nil, fmt.Errorf("failed to retry transaction: %w", err)
}
if resp.StatusCode() != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode())
}
return &res, nil
}
// WithdrawResponse is the response for the withdraw request.
type WithdrawResponse struct {
Nonce uint64 `json:"nonce"`
}
// Withdraw withdraws an ERC20 or Ether from the relayer.
func (r *relayerClient) Withdraw(ctx context.Context, req *WithdrawRequest) (*WithdrawResponse, error) {
var res WithdrawResponse
resp, err := r.client.R().SetContext(ctx).
SetResult(&res).
SetBody(req).
Post(postWithdrawRoute)
if err != nil {
return nil, fmt.Errorf("failed to withdraw transaction: %w", err)
}
if resp.StatusCode() != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode())
}
return &res, nil
}
// TxHashByNonceResponse is the request for getting a transaction hash by nonce.
type TxHashByNonceResponse struct {
Hash string `json:"withdrawTxHash"`
}
// GetTxByNonceRequest is the request for getting a transaction hash by nonce.
func (r *relayerClient) GetTxHashByNonce(ctx context.Context, req *GetTxByNonceRequest) (*TxHashByNonceResponse, error) {
var res TxHashByNonceResponse
resp, err := r.client.R().SetContext(ctx).
SetResult(&res).
SetQueryParam("chain_id", fmt.Sprintf("%d", req.ChainID)).
SetQueryParam("nonce", fmt.Sprintf("%d", req.Nonce)).
Get(getTxHashByNonceRoute)
if err != nil {
return nil, fmt.Errorf("failed to get tx hash by nonce: %w", err)
}
if resp.StatusCode() != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode())
}
return &res, nil
}
func (r *relayerClient) GetQuoteRequestByTXID(ctx context.Context, txid string) (*GetQuoteRequestResponse, error) {
var res GetQuoteRequestResponse
resp, err := r.client.R().SetContext(ctx).
SetQueryParam("id", txid).
SetResult(&res).
Get(getRequestByTxID)
if err != nil {
return nil, fmt.Errorf("failed to get quote request by tx id: %w", err)
}
if resp.StatusCode() != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode())
}
return &res, nil
}
func (r *relayerClient) GetQuoteRequestByTxHash(ctx context.Context, txHash string) (*GetQuoteRequestResponse, error) {
var res GetQuoteRequestResponse
resp, err := r.client.R().SetContext(ctx).
SetQueryParam("hash", txHash).
SetResult(&res).
Get(getRequestByTxHash)
if err != nil {
return nil, fmt.Errorf("failed to get quote request by tx hash: %w", err)
}
if resp.StatusCode() != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode())
}
return &res, nil
}