mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-18 15:10:03 +00:00
exchanges/engine: Add multichain deposit/withdrawal support (#794)
* Add exchange multichain support * Start tidying up * Add multichain transfer support for Bitfinex and fix poloniex bug * Add Coinbene multichain support * Start adjusting the deposit address manager * Fix deposit tests and further enhancements * Cleanup * Add bypass flag, expand tests plus error coverage for Huobi Adjust helpers * Address nitterinos * BFX wd changes * Address nitterinos * Minor fixes rebasing on master * Fix BFX acceptableMethods test * Add some TO-DOs for 2 tests WRT races * Fix acceptableMethods test round 2 * Address nitterinos
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/gofrs/uuid"
|
||||
grpcauth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
@@ -62,6 +63,7 @@ var (
|
||||
errAssetTypeUnset = errors.New("asset type unset")
|
||||
errDispatchSystem = errors.New("dispatch system offline")
|
||||
errCurrencyNotEnabled = errors.New("currency not enabled")
|
||||
errCurrencyNotSpecified = errors.New("a currency must be specified")
|
||||
errCurrencyPairInvalid = errors.New("currency provided is not found in the available pairs list")
|
||||
errNoTrades = errors.New("no trades returned from supplied params")
|
||||
errNilRequestData = errors.New("nil request data received, cannot continue")
|
||||
@@ -1439,6 +1441,7 @@ func (s *RPCServer) CancelAllOrders(ctx context.Context, r *gctrpc.CancelAllOrde
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ModifyOrder modifies an existing order if it exists
|
||||
func (s *RPCServer) ModifyOrder(ctx context.Context, r *gctrpc.ModifyOrderRequest) (*gctrpc.ModifyOrderResponse, error) {
|
||||
assetType, err := asset.New(r.Asset)
|
||||
if err != nil {
|
||||
@@ -1531,28 +1534,90 @@ func (s *RPCServer) RemoveEvent(ctx context.Context, r *gctrpc.RemoveEventReques
|
||||
// GetCryptocurrencyDepositAddresses returns a list of cryptocurrency deposit
|
||||
// addresses specified by an exchange
|
||||
func (s *RPCServer) GetCryptocurrencyDepositAddresses(ctx context.Context, r *gctrpc.GetCryptocurrencyDepositAddressesRequest) (*gctrpc.GetCryptocurrencyDepositAddressesResponse, error) {
|
||||
_, err := s.GetExchangeByName(r.Exchange)
|
||||
exch, err := s.GetExchangeByName(r.Exchange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !exch.GetAuthenticatedAPISupport(exchange.RestAuthentication) {
|
||||
return nil, exchange.ErrAuthenticatedRequestWithoutCredentialsSet
|
||||
}
|
||||
|
||||
result, err := s.GetCryptocurrencyDepositAddressesByExchange(r.Exchange)
|
||||
return &gctrpc.GetCryptocurrencyDepositAddressesResponse{Addresses: result}, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp gctrpc.GetCryptocurrencyDepositAddressesResponse
|
||||
resp.Addresses = make(map[string]*gctrpc.DepositAddresses)
|
||||
for k, v := range result {
|
||||
var depositAddrs []*gctrpc.DepositAddress
|
||||
for a := range v {
|
||||
depositAddrs = append(depositAddrs, &gctrpc.DepositAddress{
|
||||
Address: v[a].Address,
|
||||
Tag: v[a].Tag,
|
||||
Chain: v[a].Chain,
|
||||
})
|
||||
}
|
||||
resp.Addresses[k] = &gctrpc.DepositAddresses{Addresses: depositAddrs}
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyDepositAddress returns a cryptocurrency deposit address
|
||||
// specified by exchange and cryptocurrency
|
||||
func (s *RPCServer) GetCryptocurrencyDepositAddress(ctx context.Context, r *gctrpc.GetCryptocurrencyDepositAddressRequest) (*gctrpc.GetCryptocurrencyDepositAddressResponse, error) {
|
||||
_, err := s.GetExchangeByName(r.Exchange)
|
||||
exch, err := s.GetExchangeByName(r.Exchange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !exch.GetAuthenticatedAPISupport(exchange.RestAuthentication) {
|
||||
return nil, exchange.ErrAuthenticatedRequestWithoutCredentialsSet
|
||||
}
|
||||
|
||||
addr, err := s.GetExchangeCryptocurrencyDepositAddress(ctx,
|
||||
r.Exchange,
|
||||
"",
|
||||
currency.NewCode(r.Cryptocurrency))
|
||||
return &gctrpc.GetCryptocurrencyDepositAddressResponse{Address: addr}, err
|
||||
r.Chain,
|
||||
currency.NewCode(r.Cryptocurrency),
|
||||
r.Bypass,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &gctrpc.GetCryptocurrencyDepositAddressResponse{
|
||||
Address: addr.Address,
|
||||
Tag: addr.Tag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAvailableTransferChains returns the supported transfer chains specified by
|
||||
// exchange and cryptocurrency
|
||||
func (s *RPCServer) GetAvailableTransferChains(ctx context.Context, r *gctrpc.GetAvailableTransferChainsRequest) (*gctrpc.GetAvailableTransferChainsResponse, error) {
|
||||
exch, err := s.GetExchangeByName(r.Exchange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curr := currency.NewCode(r.Cryptocurrency)
|
||||
if curr.IsEmpty() {
|
||||
return nil, errCurrencyNotSpecified
|
||||
}
|
||||
|
||||
resp, err := exch.GetAvailableTransferChains(ctx, curr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(resp) == 0 {
|
||||
return nil, errors.New("no available transfer chains found")
|
||||
}
|
||||
|
||||
return &gctrpc.GetAvailableTransferChainsResponse{
|
||||
Chains: resp,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithdrawCryptocurrencyFunds withdraws cryptocurrency funds specified by
|
||||
@@ -1573,9 +1638,38 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.W
|
||||
Address: r.Address,
|
||||
AddressTag: r.AddressTag,
|
||||
FeeAmount: r.Fee,
|
||||
Chain: r.Chain,
|
||||
},
|
||||
}
|
||||
|
||||
exchCfg, err := s.Config.GetExchangeConfig(r.Exchange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exchCfg.API.Credentials.OTPSecret != "" {
|
||||
code, errOTP := totp.GenerateCode(exchCfg.API.Credentials.OTPSecret, time.Now())
|
||||
if errOTP != nil {
|
||||
return nil, errOTP
|
||||
}
|
||||
|
||||
codeNum, errOTP := strconv.ParseInt(code, 10, 64)
|
||||
if errOTP != nil {
|
||||
return nil, errOTP
|
||||
}
|
||||
request.OneTimePassword = codeNum
|
||||
}
|
||||
|
||||
if exchCfg.API.Credentials.PIN != "" {
|
||||
pinCode, errPin := strconv.ParseInt(exchCfg.API.Credentials.PIN, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errPin
|
||||
}
|
||||
request.PIN = pinCode
|
||||
}
|
||||
|
||||
request.TradePassword = exchCfg.API.Credentials.TradePassword
|
||||
|
||||
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1618,6 +1712,34 @@ func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFia
|
||||
},
|
||||
}
|
||||
|
||||
exchCfg, err := s.Config.GetExchangeConfig(r.Exchange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exchCfg.API.Credentials.OTPSecret != "" {
|
||||
code, errOTP := totp.GenerateCode(exchCfg.API.Credentials.OTPSecret, time.Now())
|
||||
if err != nil {
|
||||
return nil, errOTP
|
||||
}
|
||||
|
||||
codeNum, errOTP := strconv.ParseInt(code, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errOTP
|
||||
}
|
||||
request.OneTimePassword = codeNum
|
||||
}
|
||||
|
||||
if exchCfg.API.Credentials.PIN != "" {
|
||||
pinCode, errPIN := strconv.ParseInt(exchCfg.API.Credentials.PIN, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errPIN
|
||||
}
|
||||
request.PIN = pinCode
|
||||
}
|
||||
|
||||
request.TradePassword = exchCfg.API.Credentials.TradePassword
|
||||
|
||||
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user