diff --git a/xchange-binance/src/main/java/org/knowm/xchange/binance/BinanceAuthenticated.java b/xchange-binance/src/main/java/org/knowm/xchange/binance/BinanceAuthenticated.java index b8503410818..7b6e8968977 100644 --- a/xchange-binance/src/main/java/org/knowm/xchange/binance/BinanceAuthenticated.java +++ b/xchange-binance/src/main/java/org/knowm/xchange/binance/BinanceAuthenticated.java @@ -371,6 +371,7 @@ WithdrawResponse withdraw( @FormParam("addressTag") String addressTag, @FormParam("amount") BigDecimal amount, @FormParam("name") String name, + @FormParam("network") String network, @FormParam("recvWindow") Long recvWindow, @FormParam("timestamp") SynchronizedValueFactory timestamp, @HeaderParam(X_MBX_APIKEY) String apiKey, @@ -499,6 +500,7 @@ List transferSubUserHistory( @Path("/sapi/v1/capital/deposit/address") DepositAddress depositAddress( @QueryParam("coin") String coin, + @QueryParam("network") String network, @QueryParam("recvWindow") Long recvWindow, @QueryParam("timestamp") SynchronizedValueFactory timestamp, @HeaderParam(X_MBX_APIKEY) String apiKey, diff --git a/xchange-binance/src/main/java/org/knowm/xchange/binance/dto/trade/TimeInForce.java b/xchange-binance/src/main/java/org/knowm/xchange/binance/dto/trade/TimeInForce.java index 2121ff106c5..5ab2ee73a65 100644 --- a/xchange-binance/src/main/java/org/knowm/xchange/binance/dto/trade/TimeInForce.java +++ b/xchange-binance/src/main/java/org/knowm/xchange/binance/dto/trade/TimeInForce.java @@ -1,8 +1,10 @@ package org.knowm.xchange.binance.dto.trade; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.knowm.xchange.dto.Order.IOrderFlags; +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) public enum TimeInForce implements IOrderFlags { GTC, GTX, diff --git a/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountService.java b/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountService.java index fb37325ce54..e66451192f6 100644 --- a/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountService.java +++ b/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountService.java @@ -1,8 +1,6 @@ package org.knowm.xchange.binance.service; import static org.knowm.xchange.binance.BinanceExchange.EXCHANGE_TYPE; -import static org.knowm.xchange.binance.dto.ExchangeType.FUTURES; -import static org.knowm.xchange.binance.dto.ExchangeType.SPOT; import java.io.IOException; import java.math.BigDecimal; @@ -13,6 +11,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.knowm.xchange.binance.BinanceAdapters; import org.knowm.xchange.binance.BinanceErrorAdapter; import org.knowm.xchange.binance.BinanceExchange; @@ -20,6 +19,8 @@ import org.knowm.xchange.binance.dto.ExchangeType; import org.knowm.xchange.binance.dto.account.AssetDetail; import org.knowm.xchange.binance.dto.account.BinanceAccountInformation; +import org.knowm.xchange.binance.dto.account.BinanceCurrencyInfo; +import org.knowm.xchange.binance.dto.account.BinanceCurrencyInfo.Network; import org.knowm.xchange.binance.dto.account.BinanceFundingHistoryParams; import org.knowm.xchange.binance.dto.account.BinanceMasterAccountTransferHistoryParams; import org.knowm.xchange.binance.dto.account.BinanceSubAccountTransferHistoryParams; @@ -38,8 +39,10 @@ import org.knowm.xchange.dto.account.Wallet; import org.knowm.xchange.instrument.Instrument; import org.knowm.xchange.service.account.AccountService; +import org.knowm.xchange.service.account.params.RequestDepositAddressParams; import org.knowm.xchange.service.trade.params.DefaultWithdrawFundsParams; import org.knowm.xchange.service.trade.params.HistoryParamsFundingType; +import org.knowm.xchange.service.trade.params.NetworkWithdrawFundsParams; import org.knowm.xchange.service.trade.params.RippleWithdrawFundsParams; import org.knowm.xchange.service.trade.params.TradeHistoryParamCurrency; import org.knowm.xchange.service.trade.params.TradeHistoryParamLimit; @@ -187,7 +190,17 @@ public String withdrawFunds(WithdrawFundsParams params) throws IOException { rippleParams.getCurrency().getCurrencyCode(), rippleParams.getAddress(), rippleParams.getTag(), - rippleParams.getAmount()); + rippleParams.getAmount(), + Currency.XRP.getCurrencyCode()); + } else if (params instanceof NetworkWithdrawFundsParams) { + NetworkWithdrawFundsParams p = (NetworkWithdrawFundsParams) params; + withdraw = + super.withdraw( + p.getCurrency().getCurrencyCode(), + p.getAddress(), + p.getAddressTag(), + p.getAmount(), + p.getNetwork()); } else { DefaultWithdrawFundsParams p = (DefaultWithdrawFundsParams) params; withdraw = @@ -195,7 +208,8 @@ public String withdrawFunds(WithdrawFundsParams params) throws IOException { p.getCurrency().getCurrencyCode(), p.getAddress(), p.getAddressTag(), - p.getAmount()); + p.getAmount(), + null); } return withdraw.getId(); } catch (BinanceException e) { @@ -215,7 +229,47 @@ public String requestDepositAddress(Currency currency, String... args) throws IO @Override public AddressWithTag requestDepositAddressData(Currency currency, String... args) throws IOException { - DepositAddress depositAddress = super.requestDepositAddress(currency); + return prepareAddressWithTag(super.requestDepositAddress(currency)); + } + + @Override + public AddressWithTag requestDepositAddressData( + RequestDepositAddressParams requestDepositAddressParams) throws IOException { + if (StringUtils.isEmpty(requestDepositAddressParams.getNetwork())) { + return requestDepositAddressData( + requestDepositAddressParams.getCurrency(), + requestDepositAddressParams.getExtraArguments()); + } + + BinanceCurrencyInfo binanceCurrencyInfo = + super.getCurrencyInfo(requestDepositAddressParams.getCurrency()) + .orElseThrow( + () -> + new IllegalArgumentException( + "Currency not supported: " + requestDepositAddressParams.getCurrency())); + + Network binanceNetwork = + binanceCurrencyInfo.getNetworks().stream() + .filter( + network -> + requestDepositAddressParams.getNetwork().equals(network.getId()) + || network + .getId() + .equals(requestDepositAddressParams.getCurrency().getCurrencyCode())) + .findFirst() + .orElseThrow( + () -> + new IllegalArgumentException( + "Network not supported: " + requestDepositAddressParams.getNetwork())); + + DepositAddress depositAddress = + super.requestDepositAddressWithNetwork( + requestDepositAddressParams.getCurrency(), binanceNetwork.getId()); + + return prepareAddressWithTag(depositAddress); + } + + private static AddressWithTag prepareAddressWithTag(DepositAddress depositAddress) { String destinationTag = (depositAddress.addressTag == null || depositAddress.addressTag.isEmpty()) ? null @@ -223,6 +277,12 @@ public AddressWithTag requestDepositAddressData(Currency currency, String... arg return new AddressWithTag(depositAddress.address, destinationTag); } + @Override + public String requestDepositAddress(RequestDepositAddressParams requestDepositAddressParams) + throws IOException { + return requestDepositAddressData(requestDepositAddressParams).getAddress(); + } + public Map getAssetDetails() throws IOException { try { return super.requestAssetDetail(); diff --git a/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountServiceRaw.java b/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountServiceRaw.java index 4b920c56a59..fdba371a090 100644 --- a/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountServiceRaw.java +++ b/xchange-binance/src/main/java/org/knowm/xchange/binance/service/BinanceAccountServiceRaw.java @@ -7,6 +7,9 @@ import java.math.BigDecimal; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.knowm.xchange.binance.BinanceAdapters; import org.knowm.xchange.binance.BinanceExchange; import org.knowm.xchange.binance.dto.BinanceException; @@ -25,6 +28,8 @@ import org.knowm.xchange.currency.Currency; public class BinanceAccountServiceRaw extends BinanceBaseService { + private List currencyInfos; + private final Lock currencyInfoLock = new ReentrantLock(); public BinanceAccountServiceRaw( BinanceExchange exchange, ResilienceRegistries resilienceRegistries) { @@ -63,19 +68,24 @@ public WithdrawResponse withdraw(String coin, String address, BigDecimal amount) throws IOException, BinanceException { // the name parameter seams to be mandatory String name = address.length() <= 10 ? address : address.substring(0, 10); - return withdraw(coin, address, null, amount, name); + return withdraw(coin, address, null, amount, name, null); } public WithdrawResponse withdraw( - String coin, String address, String addressTag, BigDecimal amount) + String coin, String address, String addressTag, BigDecimal amount, String network) throws IOException, BinanceException { // the name parameter seams to be mandatory String name = address.length() <= 10 ? address : address.substring(0, 10); - return withdraw(coin, address, addressTag, amount, name); + return withdraw(coin, address, addressTag, amount, name, network); } private WithdrawResponse withdraw( - String coin, String address, String addressTag, BigDecimal amount, String name) + String coin, + String address, + String addressTag, + BigDecimal amount, + String name, + String network) throws IOException, BinanceException { return decorateApiCall( () -> @@ -85,6 +95,7 @@ private WithdrawResponse withdraw( addressTag, amount, name, + network, getRecvWindow(), getTimestampFactory(), apiKey, @@ -95,10 +106,16 @@ private WithdrawResponse withdraw( } public DepositAddress requestDepositAddress(Currency currency) throws IOException { + return requestDepositAddressWithNetwork(currency, null); + } + + public DepositAddress requestDepositAddressWithNetwork(Currency currency, String network) + throws IOException { return decorateApiCall( () -> binance.depositAddress( BinanceAdapters.toSymbol(currency), + network, getRecvWindow(), getTimestampFactory(), apiKey, @@ -214,4 +231,24 @@ public List getSubUserHistory( .withRateLimiter(rateLimiter(REQUEST_WEIGHT_RATE_LIMITER)) .call(); } + + protected List getCurrencyInfoCached() throws IOException { + currencyInfoLock.lock(); + try { + if (currencyInfos == null) { + currencyInfos = currencyInfos(); + } + currencyInfos = currencyInfos(); + } finally { + currencyInfoLock.unlock(); + } + + return currencyInfos; + } + + protected Optional getCurrencyInfo(Currency currency) throws IOException { + return getCurrencyInfoCached().stream() + .filter(info -> currency.equals(info.getCurrency())) + .findFirst(); + } } diff --git a/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/BitstampAdapters.java b/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/BitstampAdapters.java index 20b2266932f..dfa74b213be 100644 --- a/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/BitstampAdapters.java +++ b/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/BitstampAdapters.java @@ -242,7 +242,7 @@ public static UserTrades adaptTradeHistory(BitstampUserTransaction[] bitstampUse .timestamp(t.getDatetime()) .id(Long.toString(tradeId)) .orderId(Long.toString(t.getOrderId())) - .feeAmount(t.getFee()) + .feeAmount(getFeeFromString(t.getFee())) .feeCurrency(Currency.getInstance(t.getFeeCurrency().toUpperCase())) .build(); trades.add(trade); @@ -250,6 +250,17 @@ public static UserTrades adaptTradeHistory(BitstampUserTransaction[] bitstampUse return new UserTrades(trades, lastTradeId, TradeSortType.SortByID); } + private static BigDecimal getFeeFromString(String value) { + if("None".equals(value)) { + return BigDecimal.ZERO; + } + try { + return new BigDecimal(value); + } catch (NumberFormatException e) { + return BigDecimal.ZERO; + } + } + public static Map.Entry findNonzeroAmount(BitstampUserTransaction transaction) throws ExchangeException { for (Map.Entry entry : transaction.getAmounts().entrySet()) { @@ -294,7 +305,7 @@ public static List adaptFundingHistory( type, FundingRecord.Status.COMPLETE, null, - trans.getFee(), + getFeeFromString(trans.getFee()), null); fundingRecords.add(record); } diff --git a/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/dto/trade/BitstampUserTransaction.java b/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/dto/trade/BitstampUserTransaction.java index 03a4c6572f5..7ba5c63d3ab 100644 --- a/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/dto/trade/BitstampUserTransaction.java +++ b/xchange-bitstamp/src/main/java/org/knowm/xchange/bitstamp/dto/trade/BitstampUserTransaction.java @@ -20,7 +20,7 @@ public final class BitstampUserTransaction { private final long id; private final long order_id; private final TransactionType type; - private final BigDecimal fee; + private final String fee; private final Map amounts = new HashMap<>(); // possible pairs at the moment: btcusd, btceur, eurusd, xrpusd, xrpeur, xrpbtc private String base; // btc, eur, xrp @@ -41,7 +41,7 @@ public BitstampUserTransaction( @JsonProperty("id") long id, @JsonProperty("order_id") long order_id, @JsonProperty("type") TransactionType type, - @JsonProperty("fee") BigDecimal fee) { + @JsonProperty("fee") String fee) { this.datetime = BitstampUtils.parseDate(datetime); this.id = id; @@ -88,11 +88,11 @@ public TransactionType getType() { } public boolean isDeposit() { - return type == TransactionType.deposit; + return type == TransactionType.deposit || type == TransactionType.rippleDeposit || type == TransactionType.settlementTransfer; } public boolean isWithdrawal() { - return type == TransactionType.withdrawal; + return type == TransactionType.withdrawal || type == TransactionType.rippleWithdrawal; } public boolean isMarketTrade() { @@ -123,7 +123,7 @@ public String getBaseCurrency() { return base; } - public BigDecimal getFee() { + public String getFee() { return fee; } @@ -169,7 +169,9 @@ public enum TransactionType { sentAssetsToStaking, stakingReward, referralReward, - interAccountTransfer; + interAccountTransfer, + settlementTransfer, + unknown; @JsonCreator public static TransactionType fromString(int type) { @@ -194,10 +196,12 @@ public static TransactionType fromString(int type) { return stakingReward; case 32: return referralReward; + case 33: + return settlementTransfer; case 35: return interAccountTransfer; default: - throw new IllegalArgumentException(type + " has no corresponding value"); + return unknown; } } } diff --git a/xchange-bitstamp/src/test/java/org/knowm/xchange/bitstamp/BitstampCliTester.java b/xchange-bitstamp/src/test/java/org/knowm/xchange/bitstamp/BitstampCliTester.java new file mode 100644 index 00000000000..b9f9d89e7d3 --- /dev/null +++ b/xchange-bitstamp/src/test/java/org/knowm/xchange/bitstamp/BitstampCliTester.java @@ -0,0 +1,38 @@ +package org.knowm.xchange.bitstamp; + +import java.util.Date; +import java.util.List; +import org.knowm.xchange.Exchange; +import org.knowm.xchange.ExchangeFactory; +import org.knowm.xchange.dto.account.AccountInfo; +import org.knowm.xchange.dto.account.FundingRecord; +import org.knowm.xchange.dto.trade.UserTrades; +import org.knowm.xchange.service.account.AccountService; +import org.knowm.xchange.service.trade.TradeService; +import org.knowm.xchange.service.trade.params.DefaultTradeHistoryParamsTimeSpan; + +public class BitstampCliTester { + public static void main(String[] args) throws Exception{ + Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BitstampExchange.class, System.getenv("BITSTAMP_API_KEY"), System.getenv("BITSTAMP_SECRET_KEY")); + + AccountService accountService = exchange.getAccountService(); + + DefaultTradeHistoryParamsTimeSpan defaultTradeHistoryParamsTimeSpan = new DefaultTradeHistoryParamsTimeSpan(); + defaultTradeHistoryParamsTimeSpan.setStartTime(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24)); + + List fundingRecordList= accountService.getFundingHistory(defaultTradeHistoryParamsTimeSpan); + + System.out.println(fundingRecordList); + + + AccountInfo accountInfo = accountService.getAccountInfo(); + + System.out.println(accountInfo); + + TradeService tradeService = exchange.getTradeService(); + + UserTrades userTrades = tradeService.getTradeHistory(tradeService.createTradeHistoryParams()); + + System.out.println(userTrades); + } +} diff --git a/xchange-core/src/main/java/org/knowm/xchange/service/trade/params/NetworkWithdrawFundsParams.java b/xchange-core/src/main/java/org/knowm/xchange/service/trade/params/NetworkWithdrawFundsParams.java new file mode 100644 index 00000000000..ac5d2445d13 --- /dev/null +++ b/xchange-core/src/main/java/org/knowm/xchange/service/trade/params/NetworkWithdrawFundsParams.java @@ -0,0 +1,14 @@ +package org.knowm.xchange.service.trade.params; + +import lombok.ToString; +import lombok.Value; +import lombok.experimental.NonFinal; +import lombok.experimental.SuperBuilder; + +@Value +@NonFinal +@SuperBuilder +@ToString(callSuper = true) +public class NetworkWithdrawFundsParams extends DefaultWithdrawFundsParams { + String network; +}