Skip to content

Commit

Permalink
feat: Automate the transfer meeds token rewarding - MEED-3293 - Meeds…
Browse files Browse the repository at this point in the history
…-io/MIPs#118 (#2)

This change will automate the transfer meeds token rewarding.
  • Loading branch information
MayTekayaa authored Feb 27, 2024
1 parent 814b6c4 commit 5bd5137
Show file tree
Hide file tree
Showing 13 changed files with 641 additions and 3 deletions.
21 changes: 21 additions & 0 deletions gamification-evm-services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@
<groupId>org.exoplatform.addons.gamification</groupId>
<artifactId>gamification-services</artifactId>
</dependency>
<dependency>
<groupId>org.exoplatform.addons.wallet</groupId>
<artifactId>wallet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.wallet</groupId>
<artifactId>ert-contract</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
<build>
<finalName>gamification-evm-service</finalName>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* This file is part of the Meeds project (https://meeds.io/).
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.gamification.evm.blockchain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;

@Configuration
public class BlockchainConfiguration {

@Autowired
private BlockchainConfigurationProperties blockchainProperties;

@Bean("polygonNetwork")
public Web3j getPolygonNetworkWeb3j() {
return Web3j.build(new HttpService(blockchainProperties.getPolygonNetworkUrl()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* This file is part of the Meeds project (https://meeds.io/).
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.gamification.evm.blockchain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "meeds.gamification.evm.blockchain")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BlockchainConfigurationProperties {

private String polygonNetworkUrl;

private String meedAddress = "0x334D85047da64738c065d36E10B2AdEb965000d0";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* This file is part of the Meeds project (https://meeds.io/).
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.gamification.evm.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class EvmTrigger {

private String trigger;

private String walletAddress;

private String type;

private String transactionHash;

public EvmTrigger clone() {
return new EvmTrigger(trigger, walletAddress, type, transactionHash);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.meeds.gamification.evm.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigInteger;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TokenTransferEvent {

private String from;

private String to;

private BigInteger amount;

private String transactionHash;

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import io.meeds.gamification.plugin.ConnectorPlugin;
import io.meeds.gamification.service.ConnectorSettingService;

public class EvmConnectorPlugin extends ConnectorPlugin {
import static io.meeds.gamification.evm.utils.Utils.*;

private static final String CONNECTOR_NAME = "evm";
public class EvmConnectorPlugin extends ConnectorPlugin {

private final ConnectorSettingService connectorSettingService;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* This file is part of the Meeds project (https://meeds.io/).
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.gamification.evm.scheduling;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
@ComponentScan
public class SchedulingConfig {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* This file is part of the Meeds project (https://meeds.io/).
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.gamification.evm.scheduling.task;

import java.util.List;
import java.util.Set;

import io.meeds.common.ContainerTransactional;
import io.meeds.gamification.constant.DateFilterType;
import io.meeds.gamification.constant.EntityStatusType;
import io.meeds.gamification.evm.blockchain.BlockchainConfigurationProperties;
import io.meeds.gamification.evm.model.EvmTrigger;
import io.meeds.gamification.evm.service.EvmTriggerService;
import io.meeds.gamification.evm.service.BlockchainService;
import io.meeds.gamification.model.RuleDTO;
import io.meeds.gamification.model.filter.RuleFilter;
import io.meeds.gamification.service.EventService;
import io.meeds.gamification.service.RuleService;
import org.apache.commons.collections.CollectionUtils;
import org.exoplatform.commons.api.settings.SettingService;
import org.exoplatform.commons.api.settings.data.Context;
import org.exoplatform.commons.api.settings.data.Scope;
import org.exoplatform.commons.api.settings.SettingValue;
import org.exoplatform.services.listener.ListenerService;

import io.meeds.gamification.evm.model.TokenTransferEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import static io.meeds.gamification.evm.utils.Utils.*;

@Component
public class ERC20TransferTask {
private static final Logger LOG = LoggerFactory.getLogger(ERC20TransferTask.class);

private static final Scope SETTING_SCOPE = Scope.APPLICATION.id("GAMIFICATION_EVM");

private static final Context SETTING_CONTEXT = Context.GLOBAL.id("GAMIFICATION_EVM");

private static final String SETTING_LAST_TIME_CHECK_KEY = "transferredTokenTransactionsCheck";

@Autowired
private EventService eventService;

@Autowired
private SettingService settingService;

@Autowired
private ListenerService listenerService;

@Autowired
private BlockchainService blockchainService;

@Autowired
private EvmTriggerService evmTriggerService;

@Autowired
private BlockchainConfigurationProperties blockchainProperties;

@Autowired
private RuleService ruleService;

@ContainerTransactional
@Scheduled(cron = "15 * * * * *")
public synchronized void listenTokenTransfer() {
LOG.info("Start listening erc20 token transfers");
try {
RuleFilter ruleFilter = new RuleFilter(true);
ruleFilter.setEventType(CONNECTOR_NAME);
ruleFilter.setStatus(EntityStatusType.ENABLED);
ruleFilter.setProgramStatus(EntityStatusType.ENABLED);
ruleFilter.setDateFilterType(DateFilterType.STARTED);
List<RuleDTO> rules = ruleService.getRules(ruleFilter, 0, -1);
if (CollectionUtils.isNotEmpty(rules)) {
long lastBlock = blockchainService.getLastBlock();
long lastCheckedBlock = getLastCheckedBlock(blockchainProperties.getMeedAddress());
if (lastCheckedBlock == 0) {
// If this is the first time that it's started, save the last block as
// last checked one
saveLastCheckedBlock(lastBlock, blockchainProperties.getMeedAddress());
return;
}
Set<TokenTransferEvent> events = blockchainService.getTransferredTokensTransactions(lastCheckedBlock + 1,
lastBlock,
blockchainProperties.getMeedAddress());
if (!CollectionUtils.isEmpty(events)) {
events.forEach(event -> {
try {
EvmTrigger evmTrigger = new EvmTrigger();
evmTrigger.setTrigger(HOLD_TOKEN_EVENT);
evmTrigger.setType(CONNECTOR_NAME);
evmTrigger.setWalletAddress(event.getTo());
evmTrigger.setTransactionHash(event.getTransactionHash());
evmTriggerService.handleTriggerAsync(evmTrigger);
} catch (Exception e) {
LOG.warn("Error broadcasting event '" + event, e);
}
});
}
saveLastCheckedBlock(lastBlock, blockchainProperties.getMeedAddress());
LOG.info("End listening erc20 token transfers");
}
} catch (Exception e) {
LOG.error("An error occurred while listening erc20 token transfers", e);
}
}

@ContainerTransactional
public long getLastCheckedBlock(String contractAddress) {
long lastCheckedBlock = 0;
SettingValue<?> settingValue = settingService.get(SETTING_CONTEXT, SETTING_SCOPE, SETTING_LAST_TIME_CHECK_KEY + contractAddress);
if (settingValue != null && settingValue.getValue() != null) {
lastCheckedBlock = Long.parseLong(settingValue.getValue().toString());
}
return lastCheckedBlock;
}

@ContainerTransactional
public void saveLastCheckedBlock(long lastBlock, String contractAddress) {
settingService.set(SETTING_CONTEXT, SETTING_SCOPE, SETTING_LAST_TIME_CHECK_KEY + contractAddress, SettingValue.create(lastBlock));
}
}
Loading

0 comments on commit 5bd5137

Please sign in to comment.