-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
name: CI | ||
|
||
on: | ||
pull_request: | ||
push: | ||
branches: | ||
- master | ||
|
||
jobs: | ||
test: | ||
strategy: | ||
matrix: | ||
go-version: [1.22.x] | ||
platform: [ubuntu-latest] | ||
runs-on: ${{ matrix.platform }} | ||
steps: | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 1 | ||
- name: Test | ||
run: go test ./... | ||
lint: | ||
strategy: | ||
matrix: | ||
go-version: [1.22.x] | ||
platform: [ubuntu-latest] | ||
runs-on: ${{ matrix.platform }} | ||
steps: | ||
- uses: actions/checkout@master | ||
with: | ||
fetch-depth: 1 | ||
- uses: reviewdog/action-golangci-lint@v2 | ||
staticcheck: | ||
strategy: | ||
matrix: | ||
go-version: [ 1.22.x ] | ||
platform: [ ubuntu-latest ] | ||
runs-on: ${{ matrix.platform }} | ||
steps: | ||
- uses: actions/checkout@v1 | ||
with: | ||
fetch-depth: 1 | ||
- uses: dominikh/[email protected] | ||
with: | ||
version: "2022.1.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Squid Router | ||
|
||
This repository contains Go bindings for the [0xSquid](https://www.squidrouter.com/) API. | ||
|
||
Currently supported versions of the API: | ||
- [v1](https://squidrouter.readme.io/reference/getting-started-with-your-api-1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/project-blanc/go-squid-router | ||
|
||
go 1.21.7 | ||
|
||
require github.com/pkg/errors v0.9.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package v1 | ||
|
||
import ( | ||
"encoding/json" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
type Client struct { | ||
cli *http.Client | ||
} | ||
|
||
func NewClient() *Client { | ||
return &Client{ | ||
cli: &http.Client{}, // @TODO inject | ||
} | ||
} | ||
|
||
// Route calls the route endpoint returning route information and the call data object | ||
func (c *Client) Route(params RouteRequestParameters) (*RouteResponse, error) { | ||
if params.Slippage <= 0.0 || params.Slippage > 99.99 { | ||
return nil, errors.New("slippage must be > 0 and < 99.99") | ||
} | ||
|
||
resp, err := c.cli.Get("https://api.0xsquid.com/v1/route?" + params.ToQuery().Encode()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
return nil, errorForResponse(resp.Body) | ||
} | ||
|
||
buff, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to read response body") | ||
} | ||
|
||
rr := map[string]*RouteResponse{} | ||
err = json.Unmarshal(buff, &rr) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to unmarshal response body") | ||
} | ||
|
||
return rr["route"], nil | ||
} | ||
|
||
func errorForResponse(body io.Reader) error { | ||
buff, err := io.ReadAll(body) | ||
if err != nil { | ||
return errors.Wrap(err, "failed to read error response body") | ||
} | ||
|
||
er := map[string][]ErrorResponse{} | ||
err = json.Unmarshal(buff, &er) | ||
if err != nil { | ||
return errors.Wrap(err, "failed to unmarshal error response body") | ||
} | ||
|
||
return er["errors"][0].Err() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package v1 | ||
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
"strconv" | ||
) | ||
|
||
type CallType int | ||
|
||
const ( | ||
CallTypeDefault CallType = iota | ||
CallTypeFullTokenBalance | ||
CallTypeFullNativeBalance | ||
CollectTokenBalance | ||
) | ||
|
||
type CustomContractCall struct { | ||
CallType CallType | ||
Target string | ||
Value string | ||
CallData string | ||
EstimatedGas string | ||
Payload struct { | ||
TokenAddress string | ||
InputPosition string | ||
} | ||
} | ||
|
||
type RouteRequestParameters struct { | ||
// FromChain is the from chain id | ||
FromChain string | ||
// ToChain is the to chain id | ||
ToChain string | ||
// FromToken is the from token address | ||
FromToken string | ||
// ToToken is the to token address | ||
ToToken string | ||
// FromAmount is the amount to be sent from To Chain | ||
FromAmount string | ||
// FromAddress EVM address for EVM to Cosmos, and Cosmos address for Cosmos to EVM. | ||
FromAddress string | ||
// ToAddress is the ToChain recipient address | ||
ToAddress string | ||
// Slippage must be between 0 and 99.99 | ||
Slippage float64 | ||
// QuoteOnly returns only the route quote and excludes all call data | ||
QuoteOnly bool | ||
// EnableExpress enables express feature | ||
EnableExpress bool | ||
// CustomContractCalls array of custom contract calls | ||
CustomContractCalls []CustomContractCall | ||
// Prefer array of supported DEXs for this trade | ||
Prefer []string | ||
// ReceiveGasOnDestination receive gas on destination chain | ||
ReceiveGasOnDestination bool | ||
} | ||
|
||
func (p RouteRequestParameters) ToQuery() url.Values { | ||
query := url.Values{} | ||
query.Add("fromChain", p.FromChain) | ||
query.Add("toChain", p.ToChain) | ||
query.Add("fromToken", p.FromToken) | ||
query.Add("toToken", p.ToToken) | ||
query.Add("fromAmount", p.FromAmount) | ||
|
||
if p.FromAddress != "" { | ||
query.Add("fromAddress", p.FromAddress) | ||
} | ||
|
||
query.Add("toAddress", p.ToAddress) | ||
|
||
query.Add("slippage", strconv.FormatFloat(p.Slippage, 'f', -1, 64)) | ||
query.Add("quoteOnly", strconv.FormatBool(p.QuoteOnly)) | ||
query.Add("enableExpress", strconv.FormatBool(p.EnableExpress)) | ||
|
||
for i, call := range p.CustomContractCalls { | ||
query.Add(fmt.Sprintf("customContractCalls[%d][callType]", i), strconv.Itoa(int(call.CallType))) | ||
query.Add(fmt.Sprintf("customContractCalls[%d][target]", i), call.Target) | ||
query.Add(fmt.Sprintf("customContractCalls[%d][value]", i), call.Value) | ||
query.Add(fmt.Sprintf("customContractCalls[%d][callData]", i), call.CallData) | ||
query.Add(fmt.Sprintf("customContractCalls[%d][estimatedGas]", i), call.EstimatedGas) | ||
query.Add(fmt.Sprintf("customContractCalls[%d][payload][tokenAddress]", i), call.Payload.TokenAddress) | ||
query.Add(fmt.Sprintf("customContractCalls[%d][payload][inputPos]", i), call.Payload.InputPosition) | ||
} | ||
|
||
for i, prefer := range p.Prefer { | ||
query.Add(fmt.Sprintf("prefer[%d]", i), prefer) | ||
} | ||
|
||
query.Add("receiveGasOnDestination", strconv.FormatBool(p.ReceiveGasOnDestination)) | ||
|
||
return query | ||
} | ||
|
||
type TransactionRequest struct { | ||
TargetAddress string `json:"targetAddress"` | ||
Data string `json:"data"` | ||
Value string `json:"value"` | ||
GasLimit string `json:"gasLimit"` | ||
GasPrice string `json:"gasPrice"` | ||
MaxFeePerGas string `json:"maxFeePerGas"` | ||
MaxPriorityFeePerGas string `json:"maxPriorityFeePerGas"` | ||
} | ||
|
||
type RouteResponse struct { | ||
// @TODO estimate | ||
// @TodO params | ||
TransactionRequest TransactionRequest `json:"transactionRequest"` | ||
} | ||
|
||
type ErrorResponse struct { | ||
Message string `json:"message"` | ||
ErrorType string `json:"errorType"` | ||
} | ||
|
||
func (e ErrorResponse) Err() error { | ||
return fmt.Errorf("squid err: %s message: %s", e.ErrorType, e.Message) | ||
} |