-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: thanhpp <[email protected]>
- Loading branch information
Showing
13 changed files
with
691 additions
and
10 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
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
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,115 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
|
||
bebop "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bebop" | ||
"github.com/KyberNetwork/logger" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/go-resty/resty/v2" | ||
) | ||
|
||
const ( | ||
headerNameKey = "name" | ||
headerAuthKey = "Authorization" | ||
|
||
pathQuote = "v3/quote" | ||
|
||
errCodeBadRequest = 101 | ||
errCodeInsufficientLiquidity = 102 | ||
errCodeGasCalculationError = 103 | ||
errCodeMinSize = 104 | ||
errCodeTokenNotSupported = 105 | ||
errCodeGasExceedsSize = 106 | ||
errCodeUnexpectedPermitsError = 107 | ||
) | ||
|
||
var ( | ||
ErrRFQFailed = errors.New("rfq failed") | ||
|
||
ErrRFQBadRequest = errors.New("rfq: The API request is invalid - incorrect format or missing required fields") | ||
ErrRFQInsufficientLiquidity = errors.New("rfq: There is insufficient liquidity to serve the requested trade size for the given tokens") | ||
ErrRFQGasCalculationError = errors.New("rfq: There was a failure in calculating the gas estimate for this quotes transaction cost - this can occur when gas is fluctuating wildly") | ||
ErrRFQMinSize = errors.New("rfq: User is trying to trade smaller than the minimum acceptable size for the given tokens") | ||
ErrRFQTokenNotSupported = errors.New("rfq: The token user is trying to trade is not supported by Bebop at the moment") | ||
ErrRFQGasExceedsSize = errors.New("rfq: Execution cost (gas) doesn't cover the trade size") | ||
ErrRFQUnexpectedPermitsError = errors.New("rfq: Unexpected error when a user approves tokens via Permit or Permit2 signatures") | ||
) | ||
|
||
type HTTPClient struct { | ||
config *bebop.HTTPClientConfig | ||
client *resty.Client | ||
} | ||
|
||
func NewHTTPClient(config *bebop.HTTPClientConfig) *HTTPClient { | ||
client := resty.New(). | ||
SetBaseURL(config.BaseURL). | ||
SetTimeout(config.Timeout.Duration). | ||
SetRetryCount(config.RetryCount). | ||
SetHeader(headerNameKey, config.Name). | ||
SetAuthToken(config.Authorization) | ||
|
||
return &HTTPClient{ | ||
config: config, | ||
client: client, | ||
} | ||
} | ||
|
||
func (c *HTTPClient) QuoteSingleOrderResult(ctx context.Context, params bebop.QuoteParams) (bebop.QuoteSingleOrderResult, error) { | ||
// token address case-sensitive | ||
req := c.client.R(). | ||
SetContext(ctx). | ||
// the SellTokens address must follow the HEX format | ||
SetQueryParam(bebop.ParamsSellTokens, common.HexToAddress(params.SellTokens).Hex()). | ||
// the BuyTokens address must follow the HEX format | ||
SetQueryParam(bebop.ParamsBuyTokens, common.HexToAddress(params.BuyTokens).Hex()). | ||
SetQueryParam(bebop.ParamsSellAmounts, params.SellAmounts). | ||
SetQueryParam(bebop.ParamsTakerAddress, params.TakerAddress). | ||
SetQueryParam(bebop.ParamsReceiverAddress, params.ReceiverAddress). | ||
SetQueryParam(bebop.ParamsApproveType, "Standard"). | ||
SetQueryParam(bebop.ParamsSkipValidation, "true"). // not checking balance | ||
SetQueryParam(bebop.ParamsGasLess, "false") // self-execution | ||
|
||
var result bebop.QuoteSingleOrderResult | ||
var fail bebop.QuoteFail | ||
resp, err := req.SetResult(&result).SetError(&fail).Get(pathQuote) | ||
if err != nil { | ||
return bebop.QuoteSingleOrderResult{}, err | ||
} | ||
|
||
respBytes := resp.Body() | ||
_ = json.Unmarshal(respBytes, &result) | ||
_ = json.Unmarshal(respBytes, &fail) | ||
|
||
if !resp.IsSuccess() || fail.Failed() { | ||
return bebop.QuoteSingleOrderResult{}, parseRFQError(fail.Error.ErrorCode, fail.Error.Message) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func parseRFQError(errorCode int, message string) error { | ||
switch errorCode { | ||
case errCodeBadRequest: | ||
return ErrRFQBadRequest | ||
case errCodeInsufficientLiquidity: | ||
return ErrRFQInsufficientLiquidity | ||
case errCodeGasCalculationError: | ||
return ErrRFQGasCalculationError | ||
case errCodeMinSize: | ||
return ErrRFQMinSize | ||
case errCodeTokenNotSupported: | ||
return ErrRFQTokenNotSupported | ||
case errCodeGasExceedsSize: | ||
return ErrRFQGasExceedsSize | ||
case errCodeUnexpectedPermitsError: | ||
return ErrRFQUnexpectedPermitsError | ||
default: | ||
logger. | ||
WithFields(logger.Fields{"client": "bebop", "errorCode": errorCode, "message": message}). | ||
Error("rfq failed") | ||
return ErrRFQFailed | ||
} | ||
} |
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,39 @@ | ||
package client_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"github.com/KyberNetwork/blockchain-toolkit/time/durationjson" | ||
"github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bebop" | ||
"github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bebop/client" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestHTTPClient(t *testing.T) { | ||
t.Skip("has rate-limit for non-authorization requests") | ||
|
||
c := client.NewHTTPClient( | ||
&bebop.HTTPClientConfig{ | ||
BaseURL: "https://api.bebop.xyz/pmm/ethereum", | ||
Timeout: durationjson.Duration{ | ||
Duration: time.Second * 5, | ||
}, | ||
RetryCount: 1, | ||
Name: "", | ||
Authorization: "", | ||
}, | ||
) | ||
|
||
resp, err := c.QuoteSingleOrderResult(context.Background(), bebop.QuoteParams{ | ||
SellTokens: "0xC02aaA39b223fe8D0A0e5C4F27eAD9083C756Cc2", | ||
BuyTokens: "0xdac17F958D2ee523a2206206994597C13D831ec7", | ||
SellAmounts: "100000000000000000", | ||
TakerAddress: "0x5Bad996643a924De21b6b2875c85C33F3c5bBcB6", | ||
ApprovalType: "Standard", | ||
}) | ||
assert.NoError(t, err) | ||
|
||
t.Log(resp.ToSign) | ||
} |
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,11 @@ | ||
package bebop | ||
|
||
import "github.com/KyberNetwork/blockchain-toolkit/time/durationjson" | ||
|
||
type HTTPClientConfig struct { | ||
BaseURL string `mapstructure:"base_url" json:"base_url"` | ||
Timeout durationjson.Duration `mapstructure:"timeout" json:"timeout"` | ||
RetryCount int `mapstructure:"retry_count" json:"retry_count"` | ||
Name string `mapstructure:"name" json:"name"` | ||
Authorization string `mapstructure:"authorization" json:"authorization"` | ||
} |
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,12 @@ | ||
package bebop | ||
|
||
import ( | ||
"math/big" | ||
) | ||
|
||
const DexType = "bebop" | ||
|
||
var ( | ||
zeroBF = big.NewFloat(0) | ||
defaultGas = Gas{Quote: 200000} | ||
) |
Oops, something went wrong.