예제 #1
0
    def token_network_register(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        channel_participant_deposit_limit: TokenAmount,
        token_network_deposit_limit: TokenAmount,
        retry_timeout: NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ) -> TokenNetworkAddress:
        """Register the `token_address` in the blockchain. If the address is already
           registered but the event has not been processed this function will block
           until the next block to make sure the event is processed.

        Raises:
            InvalidBinaryAddress: If the registry_address or token_address is not a valid address.
            AlreadyRegisteredTokenAddress: If the token is already registered.
            RaidenRecoverableError: If the register transaction failed, this may
                happen because the account has not enough balance to pay for the
                gas or this register call raced with another transaction and lost.
            InvalidTokenAddress: If token_address is the null address (0x000000....00).
        """

        if not is_binary_address(registry_address):
            raise InvalidBinaryAddress(
                "registry_address must be a valid address in binary")

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "token_address must be a valid address in binary")

        if token_address == NULL_ADDRESS_BYTES:
            raise InvalidTokenAddress("token_address must be non-zero")

        # The following check is on the same chain state as the
        # `chainstate` variable defined below because the chain state does
        # not change between this line and seven lines below.
        # views.state_from_raiden() returns the same state again and again
        # as far as this gevent context is running.
        if token_address in self.get_tokens_list(registry_address):
            raise AlreadyRegisteredTokenAddress("Token already registered")

        chainstate = views.state_from_raiden(self.raiden)

        registry = self.raiden.proxy_manager.token_network_registry(
            registry_address, block_identifier=chainstate.block_hash)

        token_network_address = registry.add_token(
            token_address=token_address,
            channel_participant_deposit_limit=channel_participant_deposit_limit,
            token_network_deposit_limit=token_network_deposit_limit,
            given_block_identifier=chainstate.block_hash,
        )

        waiting.wait_for_token_network(
            raiden=self.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            retry_timeout=retry_timeout,
        )

        return token_network_address
예제 #2
0
    def get_raiden_events_payment_history_with_timestamps(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: Optional[TokenAddress] = None,
        target_address: Address = None,
        limit: int = None,
        offset: int = None,
    ) -> List[TimestampedEvent]:
        if token_address and not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for token in get_raiden_events_payment_history"
            )

        chain_state = views.state_from_raiden(self.raiden)
        token_network_address = None
        if token_address:
            token_network_address = views.get_token_network_address_by_token_address(
                chain_state=chain_state,
                token_network_registry_address=registry_address,
                token_address=token_address,
            )
            if not token_network_address:
                raise InvalidTokenAddress("Token address does not match a Raiden token network")

        if target_address and not is_binary_address(target_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for "
                "target_address in get_raiden_events_payment_history"
            )

        assert self.raiden.wal, "Raiden service has to be started for the API to be usable."

        event_types = [
            "raiden.transfer.events.EventPaymentReceivedSuccess",
            "raiden.transfer.events.EventPaymentSentFailed",
            "raiden.transfer.events.EventPaymentSentSuccess",
        ]

        events = self.raiden.wal.storage.get_raiden_events_payment_history_with_timestamps(
            event_types=event_types,
            limit=limit,
            offset=offset,
            token_network_address=token_network_address,
            partner_address=target_address,
        )
        events = [
            e
            for e in events
            if event_filter_for_payments(
                event=e.event,
                chain_state=chain_state,
                partner_address=target_address,
                token_address=token_address,
            )
        ]
        return events
예제 #3
0
    def add_token(
        self,
        token_address: TokenAddress,
        channel_participant_deposit_limit: TokenAmount,
        token_network_deposit_limit: TokenAmount,
        given_block_identifier: BlockIdentifier,
    ) -> Tuple[TransactionHash, TokenNetworkAddress]:
        """
        Register token of `token_address` with the token network.
        The limits apply for version 0.13.0 and above of raiden-contracts,
        since instantiation also takes the limits as constructor arguments.
        """
        if given_block_identifier == BLOCK_ID_LATEST:
            raise ValueError(
                'Calling a proxy with "latest" is usually wrong because '
                "the result of the precondition check is not precisely predictable."
            )

        if token_address == NULL_ADDRESS_BYTES:
            raise InvalidTokenAddress(
                "The call to register a token at 0x00..00 will fail.")

        if token_network_deposit_limit <= 0:
            raise InvalidTokenNetworkDepositLimit(
                f"Token network deposit limit must be larger than zero, "
                f"{token_network_deposit_limit} given.")

        if channel_participant_deposit_limit <= 0:
            raise InvalidTokenNetworkDepositLimit(
                f"Participant deposit limit must be larger than zero, "
                f"{channel_participant_deposit_limit} given")

        if channel_participant_deposit_limit > token_network_deposit_limit:
            raise InvalidChannelParticipantDepositLimit(
                f"Participant deposit limit must be smaller than the network "
                f"deposit limit, {channel_participant_deposit_limit} is larger "
                f"than {token_network_deposit_limit}.")

        token_proxy = self.proxy_manager.token(token_address,
                                               given_block_identifier)
        try:
            token_supply = token_proxy.total_supply(
                block_identifier=given_block_identifier)
            already_registered = self.get_token_network(
                token_address=token_address,
                block_identifier=given_block_identifier)
            deprecation_executor = self.get_deprecation_executor(
                block_identifier=given_block_identifier)
            settlement_timeout_min = self.settlement_timeout_min(
                block_identifier=given_block_identifier)
            settlement_timeout_max = self.settlement_timeout_max(
                block_identifier=given_block_identifier)
            chain_id = self.get_chain_id(
                block_identifier=given_block_identifier)
            secret_registry_address = self.get_secret_registry_address(
                block_identifier=given_block_identifier)
            max_token_networks = self.get_max_token_networks(
                block_identifier=given_block_identifier)
            token_networks_created = self.get_token_network_created(
                block_identifier=given_block_identifier)
        except ValueError:
            # If `given_block_identifier` has been pruned the checks cannot be performed
            pass
        except BadFunctionCallOutput:
            raise_on_call_returned_empty(given_block_identifier)
        else:
            if token_networks_created >= max_token_networks:
                raise MaxTokenNetworkNumberReached(
                    f"Number of token networks will exceed the maximum of {max_token_networks}"
                )

            if token_supply is None:
                raise InvalidToken("Given token address does not follow the "
                                   "ERC20 standard (missing `totalSupply()`)")
            if already_registered:
                raise BrokenPreconditionError(
                    "The token is already registered in the TokenNetworkRegistry."
                )

            if deprecation_executor == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The deprecation executor property for the TokenNetworkRegistry is invalid."
                )

            if chain_id == 0:
                raise BrokenPreconditionError(
                    "The chain ID property for the TokenNetworkRegistry is invalid."
                )

            if chain_id != self.rpc_client.chain_id:
                raise BrokenPreconditionError(
                    f"The provided chain ID {chain_id} does not match the "
                    f"network Raiden is running on: {self.rpc_client.chain_id}."
                )

            if secret_registry_address == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The secret registry address for the token network is invalid."
                )

            if settlement_timeout_min == 0:
                raise BrokenPreconditionError(
                    "The minimum settlement timeout for the token network "
                    "should be larger than zero.")

            if settlement_timeout_max <= settlement_timeout_min:
                raise BrokenPreconditionError(
                    "The maximum settlement timeout for the token network "
                    "should be larger than the minimum settlement timeout.")

        log_details = {
            "given_block_identifier": format_block_id(given_block_identifier)
        }
        return self._add_token(
            token_address=token_address,
            channel_participant_deposit_limit=channel_participant_deposit_limit,
            token_network_deposit_limit=token_network_deposit_limit,
            log_details=log_details,
        )
예제 #4
0
    def add_token(
        self,
        token_address: TokenAddress,
        channel_participant_deposit_limit: TokenAmount,
        token_network_deposit_limit: TokenAmount,
        block_identifier: BlockSpecification,
    ) -> TokenNetworkAddress:
        """
        Register token of `token_address` with the token network.
        The limits apply for version 0.13.0 and above of raiden-contracts,
        since instantiation also takes the limits as constructor arguments.
        """
        if block_identifier == "latest":
            raise ValueError(
                'Calling a proxy with "latest" is usually wrong because '
                "the result of the precondition check is not precisely predictable."
            )

        if token_address == NULL_ADDRESS_BYTES:
            raise InvalidTokenAddress(
                "The call to register a token at 0x00..00 will fail.")

        if token_network_deposit_limit <= 0:
            raise InvalidTokenNetworkDepositLimit(
                f"Token network deposit limit of {token_network_deposit_limit} is invalid"
            )

        if channel_participant_deposit_limit > token_network_deposit_limit:
            raise InvalidChannelParticipantDepositLimit(
                f"Channel participant deposit limit of "
                f"{channel_participant_deposit_limit} is invalid")

        token_proxy = self.proxy_manager.token(token_address)
        try:
            token_supply = token_proxy.total_supply(
                block_identifier=block_identifier)
            already_registered = self.get_token_network(
                token_address=token_address, block_identifier=block_identifier)
            deprecation_executor = self.get_deprecation_executor(
                block_identifier=block_identifier)
            settlement_timeout_min = self.settlement_timeout_min(
                block_identifier=block_identifier)
            settlement_timeout_max = self.settlement_timeout_max(
                block_identifier=block_identifier)
            chain_id = self.get_chain_id(block_identifier=block_identifier)
            secret_registry_address = self.get_secret_registry_address(
                block_identifier=block_identifier)
            max_token_networks = self.get_max_token_networks(
                block_identifier=block_identifier)
            token_networks_created = self.get_token_network_created(
                block_identifier=block_identifier)
        except ValueError:
            # If `block_identifier` has been pruned the checks cannot be performed
            pass
        except BadFunctionCallOutput:
            raise_on_call_returned_empty(block_identifier)
        else:
            if token_networks_created >= max_token_networks:
                raise BrokenPreconditionError(
                    f"Number of token networks will exceed the max of {max_token_networks}"
                )

            if token_supply == "":
                raise InvalidToken("Given token address does not follow the "
                                   "ERC20 standard (missing `totalSupply()`)")
            if already_registered:
                raise BrokenPreconditionError(
                    "The token is already registered in the TokenNetworkRegistry."
                )

            if deprecation_executor == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The deprecation executor property for the TokenNetworkRegistry is invalid."
                )

            if chain_id == 0:
                raise BrokenPreconditionError(
                    "The chain ID property for the TokenNetworkRegistry is invalid."
                )

            if secret_registry_address == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The secret registry address for the token network is invalid."
                )

            if settlement_timeout_min == 0:
                raise BrokenPreconditionError(
                    "The minimum settlement timeout for the token network "
                    "should be larger than zero.")

            if settlement_timeout_min == 0:
                raise BrokenPreconditionError(
                    "The minimum settlement timeout for the token network "
                    "should be larger than zero.")

            if settlement_timeout_max <= settlement_timeout_min:
                raise BrokenPreconditionError(
                    "The maximum settlement timeout for the token network "
                    "should be larger than the minimum settlement timeout.")

        log_details = {
            "node": to_checksum_address(self.node_address),
            "contract": to_checksum_address(self.address),
            "token_address": to_checksum_address(token_address),
        }
        with log_transaction(log, "add_token", log_details):
            return self._add_token(
                token_address=token_address,
                channel_participant_deposit_limit=
                channel_participant_deposit_limit,
                token_network_deposit_limit=token_network_deposit_limit,
                log_details=log_details,
            )