class CoinmateAccountService extends CoinmateAccountServiceRaw implements AccountService {

  public static final int DEFAULT_RESULT_LIMIT = 100;

  public CoinmateAccountService(Exchange exchange) {
    super(exchange);
  }

  @Override
  public AccountInfo getAccountInfo() throws IOException {
    return new AccountInfo(CoinmateAdapters.adaptWallet(getCoinmateBalance()));
  }

  @Override
  public Map<Instrument, Fee> getDynamicTradingFeesByInstrument() throws IOException {
    Set<Instrument> instruments = exchange.getExchangeMetaData().getInstruments().keySet();
    HashMap<Instrument, Fee> result = new HashMap<>();
    for (Instrument instrument : instruments) {
      CoinmateTradingFeesResponseData data =
          getCoinmateTraderFees(CoinmateUtils.getPair(instrument));
      Fee fee = new Fee(data.getMaker(), data.getTaker());
      result.put(instrument, fee);
    }
    return result;
  }

  @Override
  public String withdrawFunds(Currency currency, BigDecimal amount, String address)
      throws IOException {
    CoinmateTradeResponse response;

    if (currency.equals(Currency.BTC)) {
      response = coinmateBitcoinWithdrawal(amount, address);
    } else if (currency.equals(Currency.LTC)) {
      response = coinmateLitecoinWithdrawal(amount, address);
    } else if (currency.equals(Currency.ETH)) {
      response = coinmateEthereumWithdrawal(amount, address);
    } else if (currency.equals(Currency.XRP)) {
      response = coinmateRippleWithdrawal(amount, address);
    } else if (currency.equals(Currency.ADA)) {
      response = coinmateCardanoWithdrawal(amount, address);
    } else if (currency.equals(Currency.SOL)) {
      response = coinmateSolanaWithdrawal(amount, address);
    } else if (currency.equals(Currency.USDT)) {
      Long tradeId = coinmateWithdrawVirtualCurrency(amount, address, Currency.USDT.getCurrencyCode(), AmountType.GROSS, FeePriority.HIGH, null);
      return Long.toString(tradeId);
    } else {
      throw new IOException(
          "Wallet for currency" + currency.getCurrencyCode() + " is currently not supported");
    }

    return Long.toString(response.getData());
  }

  @Override
  public String withdrawFunds(Currency currency, BigDecimal amount, AddressWithTag address)
      throws IOException {
    if (currency.equals(Currency.XRP)) {
      Long tradeId = coinmateWithdrawVirtualCurrency(amount, address.getAddress(), currency.getCurrencyCode(), AmountType.GROSS, FeePriority.HIGH, address.getAddressTag());
      return Long.toString(tradeId);
    } else {
      return withdrawFunds(currency, amount, address.getAddress());
    }
  }

  @Override
  public String withdrawFunds(WithdrawFundsParams params) throws IOException {
    if (params instanceof DefaultWithdrawFundsParams) {
      DefaultWithdrawFundsParams defaultParams = (DefaultWithdrawFundsParams) params;

      if (defaultParams.getCurrency().equals(Currency.XRP)) {
        Long tradeId = coinmateWithdrawVirtualCurrency(defaultParams.getAmount(), defaultParams.getAddress(), defaultParams.getCurrency().getCurrencyCode(), AmountType.GROSS, FeePriority.HIGH, defaultParams.getAddressTag());
        return Long.toString(tradeId);
      }

      return withdrawFunds(
          defaultParams.getCurrency(), defaultParams.getAmount(), defaultParams.getAddress());
    }
    throw new IllegalStateException("Don't know how to withdraw: " + params);
  }

  @Override
  public String requestDepositAddress(Currency currency, String... args) throws IOException {<FILL_FUNCTION_BODY>}

  @Override
  public TradeHistoryParams createFundingHistoryParams() {
    return new CoinmateFundingHistoryParams();
  }

  @Override
  public List<FundingRecord> getFundingHistory(TradeHistoryParams params) throws IOException {

    TradeHistoryParamsSorted.Order order = TradeHistoryParamsSorted.Order.asc;
    Integer limit = 1000;
    int offset = 0;
    Long timestampFrom = null;
    Long timestampTo = null;

    if (params instanceof TradeHistoryParamsIdSpan) {
      String transactionId = ((TradeHistoryParamsIdSpan) params).getStartId();
      if (transactionId != null) {
        CoinmateTransferDetail coinmateTransferDetail =
            getCoinmateTransferDetail(toLong(transactionId));
        return CoinmateAdapters.adaptFundingDetail(coinmateTransferDetail);
      }
    }

    if (params instanceof TradeHistoryParamOffset) {
      offset = Math.toIntExact(((TradeHistoryParamOffset) params).getOffset());
    }

    if (params instanceof TradeHistoryParamLimit) {
      limit = ((TradeHistoryParamLimit) params).getLimit();
    }

    if (params instanceof TradeHistoryParamsSorted) {
      order = ((TradeHistoryParamsSorted) params).getOrder();
    }

    if (params instanceof TradeHistoryParamsTimeSpan) {
      TradeHistoryParamsTimeSpan thpts = (TradeHistoryParamsTimeSpan) params;
      if (thpts.getStartTime() != null) {
        timestampFrom = thpts.getStartTime().getTime();
      }
      if (thpts.getEndTime() != null) {
        timestampTo = thpts.getEndTime().getTime();
      }
    }
    CoinmateTransferHistory coinmateTransferHistory =
        getTransfersData(limit, timestampFrom, timestampTo);

    CoinmateTransactionHistory coinmateTransactionHistory =
        getCoinmateTransactionHistory(
            offset,
            limit,
            CoinmateAdapters.adaptSortOrder(order),
            timestampFrom,
            timestampTo,
            null);
    return CoinmateAdapters.adaptFundingHistory(
        coinmateTransactionHistory, coinmateTransferHistory);
  }

  public static class CoinmateFundingHistoryParams
      extends CoinmateTradeService.CoinmateTradeHistoryHistoryParams {}
}

    CoinmateDepositAddresses addresses;
    if (currency.equals(Currency.BTC)) {
      addresses = coinmateBitcoinDepositAddresses();
    } else if (currency.equals(Currency.LTC)) {
      addresses = coinmateLitecoinDepositAddresses();
    } else if (currency.equals(Currency.ETH)) {
      addresses = coinmateEthereumDepositAddresses();
    } else if (currency.equals(Currency.XRP)) {
      addresses = coinmateRippleDepositAddresses();
    } else if (currency.equals(Currency.ADA)) {
      addresses = coinmateCardanoDepositAddresses();
    } else if (currency.equals(Currency.SOL)) {
      addresses = coinmateSolanaDepositAddresses();
    } else if (currency.equals(Currency.USDT)) {
      List<String> addressesAll = coinmateVirtualCurrencyDepositAddresses(currency.getCurrencyCode());
      if (addressesAll.isEmpty()) {
        return null;
      }
      return addressesAll.get(0);
    } else {
      throw new IOException(
          "Wallet for currency" + currency.getCurrencyCode() + " is currently not supported");
    }

    if (addresses.getData().isEmpty()) {
      return null;
    } else {
      // here we return only the first address
      return addresses.getData().get(0);
    }
  
<methods>public void <init>(org.knowm.xchange.Exchange) ,public org.knowm.xchange.coinmate.dto.account.CoinmateDepositAddresses coinmateBitcoinDepositAddresses() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateBitcoinWithdrawal(java.math.BigDecimal, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateBitcoinWithdrawal(java.math.BigDecimal, java.lang.String, org.knowm.xchange.coinmate.dto.account.FeePriority) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateDepositAddresses coinmateCardanoDepositAddresses() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateCardanoWithdrawal(java.math.BigDecimal, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateDepositAddresses coinmateEthereumDepositAddresses() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateEthereumWithdrawal(java.math.BigDecimal, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateDepositAddresses coinmateLitecoinDepositAddresses() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateLitecoinWithdrawal(java.math.BigDecimal, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateDepositAddresses coinmateRippleDepositAddresses() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateRippleWithdrawal(java.math.BigDecimal, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateDepositAddresses coinmateSolanaDepositAddresses() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTradeResponse coinmateSolanaWithdrawal(java.math.BigDecimal, java.lang.String) throws java.io.IOException,public List<org.knowm.xchange.coinmate.dto.account.UnconfirmedDeposits> coinmateUnconfirmedVirtualCurrencyDeposits(java.lang.String) throws java.io.IOException,public ArrayList<java.lang.String> coinmateVirtualCurrencyDepositAddresses(java.lang.String) throws java.io.IOException,public java.lang.Long coinmateWithdrawVirtualCurrency(java.math.BigDecimal, java.lang.String, java.lang.String, org.knowm.xchange.coinmate.dto.account.AmountType, org.knowm.xchange.coinmate.dto.account.FeePriority, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateBalance getCoinmateBalance() throws java.io.IOException,public org.knowm.xchange.coinmate.dto.account.CoinmateTradingFeesResponseData getCoinmateTraderFees(java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTransactionHistory getCoinmateTransactionHistory(int, java.lang.Integer, java.lang.String, java.lang.Long, java.lang.Long, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTransferDetail getCoinmateTransferDetail(java.lang.Long) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTransferHistory getCoinmateTransferHistory(java.lang.Integer, java.lang.Integer, org.knowm.xchange.coinmate.dto.account.TransferHistoryOrder, java.lang.Long, java.lang.Long, java.lang.String) throws java.io.IOException,public org.knowm.xchange.coinmate.dto.trade.CoinmateTransferHistory getTransfersData(java.lang.Integer, java.lang.Long, java.lang.Long) throws java.io.IOException<variables>private final non-sealed org.knowm.xchange.coinmate.CoinmateAuthenticated coinmateAuthenticated,private final non-sealed org.knowm.xchange.coinmate.service.CoinmateDigest signatureCreator