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

#56 split gdax java into library and client #62

Merged
merged 45 commits into from
Jul 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
bd1fdb1
Initial steps to break client / desktop app out into separate modules…
robevansuk Oct 30, 2019
ffd5c3a
update websocket and REST urls in application-*.yml files to point to…
robevansuk Oct 30, 2019
83d3090
re-add application-*.yml to gitignore to prevent anyone committing th…
robevansuk Oct 30, 2019
7ccc374
rename tests that need to run against the live sandbox as "Integratio…
robevansuk Nov 2, 2019
1a82c9a
move config to spring boot application module
robevansuk Dec 11, 2019
acce2fa
Some rearrangement, remove RestTemplate as the spring context/contain…
robevansuk Dec 23, 2019
9e5935d
decoupling orderbook and websocketfeed by making use of the addMessag…
robevansuk Dec 24, 2019
e0f2e72
Begin decoupling spring from the coinbase pro library and using it on…
robevansuk Dec 24, 2019
4811269
Remove spring from api integration project.
robevansuk Dec 24, 2019
3dfc0cf
some documentation updates
robevansuk Dec 24, 2019
1a8b70e
update the documentation and the coinbase exchange class name
robevansuk Dec 24, 2019
b5db168
update the banner
robevansuk Dec 24, 2019
9ad381a
update config to use exchange as the config var name
robevansuk Dec 24, 2019
7b920f9
re-ignore application*.yml files
robevansuk Dec 24, 2019
d689a3e
use correct .yml file extension in references
robevansuk Dec 24, 2019
d513246
Successful separation of gui from library. Updated the gui to integra…
robevansuk Jan 28, 2020
974d8d6
adding desktop gui application.yml file for configuring the applicati…
robevansuk Jan 28, 2020
6e07451
clean up
robevansuk May 11, 2020
1e955ee
Merge remote-tracking branch 'origin/master' into #56_Split_gdax-java…
robevansuk May 11, 2020
7b90128
re-jig to have a gradle multiproject build that has the api as a prop…
robevansuk May 12, 2020
6e65abc
remove redundant imports
robevansuk May 12, 2020
51af91e
remove redundant gson lib
robevansuk May 12, 2020
9210796
minor improvements suggested by IntelliJ
robevansuk May 12, 2020
359b356
amend confusing javadoc message
robevansuk May 12, 2020
602c520
attempting to merge all changes together following some merge mayhem
robevansuk May 12, 2020
1be9184
refactoring the live orderbook in the Gui and the tests of OrderBookM…
robevansuk May 18, 2020
61ff51c
Large refactor. Need to fix orderbook as its currently broken
robevansuk May 27, 2020
dc8100c
fix compilation issues with market data tests
robevansuk May 27, 2020
5ad1609
refactor a order message insertion based on sequence id
robevansuk May 27, 2020
e693401
extract constants so they can be used in tests and live orderbook code
robevansuk Jun 1, 2020
7e76d30
fix json deserialising to fix missing message `type` information whic…
robevansuk Jun 2, 2020
869e3f3
Updates to ensure parsing from JSON sets the `type` for L2UpdateMessa…
robevansuk Jun 2, 2020
ae84231
Fix TickerMessage definition and addition of Test to ensure its parse…
robevansuk Jun 2, 2020
a03c873
Fix for json parsing to set the message type. This should fix the liv…
robevansuk Jun 5, 2020
c82f168
Fix datatype for product ID
robevansuk Jun 5, 2020
f94e04c
removing some redundant code,editing comments,renaming variables. A b…
robevansuk Jun 5, 2020
f8919f3
Removed CompletableFuture for the websocket. The websocket connection…
robevansuk Jun 5, 2020
e9e825f
introduce sleep after websocket connects to allow enough of a queue t…
robevansuk Jun 5, 2020
560a32e
price entries were appearing twice when we had orders with prices lik…
robevansuk Jun 6, 2020
b6ebe67
rename orderbookview to orderbookpresentation as it will host the pre…
robevansuk Jun 7, 2020
a2e28c5
Remove Gui ready for a rebuild
robevansuk Jul 13, 2020
7029dca
revert removal of websocket feed and remove all references to previou…
robevansuk Jul 14, 2020
b0f5c6a
add build.gradle for new security package
robevansuk Jul 14, 2020
6091a2a
updated README with latest changes
robevansuk Jul 14, 2020
1b77d0a
Merge branch 'master' into #56_Split_gdax-java_into_library_and_client
robevansuk Jul 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 4 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
*.iml
.idea/
.gradle/
build/
gdax.properties
*.log
classes/
out/
application*.yml
**/classes/
**/build/
**/out/
**/application.*.yml
90 changes: 51 additions & 39 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing

If you'd like to contribute you'd be more than welcome. The code base is ever growing and in order to make it usable by as many people as possible, we'd like to hear your ideas, suggestions, feedback, as well as accepting your code improvements.
If you'd like to contribute you'd be more than welcome. The code base is ever growing and in order to make it usable by as many people as possible, we'd like your ideas, suggestions, feedback, as well as accepting your code improvements.

Join us on the Gitter.im channel (chat link at the top of the main README.md file)

Expand All @@ -10,35 +10,18 @@ Please ensure where possible, tests are included with any new features. Tests in

Please also update/amend the README.md as necessary regarding changes so that it is kept up to date.

# SPRING BOOT - Dependency injection and auto wiring

Spring is great. Having developed for many years now, developers on this project have built applications large and small. Simply put without Spring/DI, the skill necessary to develop an application of this size becomes messy/chaotic due to the complexity that comes with creating large codebases with many dependencies. New-ing up classes to configure other classes, details getting lost in the code. Etc. Its all considerably easier using the Spring framework.

Spring helps alleviate all the spaghetti configuration. I'll give a high level overview of Spring concepts utilised in this codebase.

Spring Beans - Java instances. Beans are slightly different to POJOs as the lifecycle of a bean is managed by spring - from instantiation to termination.

`@Component` - whenever you write a class, marking it with the @Component annotation makes a class instance available in the Spring Context (essentially a registry of instances of various objects). Any instance in the spring context can be fetched and passed in to a constructor at instantiation using the `@Autowired` Annotation. `@Components` must be configured correctly at instantiation. After that changing them is done through event driven processes (buttons/keyboard) which you will have to write code for.
`@Autowired` - Used to get instances of a particular object at instantiation time. A constructor or field variable marked with `@Autowired` will have an instance of the class provided so long as one (and only one) exists in the Spring Context. To get a Java object into the Spring Context, mark it with `@Component`
`@SpringBootConfiguration` - tells Spring there's some configured items in the class - Beans/factories/etc.
`@SpringBootApplication` - used on the application entry point. Tells Spring where to begin from - usually some top level class file.
`@Value` - used heavily to pass properties from application.yml files, into the constructors of various classes. If we want to configure a class with a true/false switch we can just declare a new true/false variable in the application.yml called, say, `gdax.isEnabled`, set it to `true`, then when we want to pass it into a constructor we just write a constructor param and annotate it with `@Value("${gdax.isEnabled}") boolean isEnabled` and isEnabled in our code will pick up the value that is set in the config. Since .yml files are structured, we can group elements together more sensibly than a standard properties file. The only time Spring/yml struggles with config in a file is when we declare a list. We can cross that bridge if/when we get to it, For now its not a concern but something to be aware of.

Spring boot also makes our lives easier by allowing us to set a testing profile that differs from the live configuration.

# TESTING

Tests act as documentation for the code, demonstrating actual usage.
If you're not familiar with TDD then perhaps now is a great time to begin.
If you're not familiar with TDD then now is a great time to begin!
Test Driven Development will:
- help determine what to build
- help you to prioritise which elements need to be in place first
- help you to implement a solution using the minimal amount of code
- the design of your code should emerge from the tests
- frontload the stress of the design of your code, which should emerge from/be driven by the tests

Not testing code leads to poor implementations that are hard to read, debug and are typically unmaintainable.


If you'd like to contribute to the codebase, your code must be robust. To ensure its Robust you must provide tests that cover the scenarios your solution should handle.

Currently tests follow a given/when/then approach. That is:
Expand All @@ -50,23 +33,22 @@ You'll spot this pattern clearly in the test code because most of the preconditi

Test naming - typically tests are named in the following way: `shouldDoXWhenY`.

The best example to follow in this codebase is probably the `LiveOrderBookTest`

If you spot a bug, write a test for it to highlight the issue, create a fix and submit a pull request for review.
If you spot a bug, write a test for it to highlight the issue, create a fix, and submit a pull request for review.

Code that has very little in the way of testing is more likely to be rejected.

The current codebase tests what is sensible and possible to test. Mainly getting things. Testing items are submitted to the server isn't ideal as the GDAX sandbox no longer exists so it isn't particularly safe to do this especially for placing orders.
The current codebase tests what is sensible and possible to test. Mainly getting things.

# I want to create some new element in the codebase
## I want to create some new element in the codebase

Where do you start?

Add this template, add the relevant tests you want, then begin implementing your code.

Note Dependency injection is far more predictable in spring if constructor injection is used (i.e. put the @Autowired annotation on the constructor rather than a field in your class).
Note Dependency injection is far more predictable in spring if constructor injection is used i.e. put the `@Autowired`/`@Inject` annotation on the constructor rather than a field in your class.
If a class only has one constructor the `@Autowired` annotation is not necessary.

```
```java
@Component
public class NewComponent {

Expand All @@ -77,34 +59,64 @@ public class NewComponent {
}
```

Now if you want to utilise some of the already implemented features of this codebase like getting your account details, you can autowire in the already existent (@)component `AccountService`
If you want to utilise an existing service, you just need the configuration similar to below:

```java
@SpringBootConfiguration
public class ApplicationConfiguration {

@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}

@Bean
public Signature signature(@Value("${exchange.secret}") String secret) {
return new Signature(secret);
}

@Bean
public CoinbaseExchange coinbasePro(@Value("${exchange.key}") String publicKey,
@Value("${exchange.passphrase}") String passphrase,
@Value("${exchange.baseUrl}") String baseUrl,
Signature signature,
ObjectMapper objectMapper) {
return new CoinbaseExchangeImpl(publicKey, passphrase, baseUrl, signature, objectMapper);
}

/**
* now you can create services by wiring in the CoinbaseExchange object to handle incoming/outgoing requests.
**/

@Bean
public AccountService accountService(CoinbaseExchange exchange) {
return new AccountService(exchange);
}
}
```

```java
@Component
public class NewComponent {
public class MyApplication {

private AccountService accountService;

@Autowired
public NewComponent(AccountService accountService) {
public MyApplication(AccountService accountService) {
this.accountService = accountService;
}

public void printMyAccounts() {
List<Account> accounts = accountService.getAccounts();
for(Account account: accounts) {
System.out.println(accounts.getBalance());
}
}
}
```

You can now add more code to the main method of this codebase and interact with your new code. You'll need a reference to the new code which can be obtained with:

```
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(GdaxApiApplication.class)
.headless(false).run(args);
If you can do TDD, great. If not, add it after you've coded a solution.

NewComponent newComponent = ctx.getBean(newComponent.class);
newComponent.printMyAccounts();
... etc.
```
Tests all follow a "given, when, then" style... *given* some preconditions `X`, *when* I exercise a given method `Y` (typically a method call on its own line), *then* the results are expected to be `Z` (if not the test fails).