102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
package bridge
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
ccipTimeout = 5 * time.Second
|
|
defaultCCIPFee = "100000000000000000" // ~0.1 LINK (18 decimals)
|
|
)
|
|
|
|
// CCIP-supported chain pair: 138 <-> 1
|
|
var ccipSupportedPairs = map[string]bool{
|
|
"138-1": true,
|
|
"1-138": true,
|
|
}
|
|
|
|
type ccipQuoteResponse struct {
|
|
Fee string `json:"fee"`
|
|
}
|
|
|
|
// CCIPProvider implements Provider for Chainlink CCIP
|
|
type CCIPProvider struct {
|
|
quoteURL string
|
|
client *http.Client
|
|
}
|
|
|
|
// NewCCIPProvider creates a new CCIP bridge provider
|
|
func NewCCIPProvider() *CCIPProvider {
|
|
quoteURL := os.Getenv("CCIP_ROUTER_QUOTE_URL")
|
|
return &CCIPProvider{
|
|
quoteURL: quoteURL,
|
|
client: &http.Client{
|
|
Timeout: ccipTimeout,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Name returns the provider name
|
|
func (p *CCIPProvider) Name() string {
|
|
return "CCIP"
|
|
}
|
|
|
|
// SupportsRoute returns true for 138 <-> 1
|
|
func (p *CCIPProvider) SupportsRoute(fromChain, toChain int) bool {
|
|
key := strconv.Itoa(fromChain) + "-" + strconv.Itoa(toChain)
|
|
return ccipSupportedPairs[key]
|
|
}
|
|
|
|
// GetQuote returns a bridge quote for 138 <-> 1
|
|
func (p *CCIPProvider) GetQuote(ctx context.Context, req *BridgeRequest) (*BridgeQuote, error) {
|
|
if !p.SupportsRoute(req.FromChain, req.ToChain) {
|
|
return nil, fmt.Errorf("CCIP: unsupported route %d -> %d", req.FromChain, req.ToChain)
|
|
}
|
|
|
|
fee := defaultCCIPFee
|
|
if p.quoteURL != "" {
|
|
body, err := json.Marshal(map[string]interface{}{
|
|
"sourceChain": req.FromChain,
|
|
"destChain": req.ToChain,
|
|
"token": req.FromToken,
|
|
"amount": req.Amount,
|
|
})
|
|
if err == nil {
|
|
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.quoteURL, bytes.NewReader(body))
|
|
if err == nil {
|
|
httpReq.Header.Set("Content-Type", "application/json")
|
|
resp, err := p.client.Do(httpReq)
|
|
if err == nil && resp != nil {
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode == http.StatusOK {
|
|
var r ccipQuoteResponse
|
|
if json.NewDecoder(resp.Body).Decode(&r) == nil && r.Fee != "" {
|
|
fee = r.Fee
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return &BridgeQuote{
|
|
Provider: "CCIP",
|
|
FromChain: req.FromChain,
|
|
ToChain: req.ToChain,
|
|
FromAmount: req.Amount,
|
|
ToAmount: req.Amount,
|
|
Fee: fee,
|
|
EstimatedTime: "5-15 min",
|
|
Route: []BridgeStep{
|
|
{Provider: "CCIP", From: strconv.Itoa(req.FromChain), To: strconv.Itoa(req.ToChain), Type: "bridge"},
|
|
},
|
|
}, nil
|
|
}
|