|
|
|
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
|