Skip to content

Commit

Permalink
Merge pull request #11 from fedy97/feature/add-balance-command
Browse files Browse the repository at this point in the history
feat: add /balance command
  • Loading branch information
fedy97 authored Dec 14, 2023
2 parents 84a34f9 + eebe47a commit 9b18099
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 8 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ jobs:
export KUCOIN_SECRET_KEY="${{ secrets.KUCOIN_SECRET_KEY }}"
export KUCOIN_PASSPHRASE="${{ secrets.KUCOIN_PASSPHRASE }}"
docker-compose up --build -d
docker images -q -f "dangling=true" | xargs docker rmi
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- [x] Dockerized image
- [x] Deployable on VPS
- [x] Full CI/CD Flow with Actions
- [x] Withdraw funds/check chains with Kucoin
- [x] Withdraw funds/check chains/check balance with Kucoin


### Design Patterns:
Expand Down Expand Up @@ -73,6 +73,7 @@ Here is the list of commands that require authorization, defined by setting the
- `/prices`: it lists all saved coins' buy prices (requires `MONGO_DB_URI`)
- `/withdraw`: it withdraw funds from different platforms. Right now only Kucoin is available
- `/chains`: it checks which chains are available for deposit/withdraw for a specific coin, for a specific platform
- `/balance`: it checks balance for the specified exchange (platform)

#### Example Usage

Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/bot/MyBot.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ private MyBot() {
commandHandler.register(new AuthorizedCommandDecorator(new DeletePortfolioLinkCommand()));
commandHandler.register(new AuthorizedCommandDecorator(new WithdrawCommand()));
commandHandler.register(new AuthorizedCommandDecorator(new AvailableChainsCommand()));
commandHandler.register(new AuthorizedCommandDecorator(new BalanceCommand()));

CommandProcessor.getInstance().registerPortfolioCommands();

Expand Down
47 changes: 47 additions & 0 deletions src/main/java/org/bot/commands/BalanceCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.bot.commands;

import lombok.extern.slf4j.Slf4j;
import org.bot.commands.base.Command;
import org.bot.operations.Operations;
import org.bot.operations.OperationsDispatcher;
import org.bot.utils.formatters.BalanceDecorator;
import org.bot.visitor.CommandVisitor;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

import java.util.Map;


@Slf4j
public class BalanceCommand implements Command {

public BalanceCommand() {
super();
}

@Override
public void execute(Update update) throws TelegramApiException {
String[] parts = update.getMessage().getText().split(" ");
String platform = parts[1].toLowerCase().trim();

Operations operations = OperationsDispatcher.getInstance().getOperations(platform);
Map<String, Double> balance = operations.getBalance();

sendText(update.getMessage().getChatId(), new BalanceDecorator(balance.toString()).toString());
}

@Override
public String getName() {
return "/balance";
}

@Override
public String getDescription() {
return "<platform> to see the balance of your account";
}

@Override
public void accept(CommandVisitor visitor) {
visitor.visitBalanceCommand();
}
}
25 changes: 21 additions & 4 deletions src/main/java/org/bot/operations/KucoinOperations.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
import com.kucoin.sdk.KucoinRestClient;
import com.kucoin.sdk.exception.KucoinApiException;
import com.kucoin.sdk.rest.request.WithdrawApplyRequest;
import com.kucoin.sdk.rest.response.AccountBalancesResponse;
import com.kucoin.sdk.rest.response.ApiCurrencyDetailChainPropertyResponseV2;
import lombok.extern.slf4j.Slf4j;
import org.bot.utils.EnvVars;
import org.bot.utils.Helpers;
import org.bot.utils.exceptions.CommandExecutionException;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
Expand Down Expand Up @@ -73,7 +73,24 @@ public Set<String> getAvailableChains(String ticker) {
return chains.stream().map((ApiCurrencyDetailChainPropertyResponseV2::getChainId)).collect(Collectors.toSet());
} catch (IOException e) {
log.error(e.getMessage());
return new HashSet<>();
throw new CommandExecutionException(e.getMessage());
}
}

@Override
public Map<String, Double> getBalance() {
Map<String, Double> balance = new HashMap<>();
try {
List<AccountBalancesResponse> accounts = kucoinRestClient.accountAPI().listAccounts(null, null);
accounts.stream()
.filter(account -> account.getBalance().doubleValue() > 0)
.forEach(account -> Helpers.addToMapOrSum(balance, account.getCurrency(), account.getBalance().doubleValue()));
} catch (IOException e) {
log.error(e.getMessage());
throw new CommandExecutionException(e.getMessage());
} catch (KucoinApiException e) {
throw new CommandExecutionException(e.getMessage().replace('.', ' '));
}
return balance;
}
}
6 changes: 3 additions & 3 deletions src/main/java/org/bot/operations/Operations.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public interface Operations {
void withdraw(String ticker, Double amount, String chain, String address);
boolean isUsable();
void build();
String platform();
default Set<String> getAvailableChains(String ticker) {
return new HashSet<>();
}
Set<String> getAvailableChains(String ticker);
Map<String, Double> getBalance();
}
11 changes: 11 additions & 0 deletions src/main/java/org/bot/utils/Helpers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.bot.utils;

import java.util.Map;

public class Helpers {
private Helpers() {}

public static void addToMapOrSum(Map<String, Double> map, String key, Double value) {
map.compute(key, (k, v) -> (v == null) ? value : v + value);
}
}
24 changes: 24 additions & 0 deletions src/main/java/org/bot/utils/formatters/BalanceDecorator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.bot.utils.formatters;

import java.util.Arrays;

public class BalanceDecorator extends StringDecorator {

public BalanceDecorator(String decoratedString) {
super(decoratedString);
}

@Override
public String toString() {
String noCurlyBraces = decoratedString.replace("{", "").replace("}", "");
String[] coins = noCurlyBraces.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < coins.length; i++) {
String coin = coins[i].trim();
sb.append(coin.replace("=", ": "));
if (i < coins.length - 1)
sb.append("\n");
}
return sb.toString();
}
}
1 change: 1 addition & 0 deletions src/main/java/org/bot/visitor/CommandVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ public interface CommandVisitor {
void visitSaveCoinNotifyCommand();
void visitWithdrawCommand();
void visitAvailableChainsCommand();
void visitBalanceCommand();
}
13 changes: 13 additions & 0 deletions src/main/java/org/bot/visitor/ValidatingCommandVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,17 @@ public void visitAvailableChainsCommand() {
throw new InvalidCommandException("Available platforms are: " + OperationsDispatcher.getInstance().getAvailablePlatforms());
}
}

@Override
public void visitBalanceCommand() {
String[] parts = update.getMessage().getText().split(" ");
if (parts.length != 2)
throw new InvalidCommandException();
String platform = parts[1];
try {
OperationsDispatcher.getInstance().getOperations(platform);
} catch (PlatformNotAvailableException e) {
throw new InvalidCommandException("Available platforms are: " + OperationsDispatcher.getInstance().getAvailablePlatforms());
}
}
}

0 comments on commit 9b18099

Please sign in to comment.