Accounts — web3.py 7.2.0 documentation (2024)

Local vs Hosted Nodes

Hosted Node

A hosted node is controlled by someone else. You may also see these referred toas remote nodes. View a list of commercial node providers.

Local Node

A local node is started and controlled by you on your computer. For several reasons(e.g., privacy, security), this is the recommended path, but it requires more resourcesand work to set up and maintain. See ethereum.org for a guided tour.

Local vs Hosted Keys

An Ethereum private key is a 256-bit (32 bytes) random integer.For each private key, you get one Ethereum address,also known as an Externally Owned Account (EOA).

In Python, the private key is expressed as a 32-byte long Python bytes object.When a private key is presented to users in a hexadecimal format, it may or maynot contain a starting 0x hexadecimal prefix.

Local Private Key

A local private key is a locally stored secret you import to your Python application.Please read below how you can create and import a local private keyand use it to sign transactions.

Hosted Private Key

This is a legacy way to use accounts when working with unit test backends likeEthereumTesterProvider or Anvil.Calling web3.eth.accounts gives you apredefined list of accounts that have been funded with test ETH.You can use send_transaction() on any of these accountswithout further configuration.

In the past, around 2015, this was also a way to use private keysin a locally hosted node, but this practice is now discouraged.

Warning

web3.eth.send_transaction does not work with modern node providers,because they relied on a node state and all modern nodes are stateless.You must always use local private keys when working with nodes hosted bysomeone else.

Some Common Uses for Local Private Keys

A very common reason to work with local private keys is to interactwith a hosted node.

Some common things you might want to do with a Local Private Key are:

  • Sign a Transaction

  • Sign a Contract Transaction

  • Sign a Message

  • Verify a Message

Using private keys usually involves w3.eth.account in one way or another. Read on for more,or see a full list of things you can do in the docs foreth_account.Account.

Creating a Private Key

Each Ethereum address has a matching private key. To create a new Ethereumaccount you can just generate a random number that acts as a private key.

To create a private key using web3.py and command line you can do:

python -c "from web3 import Web3; w3 = Web3(); acc = w3.eth.account.create(); print(f'private key={w3.to_hex(acc.key)}, account={acc.address}')"

Which outputs a new private key and an account pair:

private key=0x480c4aec9fa..., account=0x9202a9d5D2d129CB400a40e00aC822a53ED81167
  • Never store private key with your source. Use environment variablesto store the key. Read more below.

  • You can also import the raw hex private key to MetaMask and any otherwallet - the private key can be shared between your Python codeand any number of wallets.

Funding a New Account

If you create a private key, it comes with its own Ethereum address.By default, the balance of this address is zero.Before you can send any transactions with your account,you need to top up.

  • For a local test environment (e.g., EthereumTesterProvider), anyenvironment is bootstrapped with accounts that have test ETH in them.Move ETH from default accounts to your newly created account.

  • For public mainnet, you need to buy ETH in a cryptocurrency exchangeand send it to your privately controlled account.

  • For a testnet, find a relevant testnet faucet.

Reading a Private Key from an Environment Variable

In this example we pass the private key to our Python application in anenvironment variable.This private key is then added to the transaction signing keychainwith Signing middleware.

If unfamiliar, note that you can export your private keys from Metamask and other wallets.

Warning

  • Never share your private keys.

  • Never put your private keys in source code.

  • Never commit private keys to a Git repository.

Example account_test_script.py

import osfrom eth_account import Accountfrom eth_account.signers.local import LocalAccountfrom web3 import Web3, EthereumTesterProviderfrom web3.middleware import SignAndSendRawMiddlewareBuilderw3 = Web3(EthereumTesterProvider())private_key = os.environ.get("PRIVATE_KEY")assert private_key is not None, "You must set PRIVATE_KEY environment variable"assert private_key.startswith("0x"), "Private key must start with 0x hex prefix"account: LocalAccount = Account.from_key(private_key)w3.middleware_onion.add(SignAndSendRawMiddlewareBuilder.build(account))print(f"Your hot wallet address is {account.address}")# Now you can use web3.eth.send_transaction(), Contract.functions.xxx.transact() functions# with your local private key through middleware and you no longer get the error# "ValueError: The method eth_sendTransaction does not exist/is not available

Example how to run this in UNIX shell:

# Generate a new 256-bit random integer using openssl UNIX command that acts as a private key.# You can also do:# python -c "from web3 import Web3; w3 = Web3(); acc = w3.eth.account.create(); print(f'private key={w3.to_hex(acc.key)}, account={acc.address}')"# Store this in a safe place, like in your password manager.export PRIVATE_KEY=0x`openssl rand -hex 32`# Run our scriptpython account_test_script.py

This will print:

Your hot wallet address is 0x27C8F899bb69E1501BBB96d09d7477a2a7518918

Extract private key from geth keyfile

Note

The amount of available ram should be greater than 1GB.

with open('~/.ethereum/keystore/UTC--...--5ce9454909639D2D17A3F753ce7d93fa0b9aB12E') as keyfile: encrypted_key = keyfile.read() private_key = w3.eth.account.decrypt(encrypted_key, 'correcthorsebatterystaple') # tip: do not save the key or password anywhere, especially into a shared source file

Sign a Message

Warning

There is no single message format that is broadly adoptedwith community consensus. Keep an eye on several options,like EIP-683,EIP-712, andEIP-719. Considerthe w3.eth.sign() approach be deprecated.

For this example, we will use the same message hashing mechanism thatis provided by w3.eth.sign().

>>> from web3 import Web3, EthereumTesterProvider>>> from eth_account.messages import encode_defunct>>> w3 = Web3(EthereumTesterProvider())>>> msg = "I♥SF">>> private_key = b"\xb2\\}\xb3\x1f\xee\xd9\x12''\xbf\t9\xdcv\x9a\x96VK-\xe4\xc4rm\x03[6\xec\xf1\xe5\xb3d">>> message = encode_defunct(text=msg)>>> signed_message = w3.eth.account.sign_message(message, private_key=private_key)>>> signed_messageSignedMessage(message_hash=HexBytes('0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750'), r=104389933075820307925104709181714897380569894203213074526835978196648170704563, s=28205917190874851400050446352651915501321657673772411533993420917949420456142, v=28, signature=HexBytes('0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c'))

Verify a Message

With the original message text and a signature:

>>> message = encode_defunct(text="I♥SF")>>> w3.eth.account.recover_message(message, signature=signed_message.signature)'0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E'

Prepare message for ecrecover in Solidity

Let’s say you want a contract to validate a signed message,like if you’re making payment channels, and you want tovalidate the value in Remix or web3.js.

You might have produced the signed_message locally, as inSign a Message. If so, this will prepare it for Solidity:

>>> from web3 import Web3# ecrecover in Solidity expects v as a uint8, but r and s as left-padded bytes32# Remix / web3.js expect r and s to be encoded to hex# This convenience method will do the pad & hex for us:>>> def to_32byte_hex(val):...  return Web3.to_hex(Web3.to_bytes(val).rjust(32, b'\0'))>>> ec_recover_args = (msghash, v, r, s) = (...  Web3.to_hex(signed_message.message_hash),...  signed_message.v,...  to_32byte_hex(signed_message.r),...  to_32byte_hex(signed_message.s),... )>>> ec_recover_args('0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750', 28, '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3', '0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce')

Instead, you might have received a message and a signature encoded to hex. Thenthis will prepare it for Solidity:

>>> from web3 import Web3>>> from eth_account.messages import encode_defunct, _hash_eip191_message>>> hex_message = '0x49e299a55346'>>> hex_signature = '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c'# ecrecover in Solidity expects an encoded version of the message# - encode the message>>> message = encode_defunct(hexstr=hex_message)# - hash the message explicitly>>> message_hash = _hash_eip191_message(message)# Remix / web3.js expect the message hash to be encoded to a hex string>>> hex_message_hash = Web3.to_hex(message_hash)# ecrecover in Solidity expects the signature to be split into v as a uint8,# and r, s as a bytes32# Remix / web3.js expect r and s to be encoded to hex>>> sig = Web3.to_bytes(hexstr=hex_signature)>>> v, hex_r, hex_s = Web3.to_int(sig[-1]), Web3.to_hex(sig[:32]), Web3.to_hex(sig[32:64])# ecrecover in Solidity takes the arguments in order = (msghash, v, r, s)>>> ec_recover_args = (hex_message_hash, v, hex_r, hex_s)>>> ec_recover_args('0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750', 28, '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3', '0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce')

Verify a message with ecrecover in Solidity

Create a simple ecrecover contract in Remix:

pragma solidity ^0.4.19;contract Recover { function ecr (bytes32 msgh, uint8 v, bytes32 r, bytes32 s) public pure returns (address sender) { return ecrecover(msgh, v, r, s); }}

Then call ecr with these arguments from Prepare message for ecrecover in Solidity in Remix,"0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750", 28, "0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3", "0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce"

The message is verified, because we get the correct sender ofthe message back in response: 0x5ce9454909639d2d17a3f753ce7d93fa0b9ab12e.

Sign a Transaction

Create a transaction, sign it locally, and then send it to your node for broadcasting,with send_raw_transaction().

>>> transaction = {...  'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55',...  'value': 1000000000,...  'gas': 2000000,...  'maxFeePerGas': 2000000000,...  'maxPriorityFeePerGas': 1000000000,...  'nonce': 0,...  'chainId': 1,...  'type': '0x2', # the type is optional and, if omitted, will be interpreted based on the provided transaction parameters...  'accessList': ( # accessList is optional for dynamic fee transactions...  {...  'address': '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae',...  'storageKeys': (...  '0x0000000000000000000000000000000000000000000000000000000000000003',...  '0x0000000000000000000000000000000000000000000000000000000000000007',...  )...  },...  {...  'address': '0xbb9bc244d798123fde783fcc1c72d3bb8c189413',...  'storageKeys': ()...  },...  )... }>>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318'>>> signed = w3.eth.account.sign_transaction(transaction, key)>>> signed.raw_transactionHexBytes('0x02f8e20180843b9aca008477359400831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca0080f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c001a0b9ec671ccee417ff79e06e9e52bfa82b37cf1145affde486006072ca7a11cf8da0484a9beea46ff6a90ac76e7bbf3718db16a8b4b09cef477fb86cf4e123d98fde')>>> signed.hashHexBytes('0xe85ce7efa52c16cb5c469c7bde54fbd4911639fdfde08003f65525a85076d915')>>> signed.r84095564551732371065849105252408326384410939276686534847013731510862163857293>>> signed.s32698347985257114675470251181312399332782188326270244072370350491677872459742>>> signed.v1# When you run send_raw_transaction, you get back the hash of the transaction:>>> w3.eth.send_raw_transaction(signed.raw_transaction) '0xe85ce7efa52c16cb5c469c7bde54fbd4911639fdfde08003f65525a85076d915'

Sign a Contract Transaction

To sign a transaction locally that will invoke a smart contract:

  1. Initialize your Contract object

  2. Build the transaction

  3. Sign the transaction, with w3.eth.account.sign_transaction()

  4. Broadcast the transaction with send_raw_transaction()

# When running locally, execute the statements found in the file linked below to load the EIP20_ABI variable.# See: https://github.com/carver/ethtoken.py/blob/v0.0.1-alpha.4/ethtoken/abi.py>>> from web3 import Web3, EthereumTesterProvider>>> w3 = Web3(EthereumTesterProvider())>>> unicorns = w3.eth.contract(address="0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", abi=EIP20_ABI)>>> nonce = w3.eth.get_transaction_count('0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E') # Build a transaction that invokes this contract's function, called transfer>>> unicorn_txn = unicorns.functions.transfer(...  '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',...  1,... ).build_transaction({...  'chainId': 1,...  'gas': 70000,...  'maxFeePerGas': w3.to_wei('2', 'gwei'),...  'maxPriorityFeePerGas': w3.to_wei('1', 'gwei'),...  'nonce': nonce,... })>>> unicorn_txn{'value': 0, 'chainId': 1, 'gas': 70000, 'maxFeePerGas': 2000000000, 'maxPriorityFeePerGas': 1000000000, 'nonce': 0, 'to': '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359', 'data': '0xa9059cbb000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d3590000000000000000000000000000000000000000000000000000000000000001'}>>> private_key = b"\xb2\\}\xb3\x1f\xee\xd9\x12''\xbf\t9\xdcv\x9a\x96VK-\xe4\xc4rm\x03[6\xec\xf1\xe5\xb3d">>> signed_txn = w3.eth.account.sign_transaction(unicorn_txn, private_key=private_key)>>> signed_txn.hashHexBytes('0x748db062639a45e519dba934fce09c367c92043867409160c9989673439dc817')>>> signed_txn.raw_transactionHexBytes('0x02f8b00180843b9aca0084773594008301117094fb6916095ca1df60bb79ce92ce3ea74c37c5d35980b844a9059cbb000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d3590000000000000000000000000000000000000000000000000000000000000001c001a0cec4150e52898cf1295cc4020ac0316cbf186071e7cdc5ec44eeb7cdda05afa2a06b0b3a09c7fb0112123c0bef1fd6334853a9dcf3cb5bab3ccd1f5baae926d449')>>> signed_txn.r93522894155654168208483453926995743737629589441154283159505514235904280342434>>> signed_txn.s48417310681110102814014302147799665717176259465062324746227758019974374282313>>> signed_txn.v1>>> w3.eth.send_raw_transaction(signed_txn.raw_transaction) # When you run send_raw_transaction, you get the same result as the hash of the transaction:>>> w3.to_hex(w3.keccak(signed_txn.raw_transaction))'0x748db062639a45e519dba934fce09c367c92043867409160c9989673439dc817'
Accounts — web3.py 7.2.0 documentation (2024)
Top Articles
I save things to my WATCH LIST so when I get the money If they're still available I can purchase the
Signature Bank – why the 36,000% rise in 7 months? - Undervalued Shares
Craigslist San Francisco Bay
Evil Dead Movies In Order & Timeline
Koordinaten w43/b14 mit Umrechner in alle Koordinatensysteme
Polyhaven Hdri
Tap Tap Run Coupon Codes
Teamexpress Login
CSC error CS0006: Metadata file 'SonarAnalyzer.dll' could not be found
United Dual Complete Providers
Smokeland West Warwick
Bernie Platt, former Cherry Hill mayor and funeral home magnate, has died at 90
Craigslist Greenville Craigslist
Mission Impossible 7 Showtimes Near Regal Bridgeport Village
ExploreLearning on LinkedIn: This month's featured product is our ExploreLearning Gizmos Pen Pack, the…
The Largest Banks - ​​How to Transfer Money With Only Card Number and CVV (2024)
Po Box 35691 Canton Oh
Lowe's Garden Fence Roll
Apple Original Films and Skydance Animation’s highly anticipated “Luck” to premiere globally on Apple TV+ on Friday, August 5
Redfin Skagit County
Dark Entreaty Ffxiv
Urban Dictionary Fov
Sound Of Freedom Showtimes Near Movie Tavern Brookfield Square
The Boogeyman (Film, 2023) - MovieMeter.nl
What Sells at Flea Markets: 20 Profitable Items
1636 Pokemon Fire Red U Squirrels Download
Ihs Hockey Systems
My Reading Manga Gay
Ts Modesto
Meggen Nut
Rugged Gentleman Barber Shop Martinsburg Wv
Spy School Secrets - Canada's History
Mega Millions Lottery - Winning Numbers & Results
A Small Traveling Suitcase Figgerits
Kstate Qualtrics
Craigslist Com Humboldt
2012 Street Glide Blue Book Value
THE 10 BEST Yoga Retreats in Konstanz for September 2024
How Much Is Mink V3
Pitchfork's Top 200 of the 2010s: 50-1 (clips)
That1Iggirl Mega
Crazy Balls 3D Racing . Online Games . BrightestGames.com
Worcester County Circuit Court
Arcane Bloodline Pathfinder
Free Crossword Puzzles | BestCrosswords.com
Myrtle Beach Craigs List
Haunted Mansion Showtimes Near Millstone 14
Anonib New
SF bay area cars & trucks "chevrolet 50" - craigslist
Https://Eaxcis.allstate.com
Latest Posts
Article information

Author: Saturnina Altenwerth DVM

Last Updated:

Views: 5705

Rating: 4.3 / 5 (44 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Saturnina Altenwerth DVM

Birthday: 1992-08-21

Address: Apt. 237 662 Haag Mills, East Verenaport, MO 57071-5493

Phone: +331850833384

Job: District Real-Estate Architect

Hobby: Skateboarding, Taxidermy, Air sports, Painting, Knife making, Letterboxing, Inline skating

Introduction: My name is Saturnina Altenwerth DVM, I am a witty, perfect, combative, beautiful, determined, fancy, determined person who loves writing and wants to share my knowledge and understanding with you.