107 lines
3.0 KiB
Go
107 lines
3.0 KiB
Go
package bridge
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
squidAPIBase = "https://v2.api.squidrouter.com"
|
|
squidTimeout = 10 * time.Second
|
|
squidIntegrator = "explorer-bridge-aggregator"
|
|
)
|
|
|
|
var squidSupportedChains = 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 squidReq struct {
|
|
FromAddress string `json:"fromAddress"`
|
|
FromChain string `json:"fromChain"`
|
|
FromToken string `json:"fromToken"`
|
|
FromAmount string `json:"fromAmount"`
|
|
ToChain string `json:"toChain"`
|
|
ToToken string `json:"toToken"`
|
|
ToAddress string `json:"toAddress"`
|
|
Slippage int `json:"slippage"`
|
|
}
|
|
|
|
type squidResp struct {
|
|
Route *struct {
|
|
Estimate *struct {
|
|
ToAmount string `json:"toAmount"`
|
|
ToAmountMin string `json:"toAmountMin"`
|
|
} `json:"estimate"`
|
|
} `json:"route"`
|
|
}
|
|
|
|
type SquidProvider struct {
|
|
apiBase string
|
|
client *http.Client
|
|
}
|
|
|
|
func NewSquidProvider() *SquidProvider {
|
|
return &SquidProvider{apiBase: squidAPIBase, client: &http.Client{Timeout: squidTimeout}}
|
|
}
|
|
|
|
func (p *SquidProvider) Name() string { return "Squid" }
|
|
|
|
func (p *SquidProvider) SupportsRoute(fromChain, toChain int) bool {
|
|
return squidSupportedChains[fromChain] && squidSupportedChains[toChain]
|
|
}
|
|
|
|
func (p *SquidProvider) GetQuote(ctx context.Context, req *BridgeRequest) (*BridgeQuote, error) {
|
|
addr := req.Recipient
|
|
if addr == "" {
|
|
addr = "0x0000000000000000000000000000000000000000"
|
|
}
|
|
bodyReq := squidReq{
|
|
FromAddress: addr, FromChain: strconv.Itoa(req.FromChain), FromToken: req.FromToken,
|
|
FromAmount: req.Amount, ToChain: strconv.Itoa(req.ToChain), ToToken: req.ToToken,
|
|
ToAddress: addr, Slippage: 1,
|
|
}
|
|
jsonBody, _ := json.Marshal(bodyReq)
|
|
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.apiBase+"/v2/route", bytes.NewReader(jsonBody))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
httpReq.Header.Set("Content-Type", "application/json")
|
|
httpReq.Header.Set("x-integrator-id", squidIntegrator)
|
|
resp, err := p.client.Do(httpReq)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, _ := io.ReadAll(resp.Body)
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("Squid API %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
var r squidResp
|
|
if err := json.Unmarshal(body, &r); err != nil {
|
|
return nil, err
|
|
}
|
|
if r.Route == nil || r.Route.Estimate == nil {
|
|
return nil, fmt.Errorf("Squid: no route")
|
|
}
|
|
toAmount := r.Route.Estimate.ToAmount
|
|
if toAmount == "" {
|
|
toAmount = r.Route.Estimate.ToAmountMin
|
|
}
|
|
if toAmount == "" {
|
|
return nil, fmt.Errorf("Squid: no amount")
|
|
}
|
|
return &BridgeQuote{
|
|
Provider: "Squid", FromChain: req.FromChain, ToChain: req.ToChain,
|
|
FromAmount: req.Amount, ToAmount: toAmount, Fee: "0", EstimatedTime: "1-5 min",
|
|
Route: []BridgeStep{{Provider: "Squid", From: strconv.Itoa(req.FromChain), To: strconv.Itoa(req.ToChain), Type: "bridge"}},
|
|
}, nil
|
|
}
|