Skip to content

Commit 002c80f

Browse files
authored
#56 split gdax java into library and client (#62)
* Initial steps to break client / desktop app out into separate modules and create a separate spring boot implementation of the client lib * update websocket and REST urls in application-*.yml files to point to new pro.coinbase.com urls * re-add application-*.yml to gitignore to prevent anyone committing their private API keys/secrets by mistake * rename tests that need to run against the live sandbox as "IntegrationTest" so they can be run only when we actually want to test the codebase against a live implementation of the exchange. Also updated the gradle script to use submodules * move config to spring boot application module * Some rearrangement, remove RestTemplate as the spring context/container provides this anyway, and some renaming of GDAX -> CoinbasePro * decoupling orderbook and websocketfeed by making use of the addMessageHandler method * Begin decoupling spring from the coinbase pro library and using it only in the desktop client * Remove spring from api integration project. Remove spring boot application plugin from the api project Some renaming in a vain attempt to fix the multiproject build issues * some documentation updates * update the documentation and the coinbase exchange class name * update the banner * update config to use exchange as the config var name * re-ignore application*.yml files * use correct .yml file extension in references * Successful separation of gui from library. Updated the gui to integrate with the latest websocket feed implementation - now using "full" channel. Alsoo updates to the README (some amendments still necessary) and more updates to pull apart the 'library' from the desktop GUI * adding desktop gui application.yml file for configuring the application for your trading account * clean up * re-jig to have a gradle multiproject build that has the api as a proper library and the gui and websocket feed as individual modules * remove redundant imports * remove redundant gson lib * minor improvements suggested by IntelliJ * amend confusing javadoc message * attempting to merge all changes together following some merge mayhem * refactoring the live orderbook in the Gui and the tests of OrderBookModelTest to be more concise, less repetitive. A lot of tidying up assertions. Updated CONTRIBUTING.md (minor). Getting the gradle multiproject build working. Lots of minor fixes * Large refactor. Need to fix orderbook as its currently broken * fix compilation issues with market data tests * refactor a order message insertion based on sequence id * extract constants so they can be used in tests and live orderbook code * fix json deserialising to fix missing message `type` information which has broken the live orderbook. * Updates to ensure parsing from JSON sets the `type` for L2UpdateMessages, ErrorMessages, SnapshotMessage * Fix TickerMessage definition and addition of Test to ensure its parsed correctly from Json * Fix for json parsing to set the message type. This should fix the live orderbook * Fix datatype for product ID * removing some redundant code,editing comments,renaming variables. A bit of clarity added. Test also added to test a live scenario which appeared to be failing. * Removed CompletableFuture for the websocket. The websocket connection needs to be sequential for the orderbookto work properly. Update code to remove deprecated value. * introduce sleep after websocket connects to allow enough of a queue to form for the GUI that we can reliably reconstruct a live orderbook on top of the full orderbook snapshot from the MarketData endpoint. * price entries were appearing twice when we had orders with prices like 3500.23 and 3500.23000. The comparison wasn't equivalent. setting the scale on the OrderBookMessage should fix this. * rename orderbookview to orderbookpresentation as it will host the presentation layer only * Remove Gui ready for a rebuild * revert removal of websocket feed and remove all references to previously implemented GUI. Also introduced a security package so that the Signature class can be shared between the websocketfeed module and the api module. CONTRIBUTING.md also updated * add build.gradle for new security package * updated README with latest changes Co-authored-by: robevans <[email protected]>
1 parent e4f6686 commit 002c80f

File tree

124 files changed

+2392
-2480
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+2392
-2480
lines changed

.gitignore

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
*.iml
22
.idea/
33
.gradle/
4-
build/
5-
gdax.properties
64
*.log
7-
classes/
8-
out/
9-
application*.yml
5+
**/classes/
6+
**/build/
7+
**/out/
8+
**/application.*.yml

CONTRIBUTING.md

+51-39
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing
22

3-
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.
3+
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.
44

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

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

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

13-
# SPRING BOOT - Dependency injection and auto wiring
14-
15-
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.
16-
17-
Spring helps alleviate all the spaghetti configuration. I'll give a high level overview of Spring concepts utilised in this codebase.
18-
19-
Spring Beans - Java instances. Beans are slightly different to POJOs as the lifecycle of a bean is managed by spring - from instantiation to termination.
20-
21-
`@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.
22-
`@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`
23-
`@SpringBootConfiguration` - tells Spring there's some configured items in the class - Beans/factories/etc.
24-
`@SpringBootApplication` - used on the application entry point. Tells Spring where to begin from - usually some top level class file.
25-
`@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.
26-
27-
Spring boot also makes our lives easier by allowing us to set a testing profile that differs from the live configuration.
28-
2913
# TESTING
3014

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

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

41-
4225
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.
4326

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

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

53-
The best example to follow in this codebase is probably the `LiveOrderBookTest`
54-
55-
If you spot a bug, write a test for it to highlight the issue, create a fix and submit a pull request for review.
36+
If you spot a bug, write a test for it to highlight the issue, create a fix, and submit a pull request for review.
5637

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

59-
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.
40+
The current codebase tests what is sensible and possible to test. Mainly getting things.
6041

61-
# I want to create some new element in the codebase
42+
## I want to create some new element in the codebase
6243

6344
Where do you start?
6445

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

67-
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).
48+
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.
49+
If a class only has one constructor the `@Autowired` annotation is not necessary.
6850

69-
```
51+
```java
7052
@Component
7153
public class NewComponent {
7254

@@ -77,34 +59,64 @@ public class NewComponent {
7759
}
7860
```
7961

80-
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`
62+
If you want to utilise an existing service, you just need the configuration similar to below:
8163

64+
```java
65+
@SpringBootConfiguration
66+
public class ApplicationConfiguration {
67+
68+
@Bean
69+
public ObjectMapper objectMapper() {
70+
ObjectMapper objectMapper = new ObjectMapper();
71+
objectMapper.registerModule(new JavaTimeModule());
72+
return objectMapper;
73+
}
74+
75+
@Bean
76+
public Signature signature(@Value("${exchange.secret}") String secret) {
77+
return new Signature(secret);
78+
}
79+
80+
@Bean
81+
public CoinbaseExchange coinbasePro(@Value("${exchange.key}") String publicKey,
82+
@Value("${exchange.passphrase}") String passphrase,
83+
@Value("${exchange.baseUrl}") String baseUrl,
84+
Signature signature,
85+
ObjectMapper objectMapper) {
86+
return new CoinbaseExchangeImpl(publicKey, passphrase, baseUrl, signature, objectMapper);
87+
}
88+
89+
/**
90+
* now you can create services by wiring in the CoinbaseExchange object to handle incoming/outgoing requests.
91+
**/
92+
93+
@Bean
94+
public AccountService accountService(CoinbaseExchange exchange) {
95+
return new AccountService(exchange);
96+
}
97+
}
8298
```
99+
100+
```java
83101
@Component
84-
public class NewComponent {
102+
public class MyApplication {
85103

86104
private AccountService accountService;
87105

88106
@Autowired
89-
public NewComponent(AccountService accountService) {
107+
public MyApplication(AccountService accountService) {
90108
this.accountService = accountService;
91109
}
92110

93111
public void printMyAccounts() {
94112
List<Account> accounts = accountService.getAccounts();
95113
for(Account account: accounts) {
96114
System.out.println(accounts.getBalance());
115+
}
97116
}
98117
}
99118
```
100119

101-
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:
102-
103-
```
104-
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(GdaxApiApplication.class)
105-
.headless(false).run(args);
120+
If you can do TDD, great. If not, add it after you've coded a solution.
106121

107-
NewComponent newComponent = ctx.getBean(newComponent.class);
108-
newComponent.printMyAccounts();
109-
... etc.
110-
```
122+
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).

0 commit comments

Comments
 (0)