Exemplo n.º 1
0
    def prepare_transaction(self, txn: TransactionAPI) -> TransactionAPI:
        """
        Set default values on a transaction.

        Raises:
            :class:`~ape.exceptions.AccountsError`: When the account cannot afford the transaction
              or the nonce is invalid.
            :class:`~ape.exceptions.TransactionError`: When given negative required confirmations.

        Args:
            txn (:class:`~ape.api.transactions.TransactionAPI`): The transaction to prepare.

        Returns:
            :class:`~ape.api.transactions.TransactionAPI`
        """

        # NOTE: Allow overriding nonce, assume user understand what this does
        if txn.nonce is None:
            txn.nonce = self.nonce
        elif txn.nonce < self.nonce:
            raise AccountsError("Invalid nonce, will not publish.")

        txn = self.provider.prepare_transaction(txn)

        if txn.total_transfer_value > self.balance:
            raise AccountsError(
                "Transfer value meets or exceeds account balance.\n"
                "Are you using the correct provider/account combination?\n"
                f"(transfer_value={txn.total_transfer_value}, balance={self.balance})."
            )

        return txn
Exemplo n.º 2
0
def get_user_selected_account(
        account_type: Optional[Type[AccountAPI]] = None,
        prompt_message: Optional[str] = None) -> AccountAPI:
    """
    Prompt the user to pick from their accounts and return that account.
    Use this method if you want to prompt users to select accounts _outside_
    of CLI options. For CLI options, use
    :meth:`~ape.cli.options.account_option`.

    Args:
        account_type (type[:class:`~ape.api.accounts.AccountAPI`], optional):
          If given, the user may only select an account of this type.
        prompt_message (str, optional): Customize the prompt message.

    Returns:
        :class:`~ape.api.accounts.AccountAPI`
    """

    if account_type and not issubclass(account_type, AccountAPI):
        raise AccountsError(
            f"Cannot return accounts with type '{account_type}'.")

    prompt = AccountAliasPromptChoice(account_type=account_type,
                                      prompt_message=prompt_message)
    return prompt.get_user_selected_account()
Exemplo n.º 3
0
    def deploy(self, contract: "ContractContainer", *args,
               **kwargs) -> "ContractInstance":
        """
        Create a smart contract on the blockchain. The smart contract must compile before
        deploying and a provider must be active.

        Args:
            contract (:class:`~ape.contracts.ContractContainer`):
                The type of contract to deploy.

        Returns:
            :class:`~ape.contracts.ContractInstance`: An instance of the deployed contract.
        """

        txn = contract(*args, **kwargs)
        txn.sender = self.address
        receipt = self.call(txn)

        if not receipt.contract_address:
            raise AccountsError(
                f"'{receipt.txn_hash}' did not create a contract.")

        address = click.style(receipt.contract_address, bold=True)
        contract_name = contract.contract_type.name or "<Unnamed Contract>"
        logger.success(f"Contract '{contract_name}' deployed to: {address}")

        contract_instance = self.create_contract(
            address=receipt.contract_address,  # type: ignore
            contract_type=contract.contract_type,
        )
        self.chain_manager.contracts[
            contract_instance.address] = contract_instance.contract_type
        return contract_instance
Exemplo n.º 4
0
    def get_user_selected_account(self) -> AccountAPI:
        """
        Returns the selected account.

        Returns:
            :class:`~ape.api.accounts.AccountAPI`
        """

        if not self.choices:
            raise AccountsError("No accounts found.")
        elif len(self.choices) == 1:
            return accounts.load(self.choices[0])

        self.print_choices()
        return click.prompt(self._prompt_message, type=self)
Exemplo n.º 5
0
    def remove(self, account: AccountAPI):
        """
        Delete an account.

        Raises:
            :class:`~ape.exceptions.AccountsError`: When the account is not known to ``ape``.

        Args:
            account (:class:`~ape.accounts.AccountAPI`): The account to remove.
        """
        self._verify_account_type(account)

        if account.address not in self:
            raise AccountsError(f"Account '{account.address}' not known.")

        self.__delitem__(account.address)
Exemplo n.º 6
0
    def append(self, account: AccountAPI):
        """
        Add an account to the container.

        Raises:
            :class:`~ape.exceptions.AccountsError`: When the account is already in the container.

        Args:
            account (:class:`~ape.api.accounts.AccountAPI`): The account to add.
        """
        self._verify_account_type(account)

        if account.address in self:
            raise AccountsError(
                f"Account '{account.address}' already in container.")

        self._verify_unused_alias(account)

        self.__setitem__(account.address, account)
Exemplo n.º 7
0
 def _verify_account_type(self, account):
     if not isinstance(account, self.account_type):
         message = (
             f"Container '{type(account).__name__}' is an incorrect "
             f"type for container '{type(self.account_type).__name__}'.")
         raise AccountsError(message)