mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
bybit: Add convert functions (#1993)
* bybit: Add convert functions * Update exchanges/bybit/convert.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * rm exported type and inline it within func dec * Update exchanges/bybit/convert.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/bybit/convert.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * glorious: catch * glorious: int -> int64 * bossking: nits * Update exchanges/bybit/convert.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/bybit/convert.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/bybit/convert.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/bybit/convert_types.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/bybit/convert_types.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/bybit/convert.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * gk: nits v1 * gk: mock what I can * Fix broken things that I broke * gk: nits * Update exchanges/bybit/convert_types.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * thrasher-: nits and bits * linter: fix * thrasher-:nits updoo * cranktakular: nits --------- Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Scott <gloriousCode@users.noreply.github.com> Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
146
exchanges/bybit/convert.go
Normal file
146
exchanges/bybit/convert.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package bybit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
var supportedAccountTypes = []WalletAccountType{Funding, UTA, Spot, Contract, Inverse}
|
||||
|
||||
var (
|
||||
errUnsupportedAccountType = errors.New("unsupported account type")
|
||||
errCurrencyCodesEqual = errors.New("from and to currency codes cannot be equal")
|
||||
errRequestCoinInvalid = errors.New("request coin must match from coin if provided")
|
||||
errQuoteTransactionIDEmpty = errors.New("quoteTransactionID cannot be empty")
|
||||
)
|
||||
|
||||
// GetConvertCoinList returns a list of coins you can convert to/from
|
||||
func (e *Exchange) GetConvertCoinList(ctx context.Context, accountType WalletAccountType, coin currency.Code, isCoinToBuy bool) ([]ConvertCoinResponse, error) {
|
||||
if !slices.Contains(supportedAccountTypes, accountType) {
|
||||
return nil, fmt.Errorf("%w: %q", errUnsupportedAccountType, accountType)
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("accountType", string(accountType))
|
||||
if isCoinToBuy {
|
||||
if coin.IsEmpty() {
|
||||
return nil, currency.ErrCurrencyCodeEmpty
|
||||
}
|
||||
params.Set("coin", coin.Upper().String())
|
||||
params.Set("side", "1")
|
||||
} else {
|
||||
params.Set("side", "0")
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
List []ConvertCoinResponse `json:"coins"`
|
||||
}
|
||||
|
||||
return resp.List, e.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodGet, "/v5/asset/exchange/query-coin-list", params, nil, &resp, defaultEPL)
|
||||
}
|
||||
|
||||
// RequestQuote requests a conversion quote between two coins with the specified parameters.
|
||||
func (e *Exchange) RequestQuote(ctx context.Context, params *RequestQuoteRequest) (*RequestQuoteResponse, error) {
|
||||
if !slices.Contains(supportedAccountTypes, params.AccountType) {
|
||||
return nil, fmt.Errorf("%w: %q", errUnsupportedAccountType, params.AccountType)
|
||||
}
|
||||
if params.FromCoin.IsEmpty() {
|
||||
return nil, fmt.Errorf("%w: `from` coin", currency.ErrCurrencyCodeEmpty)
|
||||
}
|
||||
if params.ToCoin.IsEmpty() {
|
||||
return nil, fmt.Errorf("%w: `to` coin", currency.ErrCurrencyCodeEmpty)
|
||||
}
|
||||
if params.FromCoin.Equal(params.ToCoin) {
|
||||
return nil, errCurrencyCodesEqual
|
||||
}
|
||||
if !params.RequestCoin.IsEmpty() {
|
||||
if !params.RequestCoin.Equal(params.FromCoin) {
|
||||
return nil, errRequestCoinInvalid
|
||||
}
|
||||
} else {
|
||||
params.RequestCoin = params.FromCoin
|
||||
}
|
||||
if params.RequestAmount <= 0 {
|
||||
return nil, fmt.Errorf("%w: %v", order.ErrAmountIsInvalid, params.RequestAmount)
|
||||
}
|
||||
|
||||
params.FromCoin = params.FromCoin.Upper()
|
||||
params.ToCoin = params.ToCoin.Upper()
|
||||
params.RequestCoin = params.RequestCoin.Upper()
|
||||
|
||||
var resp *RequestQuoteResponse
|
||||
return resp, e.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodPost, "/v5/asset/exchange/quote-apply", nil, params, &resp, defaultEPL)
|
||||
}
|
||||
|
||||
// ConfirmQuote confirms a quote transaction and executes the conversion
|
||||
func (e *Exchange) ConfirmQuote(ctx context.Context, quoteTransactionID string) (*ConfirmQuoteResponse, error) {
|
||||
if quoteTransactionID == "" {
|
||||
return nil, errQuoteTransactionIDEmpty
|
||||
}
|
||||
|
||||
payload := struct {
|
||||
QuoteTransactionID string `json:"quoteTxId"`
|
||||
}{
|
||||
QuoteTransactionID: quoteTransactionID,
|
||||
}
|
||||
|
||||
var resp *ConfirmQuoteResponse
|
||||
return resp, e.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodPost, "/v5/asset/exchange/convert-execute", nil, payload, &resp, defaultEPL)
|
||||
}
|
||||
|
||||
// GetConvertStatus retrieves the status of a conversion transaction
|
||||
func (e *Exchange) GetConvertStatus(ctx context.Context, accountType WalletAccountType, quoteTransactionID string) (*ConvertStatusResponse, error) {
|
||||
if !slices.Contains(supportedAccountTypes, accountType) {
|
||||
return nil, fmt.Errorf("%w: %q", errUnsupportedAccountType, accountType)
|
||||
}
|
||||
if quoteTransactionID == "" {
|
||||
return nil, errQuoteTransactionIDEmpty
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("quoteTxId", quoteTransactionID)
|
||||
params.Set("accountType", string(accountType))
|
||||
|
||||
var resp struct {
|
||||
ConvertStatus *ConvertStatusResponse `json:"result"`
|
||||
}
|
||||
return resp.ConvertStatus, e.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodGet, "/v5/asset/exchange/convert-result-query", params, nil, &resp, defaultEPL)
|
||||
}
|
||||
|
||||
// GetConvertHistory retrieves the conversion history.
|
||||
// All params are optional
|
||||
func (e *Exchange) GetConvertHistory(ctx context.Context, accountTypes []WalletAccountType, index, limit uint64) ([]ConvertHistoryResponse, error) {
|
||||
atOut := make([]string, 0, len(accountTypes))
|
||||
for _, accountType := range accountTypes {
|
||||
if !slices.Contains(supportedAccountTypes, accountType) {
|
||||
return nil, fmt.Errorf("%w: %q", errUnsupportedAccountType, accountType)
|
||||
}
|
||||
atOut = append(atOut, string(accountType))
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
if len(atOut) > 0 {
|
||||
params.Add("accountType", strings.Join(atOut, ","))
|
||||
}
|
||||
if index != 0 {
|
||||
params.Set("index", strconv.FormatUint(index, 10))
|
||||
}
|
||||
if limit != 0 {
|
||||
params.Set("limit", strconv.FormatUint(limit, 10))
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
List []ConvertHistoryResponse `json:"list"`
|
||||
}
|
||||
return resp.List, e.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodGet, "/v5/asset/exchange/query-convert-history", params, nil, &resp, defaultEPL)
|
||||
}
|
||||
151
exchanges/bybit/convert_test.go
Normal file
151
exchanges/bybit/convert_test.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package bybit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||
"github.com/thrasher-corp/gocryptotrader/types"
|
||||
)
|
||||
|
||||
func TestGetConvertCoinList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := e.GetConvertCoinList(t.Context(), "", currency.EMPTYCODE, true)
|
||||
assert.ErrorIs(t, err, errUnsupportedAccountType)
|
||||
|
||||
_, err = e.GetConvertCoinList(t.Context(), UTA, currency.EMPTYCODE, true)
|
||||
assert.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
||||
|
||||
if !mockTests {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||
}
|
||||
|
||||
buylist, err := e.GetConvertCoinList(t.Context(), UTA, currency.USDT, true)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, buylist)
|
||||
|
||||
sellList, err := e.GetConvertCoinList(t.Context(), UTA, currency.EMPTYCODE, false)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, sellList)
|
||||
}
|
||||
|
||||
func TestRequestQuote(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := e.RequestQuote(t.Context(), &RequestQuoteRequest{})
|
||||
assert.ErrorIs(t, err, errUnsupportedAccountType)
|
||||
|
||||
_, err = e.RequestQuote(t.Context(), &RequestQuoteRequest{AccountType: UTA})
|
||||
assert.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
||||
|
||||
_, err = e.RequestQuote(t.Context(), &RequestQuoteRequest{AccountType: UTA, FromCoin: currency.BTC})
|
||||
assert.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
||||
|
||||
_, err = e.RequestQuote(t.Context(), &RequestQuoteRequest{
|
||||
AccountType: UTA,
|
||||
FromCoin: currency.BTC,
|
||||
ToCoin: currency.BTC,
|
||||
})
|
||||
assert.ErrorIs(t, err, errCurrencyCodesEqual)
|
||||
|
||||
_, err = e.RequestQuote(t.Context(), &RequestQuoteRequest{
|
||||
AccountType: UTA,
|
||||
FromCoin: currency.BTC,
|
||||
ToCoin: currency.USDT,
|
||||
RequestCoin: currency.WOO,
|
||||
})
|
||||
assert.ErrorIs(t, err, errRequestCoinInvalid)
|
||||
|
||||
_, err = e.RequestQuote(t.Context(), &RequestQuoteRequest{
|
||||
AccountType: UTA,
|
||||
FromCoin: currency.BTC,
|
||||
ToCoin: currency.USDT,
|
||||
})
|
||||
assert.ErrorIs(t, err, order.ErrAmountIsInvalid)
|
||||
|
||||
if !mockTests {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||
}
|
||||
|
||||
quote, err := e.RequestQuote(t.Context(), &RequestQuoteRequest{
|
||||
AccountType: UTA,
|
||||
FromCoin: currency.XRP,
|
||||
ToCoin: currency.USDT,
|
||||
RequestAmount: 0.0088,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, quote.QuoteTransactionID)
|
||||
}
|
||||
|
||||
func TestConfirmQuote(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := e.ConfirmQuote(t.Context(), "")
|
||||
assert.ErrorIs(t, err, errQuoteTransactionIDEmpty)
|
||||
|
||||
if !mockTests {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||
}
|
||||
|
||||
quote, err := e.ConfirmQuote(t.Context(), "10175108571334212336947200")
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, quote.QuoteTransactionID)
|
||||
}
|
||||
|
||||
func TestGetConvertStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := e.GetConvertStatus(t.Context(), "", "")
|
||||
assert.ErrorIs(t, err, errUnsupportedAccountType)
|
||||
|
||||
_, err = e.GetConvertStatus(t.Context(), UTA, "")
|
||||
assert.ErrorIs(t, err, errQuoteTransactionIDEmpty)
|
||||
|
||||
if !mockTests {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||
}
|
||||
|
||||
status, err := e.GetConvertStatus(t.Context(), UTA, "10414247553864074960678912")
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, status)
|
||||
}
|
||||
|
||||
func TestGetConvertHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := e.GetConvertHistory(t.Context(), []WalletAccountType{""}, 0, 0)
|
||||
assert.ErrorIs(t, err, errUnsupportedAccountType)
|
||||
|
||||
if !mockTests {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||
}
|
||||
|
||||
history, err := e.GetConvertHistory(t.Context(), []WalletAccountType{UTA}, 0, 0)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, history)
|
||||
|
||||
if mockTests {
|
||||
require.Equal(t, 4, len(history), "GetConvertHistory must return 4 items in mock test")
|
||||
exp := ConvertHistoryResponse{
|
||||
AccountType: UTA,
|
||||
ExchangeTransactionID: "104231555340214158196736",
|
||||
UserID: "74199870",
|
||||
FromCoin: currency.NewCode("UXLINK"),
|
||||
FromCoinType: "crypto",
|
||||
FromAmount: 7.9952,
|
||||
ToCoin: currency.USDT,
|
||||
ToCoinType: "crypto",
|
||||
ToAmount: 2.84509740190888,
|
||||
ExchangeStatus: "success",
|
||||
ExtendedInfo: ExtendedInfoHistoryResponse{},
|
||||
ConvertRate: 0.35585068565,
|
||||
CreatedAt: types.Time(time.UnixMilli(1754880224953)),
|
||||
}
|
||||
require.Equal(t, exp, history[0])
|
||||
}
|
||||
}
|
||||
117
exchanges/bybit/convert_types.go
Normal file
117
exchanges/bybit/convert_types.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package bybit
|
||||
|
||||
import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
||||
"github.com/thrasher-corp/gocryptotrader/types"
|
||||
)
|
||||
|
||||
// WalletAccountTypes
|
||||
const (
|
||||
Funding WalletAccountType = "eb_convert_funding"
|
||||
UTA WalletAccountType = "eb_convert_uta"
|
||||
Spot WalletAccountType = "eb_convert_spot"
|
||||
Contract WalletAccountType = "eb_convert_contract"
|
||||
Inverse WalletAccountType = "eb_convert_inverse"
|
||||
)
|
||||
|
||||
// WalletAccountType represents the different types of wallet accounts
|
||||
type WalletAccountType string
|
||||
|
||||
// ConvertCoinResponse represents a coin that can be converted
|
||||
type ConvertCoinResponse struct {
|
||||
Coin currency.Code `json:"coin"`
|
||||
FullName string `json:"fullName"`
|
||||
Icon string `json:"icon"`
|
||||
IconNight string `json:"iconNight"`
|
||||
AccuracyLength uint8 `json:"accuracyLength"`
|
||||
CoinType string `json:"coinType"`
|
||||
Balance types.Number `json:"balance"`
|
||||
BalanceInUSDT types.Number `json:"uBalance"`
|
||||
SingleFromMinLimit types.Number `json:"singleFromMinLimit"` // The minimum amount of fromCoin per transaction
|
||||
SingleFromMaxLimit types.Number `json:"singleFromMaxLimit"` // The maximum amount of fromCoin per transaction
|
||||
DisableFrom bool `json:"disableFrom"` // true: the coin is disabled to be fromCoin, false: the coin is allowed to be fromCoin
|
||||
DisableTo bool `json:"disableTo"` // true: the coin is disabled to be toCoin, false: the coin is allowed to be toCoin
|
||||
TimePeriod int64 `json:"timePeriod"`
|
||||
SingleToMinLimit types.Number `json:"singleToMinLimit"`
|
||||
SingleToMaxLimit types.Number `json:"singleToMaxLimit"`
|
||||
DailyFromMinLimit types.Number `json:"dailyFromMinLimit"`
|
||||
DailyFromMaxLimit types.Number `json:"dailyFromMaxLimit"`
|
||||
DailyToMinLimit types.Number `json:"dailyToMinLimit"`
|
||||
DailyToMaxLimit types.Number `json:"dailyToMaxLimit"`
|
||||
}
|
||||
|
||||
// RequestQuoteRequest holds the parameters for requesting a quote
|
||||
type RequestQuoteRequest struct {
|
||||
RequestID string `json:"requestId,omitempty"`
|
||||
AccountType WalletAccountType `json:"accountType"`
|
||||
FromCoin currency.Code `json:"fromCoin"`
|
||||
ToCoin currency.Code `json:"toCoin"`
|
||||
RequestCoin currency.Code `json:"requestCoin"` // Must be same as FromCoin
|
||||
RequestAmount types.Number `json:"requestAmount"`
|
||||
FromCoinType string `json:"fromCoinType,omitempty"` // "crypto"
|
||||
ToCoinType string `json:"toCoinType,omitempty"` // "crypto"
|
||||
ParamType string `json:"paramType,omitempty"` // "opFrom", mainly used for API broker user
|
||||
ParamValue string `json:"paramValue,omitempty"` // Broker ID, mainly used for API broker user
|
||||
}
|
||||
|
||||
// RequestQuoteResponse represents a response for a request a quote
|
||||
type RequestQuoteResponse struct {
|
||||
QuoteTransactionID string `json:"quoteTxId"` // Quote transaction ID. It is system generated, and it is used to confirm quote and query the result of transaction
|
||||
ExchangeRate types.Number `json:"exchangeRate"`
|
||||
FromCoin currency.Code `json:"fromCoin"`
|
||||
FromCoinType string `json:"fromCoinType"`
|
||||
ToCoin currency.Code `json:"toCoin"`
|
||||
ToCoinType string `json:"toCoinType"`
|
||||
FromAmount types.Number `json:"fromAmount"`
|
||||
ToAmount types.Number `json:"toAmount"`
|
||||
ExpiredTime types.Time `json:"expiredTime"` // The expiry time for this quote (15 seconds)
|
||||
RequestID string `json:"requestId"`
|
||||
ExtendedTaxAndFee json.RawMessage `json:"extTaxAndFee"` // Compliance-related field. Currently returns an empty array, which may be used in the future
|
||||
}
|
||||
|
||||
// ConfirmQuoteResponse represents a response for confirming a quote
|
||||
type ConfirmQuoteResponse struct {
|
||||
ExchangeStatus string `json:"exchangeStatus"`
|
||||
QuoteTransactionID string `json:"quoteTxId"`
|
||||
}
|
||||
|
||||
// ConvertStatusResponse represents the response for a conversion status query
|
||||
type ConvertStatusResponse struct {
|
||||
AccountType WalletAccountType `json:"accountType"`
|
||||
ExchangeTransactionID string `json:"exchangeTxId"`
|
||||
UserID string `json:"userId"`
|
||||
FromCoin currency.Code `json:"fromCoin"`
|
||||
FromCoinType string `json:"fromCoinType"`
|
||||
FromAmount types.Number `json:"fromAmount"`
|
||||
ToCoin currency.Code `json:"toCoin"`
|
||||
ToCoinType string `json:"toCoinType"`
|
||||
ToAmount types.Number `json:"toAmount"`
|
||||
ExchangeStatus string `json:"exchangeStatus"`
|
||||
ExtendedInfo json.RawMessage `json:"extInfo"` // Reserved field, ignored for now
|
||||
ConvertRate types.Number `json:"convertRate"`
|
||||
CreatedAt types.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
// ConvertHistoryResponse represents a response for conversion history
|
||||
type ConvertHistoryResponse struct {
|
||||
AccountType WalletAccountType `json:"accountType"`
|
||||
ExchangeTransactionID string `json:"exchangeTxId"`
|
||||
UserID string `json:"userId"`
|
||||
FromCoin currency.Code `json:"fromCoin"`
|
||||
FromCoinType string `json:"fromCoinType"`
|
||||
FromAmount types.Number `json:"fromAmount"`
|
||||
ToCoin currency.Code `json:"toCoin"`
|
||||
ToCoinType string `json:"toCoinType"`
|
||||
ToAmount types.Number `json:"toAmount"`
|
||||
ExchangeStatus string `json:"exchangeStatus"`
|
||||
ExtendedInfo ExtendedInfoHistoryResponse `json:"extInfo"`
|
||||
ConvertRate types.Number `json:"convertRate"`
|
||||
CreatedAt types.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
// ExtendedInfoHistoryResponse represents the extended information for conversion history
|
||||
type ExtendedInfoHistoryResponse struct {
|
||||
ParamType string `json:"paramType"`
|
||||
ParamValue string `json:"paramValue"`
|
||||
}
|
||||
498
exchanges/bybit/testdata/http.json
vendored
498
exchanges/bybit/testdata/http.json
vendored
@@ -10676,6 +10676,89 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/exchange/convert-execute": {
|
||||
"POST": [
|
||||
{
|
||||
"data": {
|
||||
"result": {
|
||||
"exchangeStatus": "processing",
|
||||
"quoteTxId": "10175108571334212336947200"
|
||||
},
|
||||
"retCode": 0,
|
||||
"retExtInfo": {},
|
||||
"retMsg": "ok",
|
||||
"time": 1758693503803
|
||||
},
|
||||
"queryString": "",
|
||||
"bodyParams": "{\"quoteTxId\":\"10175108571334212336947200\"}",
|
||||
"headers": {
|
||||
"Content-Type": [
|
||||
"application/json"
|
||||
],
|
||||
"X-Bapi-Api-Key": [
|
||||
""
|
||||
],
|
||||
"X-Bapi-Recv-Window": [
|
||||
"5000"
|
||||
],
|
||||
"X-Bapi-Sign": [
|
||||
"8ac32a4d321aae758172178e0626903e90960372d0e8361e6920f5e7c1e2b1d4"
|
||||
],
|
||||
"X-Bapi-Timestamp": [
|
||||
"1758693503260"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/exchange/convert-result-query": {
|
||||
"GET": [
|
||||
{
|
||||
"data": {
|
||||
"result": {
|
||||
"result": {
|
||||
"accountType": "eb_convert_uta",
|
||||
"convertRate": "0.046765815395",
|
||||
"createdAt": "1754528298061",
|
||||
"exchangeStatus": "success",
|
||||
"exchangeTxId": "10414247553864074960678912",
|
||||
"extInfo": {},
|
||||
"fromAmount": "49.96",
|
||||
"fromCoin": "PIRATE",
|
||||
"fromCoinType": "crypto",
|
||||
"toAmount": "2.3364201371342",
|
||||
"toCoin": "USDT",
|
||||
"toCoinType": "crypto",
|
||||
"userId": "74199870"
|
||||
}
|
||||
},
|
||||
"retCode": 0,
|
||||
"retExtInfo": {},
|
||||
"retMsg": "ok",
|
||||
"time": 1758260135835
|
||||
},
|
||||
"queryString": "accountType=eb_convert_uta\u0026quoteTxId=10414247553864074960678912",
|
||||
"bodyParams": "",
|
||||
"headers": {
|
||||
"Content-Type": [
|
||||
"application/x-www-form-urlencoded"
|
||||
],
|
||||
"X-Bapi-Api-Key": [
|
||||
""
|
||||
],
|
||||
"X-Bapi-Recv-Window": [
|
||||
"5000"
|
||||
],
|
||||
"X-Bapi-Sign": [
|
||||
"af98ed1cf332f7d3fbdbbeecf47e5e9aae011388ac6bf40a73b3337843124f2e"
|
||||
],
|
||||
"X-Bapi-Timestamp": [
|
||||
"1758260135697"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/exchange/order-record": {
|
||||
"GET": [
|
||||
{
|
||||
@@ -10711,6 +10794,421 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/exchange/query-coin-list": {
|
||||
"GET": [
|
||||
{
|
||||
"data": {
|
||||
"result": {
|
||||
"coins": [
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "",
|
||||
"coin": "AGLD",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "AGLD",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/71c30ccc0c343d2f6ab830262ac7a5f8.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/8eb2f2348cc917081be4c28b797bd930.svg",
|
||||
"singleFromMaxLimit": "15200",
|
||||
"singleFromMinLimit": "0.015",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": ""
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "",
|
||||
"coin": "AGLA",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "AGLA",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/1857d5971bed49d9b411032f54243128.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/5bc128beb4db5e6091b3c4211e7e4c4e.svg",
|
||||
"singleFromMaxLimit": "9907900",
|
||||
"singleFromMinLimit": "10",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": ""
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "",
|
||||
"coin": "NEAR",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "NEAR",
|
||||
"icon": "https://www.bybit.com/bycsi-root/app/assets/token/3fafab371c0c1e42362813593034ee42.svg",
|
||||
"iconNight": "https://www.bybit.com/bycsi-root/app/assets/token/3fafab371c0c1e42362813593034ee42.svg",
|
||||
"singleFromMaxLimit": "4000",
|
||||
"singleFromMinLimit": "0.004",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": ""
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "",
|
||||
"coin": "AIOZ",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "AIOZ",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/603ff078bc4c032bc93bbcba375008ac.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/1ff40bb0bdcaae69fdc0cdb27b4d769d.svg",
|
||||
"singleFromMaxLimit": "30400",
|
||||
"singleFromMinLimit": "0.03",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": ""
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "",
|
||||
"coin": "WLD",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "WLD",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/ba1f955e2b609920ebc2fce92feaa006.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/ba1f955e2b609920ebc2fce92feaa006.svg",
|
||||
"singleFromMaxLimit": "7000",
|
||||
"singleFromMinLimit": "0.007",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"retCode": 0,
|
||||
"retExtInfo": {},
|
||||
"retMsg": "ok",
|
||||
"time": 1758256916514
|
||||
},
|
||||
"queryString": "accountType=eb_convert_uta\u0026coin=USDT\u0026side=1",
|
||||
"bodyParams": "",
|
||||
"headers": {
|
||||
"Content-Type": [
|
||||
"application/x-www-form-urlencoded"
|
||||
],
|
||||
"X-Bapi-Api-Key": [
|
||||
""
|
||||
],
|
||||
"X-Bapi-Recv-Window": [
|
||||
"5000"
|
||||
],
|
||||
"X-Bapi-Sign": [
|
||||
"3b10c29cba3b135d12d1ebda5f752976c84c3f443350f3719e517a72cb262292"
|
||||
],
|
||||
"X-Bapi-Timestamp": [
|
||||
"1758259225338"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"result": {
|
||||
"coins": [
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "0",
|
||||
"coin": "AGLD",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "AGLD",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/71c30ccc0c343d2f6ab830262ac7a5f8.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/8eb2f2348cc917081be4c28b797bd930.svg",
|
||||
"singleFromMaxLimit": "15200",
|
||||
"singleFromMinLimit": "0.015",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": "0"
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "",
|
||||
"coin": "AGLA",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "AGLA",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/1857d5971bed49d9b411032f54243128.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/5bc128beb4db5e6091b3c4211e7e4c4e.svg",
|
||||
"singleFromMaxLimit": "9907900",
|
||||
"singleFromMinLimit": "10",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": ""
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "0",
|
||||
"coin": "NEAR",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "NEAR",
|
||||
"icon": "https://www.bybit.com/bycsi-root/app/assets/token/3fafab371c0c1e42362813593034ee42.svg",
|
||||
"iconNight": "https://www.bybit.com/bycsi-root/app/assets/token/3fafab371c0c1e42362813593034ee42.svg",
|
||||
"singleFromMaxLimit": "4000",
|
||||
"singleFromMinLimit": "0.004",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": "0"
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "0.0052",
|
||||
"coin": "AIOZ",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "AIOZ",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/603ff078bc4c032bc93bbcba375008ac.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/1ff40bb0bdcaae69fdc0cdb27b4d769d.svg",
|
||||
"singleFromMaxLimit": "30400",
|
||||
"singleFromMinLimit": "0.03",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": "0.0017732"
|
||||
},
|
||||
{
|
||||
"accuracyLength": 8,
|
||||
"balance": "0",
|
||||
"coin": "WLD",
|
||||
"coinType": "crypto",
|
||||
"dailyFromMaxLimit": "0",
|
||||
"dailyFromMinLimit": "0",
|
||||
"dailyToMaxLimit": "0",
|
||||
"dailyToMinLimit": "0",
|
||||
"disableFrom": false,
|
||||
"disableTo": false,
|
||||
"fullName": "WLD",
|
||||
"icon": "https://s1.bycsi.com/app/assets/token/ba1f955e2b609920ebc2fce92feaa006.svg",
|
||||
"iconNight": "https://s1.bycsi.com/app/assets/token/ba1f955e2b609920ebc2fce92feaa006.svg",
|
||||
"singleFromMaxLimit": "7000",
|
||||
"singleFromMinLimit": "0.007",
|
||||
"singleToMaxLimit": "0",
|
||||
"singleToMinLimit": "0",
|
||||
"timePeriod": 0,
|
||||
"uBalance": "0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"retCode": 0,
|
||||
"retExtInfo": {},
|
||||
"retMsg": "ok",
|
||||
"time": 1758256841574
|
||||
},
|
||||
"queryString": "accountType=eb_convert_uta\u0026side=0",
|
||||
"bodyParams": "",
|
||||
"headers": {
|
||||
"Content-Type": [
|
||||
"application/x-www-form-urlencoded"
|
||||
],
|
||||
"X-Bapi-Api-Key": [
|
||||
""
|
||||
],
|
||||
"X-Bapi-Recv-Window": [
|
||||
"5000"
|
||||
],
|
||||
"X-Bapi-Sign": [
|
||||
"3e2ae23929ba5d2855dc20cb0ad81d6b975411ffc727ce52f3f9e21c966fbe0e"
|
||||
],
|
||||
"X-Bapi-Timestamp": [
|
||||
"1758259225549"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/exchange/query-convert-history": {
|
||||
"GET": [
|
||||
{
|
||||
"data": {
|
||||
"result": {
|
||||
"list": [
|
||||
{
|
||||
"accountType": "eb_convert_uta",
|
||||
"convertRate": "0.35585068565",
|
||||
"createdAt": "1754880224953",
|
||||
"exchangeStatus": "success",
|
||||
"exchangeTxId": "104231555340214158196736",
|
||||
"extInfo": {},
|
||||
"fromAmount": "7.9952",
|
||||
"fromCoin": "UXLINK",
|
||||
"fromCoinType": "crypto",
|
||||
"toAmount": "2.84509740190888",
|
||||
"toCoin": "USDT",
|
||||
"toCoinType": "crypto",
|
||||
"userId": "74199870"
|
||||
},
|
||||
{
|
||||
"accountType": "eb_convert_uta",
|
||||
"convertRate": "0.76800370605",
|
||||
"createdAt": "1754880224437",
|
||||
"exchangeStatus": "success",
|
||||
"exchangeTxId": "10164127555340212031606784",
|
||||
"extInfo": {},
|
||||
"fromAmount": "1.002",
|
||||
"fromCoin": "ME",
|
||||
"fromCoinType": "crypto",
|
||||
"toAmount": "0.7695397134621",
|
||||
"toCoin": "USDT",
|
||||
"toCoinType": "crypto",
|
||||
"userId": "74199870"
|
||||
},
|
||||
{
|
||||
"accountType": "eb_convert_uta",
|
||||
"convertRate": "1.470836214",
|
||||
"createdAt": "1754880223928",
|
||||
"exchangeStatus": "success",
|
||||
"exchangeTxId": "101214251555340209864749056",
|
||||
"extInfo": {},
|
||||
"fromAmount": "1.9984",
|
||||
"fromCoin": "VIRTUAL",
|
||||
"fromCoinType": "crypto",
|
||||
"toAmount": "2.9393190900576",
|
||||
"toCoin": "USDT",
|
||||
"toCoinType": "crypto",
|
||||
"userId": "74199870"
|
||||
},
|
||||
{
|
||||
"accountType": "eb_convert_uta",
|
||||
"convertRate": "0.046765815395",
|
||||
"createdAt": "1754528298061",
|
||||
"exchangeStatus": "success",
|
||||
"exchangeTxId": "10414247553864074960678912",
|
||||
"extInfo": {},
|
||||
"fromAmount": "49.96",
|
||||
"fromCoin": "PIRATE",
|
||||
"fromCoinType": "crypto",
|
||||
"toAmount": "2.3364201371342",
|
||||
"toCoin": "USDT",
|
||||
"toCoinType": "crypto",
|
||||
"userId": "74199870"
|
||||
}
|
||||
]
|
||||
},
|
||||
"retCode": 0,
|
||||
"retExtInfo": {},
|
||||
"retMsg": "ok",
|
||||
"time": 1758260485735
|
||||
},
|
||||
"queryString": "accountType=eb_convert_uta",
|
||||
"bodyParams": "",
|
||||
"headers": {
|
||||
"Content-Type": [
|
||||
"application/x-www-form-urlencoded"
|
||||
],
|
||||
"X-Bapi-Api-Key": [
|
||||
""
|
||||
],
|
||||
"X-Bapi-Recv-Window": [
|
||||
"5000"
|
||||
],
|
||||
"X-Bapi-Sign": [
|
||||
"d48d942ee6ed14a088beb153bc0d069048834a983ddf1258b3512e90a5980ffb"
|
||||
],
|
||||
"X-Bapi-Timestamp": [
|
||||
"1758260485632"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/exchange/quote-apply": {
|
||||
"POST": [
|
||||
{
|
||||
"data": {
|
||||
"result": {
|
||||
"exchangeRate": "2.848499537750000000",
|
||||
"expiredTime": "1758693506127",
|
||||
"extTaxAndFee": [],
|
||||
"fromAmount": "0.0088",
|
||||
"fromCoin": "XRP",
|
||||
"fromCoinType": "crypto",
|
||||
"quoteTxId": "10175108571334212336947200",
|
||||
"requestId": "",
|
||||
"toAmount": "0.0250667959322",
|
||||
"toCoin": "USDT",
|
||||
"toCoinType": "crypto"
|
||||
},
|
||||
"retCode": 0,
|
||||
"retExtInfo": {},
|
||||
"retMsg": "ok",
|
||||
"time": 1758693491155
|
||||
},
|
||||
"queryString": "",
|
||||
"bodyParams": "{\"accountType\":\"eb_convert_uta\",\"fromCoin\":\"XRP\",\"toCoin\":\"USDT\",\"requestAmount\":\"0.0088\",\"requestCoin\":\"XRP\"}",
|
||||
"headers": {
|
||||
"Content-Type": [
|
||||
"application/json"
|
||||
],
|
||||
"X-Bapi-Api-Key": [
|
||||
""
|
||||
],
|
||||
"X-Bapi-Recv-Window": [
|
||||
"5000"
|
||||
],
|
||||
"X-Bapi-Sign": [
|
||||
"48767e64f637c452bc48304d368f214a80ff31aa3b014e60eb7f384b18b25240"
|
||||
],
|
||||
"X-Bapi-Timestamp": [
|
||||
"1758693491006"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v5/asset/settlement-record": {
|
||||
"GET": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user