Skip to content

Conversation

shazbert
Copy link
Collaborator

@shazbert shazbert commented Aug 7, 2025

PR Description

Adds convert functionality

Fixes # (issue)

Type of change

Please delete options that are not relevant and add an x in [] as item is complete.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How has this been tested

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration and
also consider improving test coverage whilst working on a certain feature or package.

  • go test ./... -race
  • golangci-lint run
  • Test X

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation and regenerated documentation via the documentation tool
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally and on Github Actions with my changes
  • Any dependent changes have been merged and published in downstream modules

@shazbert shazbert self-assigned this Aug 7, 2025
@Copilot Copilot AI review requested due to automatic review settings August 7, 2025 01:12
@shazbert shazbert added the review me This pull request is ready for review label Aug 7, 2025
Copilot

This comment was marked as outdated.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link

codecov bot commented Aug 7, 2025

Codecov Report

❌ Patch coverage is 51.51515% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.79%. Comparing base (90187a3) to head (5ce194b).
⚠️ Report is 17 commits behind head on master.

Files with missing lines Patch % Lines
exchanges/bybit/convert.go 51.51% 48 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1993      +/-   ##
==========================================
+ Coverage   39.65%   39.79%   +0.13%     
==========================================
  Files         432      434       +2     
  Lines      171928   172128     +200     
==========================================
+ Hits        68186    68500     +314     
+ Misses      96616    96476     -140     
- Partials     7126     7152      +26     
Files with missing lines Coverage Δ
exchanges/bybit/convert.go 51.51% <51.51%> (ø)

... and 59 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@gloriousCode gloriousCode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a lot of comments, but its not much to change. THANKS SHAZBERT

type WalletAccountType string

// Coin represents a coin that can be converted
type Coin struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename fields according to our guidelines

}

// RequestAQuoteParams holds the parameters for requesting a quote
type RequestAQuoteParams struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is the exception, I think RequestAQuoteRequest might aggravate people

return nil, fmt.Errorf("amount %w", order.ErrAmountIsInvalid)
}

payload := &struct {
Copy link
Collaborator

@gloriousCode gloriousCode Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

y u do dis? This takes up way more space and is unnecessary I HATE IT. Already taking up extra space by not putting API types in _types

// RequestAQuoteParams holds the parameters for requesting a quote
type RequestAQuoteParams struct {
	// Required fields
	AccountType WalletAccountType `json:"accountType"`
	From        currency.Code     `json:"fromCoin"`             // Convert from coin (coin to sell)
	To          currency.Code     `json:"toCoin"`               // Convert to coin (coin to buy)
	Amount      float64           `json:"requestAmount,string"` // Convert amount
	// Optional fields
	RequestCoin  currency.Code `json:"requestCoin"`            // This will default to FromCoin
	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
	RequestID    string        `json:"requestId,omitempty"`
}

// RequestAQuoteResponse represents a response for a request a quote
type RequestAQuoteResponse 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"`
	ExtTaxAndFee json.RawMessage `json:"extTaxAndFee"` // Compliance-related field. Currently returns an empty array, which may be used in the future
}

// RequestAQuote requests a conversion quote between two coins with the specified parameters.
func (e *Exchange) RequestAQuote(ctx context.Context, params *RequestAQuoteParams) (*RequestAQuoteResponse, error) {
	if !slices.Contains(supportedAccountTypes, params.AccountType) {
		return nil, fmt.Errorf("%w: %q", errUnsupportedAccountType, params.AccountType)
	}
	if params.From.IsEmpty() {
		return nil, fmt.Errorf("from %w", currency.ErrCurrencyCodeEmpty)
	}
	if params.To.IsEmpty() {
		return nil, fmt.Errorf("to %w", currency.ErrCurrencyCodeEmpty)
	}
	if params.From.Equal(params.To) {
		return nil, errCurrencyCodesEqual
	}
	if !params.RequestCoin.IsEmpty() {
		if !params.RequestCoin.Equal(params.From) {
			return nil, errRequestCoinInvalid
		}
	} else {
		params.RequestCoin = params.From
	}
	if params.Amount <= 0 {
		return nil, fmt.Errorf("amount %w", order.ErrAmountIsInvalid)
	}
	params.From = params.From.Upper()
	params.To = params.To.Upper()
	params.RequestCoin = params.RequestCoin.Upper()
	var resp *RequestAQuoteResponse
	return resp, e.SendAuthHTTPRequestV5(ctx, exchange.RestSpot, http.MethodPost, "/v5/asset/exchange/quote-apply", nil, payload, &resp, defaultEPL)
}

struct

	r := RequestAQuoteParams{
		AccountType:  "hi",
		From:         currency.BTC,
		To:           currency.USDT,
		Amount:       1337,
		RequestCoin:  currency.LTC,
		FromCoinType: "crypto",
		ToCoinType:   "crypto",
		ParamType:    "opFrom",
		ParamValue:   "broker-id-001",
		RequestID:    "test-00002",
	}

output

{"accountType":"hi","fromCoin":"BTC","toCoin":"USDT","requestAmount":"1337","requestCoin":"LTC","fromCoinType":"crypto","toCoinType":"crypto","paramType":"opFrom","paramValue":"broker-id-001","requestId":"test-00002"}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As to why I did this; who knows. Prototyping and pushing PR and getting back to trading is the most likely culprit. I am hugging types to functions because its a quicker lookup for me; I can put them in their own types file if you want?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind that much, it was just the combination of inline struct and inline type definition. It is also in jest, I am not actually mad

@@ -0,0 +1,280 @@
package bybit
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bybit_convert.

If anything this should be bybit_convert and the other one should be convert. At least with the prefix, it suggests it part of the bybit api whereas current bybit_convert is about type conversion. I'd rename bybit_convert to unmarshal.go and this to bybit_convert.go

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bybit_convert is being removed in #1992 when you get a chance could you please review that as well.

Dropping bybit_ is fine.

// ConvertStatusResponse represents the response for a conversion status query
type ConvertStatusResponse struct {
AccountType WalletAccountType `json:"accountType"`
ExchangeTxID string `json:"exchangeTxId"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update local fields with full details as per our guidelines ie ExchangeTransactionID
Please apply to all fields in this file

FullName string `json:"fullName"`
Icon string `json:"icon"`
IconNight string `json:"iconNight"`
AccuracyLength int `json:"accuracyLength"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update int usage in file according to our guidelines

shazbert and others added 5 commits August 26, 2025 10:28
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds comprehensive convert functionality to the bybit exchange, enabling users to convert between different cryptocurrencies using Bybit's conversion API. The implementation includes support for querying available coins, requesting quotes, confirming conversions, and tracking conversion history.

  • Adds complete convert API implementation with coin listing, quote management, and history tracking
  • Implements comprehensive validation for account types, currency codes, and conversion parameters
  • Provides extensive test coverage for all convert functions with proper error handling

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
exchanges/bybit/convert.go Implements core convert functionality including coin listing, quote requests, conversion execution, and history retrieval
exchanges/bybit/convert_test.go Comprehensive test suite covering all convert functions with validation tests and authenticated function tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
review me This pull request is ready for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants