github.com/wormhole-foundation/wormhole-explorer/common@v0.0.0-20240604151348-09585b5b97c5/client/txtracker/txtracker.go (about) 1 package txtracker 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "net/http" 9 "time" 10 11 "go.uber.org/zap" 12 ) 13 14 const DefaultTimeout = 30 15 16 var ( 17 ErrCallEndpoint = errors.New("ERROR CALL ENPOINT") 18 ErrBadRequest = errors.New("BAD REQUEST") 19 ErrInternalError = errors.New("INTERNAL ERROR") 20 ) 21 22 // TxTrackerAPIClient tx tracker api client. 23 type TxTrackerAPIClient struct { 24 Client http.Client 25 BaseURL string 26 Logger *zap.Logger 27 } 28 29 // NewTxTrackerAPIClient create new instances of TxTrackerAPIClient. 30 func NewTxTrackerAPIClient(timeout int64, baseURL string, logger *zap.Logger) (TxTrackerAPIClient, error) { 31 if timeout == 0 { 32 timeout = DefaultTimeout 33 } 34 if baseURL == "" { 35 return TxTrackerAPIClient{}, errors.New("baseURL can not be empty") 36 } 37 38 return TxTrackerAPIClient{ 39 Client: http.Client{ 40 Timeout: time.Duration(timeout) * time.Second, 41 }, 42 BaseURL: baseURL, 43 Logger: logger, 44 }, nil 45 } 46 47 // ProcessVaaResponse represent a process vaa response. 48 type ProcessVaaResponse struct { 49 From string `json:"from"` 50 NativeTxHash string `json:"nativeTxHash"` 51 Attributes any `json:"attributes"` 52 } 53 54 // Process process vaa. 55 func (c *TxTrackerAPIClient) Process(vaaID string) (*ProcessVaaResponse, error) { 56 endpointUrl := fmt.Sprintf("%s/vaa/process", c.BaseURL) 57 58 // create request body. 59 payload := struct { 60 VaaID string `json:"id"` 61 }{ 62 VaaID: vaaID, 63 } 64 65 body, err := json.Marshal(payload) 66 if err != nil { 67 c.Logger.Error("error marshalling payload", zap.Error(err), zap.String("vaaID", vaaID)) 68 return nil, err 69 } 70 71 response, err := c.Client.Post(endpointUrl, "application/json", bytes.NewBuffer(body)) 72 if err != nil { 73 c.Logger.Error("error call parse vaa endpoint", zap.Error(err), zap.String("vaaID", vaaID)) 74 return nil, ErrCallEndpoint 75 } 76 defer response.Body.Close() 77 switch response.StatusCode { 78 case http.StatusOK: 79 var processVaaResponse ProcessVaaResponse 80 json.NewDecoder(response.Body).Decode(&processVaaResponse) 81 return &processVaaResponse, nil 82 case http.StatusInternalServerError: 83 return nil, ErrInternalError 84 default: 85 return nil, ErrInternalError 86 } 87 } 88 89 // CreateTxHashFunc represent a create tx hash function. 90 type CreateTxHashFunc func(vaaID, txHash string) (*TxHashResponse, error) 91 92 // TxHashResponse represent a create tx hash response. 93 type TxHashResponse struct { 94 NativeTxHash string `json:"nativeTxHash"` 95 } 96 97 // CreateTxHash create tx hash. 98 func (c *TxTrackerAPIClient) CreateTxHash(vaaID, txHash string) (*TxHashResponse, error) { 99 endpoint := fmt.Sprintf("%s/vaa/tx-hash", c.BaseURL) 100 101 // create request body. 102 payload := struct { 103 VaaID string `json:"id"` 104 TxHash string `json:"txHash"` 105 }{ 106 VaaID: vaaID, 107 TxHash: txHash, 108 } 109 110 body, err := json.Marshal(payload) 111 if err != nil { 112 c.Logger.Error("error marshalling payload", zap.Error(err), zap.String("vaaID", vaaID), zap.String("txHash", txHash)) 113 return nil, err 114 } 115 116 response, err := c.Client.Post(endpoint, "application/json", bytes.NewBuffer(body)) 117 if err != nil { 118 c.Logger.Error("error call create tx hash endpoint", 119 zap.Error(err), 120 zap.String("vaaID", vaaID), 121 zap.String("txHash", txHash)) 122 return nil, ErrCallEndpoint 123 } 124 125 defer response.Body.Close() 126 switch response.StatusCode { 127 case http.StatusOK: 128 var txHashResponse TxHashResponse 129 json.NewDecoder(response.Body).Decode(&txHashResponse) 130 return &txHashResponse, nil 131 case http.StatusBadRequest: 132 return nil, ErrBadRequest 133 case http.StatusInternalServerError: 134 return nil, ErrInternalError 135 default: 136 return nil, ErrInternalError 137 } 138 139 }