Files
explorer-monorepo/backend/bridge/socket_provider.go

93 lines
2.6 KiB
Go

package bridge
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"
)
const (
socketAPIBase = "https://public-backend.bungee.exchange"
socketTimeout = 10 * time.Second
)
var socketSupportedChains = map[int]bool{
1: true, 10: true, 137: true, 42161: true, 8453: true,
56: true, 43114: true, 100: true, 25: true, 250: true,
324: true, 59144: true, 534352: true, 42220: true, 5000: true, 1111: true,
}
type socketQuoteResponse struct {
Success bool `json:"success"`
Result *struct {
Route *struct {
ToAmount string `json:"toAmount"`
ToAmountMin string `json:"toAmountMin"`
} `json:"route"`
} `json:"result"`
Message string `json:"message"`
}
type SocketProvider struct {
apiBase string
client *http.Client
}
func NewSocketProvider() *SocketProvider {
return &SocketProvider{apiBase: socketAPIBase, client: &http.Client{Timeout: socketTimeout}}
}
func (p *SocketProvider) Name() string { return "Socket" }
func (p *SocketProvider) SupportsRoute(fromChain, toChain int) bool {
return socketSupportedChains[fromChain] && socketSupportedChains[toChain]
}
func (p *SocketProvider) GetQuote(ctx context.Context, req *BridgeRequest) (*BridgeQuote, error) {
if req.Recipient == "" {
return nil, fmt.Errorf("Socket: recipient required")
}
params := url.Values{}
params.Set("fromChainId", strconv.Itoa(req.FromChain))
params.Set("toChainId", strconv.Itoa(req.ToChain))
params.Set("fromTokenAddress", req.FromToken)
params.Set("toTokenAddress", req.ToToken)
params.Set("fromAmount", req.Amount)
params.Set("recipient", req.Recipient)
apiURL := fmt.Sprintf("%s/api/v1/bungee/quote?%s", p.apiBase, params.Encode())
httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil)
if err != nil {
return nil, err
}
resp, err := p.client.Do(httpReq)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var r socketQuoteResponse
if err := json.Unmarshal(body, &r); err != nil {
return nil, fmt.Errorf("Socket parse error: %w", err)
}
if !r.Success || r.Result == nil || r.Result.Route == nil {
return nil, fmt.Errorf("Socket API: %s", r.Message)
}
toAmount := r.Result.Route.ToAmount
if toAmount == "" {
toAmount = r.Result.Route.ToAmountMin
}
if toAmount == "" {
return nil, fmt.Errorf("Socket: no amount")
}
steps := []BridgeStep{{Provider: "Socket", From: strconv.Itoa(req.FromChain), To: strconv.Itoa(req.ToChain), Type: "bridge"}}
return &BridgeQuote{
Provider: "Socket", FromChain: req.FromChain, ToChain: req.ToChain,
FromAmount: req.Amount, ToAmount: toAmount, Fee: "0", EstimatedTime: "1-5 min", Route: steps,
}, nil
}