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
2 changes: 2 additions & 0 deletions crypto/enums/abi_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
class AbiFunction(Enum):
VOTE = 'vote'
UNVOTE = 'unvote'
USERNAME_REGISTRATION = 'registerUsername'
USERNAME_RESIGNATION = 'resignUsername'
VALIDATOR_REGISTRATION = 'registerValidator'
VALIDATOR_RESIGNATION = 'resignValidator'
6 changes: 6 additions & 0 deletions crypto/enums/contract_abi_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from enum import Enum

class ContractAbiType(Enum):
CUSTOM = 'custom'
CONSENSUS = 'consensus'
USERNAMES = 'usernames'
6 changes: 6 additions & 0 deletions crypto/enums/contract_addresses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from enum import Enum

class ContractAddresses(Enum):
CONSENSUS = '0x535B3D7A252fa034Ed71F0C53ec0C6F784cB64E1'
MULTIPAYMENT = '0x83769BeEB7e5405ef0B7dc3C66C43E3a51A6d27f'
USERNAMES = '0x2c1DE3b4Dbb4aDebEbB5dcECAe825bE2a9fc6eb6'
4 changes: 4 additions & 0 deletions crypto/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ class ArkSerializerException(ArkCryptoException):

class ArkInvalidTransaction(ArkCryptoException):
"""Raised when transaction is not valid"""


class InvalidUsernameException(Exception):
"""Raised when username is invalid"""
39 changes: 39 additions & 0 deletions crypto/transactions/builder/username_registration_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import re
from typing import Optional
from crypto.enums.contract_addresses import ContractAddresses
from crypto.exceptions import InvalidUsernameException
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.types.username_registration import UsernameRegistration

class UsernameRegistrationBuilder(AbstractTransactionBuilder):
def __init__(self, data: Optional[dict] = None):
super().__init__(data)

self.recipient_address(ContractAddresses.USERNAMES.value)

def username(self, username: str):
self.is_valid_username(username)

self.transaction.data['username'] = username
self.transaction.refresh_payload_data()

return self

def get_transaction_instance(self, data: dict):
return UsernameRegistration(data)

@staticmethod
def is_valid_username(username: str) -> bool:
if len(username) < 1 or len(username) > 20:
raise InvalidUsernameException(f'Username must be between 1 and 20 characters long. Got {len(username)} characters.')

if re.match('/[^a-z0-9_]/', username):
raise InvalidUsernameException('Username can only contain lowercase letters, numbers and underscores.')

if re.match('/^_|_$/', username):
raise InvalidUsernameException('Username cannot start or end with an underscore.')

if re.match('/__/', username):
raise InvalidUsernameException('Username cannot contain consecutive underscores.')

return True
13 changes: 13 additions & 0 deletions crypto/transactions/builder/username_resignation_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import Optional
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.types.username_resignation import UsernameResignation

class UsernameResignationBuilder(AbstractTransactionBuilder):
def __init__(self, data: Optional[dict] = None):
super().__init__(data)

self.recipient_address(ContractAddresses.USERNAMES.value)

def get_transaction_instance(self, data: dict):
return UsernameResignation(data)
21 changes: 21 additions & 0 deletions crypto/transactions/types/username_registration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from crypto.enums.contract_abi_type import ContractAbiType
from crypto.transactions.types.abstract_transaction import AbstractTransaction
from crypto.utils.abi_encoder import AbiEncoder
from crypto.enums.abi_function import AbiFunction

class UsernameRegistration(AbstractTransaction):
def __init__(self, data: dict = None):
data = data or {}
payload = self.decode_payload(data)
if payload:
data['username'] = payload.get('args', [None])[0] if payload.get('args') else None

super().__init__(data)

def get_payload(self) -> str:
if 'username' not in self.data:
return ''

encoder = AbiEncoder(ContractAbiType.USERNAMES)

return encoder.encode_function_call(AbiFunction.USERNAME_REGISTRATION.value, [self.data['username']])
10 changes: 10 additions & 0 deletions crypto/transactions/types/username_resignation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from crypto.enums.contract_abi_type import ContractAbiType
from crypto.transactions.types.abstract_transaction import AbstractTransaction
from crypto.utils.abi_encoder import AbiEncoder
from crypto.enums.abi_function import AbiFunction

class UsernameResignation(AbstractTransaction):
def get_payload(self) -> str:
encoder = AbiEncoder(ContractAbiType.USERNAMES)

return encoder.encode_function_call(AbiFunction.USERNAME_RESIGNATION.value)
Loading