# Interacting with Python

## Installation

We will use the [`web3.py`](https://web3py.readthedocs.io/en/stable/index.html) package to programatically interact with the Ethereum testnet.

```
$ pip install web3
```

Once installed, we can connect to the RPC using

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
```

In order to interact with [contracts](https://web3py.readthedocs.io/en/stable/web3.contract.html#contracts) specifically, we need to be able to provide the [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) (Application Binary Interface) of the contract. An ABI decribes the protocol for interacting with a system, in this case, for interacting with the contract. Effectively, an ABI tells `web3.py` exactly how to interact with the remote contract.

Luckily, we can use Python to generate the ABI from the source code itself. To do so, we need to install [`py-solc-x`](https://solcx.readthedocs.io/en/latest/):

```
$ pip install py-solc-x
```

`py-solc-x` handles versions of `solc`, the Solidity compiler. Different versions *could* generate different ABIs, so keep an eye on it, but generally it won't matter too much. Before we can use it to generate a contract's ABI, we have to install the version of `solc` that we want:

```python
from solcx import install_solc

# install the latest version
install_solc("0.8.29")
```

## Interacting with Contracts in Python

Now we can use the source code of the Solidity contract to generate an ABI for it. After that, everything is pretty self-explanatory!

```python
from web3 import Web3
from solcx import set_solc_version, compile_source

set_solc_version('0.8.29')

with open('src/Counter.sol') as f:
    compiled_sol = compile_source(f.read(), output_values=['abi'])

contract_id, contract_interface = compiled_sol.popitem()
abi = contract_interface['abi']

w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
counter = w3.eth.contract(
    address='0x5FbDB2315678afecb367f032d93F642f64180aa3',
    abi=abi
)

# read state
print(counter.functions.getCounter().call())

# update state
print(counter.functions.increment().transact())
```

Running this code multiple times shows the counter incrementing!

## Accounts on Local Nodes

Typically transactions - such as the last line, with `.transact()` - need to be signed using a private key. Here, we have not specified the private key, yet it still works. Why is that?

Our `anvil` testnet spins up a node locally, with several **unlocked accounts***.* Running the program locally, `w3` will take the first unlocked account and use it. We can print the unlocked accounts out:

```python
print(w3.eth.accounts)
# ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC', '0x90F79bf6EB2c4f870365E785982E1f101E93b906', '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65', '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc', '0x976EA74026E726554dB657fA54763abd0C3a0aa9', '0x14dC79964da2C08b23698B3D3cc7Ca32193d9955', '0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f', '0xa0Ee7A142d267C1f36714E4a8F75612F20a79720']
```

Comparing this to the output of `anvil`, we see that they are the same addresses in the same order. To override this functionality, we can set the variable `w3.eth.default_account`, which defaults to `None` (and when it's `None`, the default account used is `w3.eth.accounts[0]`).

```python
w3.eth.default_account = '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC'
```

Alternatively, if it's a one-off, you can set the `from` field in the `transact` method:

```python
counter.functions.increment().transact({
    'from': '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC'
})
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ir0nstone.gitbook.io/notes/blockchain/interacting-with-python.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
