all: improve binance withdraw status convertion

This commit is contained in:
c9s 2024-07-31 15:04:08 +08:00
parent a5bf3518df
commit ab20b6db89
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
8 changed files with 116 additions and 16 deletions

View File

@ -8,8 +8,9 @@ import (
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
) )
//go:generate stringer -type=TransferType
// 1 for internal transfer, 0 for external transfer // 1 for internal transfer, 0 for external transfer
//
//go:generate stringer -type=TransferType
type TransferType int type TransferType int
const ( const (
@ -33,7 +34,7 @@ type WithdrawRecord struct {
TxID string `json:"txId"` TxID string `json:"txId"`
} }
//go:generate stringer -type=WithdrawStatus //go:generate stringer -type=WithdrawStatus -trimprefix=WithdrawStatus
type WithdrawStatus int type WithdrawStatus int
// WithdrawStatus: 0(0:Email Sent,1:Cancelled 2:Awaiting Approval 3:Rejected 4:Processing 5:Failure 6:Completed) // WithdrawStatus: 0(0:Email Sent,1:Cancelled 2:Awaiting Approval 3:Rejected 4:Processing 5:Failure 6:Completed)

View File

@ -212,6 +212,12 @@ func (g *GetWithdrawHistoryRequest) GetSlugsMap() (map[string]string, error) {
return slugs, nil return slugs, nil
} }
// GetPath returns the request path of the API
func (g *GetWithdrawHistoryRequest) GetPath() string {
return "/sapi/v1/capital/withdraw/history"
}
// Do generates the request object and send the request object to the API endpoint
func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, error) { func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, error) {
// empty params for GET operation // empty params for GET operation
@ -221,7 +227,9 @@ func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, e
return nil, err return nil, err
} }
apiURL := "/sapi/v1/capital/withdraw/history" var apiURL string
apiURL = g.GetPath()
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
if err != nil { if err != nil {
@ -234,8 +242,32 @@ func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, e
} }
var apiResponse []WithdrawRecord var apiResponse []WithdrawRecord
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err type responseUnmarshaler interface {
Unmarshal(data []byte) error
}
if unmarshaler, ok := interface{}(&apiResponse).(responseUnmarshaler); ok {
if err := unmarshaler.Unmarshal(response.Body); err != nil {
return nil, err
}
} else {
// The line below checks the content type, however, some API server might not send the correct content type header,
// Hence, this is commented for backward compatibility
// response.IsJSON()
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
}
type responseValidator interface {
Validate() error
}
if validator, ok := interface{}(&apiResponse).(responseValidator); ok {
if err := validator.Validate(); err != nil {
return nil, err
}
} }
return apiResponse, nil return apiResponse, nil
} }

View File

@ -1,4 +1,4 @@
// Code generated by "stringer -type=WithdrawStatus"; DO NOT EDIT. // Code generated by "stringer -type=WithdrawStatus -trimprefix=WithdrawStatus"; DO NOT EDIT.
package binanceapi package binanceapi
@ -17,9 +17,9 @@ func _() {
_ = x[WithdrawStatusCompleted-6] _ = x[WithdrawStatusCompleted-6]
} }
const _WithdrawStatus_name = "WithdrawStatusEmailSentWithdrawStatusCancelledWithdrawStatusAwaitingApprovalWithdrawStatusRejectedWithdrawStatusProcessingWithdrawStatusFailureWithdrawStatusCompleted" const _WithdrawStatus_name = "EmailSentCancelledAwaitingApprovalRejectedProcessingFailureCompleted"
var _WithdrawStatus_index = [...]uint8{0, 23, 46, 76, 98, 122, 143, 166} var _WithdrawStatus_index = [...]uint8{0, 9, 18, 34, 42, 52, 59, 68}
func (i WithdrawStatus) String() string { func (i WithdrawStatus) String() string {
if i < 0 || i >= WithdrawStatus(len(_WithdrawStatus_index)-1) { if i < 0 || i >= WithdrawStatus(len(_WithdrawStatus_index)-1) {

View File

@ -9,10 +9,32 @@ import (
"github.com/adshao/go-binance/v2/futures" "github.com/adshao/go-binance/v2/futures"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
) )
func toGlobalWithdrawStatus(status binanceapi.WithdrawStatus) (types.WithdrawStatus, error) {
switch status {
case binanceapi.WithdrawStatusEmailSent:
return types.WithdrawStatusSent, nil
case binanceapi.WithdrawStatusCancelled:
return types.WithdrawStatusCancelled, nil
case binanceapi.WithdrawStatusAwaitingApproval:
return types.WithdrawStatusAwaitingApproval, nil
case binanceapi.WithdrawStatusRejected:
return types.WithdrawStatusRejected, nil
case binanceapi.WithdrawStatusProcessing:
return types.WithdrawStatusProcessing, nil
case binanceapi.WithdrawStatusFailure:
return types.WithdrawStatusFailed, nil
case binanceapi.WithdrawStatusCompleted:
return types.WithdrawStatusCompleted, nil
default:
return types.WithdrawStatusUnknown, fmt.Errorf("unable to convert the withdraw status: %s", status)
}
}
func toGlobalMarket(symbol binance.Symbol) types.Market { func toGlobalMarket(symbol binance.Symbol) types.Market {
market := types.Market{ market := types.Market{
Exchange: types.ExchangeBinance, Exchange: types.ExchangeBinance,

View File

@ -571,6 +571,11 @@ func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since
return nil, err return nil, err
} }
status, err := toGlobalWithdrawStatus(d.Status)
if err != nil {
return nil, err
}
withdraws = append(withdraws, types.Withdraw{ withdraws = append(withdraws, types.Withdraw{
Exchange: types.ExchangeBinance, Exchange: types.ExchangeBinance,
ApplyTime: types.Time(applyTime), ApplyTime: types.Time(applyTime),
@ -581,7 +586,8 @@ func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since
TransactionFee: d.TransactionFee, TransactionFee: d.TransactionFee,
WithdrawOrderID: d.WithdrawOrderID, WithdrawOrderID: d.WithdrawOrderID,
Network: d.Network, Network: d.Network,
Status: d.Status.String(), Status: status,
OriginalStatus: fmt.Sprintf("%s (%d)", d.Status.String(), int(d.Status)),
}) })
} }

View File

@ -114,6 +114,26 @@ func (s *Strategy) aggregateBalances(
return totalBalances, sessionBalances return totalBalances, sessionBalances
} }
func (s *Strategy) detectActiveTransfers(ctx context.Context, sessions map[string]*bbgo.ExchangeSession) {
until := time.Now()
since := until.Add(-time.Hour * 24)
for _, session := range sessions {
if transferService, ok := session.Exchange.(types.ExchangeTransferHistoryService); ok {
withdraws, err := transferService.QueryWithdrawHistory(ctx, "", since, until)
if err != nil {
log.WithError(err).Errorf("unable to query withdraw history")
continue
}
for _, withdraw := range withdraws {
_ = withdraw
// withdraw.
}
}
}
}
func (s *Strategy) selectSessionForCurrency( func (s *Strategy) selectSessionForCurrency(
ctx context.Context, sessions map[string]*bbgo.ExchangeSession, currency string, changeQuantity fixedpoint.Value, ctx context.Context, sessions map[string]*bbgo.ExchangeSession, currency string, changeQuantity fixedpoint.Value,
) (*bbgo.ExchangeSession, *types.SubmitOrder) { ) (*bbgo.ExchangeSession, *types.SubmitOrder) {

View File

@ -149,6 +149,11 @@ type CustomIntervalProvider interface {
IsSupportedInterval(interval Interval) bool IsSupportedInterval(interval Interval) bool
} }
type ExchangeTransferHistoryService interface {
QueryDepositHistory(ctx context.Context, asset string, since, until time.Time) (allDeposits []Deposit, err error)
QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []Withdraw, err error)
}
type ExchangeTransferService interface { type ExchangeTransferService interface {
QueryDepositHistory(ctx context.Context, asset string, since, until time.Time) (allDeposits []Deposit, err error) QueryDepositHistory(ctx context.Context, asset string, since, until time.Time) (allDeposits []Deposit, err error)
QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []Withdraw, err error) QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []Withdraw, err error)

View File

@ -7,14 +7,28 @@ import (
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
) )
type WithdrawStatus string
const (
WithdrawStatusSent WithdrawStatus = "sent"
WithdrawStatusCancelled WithdrawStatus = "cancelled"
WithdrawStatusAwaitingApproval WithdrawStatus = "awaiting_approval"
WithdrawStatusRejected WithdrawStatus = "rejected"
WithdrawStatusProcessing WithdrawStatus = "processing"
WithdrawStatusFailed WithdrawStatus = "failed"
WithdrawStatusCompleted WithdrawStatus = "completed"
WithdrawStatusUnknown WithdrawStatus = "unknown"
)
type Withdraw struct { type Withdraw struct {
GID int64 `json:"gid" db:"gid"` GID int64 `json:"gid" db:"gid"`
Exchange ExchangeName `json:"exchange" db:"exchange"` Exchange ExchangeName `json:"exchange" db:"exchange"`
Asset string `json:"asset" db:"asset"` Asset string `json:"asset" db:"asset"`
Amount fixedpoint.Value `json:"amount" db:"amount"` Amount fixedpoint.Value `json:"amount" db:"amount"`
Address string `json:"address" db:"address"` Address string `json:"address" db:"address"`
AddressTag string `json:"addressTag"` AddressTag string `json:"addressTag"`
Status string `json:"status"` Status WithdrawStatus `json:"status"`
OriginalStatus string `json:"originalStatus"`
TransactionID string `json:"transactionID" db:"txn_id"` TransactionID string `json:"transactionID" db:"txn_id"`
TransactionFee fixedpoint.Value `json:"transactionFee" db:"txn_fee"` TransactionFee fixedpoint.Value `json:"transactionFee" db:"txn_fee"`