local.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. from typing import (
  2. Any,
  3. Dict,
  4. Optional,
  5. cast,
  6. )
  7. from eth_keyfile.keyfile import (
  8. KDFType,
  9. )
  10. from eth_keys.datatypes import (
  11. PrivateKey,
  12. )
  13. from eth_typing import (
  14. ChecksumAddress,
  15. Hash32,
  16. )
  17. from eth_account.account_local_actions import (
  18. AccountLocalActions,
  19. )
  20. from eth_account.datastructures import (
  21. SignedMessage,
  22. SignedTransaction,
  23. )
  24. from eth_account.messages import (
  25. SignableMessage,
  26. )
  27. from eth_account.signers.base import (
  28. BaseAccount,
  29. )
  30. from eth_account.types import (
  31. Blobs,
  32. TransactionDictType,
  33. )
  34. class LocalAccount(BaseAccount):
  35. r"""
  36. A collection of convenience methods to sign and encrypt, with an
  37. embedded private key.
  38. :var bytes key: the 32-byte private key data
  39. .. code-block:: python
  40. >>> my_local_account.address
  41. "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55"
  42. >>> my_local_account.key
  43. b"\x01\x23..."
  44. You can also get the private key by casting the account to :class:`bytes`:
  45. .. code-block:: python
  46. >>> bytes(my_local_account)
  47. b"\\x01\\x23..."
  48. """
  49. def __init__(self, key: PrivateKey, account: AccountLocalActions):
  50. """
  51. Initialize a new account with the given private key.
  52. :param eth_keys.PrivateKey key: to prefill in private key execution
  53. :param ~eth_account.account.Account account: the key-unaware management API
  54. """
  55. self._publicapi: AccountLocalActions = account
  56. self._address: ChecksumAddress = key.public_key.to_checksum_address()
  57. key_raw: bytes = key.to_bytes()
  58. self._private_key = key_raw
  59. self._key_obj: PrivateKey = key
  60. def __bytes__(self) -> bytes:
  61. return self.key
  62. @property
  63. def address(self) -> ChecksumAddress:
  64. return self._address
  65. @property
  66. def key(self) -> bytes:
  67. """
  68. Get the private key.
  69. """
  70. return self._private_key
  71. def encrypt(
  72. self,
  73. password: str,
  74. kdf: Optional[KDFType] = None,
  75. iterations: Optional[int] = None,
  76. ) -> Dict[str, Any]:
  77. """
  78. Generate a string with the encrypted key.
  79. This uses the same structure as in
  80. :meth:`~eth_account.account.Account.encrypt`, but without a
  81. private key argument.
  82. """
  83. return self._publicapi.encrypt(
  84. self.key, password, kdf=kdf, iterations=iterations
  85. )
  86. def unsafe_sign_hash(self, message_hash: Hash32) -> SignedMessage:
  87. return cast(
  88. SignedMessage,
  89. self._publicapi.unsafe_sign_hash(
  90. message_hash,
  91. private_key=self.key,
  92. ),
  93. )
  94. def sign_message(self, signable_message: SignableMessage) -> SignedMessage:
  95. """
  96. Generate a string with the encrypted key.
  97. This uses the same structure as in
  98. :meth:`~eth_account.account.Account.sign_message`, but without a
  99. private key argument.
  100. """
  101. return cast(
  102. SignedMessage,
  103. self._publicapi.sign_message(signable_message, private_key=self.key),
  104. )
  105. def sign_transaction(
  106. self, transaction_dict: TransactionDictType, blobs: Optional[Blobs] = None
  107. ) -> SignedTransaction:
  108. return cast(
  109. SignedTransaction,
  110. self._publicapi.sign_transaction(transaction_dict, self.key, blobs=blobs),
  111. )
  112. def sign_typed_data(
  113. self,
  114. domain_data: Optional[Dict[str, Any]] = None,
  115. message_types: Optional[Dict[str, Any]] = None,
  116. message_data: Optional[Dict[str, Any]] = None,
  117. full_message: Optional[Dict[str, Any]] = None,
  118. ) -> SignedMessage:
  119. """
  120. Sign the provided EIP-712 message with the local private key.
  121. This uses the same structure as in
  122. :meth:`~eth_account.account.Account.sign_typed_data`, but without a
  123. private key argument.
  124. """
  125. return cast(
  126. SignedMessage,
  127. self._publicapi.sign_typed_data(
  128. private_key=self.key,
  129. domain_data=domain_data,
  130. message_types=message_types,
  131. message_data=message_data,
  132. full_message=full_message,
  133. ),
  134. )
  135. def sign_authorization(self, authorization: Dict[str, Any]) -> SignedMessage:
  136. return cast(
  137. SignedMessage,
  138. self._publicapi.sign_authorization(authorization, private_key=self.key),
  139. )