cassandre-tech / cassandre-trading-bot

Create your Java crypto trading bot in minutes. Our Spring boot starter takes care of exchange connections, accounts, orders, trades, and positions so you can focus on building your strategies.
https://trading-bot.cassandre.tech
GNU General Public License v3.0
581 stars 164 forks source link

Kucoin - java.lang.NoSuchFieldError: TOO_MANY_REQUESTS at startup #787

Closed sebasira closed 2 years ago

sebasira commented 2 years ago

Release number Cassandre v5.0.5

Describe the bug When trying to connect to Kucoin real servers (no sandbox) I get

java.lang.IllegalStateException: java.lang.NoSuchFieldError: TOO_MANY_REQUESTS

The full trace is:

java.lang.IllegalStateException: java.lang.NoSuchFieldError: TOO_MANY_REQUESTS
    at org.knowm.xchange.client.ResilienceUtils$CallableApi.lambda$wrapCallable$0(ResilienceUtils.java:44)
    at org.knowm.xchange.client.ResilienceUtils$DecorateCallableApi.call(ResilienceUtils.java:86)
    at org.knowm.xchange.kucoin.KucoinMarketDataServiceRaw.lambda$getKucoinBaseFee$7(KucoinMarketDataServiceRaw.java:68)
    at org.knowm.xchange.kucoin.KucoinExceptionClassifier.classifyingExceptions(KucoinExceptionClassifier.java:15)
    at org.knowm.xchange.kucoin.KucoinMarketDataServiceRaw.getKucoinBaseFee(KucoinMarketDataServiceRaw.java:62)
    at org.knowm.xchange.kucoin.KucoinExchange.remoteInit(KucoinExchange.java:95)
    at org.knowm.xchange.BaseExchange.applySpecification(BaseExchange.java:113)
    at org.knowm.xchange.kucoin.KucoinExchange.applySpecification(KucoinExchange.java:53)
    at org.knowm.xchange.ExchangeFactory.createExchange(ExchangeFactory.java:130)
    at tech.cassandre.trading.bot.configuration.ExchangeAutoConfiguration.configure(ExchangeAutoConfiguration.java:150)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:429)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1780)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298)
    at ar.com.sebasira.anttrader.App.main(App.java:20)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NoSuchFieldError: TOO_MANY_REQUESTS
    at org.knowm.xchange.kucoin.KucoinResilience.lambda$createRegistries$0(KucoinResilience.java:28)
    at io.github.resilience4j.ratelimiter.RateLimiter.drainIfNeeded(RateLimiter.java:606)
    at io.github.resilience4j.ratelimiter.RateLimiter.onResult(RateLimiter.java:722)
    at io.github.resilience4j.ratelimiter.RateLimiter.lambda$decorateCheckedSupplier$9076412b$1(RateLimiter.java:216)
    at io.vavr.CheckedFunction0.lambda$unchecked$52349c75$1(CheckedFunction0.java:247)
    at io.vavr.Function0.get(Function0.java:149)
    at io.github.resilience4j.ratelimiter.RateLimiter.lambda$decorateCallable$6(RateLimiter.java:442)
    at org.knowm.xchange.client.ResilienceUtils$CallableApi.lambda$wrapCallable$0(ResilienceUtils.java:40)
    ... 40 more

To Reproduce Just run the proposed demo with Cassandre v5.0.5 and XChange v5.0.10 onwards. For older versions of XChange I get another issue, for that see #786

straumat commented 2 years ago

@sebasira can you tell me which rates did you put in your applications.properties ? thx

sebasira commented 2 years ago

Yes, of course! I'll put all the properties

cassandre.trading.bot.exchange.driver-class-name=kucoin
cassandre.trading.bot.exchange.username=<the-username>
cassandre.trading.bot.exchange.passphrase=<the-passphrase>
cassandre.trading.bot.exchange.key=<the-key>
cassandre.trading.bot.exchange.secret=<the-secret>

cassandre.trading.bot.exchange.modes.sandbox = false
cassandre.trading.bot.exchange.modes.dry = false

#  15seconds
cassandre.trading.bot.exchange.rates.account = 15000
cassandre.trading.bot.exchange.rates.ticker = 15000
cassandre.trading.bot.exchange.rates.trade = 15000

Then the @CassandreStrategy code is exactly the same as the one in the Quick Start

UPDATE

This is the relevant part of the logs

2021-10-26 09:07:10.285  INFO 11365 --- [  restartedMain] org.knowm.xchange.kucoin.KucoinExchange  : Calling Remote Init...
java.lang.IllegalStateException: java.lang.NoSuchFieldError: TOO_MANY_REQUESTS
    at org.knowm.xchange.client.ResilienceUtils$CallableApi.lambda$wrapCallable$0(ResilienceUtils.java:44)
    at org.knowm.xchange.client.ResilienceUtils$DecorateCallableApi.call(ResilienceUtils.java:86)
    at org.knowm.xchange.kucoin.KucoinMarketDataServiceRaw.lambda$getKucoinBaseFee$7(KucoinMarketDataServiceRaw.java:68)
    at org.knowm.xchange.kucoin.KucoinExceptionClassifier.classifyingExceptions(KucoinExceptionClassifier.java:15)
    at org.knowm.xchange.kucoin.KucoinMarketDataServiceRaw.getKucoinBaseFee(KucoinMarketDataServiceRaw.java:62)
    at org.knowm.xchange.kucoin.KucoinExchange.remoteInit(KucoinExchange.java:95)
    at org.knowm.xchange.BaseExchange.applySpecification(BaseExchange.java:113)
    at org.knowm.xchange.kucoin.KucoinExchange.applySpecification(KucoinExchange.java:53)
    at org.knowm.xchange.ExchangeFactory.createExchange(ExchangeFactory.java:130)
    at tech.cassandre.trading.bot.configuration.ExchangeAutoConfiguration.configure(ExchangeAutoConfiguration.java:150)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:429)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1780)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298)
    at ar.com.sebasira.anttrader.App.main(App.java:20)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NoSuchFieldError: TOO_MANY_REQUESTS
    at org.knowm.xchange.kucoin.KucoinResilience.lambda$createRegistries$0(KucoinResilience.java:28)
    at io.github.resilience4j.ratelimiter.RateLimiter.drainIfNeeded(RateLimiter.java:606)
    at io.github.resilience4j.ratelimiter.RateLimiter.onResult(RateLimiter.java:722)
    at io.github.resilience4j.ratelimiter.RateLimiter.lambda$decorateCheckedSupplier$9076412b$1(RateLimiter.java:216)
    at io.vavr.CheckedFunction0.lambda$unchecked$52349c75$1(CheckedFunction0.java:247)
    at io.vavr.Function0.get(Function0.java:149)
    at io.github.resilience4j.ratelimiter.RateLimiter.lambda$decorateCallable$6(RateLimiter.java:442)
    at org.knowm.xchange.client.ResilienceUtils$CallableApi.lambda$wrapCallable$0(ResilienceUtils.java:40)
    ... 40 more
2021-10-26 09:07:11.825  WARN 11365 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tech.cassandre.trading.bot.configuration.ExchangeAutoConfiguration': Invocation of init method failed; nested exception is tech.cassandre.trading.bot.util.exception.ConfigurationException: Unknown configuration error: java.lang.NoSuchFieldError: TOO_MANY_REQUESTS
straumat commented 2 years ago

@sebasira do you run it with maven? can you make another try please with mvn spring-boot:run ? thx

sebasira commented 2 years ago

I use gradle, but it should be the same as running with maven. I use IntelliJ and it's configured to run using gradle so unless you want me to try any specific thing, that's how I'm running the app.

I'm willing to help with anything I can, so let me know

straumat commented 2 years ago

@sebasira from my point of view, it can't come from gradle or intellij :( but I don't know yet why you have this. (For information, my trading bot runs on Kucoin). Can you copy the application logs at start ? Maybe i could see something :(

sebasira commented 2 years ago

Sorry the logs are the ones from above, before that there are the liquibase script execution.

I will try to create manually the connection using XChange library alone (maybe the errro is at their side). Maybe the problem is my account or my credentials. I'm also running them over Java 15, but I wouldn't see that as a problem.

I'll keep you posted!

sebasira commented 2 years ago

Just to add some ideas...

In the Spring Documentation of org.springframework.http.HttpStatus

TOO_MANY_REQUESTS public static final HttpStatus TOO_MANY_REQUESTS 429 Too Many Requests.

From the Kucoin docs:

Request Rate Limit When a rate limit is exceeded, a status of 429 will be returned.

These are my rates (I honestly don't believe a rate limit could be the issue):

cassandre.trading.bot.exchange.rates.account = 15000
cassandre.trading.bot.exchange.rates.ticker = 15000
cassandre.trading.bot.exchange.rates.trade = 15000

And I'm using Spring Boot v2.4.1 and I think you are using v2.5.6

And finally a kind of similar error from this StackOverflow question How do I resolve this error: java.lang.NoSuchFieldError: UTF_32BE?:

The problem occurs because you have a version of Apache Commons IO in your classpath that is incompatible with the Owl API.

Do any of this ring a bell?

sebasira commented 2 years ago

News here!

I've clone the repo crypto-trading-bot-tutorial, make some adjustments to use Gradle instead of Maven and also update some parts of the code according to newer version of the libraries and I'm using my credentials and I connect to Kucoin successfully. I'm still getting this other issue #786, but not the:

java.lang.NoSuchFieldError: TOO_MANY_REQUESTS at startup

What I've done based on the previous comment, I remove any other dependencies I had. So maybe the problem lies there. I will try adding them one by one and let you know when I found the troublemaker one.

straumat commented 2 years ago

@sebasira thx for searching. I will try to look at all issues tomorrow night

sebasira commented 2 years ago

Gotcha!

It was due to this dependency:

compile "com.sun.jersey:jersey-client:1.18.1"

I try updating it to latest 1.19.4 but the same error occurs. If I remove it, then it won't throw that exception.

That dependency was for a feature in my app that I won't implement right now so I can remove it.