Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binance dapi fix #4876

Merged
merged 11 commits into from
May 11, 2024
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
package org.knowm.xchange.binance;

import static org.knowm.xchange.binance.dto.ExchangeType.SPOT;

import java.util.Map;
import org.knowm.xchange.BaseExchange;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.binance.dto.ExchangeType;
import org.knowm.xchange.binance.dto.account.AssetDetail;
import org.knowm.xchange.binance.service.BinanceAccountService;
import org.knowm.xchange.binance.service.BinanceMarketDataService;
import org.knowm.xchange.binance.service.BinanceTradeService;
import org.knowm.xchange.client.ExchangeRestProxyBuilder;
import org.knowm.xchange.client.ResilienceRegistries;
import org.knowm.xchange.exceptions.ExchangeException;
import org.knowm.xchange.utils.AuthUtils;
import si.mazi.rescu.SynchronizedValueFactory;

public class BinanceExchange extends BaseExchange implements Exchange {
public static final String SPECIFIC_PARAM_USE_SANDBOX = "Use_Sandbox";
public static final String SPECIFIC_PARAM_USE_FUTURES_SANDBOX = "Use_Sandbox_Futures";
public static final String SPECIFIC_PARAM_FUTURES_ENABLED = "Futures_Enabled";
public static final String SPECIFIC_PARAM_PORTFOLIO_MARGIN_ENABLED = "Portfolio_Margin_Enabled";
public static String EXCHANGE_TYPE = "Exchange_Type";
private static final String SPOT_URL = "https://api.binance.com";
public static final String FUTURES_URL = "https://dapi.binance.com";
public static final String FUTURES_URL = "https://fapi.binance.com";
public static final String INVERSE_FUTURES_URL = "https://dapi.binance.com";
public static final String PORTFOLIO_MARGIN_URL = "https://papi.binance.com";

public static final String SANDBOX_SPOT_URL = "https://testnet.binance.vision";
public static final String SANDBOX_FUTURES_URL = "https://testnet.binancefuture.com";
public static final String SANDBOX_INVERSE_FUTURES_URL = "https://testnet.binancefuture.com";

protected static ResilienceRegistries RESILIENCE_REGISTRIES;
protected SynchronizedValueFactory<Long> timestampFactory;

Expand Down Expand Up @@ -61,13 +65,14 @@ public ResilienceRegistries getResilienceRegistries() {

@Override
public ExchangeSpecification getDefaultExchangeSpecification() {

ExchangeSpecification spec = new ExchangeSpecification(this.getClass());
spec.setSslUri(SPOT_URL);
spec.setHost("www.binance.com");
spec.setPort(80);
spec.setExchangeName("Binance");
spec.setExchangeDescription("Binance Exchange.");
spec.setExchangeSpecificParametersItem(EXCHANGE_TYPE, SPOT);
spec.setExchangeSpecificParametersItem(USE_SANDBOX, false);
AuthUtils.setApiAndSecretKey(spec, "binance");
return spec;
}
Expand All @@ -78,21 +83,14 @@ public void applySpecification(ExchangeSpecification exchangeSpecification) {
super.applySpecification(exchangeSpecification);
}

public boolean isFuturesSandbox() {
return Boolean.TRUE.equals(
exchangeSpecification.getExchangeSpecificParametersItem(
SPECIFIC_PARAM_USE_FUTURES_SANDBOX));
}

public boolean isFuturesEnabled() {
return Boolean.TRUE.equals(
exchangeSpecification.getExchangeSpecificParametersItem(SPECIFIC_PARAM_FUTURES_ENABLED));
return ExchangeType.FUTURES.equals(exchangeSpecification.
getExchangeSpecificParametersItem(EXCHANGE_TYPE));
}

public boolean isPortfolioMarginEnabled() {
return Boolean.TRUE.equals(
exchangeSpecification.getExchangeSpecificParametersItem(
SPECIFIC_PARAM_PORTFOLIO_MARGIN_ENABLED));
return ExchangeType.PORTFOLIO_MARGIN.equals(exchangeSpecification
.getExchangeSpecificParametersItem(EXCHANGE_TYPE));
}

public boolean usingSandbox() {
Expand All @@ -101,35 +99,35 @@ public boolean usingSandbox() {

@Override
public void remoteInit() {

try {
BinanceMarketDataService marketDataService =
(BinanceMarketDataService) this.marketDataService;

BinanceAccountService accountService = (BinanceAccountService) getAccountService();
Map<String, AssetDetail> assetDetailMap = null;
if (!usingSandbox() && isAuthenticated()) {
assetDetailMap = accountService.getAssetDetails(); // not available in sndbox
}
if (usingSandbox()) {
if (isFuturesSandbox()) {
BinanceAdapters.adaptFutureExchangeMetaData(
exchangeMetaData, marketDataService.getFutureExchangeInfo());
} else {
exchangeMetaData =
BinanceAdapters.adaptExchangeMetaData(
marketDataService.getExchangeInfo(), assetDetailMap);
}
} else {
//hook for Binance US
if(exchangeSpecification.getExchangeSpecificParametersItem(EXCHANGE_TYPE) ==null) {
exchangeMetaData =
BinanceAdapters.adaptExchangeMetaData(
marketDataService.getExchangeInfo(), assetDetailMap);
if (isFuturesEnabled()) {
BinanceAdapters.adaptFutureExchangeMetaData(
exchangeMetaData, marketDataService.getFutureExchangeInfo());
} else {
switch ((ExchangeType) exchangeSpecification.getExchangeSpecificParametersItem(
EXCHANGE_TYPE)) {
case SPOT: {
exchangeMetaData =
BinanceAdapters.adaptExchangeMetaData(
marketDataService.getExchangeInfo(), assetDetailMap);
break;
}
case FUTURES: {
BinanceAdapters.adaptFutureExchangeMetaData(
exchangeMetaData, marketDataService.getFutureExchangeInfo());
break;
}
}
}

} catch (Exception e) {
throw new ExchangeException("Failed to initialize: " + e.getMessage(), e);
}
Expand All @@ -141,21 +139,38 @@ protected boolean isAuthenticated() {
&& exchangeSpecification.getSecretKey() != null;
}

/** Adjust host parameters depending on exchange specific parameters */
/**
* Adjust host parameters depending on exchange specific parameters
*/
private static void concludeHostParams(ExchangeSpecification exchangeSpecification) {
if (exchangeSpecification.getExchangeSpecificParameters() != null) {
if (enabledSandbox(exchangeSpecification)) {
exchangeSpecification.setSslUri("https://testnet.binance.vision");
exchangeSpecification.setHost("testnet.binance.vision");
if(exchangeSpecification.getExchangeSpecificParametersItem(EXCHANGE_TYPE) != null) {
switch ((ExchangeType)exchangeSpecification.getExchangeSpecificParametersItem(EXCHANGE_TYPE)) {
case SPOT: {
if (enabledSandbox(exchangeSpecification))
exchangeSpecification.setSslUri(SANDBOX_SPOT_URL);
break;
}
case FUTURES: {
if (!enabledSandbox(exchangeSpecification))
exchangeSpecification.setSslUri(FUTURES_URL);
else
exchangeSpecification.setSslUri(SANDBOX_FUTURES_URL);
break;
}
case INVERSE: {
if (!enabledSandbox(exchangeSpecification))
exchangeSpecification.setSslUri(INVERSE_FUTURES_URL);
else
exchangeSpecification.setSslUri(SANDBOX_INVERSE_FUTURES_URL);
break;
}
}
}
}


private static boolean enabledSandbox(ExchangeSpecification exchangeSpecification) {
return Boolean.TRUE.equals(
exchangeSpecification.getExchangeSpecificParametersItem(SPECIFIC_PARAM_USE_SANDBOX))
|| Boolean.TRUE.equals(
exchangeSpecification.getExchangeSpecificParametersItem(
SPECIFIC_PARAM_USE_FUTURES_SANDBOX));
return Boolean.TRUE.equals(exchangeSpecification.getExchangeSpecificParametersItem(USE_SANDBOX));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.knowm.xchange.binance;

import static org.knowm.xchange.binance.dto.ExchangeType.SPOT;

import java.io.IOException;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.binance.service.BinanceMarketDataService;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.knowm.xchange.binance.dto;

import lombok.Getter;

@Getter
public enum ExchangeType {
SPOT,
FUTURES,
INVERSE,
PORTFOLIO_MARGIN;
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.knowm.xchange.binance.service;

import static org.knowm.xchange.binance.BinanceExchange.EXCHANGE_TYPE;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
Expand All @@ -9,6 +11,7 @@
import org.knowm.xchange.binance.BinanceErrorAdapter;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.dto.BinanceException;
import org.knowm.xchange.binance.dto.ExchangeType;
import org.knowm.xchange.binance.dto.account.*;
import org.knowm.xchange.binance.dto.account.BinanceMasterAccountTransferHistoryParams;
import org.knowm.xchange.binance.dto.account.BinanceSubAccountTransferHistoryParams;
Expand Down Expand Up @@ -91,25 +94,19 @@ public AccountInfo getAccountInfo() throws IOException {
try {
List<Wallet> wallets = new ArrayList<>();
List<OpenPosition> openPositions = new ArrayList<>();

if (exchange.usingSandbox()) {
if (exchange.isFuturesSandbox()) {
BinanceFutureAccountInformation futureAccountInformation = futuresAccount();
wallets.add(BinanceAdapters.adaptBinanceFutureWallet(futureAccountInformation));
openPositions.addAll(
BinanceAdapters.adaptOpenPositions(futureAccountInformation.getPositions()));

} else {
switch (exchange.getExchangeSpecification().getExchangeSpecificParametersItem(
EXCHANGE_TYPE).toString()) {
case "SPOT": {
rizer1980 marked this conversation as resolved.
Show resolved Hide resolved
wallets.add(BinanceAdapters.adaptBinanceSpotWallet(account()));
break;
}
} else {
if (exchange.isFuturesEnabled()) {
case "FUTURES": {
BinanceFutureAccountInformation futureAccountInformation = futuresAccount();
wallets.add(BinanceAdapters.adaptBinanceFutureWallet(futureAccountInformation));
openPositions.addAll(
BinanceAdapters.adaptOpenPositions(futureAccountInformation.getPositions()));
break;
}
wallets.add(BinanceAdapters.adaptBinanceSpotWallet(account()));
}
return new AccountInfo(
exchange.getExchangeSpecification().getUserName(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.knowm.xchange.binance.service;

import static org.knowm.xchange.binance.BinanceExchange.EXCHANGE_TYPE;
import static org.knowm.xchange.binance.BinanceResilience.REQUEST_WEIGHT_RATE_LIMITER;

import java.io.IOException;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.binance.BinanceAuthenticated;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.BinanceFuturesAuthenticated;
import org.knowm.xchange.binance.dto.ExchangeType;
import org.knowm.xchange.binance.dto.meta.BinanceSystemStatus;
import org.knowm.xchange.binance.dto.meta.exchangeinfo.BinanceExchangeInfo;
import org.knowm.xchange.client.ExchangeRestProxyBuilder;
Expand All @@ -23,8 +25,8 @@ public class BinanceBaseService extends BaseResilientExchangeService<BinanceExch

protected final String apiKey;
protected final BinanceAuthenticated binance;
protected final BinanceFuturesAuthenticated binanceFutures;
protected final BinanceFuturesAuthenticated inverseBinanceFutures;
protected BinanceFuturesAuthenticated binanceFutures;
protected BinanceFuturesAuthenticated inverseBinanceFutures;
protected final ParamsDigest signatureCreator;

protected BinanceBaseService(
Expand All @@ -35,30 +37,34 @@ protected BinanceBaseService(
ExchangeRestProxyBuilder.forInterface(
BinanceAuthenticated.class, exchange.getExchangeSpecification())
.build();
ExchangeSpecification futuresSpec = exchange.getDefaultExchangeSpecification();
ExchangeSpecification inverseFuturesSpec = futuresSpec;
futuresSpec.setSslUri(
(exchange.usingSandbox())
? BinanceExchange.SANDBOX_FUTURES_URL
: (exchange.isPortfolioMarginEnabled())
? BinanceExchange.PORTFOLIO_MARGIN_URL
: BinanceExchange.FUTURES_URL);
if (!exchange.isPortfolioMarginEnabled()) {
inverseFuturesSpec.setSslUri(
(exchange.usingSandbox())
? BinanceExchange.SANDBOX_FUTURES_URL
: BinanceExchange.INVERSE_FUTURES_URL);
this.inverseBinanceFutures =
ExchangeRestProxyBuilder.forInterface(
BinanceFuturesAuthenticated.class, inverseFuturesSpec)
.build();
} else {
this.inverseBinanceFutures = null;
ExchangeSpecification futuresSpec;
ExchangeSpecification inverseFuturesSpec;
if(exchange.getExchangeSpecification().getExchangeSpecificParametersItem(EXCHANGE_TYPE) != null)
{
switch ((ExchangeType) exchange.getExchangeSpecification()
.getExchangeSpecificParametersItem(EXCHANGE_TYPE)) {
case SPOT: {
break;
}
case FUTURES: {
futuresSpec = exchange.getExchangeSpecification();
binanceFutures =
rizer1980 marked this conversation as resolved.
Show resolved Hide resolved
ExchangeRestProxyBuilder.forInterface(BinanceFuturesAuthenticated.class, futuresSpec)
.build();
inverseBinanceFutures = null;
break;
}
case INVERSE: {
inverseFuturesSpec = exchange.getExchangeSpecification();
inverseBinanceFutures =
ExchangeRestProxyBuilder.forInterface(BinanceFuturesAuthenticated.class,
inverseFuturesSpec)
.build();
binanceFutures = null;
break;
}
}
}
this.binanceFutures =
ExchangeRestProxyBuilder.forInterface(BinanceFuturesAuthenticated.class, futuresSpec)
.build();

this.apiKey = exchange.getExchangeSpecification().getApiKey();
this.signatureCreator =
BinanceHmacDigest.createInstance(exchange.getExchangeSpecification().getSecretKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public Ticker getTicker(Instrument instrument, Object... args) throws IOExceptio
@Override
public List<Ticker> getTickers(Params params) throws IOException {
try {
if (this.exchange.isFuturesEnabled() || this.exchange.isFuturesSandbox()) {
if (this.exchange.isFuturesEnabled()) {
return ticker24hAllProducts(true).stream().map(f -> f.toTicker(true))
.collect(Collectors.toList());
} else {
Expand Down
Loading
Loading