Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ivan.solscanbot.dto.external;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Set;
import lombok.Data;

@Data
public class BalanceActivitiesResponseDto {
@JsonProperty("data")
private Set<SingleBalanceActivityResponseDto> activities;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ivan.solscanbot.dto.external;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;

@Data
public class SingleBalanceActivityResponseDto {
private String address;
@JsonProperty("token_address")
private String tokenAddress;
@JsonProperty("activity_type")
private String activityType;
private BigDecimal amount;
@JsonProperty("pre_balance")
private BigDecimal preBalance;
private Date time;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ivan.solscanbot.dto.external;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import lombok.Data;

@Data
public class SingleTokenPortfolioResponseDto {
@JsonProperty("token_name")
private String tokenName;
@JsonProperty("token_address")
private String tokenAddress;
@JsonProperty("token_balance")
private String tokenBalance;
@JsonProperty("value")
private BigDecimal tokenValue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ivan.solscanbot.dto.external;

import lombok.Data;

@Data
public class TokenMetaResponseDto {
private String name;
private String symbol;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ivan.solscanbot.dto.external;

import java.util.Set;
import lombok.Data;

@Data
public class TokenPortfoliosResponseDto {
private Set<SingleTokenPortfolioResponseDto> tokens;
}
40 changes: 40 additions & 0 deletions src/main/java/ivan/solscanbot/dto/internal/BalanceActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ivan.solscanbot.dto.internal;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;

@Data
@Entity
@NoArgsConstructor
@Accessors(chain = true)
@SQLDelete(sql = "UPDATE roles SET is_deleted = true WHERE id = ?")
@SQLRestriction("is_deleted = false")
public class BalanceActivity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String address;
@Column(nullable = false, name = "token_address")
private String tokenAddress;
@Column(nullable = false, name = "token_name")
private String tokenName;
@Column(nullable = false, name = "token_symbol")
private String tokenSymbol;
@Column(nullable = false)
private BigDecimal amount;
@Column(nullable = false)
private Date time;
@Column(nullable = false, name = "is_deleted")
private boolean isDeleted = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.hibernate.annotations.SQLRestriction;

@Entity
@Data
@NoArgsConstructor
@SQLDelete(sql = "UPDATE roles SET is_deleted = true WHERE id = ?")
@Where(clause = "is_deleted = false")
@SQLRestriction("is_deleted = false")
public class MonitoredAddress {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/ivan/solscanbot/dto/internal/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,29 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.math.BigDecimal;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.hibernate.annotations.SQLRestriction;

@Data
@Entity
@NoArgsConstructor
@SQLDelete(sql = "UPDATE roles SET is_deleted = true WHERE id = ?")
@Where(clause = "is_deleted = false")
@SQLRestriction("is_deleted = false")
public class Token {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false, name = "token_name")
private String tokenName;
@Column(unique = true, nullable = false, name = "token_address")
private String tokenAddress;
@Column(unique = true, nullable = false, name = "token_balance")
private String tokenBalance;
@Column(unique = true, nullable = false, name = "token_value")
private BigDecimal tokenValue;
@Column(name = "is_deleted")
private boolean isDeleted = false;
}
11 changes: 11 additions & 0 deletions src/main/java/ivan/solscanbot/mapper/ActivityMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ivan.solscanbot.mapper;

import ivan.solscanbot.config.MapperConfig;
import ivan.solscanbot.dto.external.SingleBalanceActivityResponseDto;
import ivan.solscanbot.dto.internal.BalanceActivity;
import org.mapstruct.Mapper;

@Mapper(config = MapperConfig.class)
public interface ActivityMapper {
BalanceActivity toModel(SingleBalanceActivityResponseDto activityDto);
}
4 changes: 2 additions & 2 deletions src/main/java/ivan/solscanbot/mapper/TokenMapper.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package ivan.solscanbot.mapper;

import ivan.solscanbot.config.MapperConfig;
import ivan.solscanbot.dto.external.SingleTokenNameResponseDto;
import ivan.solscanbot.dto.external.SingleTokenPortfolioResponseDto;
import ivan.solscanbot.dto.internal.Token;
import org.mapstruct.Mapper;

@Mapper(config = MapperConfig.class)
public interface TokenMapper {
Token toModel(SingleTokenNameResponseDto dto);
Token toModel(SingleTokenPortfolioResponseDto dto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ivan.solscanbot.repository;

import ivan.solscanbot.dto.internal.BalanceActivity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ActivityRepository extends JpaRepository<BalanceActivity, Long> {
}
51 changes: 39 additions & 12 deletions src/main/java/ivan/solscanbot/service/MonitoringService.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,59 @@
package ivan.solscanbot.service;

import ivan.solscanbot.dto.external.TokenMetaResponseDto;
import ivan.solscanbot.dto.internal.BalanceActivity;
import ivan.solscanbot.dto.internal.MonitoredAddress;
import ivan.solscanbot.mapper.ActivityMapper;
import ivan.solscanbot.repository.ActivityRepository;
import ivan.solscanbot.repository.MonitoredAddressRepository;
import java.math.BigDecimal;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.jvnet.hk2.annotations.Service;
import org.springframework.scheduling.annotation.Scheduled;

@Service
@RequiredArgsConstructor
public class MonitoringService {
private final MonitoredAddressRepository addressRepository;
private final DeFiMonitorBot deFiMonitorBot;
private final SolScanServiceImpl solScanService;

public MonitoringService(
MonitoredAddressRepository addressRepository,
DeFiMonitorBot deFiMonitorBot,
SolScanServiceImpl solScanService) {
this.addressRepository = addressRepository;
this.deFiMonitorBot = deFiMonitorBot;
this.solScanService = solScanService;
}
private final ActivityRepository activityRepository;
private final ActivityMapper activityMapper;

@Scheduled(fixedRate = 15000)
public void sendTokenList() {
for (MonitoredAddress address : addressRepository.findAll()) {
try {
String notification = "Tokens for address: " + address.getAddress()
+ solScanService.getTokensByAddress(address.getAddress());
deFiMonitorBot.sendNotification(address.getId(), notification);
Set<BalanceActivity> activities =
solScanService.getNewBalanceActivities(address.getAddress())
.stream()
.filter(a -> BigDecimal.ZERO.equals(a.getPreBalance()))
.map(activityMapper::toModel)
.collect(Collectors.toSet());
if (!activities.isEmpty()) {
StringBuilder notification = new StringBuilder();
notification.append("New activity for Solana address\n")
.append(address.getAddress())
.append("was found");
int count = 1;
for (BalanceActivity activity : activities) {
TokenMetaResponseDto meta =
solScanService.getTokenMetaFromAddress(address.getAddress());
activity.setTokenName(meta.getName())
.setTokenSymbol(meta.getSymbol());
notification.append("\n").append(count++)
.append(". token address: ").append(activity.getTokenAddress())
.append("\n")
.append(". token address: ").append(activity.getTokenAddress())
.append("\n")
.append("token amount: ").append(activity.getAmount()).append("\n")
.append("time: ").append(activity.getTime()).append("\n");
}
activityRepository.saveAll(activities);
deFiMonitorBot.sendNotification(address.getChatId(), notification.toString());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/ivan/solscanbot/service/SolScanService.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package ivan.solscanbot.service;

import ivan.solscanbot.dto.external.SingleTokenNameResponseDto;
import ivan.solscanbot.dto.external.SingleBalanceActivityResponseDto;
import ivan.solscanbot.dto.external.SingleTokenPortfolioResponseDto;
import ivan.solscanbot.dto.external.TokenMetaResponseDto;
import java.util.Set;

public interface SolScanService {
Set<SingleTokenNameResponseDto> getTokensByAddress(String address);
Set<SingleTokenPortfolioResponseDto> getTokensByAddress(String address);

Set<SingleBalanceActivityResponseDto> getNewBalanceActivities(String address);

TokenMetaResponseDto getTokenMetaFromAddress(String address);
}
Loading