Source code for matic.plasma.erc_20

from __future__ import annotations

from typing import Callable

from eth_typing import HexAddress

from matic.abstracts import BaseContract
from matic.constants import (
    MATIC_TOKEN_ADDRESS_ON_POLYGON,
    MAX_AMOUNT,
    PlasmaLogEventSignature,
)
from matic.exceptions import NullSpenderAddressException
from matic.json_types import (
    IAllowanceTransactionOption,
    IPlasmaClientConfig,
    IPlasmaContracts,
    ITransactionOption,
    ITransactionWriteResult,
)
from matic.plasma.plasma_token import PlasmaToken
from matic.utils.web3_side_chain_client import Web3SideChainClient


[docs]class ERC20(PlasmaToken): """ERC-20-compliant token on plasma bridge.""" WITHDRAW_EXIT_SIGNATURE = PlasmaLogEventSignature.ERC_20_WITHDRAW_EVENT_SIG """Withdraw event signature, used for exit methods.""" def __init__( self, token_address: HexAddress, is_parent: bool, client: Web3SideChainClient[IPlasmaClientConfig], contracts: Callable[[], IPlasmaContracts], ): is_matic_token = token_address == MATIC_TOKEN_ADDRESS_ON_POLYGON super().__init__( is_parent=is_parent, address=token_address, name='MRC20' if is_matic_token else 'ChildERC20', client=client, get_helper_contracts=contracts, ) @property def predicate(self) -> BaseContract: """Get predicate contract for token.""" return self._fetch_predicate( 'erc20Predicate', 'ERC20Predicate', self.client.config.get('erc_20_predicate'), )
[docs] def get_balance( self, user_address: HexAddress, option: ITransactionOption | None = None ) -> int: """Get user balance.""" method = self.contract.method('balanceOf', user_address) return self.process_read(method, option)
[docs] def get_allowance( self, user_address: HexAddress, option: IAllowanceTransactionOption | None = None, ) -> int: """Get allowance for the user.""" option_fixed = self._check_option(option) spender_address = option_fixed.get('spender_address') method = self.contract.method( 'allowance', user_address, spender_address or self.get_helper_contracts().deposit_manager.address, ) return self.process_read(method, option_fixed)
[docs] def approve( self, amount: int, private_key: str | None = None, option: IAllowanceTransactionOption | None = None, ) -> ITransactionWriteResult: """Approve spender to spend some tokens.""" spender_address = option.get('spender_address') if option else None if not spender_address and not self.is_parent: raise NullSpenderAddressException method = self.contract.method( 'approve', spender_address or self.get_helper_contracts().deposit_manager.address, amount, ) return self.process_write(method, option, private_key)
[docs] def approve_max( self, private_key: str | None = None, option: IAllowanceTransactionOption | None = None, ) -> ITransactionWriteResult: """Approve spender to spend all tokens.""" return self.approve(MAX_AMOUNT, private_key, option)
[docs] def deposit( self, amount: int, user_address: HexAddress, private_key: str | None = None, option: ITransactionOption | None = None, ) -> ITransactionWriteResult: """Deposit amount of token for user.""" self.check_for_root() contract = self.get_helper_contracts().deposit_manager.contract method = contract.method( 'depositERC20ForUser', self.address, user_address, amount, ) return self.process_write(method, option, private_key)
def _deposit_ether( self, amount: int, private_key: str | None = None, option: ITransactionOption | None = None, ) -> ITransactionWriteResult: self.check_for_root() option = self._check_option(option) contract = self.get_helper_contracts().deposit_manager.contract option['value'] = amount method = contract.method('depositEther') return self.process_write(method, option, private_key)
[docs] def withdraw_start( self, amount: int, private_key: str | None = None, option: ITransactionOption | None = None, ) -> ITransactionWriteResult: """Initialize withdrawal process.""" self.check_for_child() if self.address == MATIC_TOKEN_ADDRESS_ON_POLYGON: option = self._check_option(option) option['value'] = amount method = self.contract.method('withdraw', amount) return self.process_write(method, option, private_key)
[docs] def transfer( self, amount: int, to: HexAddress, private_key: str | None = None, option: ITransactionOption | None = None, ) -> ITransactionWriteResult: """Transfer given amount of token to another user.""" if self.address == MATIC_TOKEN_ADDRESS_ON_POLYGON: option = self._check_option(option) option['to'] = to option['value'] = amount return self.send_transaction(option, private_key) return self.transfer_erc_20(to, amount, private_key, option)