knowm / XChange

XChange is a Java library providing a streamlined API for interacting with 60+ Bitcoin and Altcoin exchanges providing a consistent interface for trading and accessing market data.
http://knowm.org/open-source/xchange/
MIT License
3.87k stars 1.94k forks source link

JsonMappingException in BTERPollingAccountService.getAccountInfo() #367

Closed nimrood closed 10 years ago

nimrood commented 10 years ago
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token
 at [Source: java.io.StringReader@599855ed; line: 1, column: 17]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:306)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:559)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:393)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942)
    at si.mazi.rescu.HttpTemplate.executeRequest(HttpTemplate.java:143)
    at si.mazi.rescu.RestInvocationHandler.invokeHttp(RestInvocationHandler.java:68)
    at si.mazi.rescu.RestInvocationHandler.invoke(RestInvocationHandler.java:53)
    at com.sun.proxy.$Proxy10.getFunds(Unknown Source)
    at com.xeiam.xchange.bter.service.polling.BTERPollingAccountServiceRaw.getBTERAccountInfo(BTERPollingAccountServiceRaw.java:44)
    at com.xeiam.xchange.bter.service.polling.BTERPollingAccountService.getAccountInfo(BTERPollingAccountService.java:49)
nimrood commented 10 years ago

Not sure what's going on here --- OrderHistory seems to work fine. I haven't tried to place/cancel orders yet because when I try to get account balance ----- BTER class throws an exception.

timmolter commented 10 years ago

If you can log the returned raw JSON and paste it here, I could take a look at what's going on.

nimrood commented 10 years ago

Yes, I was just getting ready to try and set up XChange develop branch (I hear it's a bear to get it up and running w/ all the deps).

At any rate, I just found this similar issue also: #261 Seems similar. BTER Added a new currency on 3/17 ... maybe it isn't mapped? https://bter.com/article/303

nimrood commented 10 years ago

@timmolter is it possible to have mazi.rescu log the JSON? DEBUG log level doesn't seem provide the JSON response.

timmolter commented 10 years ago

try TRACE. That's what I always set it to.

nimrood commented 10 years ago

Got it! Appears to be a valid bug --- all my wallets are empty, and so is the accountInfo JSON response:

[main] TRACE si.mazi.rescu.HttpTemplate - Response body: {"result":"true","available_funds":[]}
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token
nimrood commented 10 years ago

accountInfo() works fine as long as you a balance in a wallet.

timmolter commented 10 years ago

@mmazi We need your advice here! How would you handle the deserialization of the two possible return examples below?

{
   "result":"true",
   "available_funds":{
      "BTC":"0.00010165",
      "LTC":"0.00166859",
      "FTC":"0.00003326",
      "CNY":"0.01018463"
   },
   "locked_funds":{
      "LTC":"0.384"
   }
}

And when available_funds is empty...

{
    "result":"true",
    "available_funds":[]
}
mmazi commented 10 years ago

This looks like a pure json/jackson issue; I don't really know how to solve it. It seems to me that [] is actually an invalid json for a map/object (should be {}); then this is a bug on BTER's side. Or perhaps jackson can be persuaded to deserialize it correctly as an empty map somehow.

timmolter commented 10 years ago

Thanks, @mmazi .

sacrelege commented 10 years ago

Not sure if this is related, but I'm getting the following exception "sometimes" on android using xchange-2.0.0, when executing PollingAccountService.getAccountInfo() on bitstamp. This is because of the unexpected response from bitstamp (see the response at the bottom).

04-14 14:37:17.030: W/System.err(28909): com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')

Here the POST request (I've removed the key, signature and nonce):

04-14 14:37:16.719: D/s*.m*.r*.HttpTemplate(28909): Executing POST request at https://www.bitstamp.net/api/balance/
04-14 14:37:16.719: V/s*.m*.r*.HttpTemplate(28909): Request body = key=[key]&signature=[sig]&nonce=[none]
04-14 14:37:16.719: V/s*.m*.r*.HttpTemplate(28909): Request headers = {}
04-14 14:37:16.719: V/s*.m*.r*.HttpTemplate(28909): Header request property: key='Content-Type', value='application/x-www-form-urlencoded'
04-14 14:37:16.719: V/s*.m*.r*.HttpTemplate(28909): Header request property: key='Accept', value='application/json'
04-14 14:37:16.719: V/s*.m*.r*.HttpTemplate(28909): Header request property: key='User-Agent', value='ResCU JDK/6 AppleWebKit/535.7 Chrome/16.0.912.36 Safari/535.7'
04-14 14:37:16.719: V/s*.m*.r*.HttpTemplate(28909): Header request property: key='Accept-Charset', value='UTF-8'

The response from bitstamp:

04-14 14:37:17.030: V/s*.m*.r*.HttpTemplate(28909): Response body: <html><head><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW"><meta name="format-detection" content="telephone=no"><meta name="viewport" content="initial-scale=1.0"></head><body style="margin:0px"><iframe src="/_Incapsula_Resource?CWUDNSAI=23&incident_id=189000100074143718-348506535606681760&edet=12&cinfo=2e7f8005b90b7dbb08000000" frameborder=0 width="100%" height="100%" marginheight="0px" marginwidth="0px">Request unsuccessful. Incapsula incident ID: 189000100074143718-348506535606681760</iframe></body></html>

I have a positive BTC balance and 0 USD at bitstamp. Sometimes it works, sometimes I get the "Request unsuccessful" from bitstamp. I do not change any code during the test runs and I didn't execute any trades on bitstamp - so the balance and everything else stays the same. Even if I kill my android app and restart it, its like a 50:50 chance to get the accountinfo/balance.

Related code:

ExchangeSpecification exchangeSpecification = new BitstampExchange().getDefaultExchangeSpecification();
exchangeSpecification.setUserName("123456");
exchangeSpecification.setApiKey("asdf");
exchangeSpecification.setSecretKey("yxcv");
exchange = ExchangeFactory.INSTANCE.createExchange(exchangeSpecification);
accountService = exchange.getPollingAccountService();
AccountInfo accountInfo = accountService.getAccountInfo();
mmazi commented 10 years ago

The way I understand this is that this is due to Bitstamp's Incapsula DOS protection. Some of your requests are not coming through the Incapsula protection to Bitstamps's servers. There is no useful data in the response in such cases.

Make sure you're not querying the API too frequently (I think there are some limits, please check the Bitstamp API docs).

There have been some DDoS attacks targeted at BTC-E lately, perhaps Bitstamps is under some attacs too and Incapsula might be tightening their security and denying too frequent requests from you. I think it's pretty hard to tell DDoS attack request from frequent honest client requests.

sacrelege commented 10 years ago

According to their doc, the limit is 600 per 10min. However it seems to be lower. Thanks for your fast reply.