Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
89b4e0c
Make enum for network type
mabredin Apr 8, 2025
f9b9a0d
feat(all_airdrops): change Slack notifications to MM notifications
mabredin Apr 10, 2025
9bb3c5b
Remove another duplicate code
mabredin Apr 10, 2025
f27642a
Add change address method in base airdrop
mabredin Apr 10, 2025
f15131a
Merge pull request #299 from singnet/SNRA-35
mabredin Apr 11, 2025
4eb6fd3
Change the recognition function of the blockchain network
mabredin Apr 11, 2025
996d9d0
Merge branch 'development' into SNRA-59
mabredin Apr 11, 2025
9d4739c
Merge pull request #300 from singnet/SNRA-59
mabredin Apr 11, 2025
42fc880
Add a new group of exceptions to handlers without notifications
mabredin Apr 15, 2025
e37130d
Change information in logs for exceptions
mabredin Apr 15, 2025
392d681
Merge pull request #301 from singnet/SNRA-35
mabredin Apr 15, 2025
baeb604
Fix functionality for receiving registration details
mabredin Jun 27, 2025
453485d
Fix bugs after review
mabredin Jun 27, 2025
e79d3ed
Clean up comment code in user_registraion_repo
mabredin Jun 27, 2025
478bf25
Remove unnecessary imports
mabredin Jun 27, 2025
ed24203
Fix one more
mabredin Jun 27, 2025
97e1668
Add new UserClaimStatus value
mabredin Jun 27, 2025
aa3e99b
Merge pull request #303 from singnet/SNRA-86
mabredin Jun 30, 2025
22441cf
Merge branch 'development' into SNRA-85
mabredin Jul 1, 2025
2719eb2
Merge pull request #302 from singnet/SNRA-85
mabredin Jul 1, 2025
d04ab3d
Fix query bugs
mabredin Jul 1, 2025
918b531
Remove query param from db url creating
mabredin Jul 1, 2025
a94a0c1
Merge pull request #305 from singnet/fix_bugs_and_typos
mabredin Jul 2, 2025
d98b549
rejuve airdrop: fixed issue with not registered window claim; merged …
sassless Jul 30, 2025
dcdba9a
Merge pull request #306 from singnet/rejuve_fixes
sassless Jul 31, 2025
d1cdd6c
fix rejuve airdrop update registration
sassless Jul 31, 2025
1d7afaa
Merge pull request #307 from singnet/rejuve_fixes
sassless Jul 31, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ external_packages/**

*/config.py
config.local.json
config.dev.json
/package.json
/requirements.txt
/serverless.yml
28 changes: 14 additions & 14 deletions airdrop/application/handlers/airdrop_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
sys.path.append('/opt')

from common.exception_handler import exception_handler
from airdrop.config import SLACK_HOOK, NETWORK_ID
from airdrop.config import MATTERMOST_CONFIG, NETWORK_ID
from common.logger import get_logger
from common.utils import generate_lambda_response, request
from airdrop.application.services.airdrop_services import AirdropServices
Expand All @@ -14,7 +14,7 @@
logger = get_logger(__name__)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def get_airdrop_schedules(event, context):
logger.info(f"Got Airdrops Event {event}")
parameters = event['pathParameters']
Expand All @@ -28,7 +28,7 @@ def get_airdrop_schedules(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def user_registration(event, context):
logger.info(f"Got Airdrops Event {event}")
status, response = UserRegistrationServices().register(request(event))
Expand All @@ -40,7 +40,7 @@ def user_registration(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def user_registration_update(event, context):
logger.info(f"Got Airdrops Event {event}")
status, response = UserRegistrationServices().update_registration(request(event))
Expand All @@ -52,7 +52,7 @@ def user_registration_update(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def airdrop_window_stake_details(event, context):
logger.info(f"Got Airdrops Window Stake details {event}")
status, response = AirdropServices().get_airdrop_window_stake_details(request(event))
Expand All @@ -64,7 +64,7 @@ def airdrop_window_stake_details(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def address_eligibility(event, context):
logger.info(f"Got Airdrops Event {event}")
status, response = UserRegistrationServices().eligibility_v2(request(event))
Expand All @@ -76,7 +76,7 @@ def address_eligibility(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def user_eligibility(event, context):
logger.info(f"Got Airdrops Event {event}")
status, response = UserRegistrationServices().eligibility(request(event))
Expand All @@ -88,7 +88,7 @@ def user_eligibility(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def occam_airdrop_window_claim(event, context):
logger.info(f"Got occam_airdrop_window_claim event {event}")
status, response = AirdropServices().occam_airdrop_window_claim(request(event))
Expand All @@ -100,7 +100,7 @@ def occam_airdrop_window_claim(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def airdrop_window_claim(event, context):
logger.info(f"Got airdrop_window_claim Events {event}")
status, response = AirdropServices().airdrop_window_claim(request(event))
Expand All @@ -112,7 +112,7 @@ def airdrop_window_claim(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def airdrop_window_claim_status(event, context):
logger.info(f"Got Airdrops Window Claims Statys Events {event}")
status, response = AirdropServices(
Expand All @@ -125,7 +125,7 @@ def airdrop_window_claim_status(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def airdrop_window_claim_history(event, context):
logger.info(f"Got Airdrops Window Claims Statys Events {event}")
status, response = AirdropServices(
Expand All @@ -138,7 +138,7 @@ def airdrop_window_claim_history(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def airdrop_event_consumer(event, context):
logger.info(f"Got Airdrops event listener {event}")
status, response = AirdropServices(
Expand All @@ -151,13 +151,13 @@ def airdrop_event_consumer(event, context):
)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def airdrop_txn_watcher(event, context):
logger.info(f"Got Airdrops txn status watcher {event}")
AirdropServices().airdrop_txn_watcher()


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger)
def user_notifications(event, context):
logger.info(f"Got Airdrops user notifications {event}")
status, response = UserNotificationService(
Expand Down
12 changes: 7 additions & 5 deletions airdrop/application/handlers/consumer_handler.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import sys

sys.path.append('/opt')
from airdrop.config import SLACK_HOOK, NETWORK_ID
from airdrop.config import MATTERMOST_CONFIG, NETWORK_ID
from airdrop.application.services.event_consumer_service import DepositEventConsumerService
from common.logger import get_logger
from common.utils import generate_lambda_response
from common.exception_handler import exception_handler
from common.exceptions import ValidationFailedException
from common.exceptions import BlockConfirmationException, ValidationFailedException

logger = get_logger(__name__)
EXCEPTIONS = (ValidationFailedException,)
NOT_RAISED_CUSTOM_EXCEPTIONS = (ValidationFailedException,)
RAISED_CUSTOM_EXCEPTIONS = (BlockConfirmationException,)


@exception_handler(SLACK_HOOK=SLACK_HOOK, NETWORK_ID=NETWORK_ID, logger=logger, EXCEPTIONS=EXCEPTIONS,
RAISE_EXCEPTION=True)
@exception_handler(PROCESSOR_CONFIG=MATTERMOST_CONFIG, NETWORK_ID=NETWORK_ID, logger=logger,
NOT_RAISED_EXCEPTIONS=NOT_RAISED_CUSTOM_EXCEPTIONS,
RAISED_EXCEPTIONS=RAISED_CUSTOM_EXCEPTIONS, RAISE_EXCEPTION=True)
def deposit_event_consumer(event, context):
logger.info(f"Got deposit event {event}")
response = DepositEventConsumerService(event).validate_deposit_event()
Expand Down
42 changes: 23 additions & 19 deletions airdrop/application/services/airdrop_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,43 @@
import web3
from eth_account.messages import encode_defunct
from jsonschema import validate, ValidationError
from sqlalchemy.exc import NoResultFound
from web3 import Web3, types

from airdrop.config import NETWORK, DEFAULT_REGION
from airdrop.config import (
SIGNER_PRIVATE_KEY,
SIGNER_PRIVATE_KEY_STORAGE_REGION,
NUNET_SIGNER_PRIVATE_KEY_STORAGE_REGION,
DEFAULT_REGION,
MATTERMOST_CONFIG,
NETWORK,
NUNET_SIGNER_PRIVATE_KEY,
SLACK_HOOK
NUNET_SIGNER_PRIVATE_KEY_STORAGE_REGION,
SIGNER_PRIVATE_KEY,
SIGNER_PRIVATE_KEY_STORAGE_REGION
)
from airdrop.constants import (
STAKING_CONTRACT_PATH,
CLAIM_SCHEMA,
AirdropEvents,
PROCESSOR_PATH,
STAKING_CONTRACT_PATH,
AirdropClaimStatus,
PROCESSOR_PATH
AirdropEvents,
Blockchain
)
from airdrop.domain.factory.airdrop_factory import AirdropFactory
from airdrop.infrastructure.repositories.airdrop_repository import AirdropRepository
from airdrop.infrastructure.repositories.airdrop_window_repository import AirdropWindowRepository
from airdrop.processor.default_airdrop import DefaultAirdrop, BaseAirdrop
from airdrop.utils import Utils as ut
from airdrop.utils import Utils
from common.alerts import MattermostProcessor
from common.boto_utils import BotoUtils
from common.logger import get_logger
from common.utils import (
generate_claim_signature,
generate_claim_signature_with_total_eligibile_amount,
get_contract_instance,
get_transaction_receipt_from_blockchain,
get_checksum_address,
Utils
get_checksum_address
)

alert_processor = MattermostProcessor(config=MATTERMOST_CONFIG)
logger = get_logger(__name__)


Expand Down Expand Up @@ -177,10 +181,10 @@ def get_stake_info(self, contract_address, user_wallet_address, airdrop_rewards,

except BaseException as e:
logger.error(e)
Utils().report_slack(
type=0, slack_message=f"Issue with Stake window Opened exeption {e} user_address {user_wallet_address},"
f" stake_contract_address: {contract_address}", slack_config=SLACK_HOOK
)
alert_processor.send(type=1,
message=f"Issue with Stake window Opened exeption {e} "
f"user_address {user_wallet_address}, "
f"stake_contract_address: {contract_address}")
return False, 0, airdrop_rewards

def get_stake_and_claimable_amounts(self, airdrop_rewards, is_stake_window_is_open, max_stake_amount,
Expand Down Expand Up @@ -321,7 +325,7 @@ def airdrop_window_claim_status(self, inputs):
amount = inputs["amount"]
blockchain_method = inputs["blockchain_method"]

if ut.recognize_blockchain_network(user_address) == "Ethereum":
if Utils.recognize_blockchain_network(user_address) == Blockchain.ETHEREUM.value:
user_address = Web3.to_checksum_address(user_address)

AirdropRepository().airdrop_window_claim_txn(
Expand Down Expand Up @@ -479,12 +483,12 @@ def get_signature_for_airdrop_window_id_with_totaleligibilty_amount(self, amount
raise e

def get_airdrops_schedule(self, airdrop_id):
status = HTTPStatus.BAD_REQUEST
try:
response = AirdropRepository().get_airdrops_schedule(airdrop_id)
status = HTTPStatus.OK
except ValidationError as e:
response = e.message
except NoResultFound as e:
response = f"Airdrop with id = {airdrop_id} does not exist"
status = HTTPStatus.BAD_REQUEST
except BaseException as e:
response = str(e)
status = HTTPStatus.INTERNAL_SERVER_ERROR
Expand Down
33 changes: 33 additions & 0 deletions airdrop/application/services/common_logic_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from typing import Optional, Tuple, Union

from airdrop.constants import CARDANO_ADDRESS_PREFIXES, Blockchain, CardanoEra
from airdrop.infrastructure.models import UserRegistration
from airdrop.infrastructure.repositories.user_registration_repo import UserRegistrationRepository
from airdrop.utils import Utils


class CommonLogicService:

@staticmethod
def get_user_registration_details(
address: str,
airdrop_window_id: int,
registration_id: Optional[str] = None
) -> Tuple[bool, Optional[Union[UserRegistration, list[UserRegistration]]]]:
registration_repo = UserRegistrationRepository()
network = Utils.recognize_blockchain_network(address)
if (network == Blockchain.ETHEREUM.value or
address.startswith(tuple(CARDANO_ADDRESS_PREFIXES[CardanoEra.BYRON]))):
return registration_repo.get_user_registration_details(
address=address,
airdrop_window_id=airdrop_window_id,
registration_id=registration_id
)
elif network == Blockchain.CARDANO.value:
payment_part, staking_part = Utils.get_payment_staking_parts(address)
return registration_repo.get_user_registration_details(
payment_part=payment_part,
staking_part=staking_part,
airdrop_window_id=airdrop_window_id,
registration_id=registration_id
)
4 changes: 2 additions & 2 deletions airdrop/application/services/event_consumer_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from airdrop.infrastructure.repositories.airdrop_repository import AirdropRepository
from airdrop.infrastructure.repositories.airdrop_window_repository import AirdropWindowRepository
from airdrop.infrastructure.repositories.user_registration_repo import UserRegistrationRepository
from common.exceptions import ValidationFailedException
from common.exceptions import BlockConfirmationException, ValidationFailedException
from common.logger import get_logger

user_registration_repo = UserRegistrationRepository()
Expand Down Expand Up @@ -51,7 +51,7 @@ def validate_block_confirmation(self, transaction_block_no):
current_block_no = EventConsumerService.get_current_block_no()
if current_block_no > (transaction_block_no + MIN_BLOCK_CONFIRMATION_REQUIRED):
return None
raise Exception(f"Block confirmation is not enough for event {self.event}")
raise BlockConfirmationException(f"Block confirmation is not enough for event {self.event}")

@staticmethod
def get_stake_key_address(address):
Expand Down
10 changes: 5 additions & 5 deletions airdrop/application/services/user_claim_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
import requests

from airdrop.application.services.airdrop_services import AirdropServices
from airdrop.config import TokenTransferCardanoService, SLACK_HOOK, MIN_BLOCK_CONFIRMATION_REQUIRED
from airdrop.config import MATTERMOST_CONFIG, TokenTransferCardanoService, MIN_BLOCK_CONFIRMATION_REQUIRED
from airdrop.constants import AirdropClaimStatus
from airdrop.infrastructure.repositories.airdrop_repository import AirdropRepository
from airdrop.infrastructure.repositories.claim_history_repo import ClaimHistoryRepository
from airdrop.application.services.event_consumer_service import EventConsumerService
from common.alerts import MattermostProcessor
from common.logger import get_logger
from common.utils import Utils

alert_processor = MattermostProcessor(config=MATTERMOST_CONFIG)
logger = get_logger(__name__)
utils = Utils()


class UserClaimService:
Expand Down Expand Up @@ -54,7 +54,7 @@ def invoke_token_transfer_cardano_service(payload):
f'{response_body.get("error", {}).get("message", "")}\nDetails ' \
f'{response_body.get("error", {}).get("details", "")}.'
logger.exception(error_message)
utils.report_slack(type=1, slack_message=error_message, slack_config=SLACK_HOOK)
alert_processor.send(type=1, message=error_message)
return {}
return response_body

Expand Down Expand Up @@ -86,7 +86,7 @@ def initiate_claim_for_users(self):
transaction_status = AirdropClaimStatus.CLAIM_SUBMITTED.value
else:
transaction_status = AirdropClaimStatus.CLAIM_FAILED.value
utils.report_slack(type=0, slack_message="Token Transfer Cardano Service Failed!", slack_config=SLACK_HOOK)
alert_processor.send(type=1, message="Token Transfer Cardano Service Failed!")
transaction_id = None

# Update claim status as CLAIM_FAILED/CLAIM_SUBMITTED
Expand Down
Loading