AccountService.java
package com.github.badpop.jcoinbase.service.account;
import com.github.badpop.jcoinbase.JCoinbaseClient;
import com.github.badpop.jcoinbase.control.CallResult;
import com.github.badpop.jcoinbase.exception.InvalidRequestException;
import com.github.badpop.jcoinbase.exception.JCoinbaseException;
import com.github.badpop.jcoinbase.exception.NoNextPageException;
import com.github.badpop.jcoinbase.exception.NoPreviousPageException;
import com.github.badpop.jcoinbase.model.CoinbaseError;
import com.github.badpop.jcoinbase.model.PaginatedResponse;
import com.github.badpop.jcoinbase.model.Pagination;
import com.github.badpop.jcoinbase.model.account.Account;
import com.github.badpop.jcoinbase.model.account.AccountsPage;
import com.github.badpop.jcoinbase.model.request.UpdateAccountRequest;
import com.github.badpop.jcoinbase.service.ErrorManagerService;
import com.github.badpop.jcoinbase.service.auth.AuthenticationService;
import com.github.badpop.jcoinbase.service.utils.StringUtils;
import io.vavr.collection.Seq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import java.util.List;
import java.util.Objects;
import static io.vavr.API.Option;
import static io.vavr.API.Try;
/**
* This service allows you to request coinbase accounts data. <strong>To properly use this service,
* you must provide an API Key and an API secret when building a JCoinbaseClient instance.</strong>
*/
@Slf4j
@RequiredArgsConstructor
public class AccountService {
private static final String INVALID_ID_MESSAGE =
"Please provide a non blank id to get an account by id";
private final JCoinbaseClient client;
private final CoinbaseAccountService service;
private final AuthenticationService authentication;
/**
* Get the first accounts page
*
* @return a {@link CallResult} containing an {@link AccountsPage} object if it's ok, a List of
* {@link CoinbaseError} otherwise.
* @throws JCoinbaseException on unknown errors
*/
public CallResult<List<CoinbaseError>, AccountsPage> getAccountsPageAsJava() {
return getAccountsPage().mapFailure(Seq::asJava);
}
/**
* Get the first accounts page
*
* @return a {@link CallResult} containing an {@link AccountsPage} object if it's ok, a Seq of
* {@link CoinbaseError} otherwise.
* @throws JCoinbaseException on unknown errors
*/
public CallResult<Seq<CoinbaseError>, AccountsPage> getAccountsPage() {
return service
.fetchAccountPageByUri(client, authentication, client.getProperties().getAccountsPath())
.onSuccess(paginatedResponses -> log.info("Successfully get accounts page"))
.onFailure(
throwable ->
ErrorManagerService.manageOnError(
new JCoinbaseException(throwable),
"An error occurred while fetching accounts list",
throwable))
.get()
.map(this::toAccountsPage);
}
/**
* Get the next accounts page
*
* @param pagination a pagination object that will allow JCoinbase to request the next accounts
* page
* @return a {@link CallResult} containing an {@link AccountsPage} object if it's ok, a List of
* {@link CoinbaseError} otherwise.
* @throws NullPointerException if the pagination is null
* @throws NoNextPageException if there is no next page
* @throws JCoinbaseException on unknown errors
*/
public CallResult<List<CoinbaseError>, AccountsPage> getNextAccountsPageAsJava(
final Pagination pagination) {
return getNextAccountsPage(pagination).mapFailure(Seq::asJava);
}
/**
* Get the next accounts page
*
* @param pagination a pagination object that will allow JCoinbase to request the next accounts
* page
* @return a {@link CallResult} containing an {@link AccountsPage} object if it's ok, a Seq of
* {@link CoinbaseError} otherwise.
* @throws NullPointerException if the pagination is null
* @throws NoNextPageException if there is no next page
* @throws JCoinbaseException on unknown errors
*/
public CallResult<Seq<CoinbaseError>, AccountsPage> getNextAccountsPage(
final Pagination pagination) {
Objects.requireNonNull(pagination, "Pagination is null");
val nextUri =
Option(pagination.getNextUri())
.onEmpty(
() ->
ErrorManagerService.manageOnError(
new NoNextPageException("There is no next page available for your request"),
"There is no next page available for your request"))
.get();
return service
.fetchAccountPageByUri(client, authentication, nextUri)
.onSuccess(paginatedResponses -> log.info("Successfully fetch next accounts page"))
.onFailure(
throwable ->
ErrorManagerService.manageOnError(
new JCoinbaseException(throwable),
"An error occurred while fetching next accounts page",
throwable))
.get()
.map(this::toAccountsPage);
}
/**
* Get the previous accounts page
*
* @param pagination a pagination object that will allow JCoinbase to request the next accounts
* page
* @return a {@link CallResult} containing an {@link AccountsPage} object if it's ok, a List of
* {@link CoinbaseError} otherwise.
* @throws NullPointerException if the pagination is null
* @throws NoPreviousPageException if there is no previous page
* @throws JCoinbaseException on unknown errors
*/
public CallResult<List<CoinbaseError>, AccountsPage> getPreviousAccountsPageAsJava(
final Pagination pagination) {
return getPreviousAccountsPage(pagination).mapFailure(Seq::asJava);
}
/**
* Get the previous accounts page
*
* @param pagination a pagination object that will allow JCoinbase to request the next accounts
* page
* @return a {@link CallResult} containing an {@link AccountsPage} object if it's ok, a Seq of
* {@link CoinbaseError} otherwise.
* @throws NullPointerException if the pagination is null
* @throws NoPreviousPageException if there is no previous page
* @throws JCoinbaseException on unknown errors
*/
public CallResult<Seq<CoinbaseError>, AccountsPage> getPreviousAccountsPage(
final Pagination pagination) {
Objects.requireNonNull(pagination, "Pagination is null");
val previousUri =
Option(pagination.getPreviousUri())
.onEmpty(
() ->
ErrorManagerService.manageOnError(
new NoPreviousPageException(
"There is no previous page available for your request"),
"There is no previous page available for your request"))
.get();
return service
.fetchAccountPageByUri(client, authentication, previousUri)
.onSuccess(paginatedResponses -> log.info("Successfully fetch previous accounts page"))
.onFailure(
throwable ->
ErrorManagerService.manageOnError(
new JCoinbaseException(throwable),
"An error occurred while fetching previous accounts page",
throwable))
.get()
.map(this::toAccountsPage);
}
/**
* Get an account by its id
*
* @param id the account's id
* @return a {@link CallResult} containing an {@link Account} object if it's ok, a List of {@link
* CoinbaseError} otherwise.
* @throws InvalidRequestException if the given id is not valid
* @throws JCoinbaseException on unknown errors
*/
public CallResult<List<CoinbaseError>, Account> getAccountAsJava(final String id) {
return getAccount(id).mapFailure(Seq::asJava);
}
/**
* Get an account by its id
*
* @param id the account's id
* @return a {@link CallResult} containing an {@link Account} object if it's ok, a Seq of {@link
* CoinbaseError} otherwise.
* @throws InvalidRequestException if the given id is not valid
* @throws JCoinbaseException on unknown errors
*/
public CallResult<Seq<CoinbaseError>, Account> getAccount(final String id) {
if (StringUtils.isBlank(id)) {
ErrorManagerService.manageOnError(
new InvalidRequestException(INVALID_ID_MESSAGE), INVALID_ID_MESSAGE);
}
val uri = client.getProperties().getAccountsPath() + "/" + id;
return service
.send(client, authentication, uri, "GET", "")
.onSuccess(paginatedResponses -> log.info("Successfully fetch account by id"))
.onFailure(
throwable ->
ErrorManagerService.manageOnError(
new JCoinbaseException(throwable),
"An error occurred while fetching account by id",
throwable))
.get();
}
/**
* Update an account by its id
*
* @param id the account's id
* @param request a valid {@link UpdateAccountRequest} containing the changes you want to apply on
* this account
* @return a {@link CallResult} containing the updated {@link Account} if it's ok, a List of
* {@link CoinbaseError} otherwise.
* @throws NullPointerException if the given request is null
* @throws InvalidRequestException if the given id is not valid
* @throws JCoinbaseException on unknown errors
*/
public CallResult<List<CoinbaseError>, Account> updateAccountAsJava(
final String id, final UpdateAccountRequest request) {
return updateAccount(id, request).mapFailure(Seq::asJava);
}
/**
* Update an account by its id
*
* @param id the account's id
* @param request a valid {@link UpdateAccountRequest} containing the changes you want to apply on
* this account
* @return a {@link CallResult} containing the updated {@link Account} if it's ok, a Seq of {@link
* CoinbaseError} otherwise.
* @throws NullPointerException if the given request is null
* @throws InvalidRequestException if the given id is not valid
* @throws JCoinbaseException on unknown errors
*/
public CallResult<Seq<CoinbaseError>, Account> updateAccount(
final String id, final UpdateAccountRequest request) {
Objects.requireNonNull(request, "request is null");
if (StringUtils.isBlank(id)) {
ErrorManagerService.manageOnError(
new InvalidRequestException(INVALID_ID_MESSAGE), INVALID_ID_MESSAGE);
}
val uri = client.getProperties().getAccountsPath() + "/" + id;
return Try(() -> client.getJsonSerDes().writeValueAsString(request))
.flatMapTry(body -> service.send(client, authentication, uri, "PUT", body))
.onSuccess(account -> log.info("Successfully update account"))
.onFailure(
throwable ->
ErrorManagerService.manageOnError(
new JCoinbaseException(throwable),
"An error occurred while updating account with id",
throwable,
id))
.get();
}
private AccountsPage toAccountsPage(final PaginatedResponse<Account> response) {
return new AccountsPage(response.getPagination(), response.getData());
}
}