Пример #1
0
class MsgUndelegate(StdMsg):

    type = "staking/MsgUndelegate"
    action = "begin_unbonding"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^staking/MsgUndelegate\Z"),
        value=S.OBJECT(
            delegator_address=S.ACC_ADDRESS,
            validator_address=S.VAL_ADDRESS,
            amount=Coin.__schema__,
        ),
    )

    delegator_address: AccAddress
    validator_address: ValAddress
    amount: Coin

    def __post_init__(self):
        self.delegator_address = validate_acc_address(self.delegator_address)
        self.validator_address = validate_val_address(self.validator_address)

    @classmethod
    def from_data(cls, data: dict) -> MsgUndelegate:
        data = data["value"]
        return cls(
            delegator_address=data["delegator_address"],
            validator_address=data["validator_address"],
            amount=Coin.from_data(data["amount"]),
        )
Пример #2
0
class CommunityPoolSpendProposal(Content):

    type = "distribution/CommunityPoolSpendProposal"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(
            r"^distribution/CommunityPoolSpendProposal\Z"),
        value=S.OBJECT(
            title=S.STRING,
            description=S.STRING,
            recipient=S.ACC_ADDRESS,
            amount=Coins.__schema__,
        ),
    )

    title: str
    description: str
    recipient: AccAddress
    amount: Coins

    @classmethod
    def from_data(cls, data: dict) -> CommunityPoolSpendProposal:
        data = data["value"]
        return cls(
            title=data["title"],
            description=data["description"],
            recipient=data["recipient"],
            amount=Coins.from_data(data["amount"]),
        )
Пример #3
0
class MsgSwap(StdMsg):

    type = "market/MsgSwap"
    action = "swap"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^market/MsgSwap\Z"),
        value=S.OBJECT(trader=S.ACC_ADDRESS,
                       offer_coin=Coin.__schema__,
                       ask_denom=S.STRING),
    )

    trader: AccAddress
    offer_coin: Coin
    ask_denom: str

    def __post_init__(self):
        self.trader = validate_acc_address(self.trader)

    @classmethod
    def from_data(cls, data: dict) -> MsgSwap:
        data = data["value"]
        return cls(
            trader=data["trader"],
            offer_coin=Coin.from_data(data["offer_coin"]),
            ask_denom=data["ask_denom"],
        )
Пример #4
0
class ParameterChangeProposal(Content):

    type = "params/ParameterChangeProposal"
    ParamChanges = ParamChanges  # alias for easy access

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^params/ParameterChangeProposal\Z"),
        value=S.OBJECT(
            title=S.STRING,
            description=S.STRING,
            changes=ParamChanges.__schema__,
        ),
    )

    title: str
    description: str
    changes: ParamChanges = field(default_factory=ParamChanges)

    def __post_init__(self):
        # validation checks for key
        if isinstance(self.changes, dict):
            self.changes = ParamChanges(self.changes)

    @classmethod
    def from_data(cls, data: dict) -> ParameterChangeProposal:
        data = data["value"]
        return cls(
            title=data["title"],
            description=data["description"],
            changes=ParamChanges.from_data(data["changes"]),
        )
Пример #5
0
class MsgSend(StdMsg):

    type = "bank/MsgSend"
    action = "send"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^bank/MsgSend\Z"),
        value=S.OBJECT(
            from_address=S.ACC_ADDRESS,
            to_address=S.ACC_ADDRESS,
            amount=Coins.__schema__,
        ),
    )

    from_address: AccAddress
    to_address: AccAddress
    amount: Union[Coins, List[Coin]]

    def __post_init__(self):
        self.from_address = validate_acc_address(self.from_address)
        self.to_address = validate_acc_address(self.to_address)
        self.amount = Coins(self.amount)

    @classmethod
    def from_data(cls, data: dict) -> MsgSend:
        data = data["value"]
        amount = Coins.from_data(data["amount"])
        return cls(
            from_address=data["from_address"],
            to_address=data["to_address"],
            amount=amount,
        )
Пример #6
0
class MsgExchangeRatePrevote(StdMsg):

    type = "oracle/MsgExchangeRatePrevote"
    action = "exchangerateprevote"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^oracle/MsgExchangeRatePrevote\Z"),
        value=S.OBJECT(
            hash=S.STRING,
            denom=S.STRING,
            feeder=S.ACC_ADDRESS,
            validator=S.VAL_ADDRESS,
        ),
    )

    hash: str
    denom: str
    feeder: AccAddress
    validator: ValAddress

    def __post_init__(self):
        self.feeder = AccAddress(self.feeder)
        self.validator = ValAddress(self.validator)

    @classmethod
    def from_data(cls, data: dict) -> MsgExchangeRatePrevote:
        data = data["value"]
        return cls(
            hash=data["hash"],
            denom=data["denom"],
            feeder=data["feeder"],
            validator=data["validator"],
        )
Пример #7
0
class MsgExchangeRateVote(StdMsg):

    type = "oracle/MsgExchangeRateVote"
    action = "exchangeratevote"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^oracle/MsgExchangeRateVote\Z"),
        value=S.OBJECT(
            exchange_rate=Dec.__schema__,
            salt=S.STRING,
            denom=S.STRING,
            feeder=S.ACC_ADDRESS,
            validator=S.VAL_ADDRESS,
        ),
    )

    exchange_rate: Union[str, Type[Decimal], Coin, int]
    salt: str
    denom: str
    feeder: AccAddress
    validator: ValAddress

    def __post_init__(self):
        self.feeder = validate_acc_address(self.feeder)
        self.validator = validate_val_address(self.validator)
        if not isinstance(self.exchange_rate, Coin):
            self.exchange_rate = Coin(self.denom, self.exchange_rate)
        else:
            validate_same_denom(self.exchange_rate.denom, self.denom)

    def msg_value(self) -> dict:
        d = dict(self.__dict__)
        d["exchange_rate"] = str(self.exchange_rate.amount)
        return d

    @property
    def vote_hash(self):
        return vote_hash(self.salt, self.exchange_rate.amount, self.denom,
                         self.validator)

    @property
    def prevote(self):
        return MsgExchangeRatePrevote(
            hash=self.vote_hash,
            denom=self.denom,
            feeder=self.feeder,
            validator=self.validator,
        )

    @classmethod
    def from_data(cls, data: dict) -> MsgExchangeRateVote:
        data = data["value"]
        xr = Coin(data["denom"], data["exchange_rate"])
        return cls(
            exchange_rate=xr,
            salt=data["salt"],
            denom=xr.denom,
            feeder=data["feeder"],
            validator=data["validator"],
        )
Пример #8
0
class MsgDeposit(StdMsg):

    type = "gov/MsgDeposit"
    action = "deposit"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^gov/MsgDeposit\Z"),
        value=S.OBJECT(
            proposal_id=S.STRING_INTEGER,
            depositor=S.ACC_ADDRESS,
            amount=Coins.__schema__,
        ),
    )

    proposal_id: int
    depositor: AccAddress
    amount: Coins

    def __post_init__(self):
        self.depositor = validate_acc_address(self.depositor)
        self.amount = Coins(self.amount)

    def msg_value(self) -> dict:
        d = dict(self.__dict__)
        d["proposal_id"] = str(self.proposal_id)
        return d

    @classmethod
    def from_data(cls, data: dict) -> MsgDeposit:
        data = data["value"]
        return cls(
            proposal_id=int(data["proposal_id"]),
            depositor=data["depositor"],
            amount=Coins.from_data(data["amount"]),
        )
Пример #9
0
class StdTx(JsonSerializable, JsonDeserializable):

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^core/StdTx\Z"),
        value=S.OBJECT(
            fee=StdFee.__schema__,
            msg=S.ARRAY(S.ANY(*(mt.__schema__ for mt in MSG_TYPES.values()))),
            signatures=S.ARRAY(StdSignature.__schema__),
            memo=S.STRING,
        ),
    )

    # NOTE: msg is not plural, and is NOT a typo. This may change later for consistency.
    fee: Optional[StdFee] = None
    msg: List[StdMsg] = field(default_factory=list)
    signatures: List[StdSignature] = field(default_factory=list)
    memo: str = ""

    def to_data(self) -> dict:
        return {
            "type": "core/StdTx",
            "value": dict(self.__dict__),
        }

    @classmethod
    def from_data(cls, data: dict) -> StdTx:
        data = data["value"]
        fee = StdFee.from_data(data["fee"])
        # deserialize the messages
        msg = []
        for m in data["msg"]:
            msg_type = MSG_TYPES[m["type"]]
            msg.append(msg_type.from_data(m))
        signatures = [StdSignature.from_data(s) for s in data["signatures"]]
        return cls(fee=fee, msg=msg, signatures=signatures, memo=data["memo"])
Пример #10
0
class MsgSubmitProposal(StdMsg):

    type = "gov/MsgSubmitProposal"
    action = "submit_proposal"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^gov/MsgSubmitProposal\Z"),
        value=S.OBJECT(
            content=S.ANY(*(pt.__schema__ for pt in PROPOSAL_TYPES.values())),
            initial_deposit=Coins.__schema__,
            proposer=S.ACC_ADDRESS,
        ),
    )

    content: Type[Content]
    initial_deposit: Coins
    proposer: AccAddress

    def __post_init__(self):
        self.proposer = validate_acc_address(self.proposer)
        self.initial_deposit = Coins(self.initial_deposit)

    @classmethod
    def from_data(cls, data: dict) -> MsgSubmitProposal:
        data = data["value"]
        p_type = PROPOSAL_TYPES[data["content"]["type"]]
        content = p_type.from_data(data["content"])
        return cls(
            content=content,
            initial_deposit=Coins.from_data(data["initial_deposit"]),
            proposer=data["proposer"],
        )
Пример #11
0
class MsgWithdrawDelegationReward(StdMsg):

    type = "distribution/MsgWithdrawDelegationReward"
    action = "withdraw_delegation_reward"

    schema = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^distribution/MsgWithdrawDelegationReward\Z"),
        value=S.OBJECT(
            delegator_address=S.ACC_ADDRESS, validator_address=S.VAL_ADDRESS
        ),
    )

    delegator_address: AccAddress
    validator_address: ValAddress

    def __post_init__(self):
        self.delegator_address = validate_acc_address(self.delegator_address)
        self.validator_address = validate_val_address(self.validator_address)

    @classmethod
    def from_data(cls, data: dict) -> MsgWithdrawDelegationReward:
        data = data["value"]
        return cls(
            delegator_address=data["delegator_address"],
            validator_address=data["validator_address"],
        )
Пример #12
0
class MsgMultiSend(StdMsg):

    type = "bank/MsgMultiSend"
    action = "multisend"

    Input = Input  # alias
    Output = Output  # alias

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^bank/MsgMultiSend\Z"),
        value=S.OBJECT(inputs=S.ARRAY(Input.__schema__),
                       outputs=S.ARRAY(Output.__schema__)),
    )

    inputs: List[Union[Input, dict]]
    outputs: List[Union[Output, dict]]

    def __init__(
        self,
        inputs: List[Input],
        outputs: List[Output],
    ):
        self.inputs = []
        self.outputs = []

        for i in inputs:
            if isinstance(i, dict):
                self.inputs.append(
                    Input(address=i["address"], coins=i["coins"]))
            elif isinstance(i, Input):
                self.inputs.append(i)
            else:
                raise TypeError(
                    f"invalid item {type(i)} encountered in MsgMultiSend.inputs, can only accept 'Input' or 'dict'."
                )
        for o in outputs:
            if isinstance(o, dict):
                self.outputs.append(
                    Output(address=o["address"], coins=o["coins"]))
            elif isinstance(o, Output):
                self.outputs.append(o)
            else:
                raise TypeError(
                    f"invalid item {type(o)} encountered in MsgMultiSend.outputs, can only accept 'Output' or 'dict'."
                )

    @classmethod
    def from_data(cls, data: dict) -> MsgMultiSend:
        data = data["value"]
        return cls(
            inputs=[Input.from_data(i) for i in data["inputs"]],
            outputs=[Output.from_data(o) for o in data["outputs"]],
        )
Пример #13
0
class MsgCreateValidator(StdMsg):

    type = "staking/MsgCreateValidator"
    action = "create_validator"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^staking/MsgCreateValidator\Z"),
        value=S.OBJECT(
            description=Description.__schema__,
            commission=CommissionRates.__schema__,
            min_self_delegation=S.STRING_INTEGER,
            delegator_address=S.ACC_ADDRESS,
            validator_address=S.VAL_ADDRESS,
            pubkey=S.VAL_CONSPUBKEY,
            value=Coin.__schema__,
        ),
    )

    description: Description
    commission: CommissionRates
    min_self_delegation: int
    delegator_address: AccAddress
    validator_address: ValAddress
    pubkey: ValConsPubKey
    value: Coin

    def __post_init__(self):
        self.delegator_address = validate_acc_address(self.delegator_address)
        self.validator_address = validate_val_address(self.validator_address)
        validate_val_conspubkey(self.pubkey)
        self.min_self_delegation = int(self.min_self_delegation)

    def msg_value(self) -> dict:
        d = dict(self.__dict__)
        msd = self.min_self_delegation
        d["min_self_delegation"] = str(msd)
        return d

    @classmethod
    def from_data(cls, data: dict) -> MsgCreateValidator:
        data = data["value"]
        return cls(
            description=Description.from_data(data["description"]),
            commission=CommissionRates.from_data(data["commission"]),
            min_self_delegation=int(data["min_self_delegation"]),
            delegator_address=data["delegator_address"],
            validator_address=data["validator_address"],
            pubkey=data["pubkey"],
            value=Coin.from_data(data["value"]),
        )
Пример #14
0
class TextProposal(Content):

    type = "gov/TextProposal"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^gov/TextProposal\Z"),
        value=S.OBJECT(title=S.STRING, description=S.STRING),
    )

    title: str
    description: str

    @classmethod
    def from_data(cls, data: dict) -> TextProposal:
        data = data["value"]
        return cls(title=data["title"], description=data["description"])
Пример #15
0
class Account(JsonSerializable, JsonDeserializable):

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^core/Account\Z"),
        value=S.OBJECT(
            address=S.ACC_ADDRESS,
            coins=Coins.__schema__,
            public_key=S.OPTIONAL(PublicKey.__schema__),
            account_number=S.STRING_INTEGER,
            sequence=S.STRING_INTEGER,
        ),
    )

    address: str
    coins: Coins
    public_key: Optional[PublicKey]
    account_number: int
    sequence: int

    def __post_init__(self):
        if self.address:
            self.address = validate_acc_address(self.address)
        if self.coins:
            self.coins = Coins(self.coins)
        self.account_number = int(self.account_number)
        self.sequence = int(self.sequence)

    def to_data(self) -> dict:
        d = dict(self.__dict__)
        d["account_number"] = str(self.account_number)
        d["sequence"] = str(self.sequence)
        return {"type": "core/Account", "value": d}

    @classmethod
    def from_data(cls, data: dict) -> Account:
        if "type" in data:
            data = data["value"]
        pk = data["public_key"]
        if pk is not None:
            pk = PublicKey.deserialize(data["public_key"])
        return cls(
            address=data["address"],
            coins=Coins.from_data(data["coins"]),
            public_key=pk,
            account_number=data["account_number"],
            sequence=data["sequence"],
        )
Пример #16
0
class MsgEditValidator(StdMsg):

    type = "staking/MsgEditValidator"
    action = "edit_validator"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^staking/MsgEditValidator\Z"),
        value=S.OBJECT(
            Description=Description.__schema__,
            address=S.VAL_ADDRESS,
            commission_rate=S.OPTIONAL(Dec.__schema__),
            min_self_delegation=S.OPTIONAL(S.STRING_INTEGER),
        ),
    )

    Description: Description
    address: ValAddress
    commission_rate: Optional[Dec] = None
    min_self_delegation: Optional[int] = None

    def __post_init__(self):
        if self.commission_rate is not None:
            self.commission_rate = Dec(self.commission_rate)
        if self.min_self_delegation is not None:
            self.min_self_delegation = int(self.min_self_delegation)
        self.address = validate_val_address(self.address)

    def msg_value(self) -> dict:
        d = dict(self.__dict__)
        msd = self.min_self_delegation
        if msd is not None:
            msd = str(msd)
        d["min_self_delegation"] = msd
        return d

    @classmethod
    def from_data(cls, data: dict) -> MsgEditValidator:
        data = data["value"]
        msd = int(data["min_self_delegation"]) if data["min_self_delegation"] else None
        cr = Dec(data["commission_rate"]) if data["commission_rate"] else None
        return cls(
            Description=data["Description"],
            address=data["address"],
            commission_rate=cr,
            min_self_delegation=msd,
        )
Пример #17
0
class MsgUnjail(StdMsg):

    type = "cosmos/MsgUnjail"
    action = "unjail"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^cosmos/MsgUnjail\Z"),
        value=S.OBJECT(address=S.VAL_ADDRESS),
    )

    address: ValAddress

    def __post_init__(self):
        self.address = validate_val_address(self.address)

    @classmethod
    def from_data(cls, data: dict) -> MsgUnjail:
        data = data["value"]
        return cls(address=data["address"])
Пример #18
0
class MsgWithdrawValidatorCommission(StdMsg):

    type = "distribution/MsgWithdrawValidatorCommission"
    action = "withdraw_validator_commission"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^distribution/MsgWithdrawValidatorCommission\Z"),
        value=S.OBJECT(validator_address=S.VAL_ADDRESS),
    )

    validator_address: ValAddress

    def __post_init__(self):
        self.validator_address = validate_val_address(self.validator_address)

    @classmethod
    def from_data(cls, data: dict) -> MsgWithdrawValidatorCommission:
        data = data["value"]
        return cls(validator_address=data["validator_address"])
Пример #19
0
class MsgDelegateFeedConsent(StdMsg):

    type = "oracle/MsgDelegateFeedConsent"
    action = "delegatefeeder"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^oracle/MsgDelegateFeedConsent\Z"),
        value=S.OBJECT(operator=S.VAL_ADDRESS, delegate=S.ACC_ADDRESS),
    )

    operator: ValAddress
    delegate: AccAddress

    def __post_init__(self):
        self.operator = validate_val_address(self.operator)
        self.delegate = validate_acc_address(self.delegate)

    @classmethod
    def from_data(cls, data: dict) -> MsgDelegateFeedConsent:
        data = data["value"]
        return cls(operator=data["operator"], delegate=data["delegate"])
Пример #20
0
class MsgVote(StdMsg):

    type = "gov/MsgVote"
    action = "vote"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^gov/MsgVote\Z"),
        value=S.OBJECT(
            proposal_id=S.STRING_INTEGER,
            voter=S.ACC_ADDRESS,
            option=S.ONE(S.STRING, S.INTEGER),  # signing is different
        ),
    )

    EMPTY = "Empty"
    YES = "Yes"
    ABSTAIN = "Abstain"
    NO = "No"
    NO_WITH_VETO = "NoWithVeto"

    proposal_id: int
    voter: AccAddress
    option: str

    def __post_init__(self):
        self.voter = validate_acc_address(self.voter)

    def msg_value(self) -> dict:
        d = dict(self.__dict__)
        d["proposal_id"] = str(self.proposal_id)
        return d

    @classmethod
    def from_data(cls, data: dict) -> MsgVote:
        data = data["value"]
        return cls(
            proposal_id=int(data["proposal_id"]),
            voter=data["voter"],
            option=data["option"],
        )
Пример #21
0
class TaxRateUpdateProposal(Content):

    type = "treasury/TaxRateUpdateProposal"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^treasury/TaxRateUpdateProposal\Z"),
        value=S.OBJECT(title=S.STRING,
                       description=S.STRING,
                       tax_rate=Dec.__schema__),
    )

    title: str
    description: str
    tax_rate: Dec

    @classmethod
    def from_data(cls, data: dict) -> TaxRateUpdateProposal:
        data = data["value"]
        return cls(
            title=data["title"],
            description=data["description"],
            tax_rate=Dec(data["tax_rate"]),
        )
Пример #22
0
class RewardWeightUpdateProposal(Content):

    type = "treasury/RewardWeightUpdateProposal"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^treasury/RewardWeightUpdateProposal\Z"),
        value=S.OBJECT(title=S.STRING,
                       description=S.STRING,
                       reward_weight=Dec.__schema__),
    )

    title: str
    description: str
    reward_weight: Dec

    @classmethod
    def from_data(cls, data: dict) -> RewardWeightUpdateProposal:
        data = data["value"]
        return cls(
            title=data["title"],
            description=data["description"],
            reward_weight=Dec(data["reward_weight"]),
        )
Пример #23
0
class MsgModifyWithdrawAddress(StdMsg):

    type = "distribution/MsgModifyWithdrawAddress"
    action = "set_withdraw_address"

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^distribution/MsgModifyWithdrawAddress\Z"),
        value=S.OBJECT(delegator_address=S.ACC_ADDRESS, withdraw_address=S.ACC_ADDRESS),
    )

    delegator_address: AccAddress
    withdraw_address: AccAddress

    def __post_init__(self):
        self.delegator_address = validate_acc_address(self.delegator_address)
        self.withdraw_address = validate_acc_address(self.withdraw_address)

    @classmethod
    def from_data(cls, data: dict) -> MsgModifyWithdrawAddress:
        data = data["value"]
        return cls(
            delegator_address=data["delegator_address"],
            withdraw_address=data["withdraw_address"],
        )
Пример #24
0
class Timestamp(wrapt.ObjectProxy, JsonSerializable, JsonDeserializable):

    # we have 2 patterns, 1 for serdes-checking in tests and 1 for checking if it works
    # python's builtin datetime
    pattern = re.compile(
        r"^(0001|[1-9]\d{3})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([0-1]\d|2[0-3]):([0-5]\d):([0-5]\d)(\.\d+)?Z\Z"
    )

    __schema__ = S.STRING_WITH_PATTERN(
        r"^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?Z\Z")

    def __init__(self,
                 year,
                 month,
                 day,
                 hour,
                 minute,
                 second,
                 ns=0,
                 precision=0):
        wrapt.ObjectProxy.__init__(
            self, datetime(year, month, day, hour, minute, second, ns // 1000))
        self._self_ns = ns
        self._self_precision = min(9, precision)

    @property
    def ns(self):
        return self._self_ns

    @property
    def precision(self):
        return self._self_precision

    @property
    def nanosecond(self):
        return int(self.ns % 1000)

    def __str__(self) -> str:
        Y = str(self.year).rjust(4, "0")
        M = str(self.month).rjust(2, "0")
        D = str(self.day).rjust(2, "0")
        h = str(self.hour).rjust(2, "0")
        m = str(self.minute).rjust(2, "0")
        s = str(self.second).rjust(2, "0")
        r = f"{Y}-{M}-{D}T{h}:{m}:{s}"
        if self.precision > 0:
            r += "."
            r += str(self.microsecond * 1000 + self.nanosecond).rjust(
                9, "0")[:self.precision]
        return r + "Z"

    def __repr__(self) -> str:
        s = self
        p = f", {s.precision}" if s.precision != 0 else ""
        return f"Timestamp({s.year}, {s.month}, {s.day}, {s.hour}, {s.minute}, {s.second}, {s.ns}{p})"

    def to_data(self) -> str:
        return str(self)

    def _pretty_repr_(self, path: str = ""):
        return self.strftime("%a %b %d '%y - %H:%M:%S.%f")

    @classmethod
    def from_datetime(cls, dt: datetime) -> Timestamp:
        return cls(
            year=dt.year,
            month=dt.month,
            day=dt.day,
            hour=dt.hour,
            minute=dt.minute,
            second=dt.second,
            ns=dt.microsecond * 1000,
            precision=6 if dt.microsecond > 0 else 0,
        )

    @classmethod
    def from_data(cls, data: str) -> Timestamp:
        m = cls.pattern.match(data)
        # m = re.match(cls.__schema__["pattern"], data)
        if m:
            year, month, day, hour, minute, second = [
                int(m.group(x)) for x in range(1, 7)
            ]
            if m.group(7) is not None:
                # keep only nanosecond precision
                ns = int(Decimal(m.group(7)) * 1_000_000_000)
                precision = min(9, len(m.group(7)) - 1)
            else:
                ns = 0
                precision = 0
            return cls(year, month, day, hour, minute, second, ns, precision)
        else:
            raise ValueError(f"Timestamp could not deserialize: {data}")

    @classmethod
    def from_str(cls, string: str) -> Timestamp:
        return cls.from_data(string)

    # TODO: write datetime analogous functions for things that return datetime
    # Not sure if this is too high priority as Timestamp is not a replacement for datetime.

    def __eq__(self, other):
        if isinstance(other, Timestamp):
            return self.__wrapped__ == other.__wrapped__ and self.ns == other.ns
        return self.__wrapped__ == other and self.nanosecond == 0

    def __ne__(self, other):
        return not self.__eq__(other)

    def __lt__(self, other):
        if isinstance(other, Timestamp):
            if self.__wrapped__ == other.__wrapped__:
                return self.ns < other.ns
            else:
                return self.__wrapped__ < other.__wrapped__
        return self.__wrapped__ < other

    def __le__(self, other):
        return self == other or self < other

    def __gt__(self, other):
        if isinstance(other, Timestamp):
            if self.__wrapped__ == other.__wrapped__:
                return self.ns > other.ns
            else:
                return self.__wrapped__ > other.__wrapped__
        if self.__wrapped__ == other:
            return self.ns > 0
        else:
            return self.__wrapped__ > other

    def __ge__(self, other):
        return self == other or self > other
Пример #25
0
class Dec(JsonSerializable, JsonDeserializable):

    __schema__ = S.STRING_WITH_PATTERN(SDK_DEC_REGEX_PATTERN)

    def __init__(self, arg):
        """BigInt-based Decimal representation with basic arithmetic operations with
        compatible Python numeric types (int, float, Decimal). Does not work with
        NaN, Infinity, +0, -0, etc. Serializes as a string with 18 points of decimal
        precision.
        """
        if isinstance(arg, float):
            arg = str("%f" % arg)
        if isinstance(arg, str):
            parts = PATTERN.match(arg)
            if parts is None:
                raise ValueError(
                    f"Unable to parse Dec object from string: {arg}")
            self.i = int(parts.group(2)) * SDK_DEC_UNIT  # integer part
            if parts.group(3):
                fraction = (parts.group(3).lstrip(".")[0:SDK_DEC_PREC].ljust(
                    SDK_DEC_PREC, "0"))
                self.i += int(fraction)
            if parts.group(1) is not None:
                self.i *= -1
        elif isinstance(arg, int):
            self.i = arg * SDK_DEC_UNIT
        elif isinstance(arg, Dec):
            self.i = arg.i
        elif isinstance(arg, Decimal):
            whole = int(arg)
            fraction = arg % 1
            self.i = (whole * SDK_DEC_UNIT) + (fraction * SDK_DEC_UNIT)
        else:
            raise TypeError(
                f"Unable to create Dec object from given argument {arg}")
        # guarantee int
        self.i = int(self.i)

    @property
    def short_str(self):
        parity = "-" if self.i < 0 else ""
        frac = self.frac.rstrip("0")
        dot = "." if len(frac) > 0 else ""
        return f"{parity}{self.whole}{dot}{frac}"

    def __repr__(self):
        return f"Dec({self.short_str!r})"  # short representation

    def __str__(self) -> str:
        if self.i == 0:
            return "0." + SDK_DEC_PREC * "0"
        parity = "-" if self.i < 0 else ""
        return f"{parity}{self.whole}.{self.frac}"

    def __int__(self) -> int:
        int_part = abs(self.i) // SDK_DEC_UNIT
        int_part *= -1 if self.i < 0 else 1
        return int_part

    def __float__(self) -> float:
        # NOTE: This is not robust enough for: float(Dec(float)) to give the same output,
        # and should mainly be used as getting a rough value from the Dec object.
        return self.i / SDK_DEC_UNIT

    @property
    def parity(self) -> int:
        return -1 if self.i < 0 else 1

    @property
    def whole(self) -> str:
        return str(abs(self.i) // SDK_DEC_UNIT)

    @property
    def frac(self) -> str:
        return str(abs(self.i) % SDK_DEC_UNIT).rjust(SDK_DEC_PREC, "0")

    def to_data(self) -> str:
        return str(self)

    def _pretty_repr_(self, path: str = ""):
        return self.short_str

    def __eq__(self, other) -> bool:
        try:
            return self._i_binop(other, int.__eq__, "==")
        except TypeError:
            return False

    def __lt__(self, other) -> bool:
        if isinstance(other, Dec):
            return self.i < other.i
        return (Decimal(self.i) / SDK_DEC_UNIT) < other

    def __le__(self, other) -> bool:
        return self < other or self == other

    def __gt__(self, other) -> bool:
        if isinstance(other, Dec):
            return self.i > other.i
        return (Decimal(self.i) / SDK_DEC_UNIT) > other

    def __ge__(self, other) -> bool:
        return self > other or self == other

    def __add__(self, other) -> Dec:
        new_val = self._i_binop(other, int.__add__, "+")
        nd = Dec(0)
        nd.i = new_val
        return nd

    def __radd__(self, other):
        return Dec.__add__(Dec(other), self)

    def __sub__(self, other) -> Dec:
        new_val = self._i_binop(other, int.__sub__, "-")
        nd = Dec(0)
        nd.i = new_val
        return nd

    def __rsub__(self, other):
        return Dec.__sub__(Dec(other), self)

    def __mul__(self, other):
        if isinstance(other, Dec):
            new_val = self.i * other.i
        elif (isinstance(other, int) or isinstance(other, float)
              or isinstance(other, Decimal)):
            new_val = self.i * Dec(other).i
        else:
            raise TypeError(
                f"unsupported operand types for *: 'Dec' and '{type(other)}'")
        nd = Dec(0)
        nd.i = new_val // SDK_DEC_UNIT
        return nd

    def __rmul__(self, other):
        return Dec.__mul__(Dec(other), self)

    def __truediv__(self, other):
        try:
            # we need the decimal value's better precision.
            d1 = Decimal(self.i)
            d2 = Decimal(other.i)
            new_val = d1 / d2
        except AttributeError:
            new_val = self._i_binop(other, int.__truediv__, "/")
        nd = Dec(0)
        nd.i = int(new_val * SDK_DEC_UNIT)
        return nd

    def __rtruediv__(self, other):
        return Dec.__truediv__(Dec(other), self)

    def __floordiv__(self, other):
        return Dec(int(self / Dec(other)))

    def __neg__(self):
        x = Dec(self)
        x.i *= -1
        return x

    def __abs__(self):
        x = Dec(self)
        x.i = abs(x.i)
        return x

    def __pos__(self):
        return abs(self)

    @classmethod
    def from_data(cls, data: str) -> Dec:
        return cls(data)

    @classmethod
    def with_prec(cls, i: int, prec: int) -> Dec:
        """Replicates Dec.with_prec(i, prec)"""
        d = cls(0)
        i = int(i)
        d.i = i * 10**(SDK_DEC_PREC - int(prec))
        return d

    def _i_binop(self, other, binop, binop_name):
        """Helper method that tries to work with compatible number types by first converting
        them into Dec and working with their internal BigInt representation.
        """
        if isinstance(other, Dec):
            new_val = binop(self.i, other.i)
        elif (isinstance(other, int) or isinstance(other, float)
              or isinstance(other, Decimal)):
            new_val = binop(self.i, Dec(other).i)
        else:
            raise TypeError(
                f"unsupported operand types for {binop_name}: 'Dec' and '{type(other)}'"
            )
        return new_val
Пример #26
0
class LazyGradedVestingAccount(Account):

    __schema__ = S.OBJECT(
        type=S.STRING_WITH_PATTERN(r"^core/LazyGradedVestingAccount\Z"),
        value=S.OBJECT(
            BaseVestingAccount=S.OBJECT(
                BaseAccount=Account.__schema__["properties"]["value"],
                original_vesting=Coins.__schema__,
                delegated_free=Coins.__schema__,
                delegated_vesting=Coins.__schema__,
                end_time=S.STRING_INTEGER,
            ),
            vesting_schedules=S.ARRAY(
                S.OBJECT(denom=S.STRING,
                         schedules=S.ARRAY(VestingScheduleEntry.__schema__))),
        ),
    )

    original_vesting: Coins
    delegated_free: Coins
    delegated_vesting: Coins
    end_time: int
    vesting_schedules: Dict[str, List[VestingScheduleEntry]]

    def __init__(
        self,
        base_account: Account,
        original_vesting: Coins,
        delegated_free: Coins,
        delegated_vesting: Coins,
        end_time: int,
        vesting_schedules: Dict[str, List[VestingScheduleEntry]],
    ):
        Account.__init__(
            self,
            address=base_account.address,
            coins=base_account.coins,
            public_key=base_account.public_key,
            account_number=base_account.account_number,
            sequence=base_account.sequence,
        )
        self._base_account = base_account
        self.original_vesting = original_vesting
        self.delegated_free = delegated_free
        self.delegated_vesting = delegated_vesting
        self.end_time = end_time
        self.vesting_schedules = vesting_schedules

    def to_data(self):
        return {
            "type": "core/LazyGradedVestingAccount",
            "value": {
                "BaseVestingAccount": {
                    "BaseAccount":
                    Account.to_data(self._base_account)["value"],
                    "original_vesting": self.original_vesting,
                    "delegated_free": self.delegated_free,
                    "delegated_vesting": self.delegated_vesting,
                    "end_time": str(self.end_time),
                },
                "vesting_schedules": [{
                    "denom":
                    denom,
                    "schedules":
                    self.vesting_schedules[denom]
                } for denom in self.vesting_schedules],
            },
        }

    @property
    def pretty_data(self):
        d = dict(self.__dict__)
        d.pop("_base_account")
        return d.items()

    @classmethod
    def from_data(cls, data: dict) -> LazyGradedVestingAccount:
        if "type" in data:
            data = data["value"]  # disregard type
        bva = data[
            "BaseVestingAccount"]  # value = { bva { ... } vesting_schedules { } }
        original_vesting = Coins.from_data(bva["original_vesting"])
        delegated_free = Coins.from_data(bva["delegated_free"])
        delegated_vesting = Coins.from_data(bva["delegated_vesting"])
        vesting_schedules = JiguBox({})
        for s in data["vesting_schedules"]:
            vesting_schedules[s["denom"]] = [
                VestingScheduleEntry.deserialize(e) for e in s["schedules"]
            ]
        return cls(
            base_account=Account.from_data(bva["BaseAccount"]),
            original_vesting=original_vesting,
            delegated_free=delegated_free,
            delegated_vesting=delegated_vesting,
            end_time=int(bva["end_time"]),
            vesting_schedules=vesting_schedules,
        )