from enum import Enum, auto from rlp.sedes import big_endian_int, Binary, CountableList, List, Text from eth_rlp import HashableRLP from eth_utils.curried import ( to_int, hexstr_if_str, ) class StakingSettings: PRECISION = 18 MAX_DECIMAL = 1000000000000000000 class Directive( Enum ): # https://github.com/harmony-one/sdk/blob/99a827782fabcd5f91f025af0d8de228956d42b4/packages/harmony-staking/src/stakingTransaction.ts#L120 def _generate_next_value_(name, start, count, last_values): return count CreateValidator = auto() EditValidator = auto() Delegate = auto() Undelegate = auto() CollectRewards = auto() FORMATTERS = { "directive": hexstr_if_str( to_int ), # delegatorAddress is already formatted before the call "nonce": hexstr_if_str(to_int), "gasPrice": hexstr_if_str(to_int), "gasLimit": hexstr_if_str(to_int), "chainId": hexstr_if_str(to_int), } class CollectRewards: @staticmethod def UnsignedChainId(): class UnsignedChainId(HashableRLP): fields = ( ("directive", big_endian_int), ("stakeMsg", CountableList(Binary.fixed_length(20, allow_empty=True))), ("nonce", big_endian_int), ("gasPrice", big_endian_int), ("gasLimit", big_endian_int), ("chainId", big_endian_int), ) return UnsignedChainId @staticmethod def SignedChainId(): class SignedChainId(HashableRLP): fields = CollectRewards.UnsignedChainId()._meta.fields[ :-1 ] + ( # drop chainId ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return SignedChainId @staticmethod def Unsigned(): class Unsigned(HashableRLP): fields = CollectRewards.UnsignedChainId()._meta.fields[:-1] # drop chainId return Unsigned @staticmethod def Signed(): class Signed(HashableRLP): fields = CollectRewards.Unsigned()._meta.fields[ :-3 ] + ( # drop last 3 for raw.pop() ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return Signed class DelegateOrUndelegate: @staticmethod def UnsignedChainId(): class UnsignedChainId(HashableRLP): fields = ( ("directive", big_endian_int), ( "stakeMsg", List( [ Binary.fixed_length(20, allow_empty=True), Binary.fixed_length(20, allow_empty=True), big_endian_int, ], True, ), ), ("nonce", big_endian_int), ("gasPrice", big_endian_int), ("gasLimit", big_endian_int), ("chainId", big_endian_int), ) return UnsignedChainId @staticmethod def SignedChainId(): class SignedChainId(HashableRLP): fields = DelegateOrUndelegate.UnsignedChainId()._meta.fields[ :-1 ] + ( # drop chainId ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return SignedChainId @staticmethod def Unsigned(): class Unsigned(HashableRLP): fields = DelegateOrUndelegate.UnsignedChainId()._meta.fields[ :-1 ] # drop chainId return Unsigned @staticmethod def Signed(): class Signed(HashableRLP): fields = DelegateOrUndelegate.Unsigned()._meta.fields[ :-3 ] + ( # drop last 3 for raw.pop() ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return Signed class CreateValidator: @staticmethod def UnsignedChainId(): class UnsignedChainId(HashableRLP): fields = ( ("directive", big_endian_int), ( "stakeMsg", List( [ # list with the following members Binary.fixed_length( 20, allow_empty=True ), # validatorAddress List( [Text()] * 5, True ), # description is Text of 5 elements List( [List([big_endian_int], True)] * 3, True ), # commission rate is made up of 3 integers in an array [ [int1], [int2], [int3] ] big_endian_int, # min self delegation big_endian_int, # max total delegation CountableList( Binary.fixed_length(48, allow_empty=True) ), # bls-public-keys array of unspecified length, each key of 48 CountableList( Binary.fixed_length(96, allow_empty=True) ), # bls-key-sigs array of unspecified length, each sig of 96 big_endian_int, # amount ], True, ), ), # strictly these number of elements ("nonce", big_endian_int), ("gasPrice", big_endian_int), ("gasLimit", big_endian_int), ("chainId", big_endian_int), ) return UnsignedChainId @staticmethod def SignedChainId(): class SignedChainId(HashableRLP): fields = CreateValidator.UnsignedChainId()._meta.fields[ :-1 ] + ( # drop chainId ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return SignedChainId @staticmethod def Unsigned(): class Unsigned(HashableRLP): fields = CreateValidator.UnsignedChainId()._meta.fields[:-1] # drop chainId return Unsigned @staticmethod def Signed(): class Signed(HashableRLP): fields = CreateValidator.Unsigned()._meta.fields[ :-3 ] + ( # drop last 3 for raw.pop() ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return Signed class EditValidator: @staticmethod def UnsignedChainId(): class UnsignedChainId(HashableRLP): fields = ( ("directive", big_endian_int), ( "stakeMsg", List( [ # list with the following members Binary.fixed_length( 20, allow_empty=True ), # validatorAddress List( [Text()] * 5, True ), # description is Text of 5 elements List([big_endian_int], True), # new rate is in a list big_endian_int, # min self delegation big_endian_int, # max total delegation Binary.fixed_length( 48, allow_empty=True ), # slot key to remove Binary.fixed_length( 48, allow_empty=True ), # slot key to add ], True, ), ), # strictly these number of elements ("nonce", big_endian_int), ("gasPrice", big_endian_int), ("gasLimit", big_endian_int), ("chainId", big_endian_int), ) return UnsignedChainId @staticmethod def SignedChainId(): class SignedChainId(HashableRLP): fields = EditValidator.UnsignedChainId()._meta.fields[ :-1 ] + ( # drop chainId ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return SignedChainId @staticmethod def Unsigned(): class Unsigned(HashableRLP): fields = EditValidator.UnsignedChainId()._meta.fields[:-1] # drop chainId return Unsigned @staticmethod def Signed(): class Signed(HashableRLP): fields = EditValidator.Unsigned()._meta.fields[ :-3 ] + ( # drop last 3 for raw.pop() ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ) return Signed