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:
Adrian Gallagher
2021-10-15 15:55:38 +11:00
committed by GitHub
parent b093a7df19
commit 0c00b7e1df
145 changed files with 46329 additions and 5507 deletions

View File

@@ -16,6 +16,7 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/deposit"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
@@ -77,26 +78,29 @@ func (e *EXMO) SetDefaults() {
REST: true,
Websocket: false,
RESTCapabilities: protocol.Features{
TickerBatching: true,
TickerFetching: true,
TradeFetching: true,
OrderbookFetching: true,
AutoPairUpdates: true,
AccountInfo: true,
GetOrder: true,
GetOrders: true,
CancelOrder: true,
SubmitOrder: true,
DepositHistory: true,
WithdrawalHistory: true,
UserTradeHistory: true,
CryptoDeposit: true,
CryptoWithdrawal: true,
TradeFee: true,
FiatDepositFee: true,
FiatWithdrawalFee: true,
CryptoDepositFee: true,
CryptoWithdrawalFee: true,
TickerBatching: true,
TickerFetching: true,
TradeFetching: true,
OrderbookFetching: true,
AutoPairUpdates: true,
AccountInfo: true,
GetOrder: true,
GetOrders: true,
CancelOrder: true,
SubmitOrder: true,
DepositHistory: true,
WithdrawalHistory: true,
UserTradeHistory: true,
CryptoDeposit: true,
CryptoWithdrawal: true,
TradeFee: true,
FiatDepositFee: true,
FiatWithdrawalFee: true,
CryptoDepositFee: true,
CryptoWithdrawalFee: true,
MultiChainDeposits: true,
MultiChainWithdrawals: true,
MultiChainDepositRequiresChainSet: true,
},
WithdrawPermissions: exchange.AutoWithdrawCryptoWithSetup |
exchange.NoFiatWithdrawals,
@@ -524,19 +528,42 @@ func (e *EXMO) GetOrderInfo(ctx context.Context, orderID string, pair currency.P
}
// GetDepositAddress returns a deposit address for a specified currency
func (e *EXMO) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _ string) (string, error) {
func (e *EXMO) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _, chain string) (*deposit.Address, error) {
fullAddr, err := e.GetCryptoDepositAddress(ctx)
if err != nil {
return "", err
return nil, err
}
// TODO: Protect map with mutex
addr, ok := fullAddr[cryptocurrency.String()]
curr := cryptocurrency.Upper().String()
if chain != "" && !strings.EqualFold(chain, curr) {
curr += strings.ToUpper(chain)
}
addr, ok := fullAddr[curr]
if !ok {
return "", fmt.Errorf("currency %s could not be found, please generate via the exmo website", cryptocurrency.String())
chains, err := e.GetAvailableTransferChains(ctx, cryptocurrency)
if err != nil {
return nil, err
}
if len(chains) > 1 {
// rather than assume, return an error
return nil, fmt.Errorf("currency %s has %v chains available, one must be specified", cryptocurrency, chains)
}
return nil, fmt.Errorf("deposit address for %s could not be found, please generate via the exmo website", cryptocurrency.String())
}
return addr, nil
var tag string
if strings.Contains(addr, ",") {
split := strings.Split(addr, ",")
addr, tag = split[0], split[1]
}
return &deposit.Address{
Address: addr,
Tag: tag,
Chain: chain,
}, nil
}
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
@@ -549,6 +576,7 @@ func (e *EXMO) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest
withdrawRequest.Currency.String(),
withdrawRequest.Crypto.Address,
withdrawRequest.Crypto.AddressTag,
withdrawRequest.Crypto.Chain,
withdrawRequest.Amount)
return &withdraw.ExchangeResponse{
@@ -680,3 +708,30 @@ func (e *EXMO) GetHistoricCandles(ctx context.Context, pair currency.Pair, a ass
func (e *EXMO) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{}, common.ErrFunctionNotSupported
}
// GetAvailableTransferChains returns the available transfer blockchains for the specific
// cryptocurrency
func (e *EXMO) GetAvailableTransferChains(ctx context.Context, cryptocurrency currency.Code) ([]string, error) {
chains, err := e.GetCryptoPaymentProvidersList(ctx)
if err != nil {
return nil, err
}
methods, ok := chains[cryptocurrency.Upper().String()]
if !ok {
return nil, errors.New("no available chains")
}
var availChains []string
for x := range methods {
if methods[x].Type == "deposit" && methods[x].Enabled {
chain := methods[x].Name
if strings.Contains(chain, "(") && strings.Contains(chain, ")") {
chain = chain[strings.Index(chain, "(")+1 : strings.Index(chain, ")")]
}
availChains = append(availChains, chain)
}
}
return availChains, nil
}