# Flare for Python Devs

> Learn how to interact with Flare using web3.py.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

Source: https://dev.flare.network/network/guides/flare-for-python-developers

This guide is for developers who want to interact with Flare using Python. In this guide, using Python, you will learn how to:

-   Query a contract on Flare using [web3.py](https://github.com/ethereum/web3.py), an async/sync library for interacting with Ethereum-like chains.
-   Compile a Solidity contract using [py-solc-x](https://github.com/ApeWorX/py-solc-x), a wrapper around the Solidity compiler.
-   Deploy your compiled contract on Flare.

tip

All examples in this guide are available at [developer-hub/examples](https://github.com/flare-foundation/developer-hub/tree/main/examples).

## Getting started[​](#getting-started "Direct link to Getting started")

```
uv add web3 py-solc-x
```

```
pip install web3 py-solc-x
```

### Usage[​](#usage "Direct link to Usage")

You need to connect to testnet or mainnet via an RPC, any RPC listed on the [Network Configuration](/network/overview#configuration) page will work. For this guide, you can use the Public RPC.

chain\_id.py

```
import asynciofrom web3 import AsyncHTTPProvider, AsyncWeb3from web3.middleware import ExtraDataToPOAMiddlewareasync def main() -> int:    # Inject middleware to handle testnet PoA consensus    w3 = AsyncWeb3(        AsyncHTTPProvider("https://coston2-api.flare.network/ext/C/rpc"),        middleware=[ExtraDataToPOAMiddleware],    )    chain_id = await w3.eth.chain_id    print(f"Chain ID: {chain_id}")    # Chain ID: 114    return chain_idif __name__ == "__main__":    asyncio.run(main())
```

chain\_id.py

```
import asynciofrom web3 import AsyncHTTPProvider, AsyncWeb3async def main() -> int:    w3 = AsyncWeb3(        AsyncHTTPProvider("https://flare-api.flare.network/ext/C/rpc"),    )    chain_id = await w3.eth.chain_id    print(f"Chain ID: {chain_id}")    # Chain ID: 14    return chain_idif __name__ == "__main__":    asyncio.run(main())
```

## Querying a contract[​](#querying-a-contract "Direct link to Querying a contract")

To query a contract, two pieces of information are required:

-   Contract address
-   Contract ABI (Application Binary Interface)

For this example, you can query the `FlareContractRegistry` contract which has the same address `0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019` across both testnet and mainnet.

### Fetch ABI[​](#fetch-abi "Direct link to Fetch ABI")

To fetch a contract's ABI programmatically, you can query the [Flare Blockchain Explorer API](https://flare-explorer.flare.network/api-docs):

fetch\_abi.py

```
import asyncioimport jsonimport aiohttpasync def main() -> dict:    params = {        "module": "contract",        "action": "getabi",        "address": "0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019",    }    async with (        aiohttp.ClientSession() as session,        session.get(            "https://coston2-explorer.flare.network/api", params=params        ) as response,    ):        abi = json.loads((await response.json())["result"])        print(abi[4]["name"])        # getContractAddressByName    return abiif __name__ == "__main__":    asyncio.run(main())
```

fetch\_abi.py

```
import asyncioimport jsonimport aiohttpasync def main() -> dict:    params = {        "module": "contract",        "action": "getabi",        "address": "0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019",    }    async with (        aiohttp.ClientSession() as session,        session.get(            "https://flare-explorer.flare.network/api", params=params        ) as response,    ):        res = await response.json()        abi = json.loads(res["result"])        print(abi[4]["name"])        # getContractAddressByName    return abiif __name__ == "__main__":    asyncio.run(main())
```

### Make query[​](#make-query "Direct link to Make query")

You can now query the `FlareContractRegistry` contract to get the addresses of other Flare contracts.

For example, querying it for the address of the `WNat` contract:

make\_query.py

```
import asyncioimport jsonimport aiohttpfrom web3 import AsyncHTTPProvider, AsyncWeb3from web3.middleware import ExtraDataToPOAMiddlewareasync def main() -> str:    registry_addr = "0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019"    w3 = AsyncWeb3(        AsyncHTTPProvider("https://coston2-api.flare.network/ext/C/rpc"),        middleware=[ExtraDataToPOAMiddleware],    )    params = {        "module": "contract",        "action": "getabi",        "address": registry_addr,    }    async with (        aiohttp.ClientSession() as session,        session.get(            "https://coston2-explorer.flare.network/api", params=params        ) as response,    ):        res = await response.json()        abi = json.loads(res["result"])    registry = w3.eth.contract(address=w3.to_checksum_address(registry_addr), abi=abi)    res = await registry.functions.getContractAddressByName("WNat").call()    print(f"WNat address: {res}")    # WNat address: 0xC67DCE33D7A8efA5FfEB961899C73fe01bCe9273    return resif __name__ == "__main__":    asyncio.run(main())
```

make\_query.py

```
import asyncioimport jsonimport aiohttpfrom web3 import AsyncHTTPProvider, AsyncWeb3from web3.middleware import ExtraDataToPOAMiddlewareasync def main() -> str:    registry_addr = "0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019"    w3 = AsyncWeb3(        AsyncHTTPProvider("https://flare-api.flare.network/ext/C/rpc"),        middleware=[ExtraDataToPOAMiddleware],    )    params = {        "module": "contract",        "action": "getabi",        "address": registry_addr,    }    async with (        aiohttp.ClientSession() as session,        session.get(            "https://flare-explorer.flare.network/api", params=params        ) as response,    ):        res = await response.json()        abi = json.loads(res["result"])    registry = w3.eth.contract(address=w3.to_checksum_address(registry_addr), abi=abi)    res = await registry.functions.getContractAddressByName("WNat").call()    print(f"WNat address: {res}")    # WNat address: 0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d    return resif __name__ == "__main__":    asyncio.run(main())
```

## Compiling a contract[​](#compiling-a-contract "Direct link to Compiling a contract")

For this example, you can use the `FtsoV2FeedConsumer` contract to query the FTSOv2 feeds. Copy the `FtsoV2FeedConsumer` sample contract code given below, and save the `.sol` file in the same folder as your Python script.

<details>
<summary>FtsoV2FeedConsumer sample contract</summary>

`FtsoV2FeedConsumer` sample contract

Note that the contract interface dependencies have been inlined to avoid any import issues.

FtsoV2FeedConsumer.sol

```
// SPDX-License-Identifier: MITpragma solidity >=0.8.0 <0.9.0;interface IFlareContractRegistry {    function getContractAddressByName(        string calldata _name    ) external view returns (address);}/** * THIS IS A TEST INTERFACE. * Functions are payable in the production interface. */interface TestFtsoV2Interface {    function getFeedsById(        bytes21[] calldata _feedIds    )        external        view        returns (            uint256[] memory _values,            int8[] memory _decimals,            uint64 _timestamp        );}/** * THIS IS AN EXAMPLE CONTRACT. * DO NOT USE THIS CODE IN PRODUCTION. */contract FtsoV2FeedConsumer {    IFlareContractRegistry internal contractRegistry;    TestFtsoV2Interface internal ftsoV2;    // Feed IDs, see https://dev.flare.network/ftso/feeds for full list    bytes21[] public feedIds = [        bytes21(0x01464c522f55534400000000000000000000000000), // FLR/USD        bytes21(0x014254432f55534400000000000000000000000000), // BTC/USD        bytes21(0x014554482f55534400000000000000000000000000) // ETH/USD    ];    /**     * Constructor initializes the FTSOv2 contract.     * The contract registry is used to fetch the FtsoV2 contract address.     */    constructor() {        contractRegistry = IFlareContractRegistry(            0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019        );        ftsoV2 = TestFtsoV2Interface(            contractRegistry.getContractAddressByName("FtsoV2")        );    }    /**     * Get the current value of the feeds.     */    function getFtsoV2CurrentFeedValues()        external        view        returns (            uint256[] memory _feedValues,            int8[] memory _decimals,            uint64 _timestamp        )    {        /* Your custom feed consumption logic. In this example the values are just returned. */        return ftsoV2.getFeedsById(feedIds);    }}
```

</details>

### Set up utils[​](#set-up-utils "Direct link to Set up utils")

To compile the contracts, you need to first set up some basic helper functions to read the `.sol` file and write the compiled output to a `.json` file. In a `utils.py` file, you can define the following functions:

utils.py

```
import jsonfrom pathlib import PathCURRENT_DIR = Path(__file__).resolve().parentdef load_contract(name: str) -> str:    """Load contract from Solidity file."""    with (CURRENT_DIR / f"{name}.sol").open() as file:        return file.read()def save_compiled_contract(name: str, compiled_contract: dict) -> None:    """Save compiled contract to JSON file."""    with (CURRENT_DIR / f"{name}.json").open("w") as file:        json.dump(compiled_contract, file)def load_contract_interface(name: str) -> dict:    """Load contract interface from JSON."""    with (CURRENT_DIR / f"{name}.json").open() as file:        compiled_contract = json.load(file)    return compiled_contract["contracts"][f"{name}.sol"][f"{name}"]
```

### Compile with py-solc-x[​](#compile-with-py-solc-x "Direct link to Compile with py-solc-x")

With these functions ready, you can now compile the contract. In a `compile_contract.py` file, you can define the following code to install the correct version of the Solidity compiler and compile the contract:

compile\_contract.py

```
from solcx import compile_standard, install_solcfrom utils import load_contract, save_compiled_contractif __name__ == "__main__":    contract_name = "FtsoV2FeedConsumer"    contract_code = load_contract(contract_name)    # Install the solc compiler    # Versions >0.8.25 may work, but have not been tested    solc_version = "0.8.25"    install_solc(solc_version)    compiled_sol = compile_standard(        {            "language": "Solidity",            "sources": {f"{contract_name}.sol": {"content": contract_code}},            "settings": {                "outputSelection": {                    "*": {                        "*": [                            "abi",                            "metadata",                            "evm.bytecode",                            "evm.bytecode.sourceMap",                        ],                    }                },                "optimizer": {"enabled": True, "runs": 200},                "evmVersion": "cancun",            },        },        solc_version=solc_version,    )    save_compiled_contract(contract_name, compiled_sol)
```

You can now run the `compile_contract.py` script to compile the contract. The compiled output will be saved to `FtsoV2FeedConsumer.json`.

```
uv run compile_contract.py
```

```
python compile_contract.py 
```

## Create account[​](#create-account "Direct link to Create account")

Before deploying a contract, you need to have an account with some testnet or mainnet gas tokens. You can create a new Flare account from the CLI:

create\_account.py

```
from web3 import Web3w3 = Web3()acc = w3.eth.account.create()print(f"Account: {acc.address}, Private Key: {w3.to_hex(acc.key)}")
```

This will output a new private key and an account pair.

danger

-   Never share your private keys.
-   Never put your private keys in source code.
-   Never commit private keys to a Git repository.

You can save the account and private key into environment variables `ACCOUNT` and `ACCOUNT_PRIVATE_KEY` respectively.

```
export ACCOUNT=<address above>export ACCOUNT_PRIVATE_KEY=<private key above>
```

note

You can also import the raw hex private key to MetaMask and any other wallet - the private key can be shared between your Python code and any number of wallets.

-   For testnet, you can get free testnet C2FLR on the [Coston2 Faucet](https://faucet.flare.network/coston2).
-   For mainnet you will need FLR.

## Deploying with web3.py[​](#deploying-with-web3py "Direct link to Deploying with web3.py")

With the functions and account ready, you can now deploy the contract. In a `deploy_contract.py` file, you can define the following code to deploy the contract:

deploy\_contract.py

```
# THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.import asyncioimport osfrom web3 import AsyncHTTPProvider, AsyncWeb3from web3.middleware import ExtraDataToPOAMiddlewarefrom utils import load_contract_interfaceasync def main() -> None:    account, private_key = os.getenv("ACCOUNT"), os.getenv("ACCOUNT_PRIVATE_KEY")    contract_interface = load_contract_interface("FtsoV2FeedConsumer")    w3 = AsyncWeb3(        AsyncHTTPProvider("https://coston2-api.flare.network/ext/C/rpc"),        middleware=[ExtraDataToPOAMiddleware],    )    account = w3.to_checksum_address(account)    ftso_v2_feed_consumer = w3.eth.contract(        abi=contract_interface["abi"],        bytecode=contract_interface["evm"]["bytecode"]["object"],    )    tx = await ftso_v2_feed_consumer.constructor().build_transaction(        {            "from": account,            "nonce": await w3.eth.get_transaction_count(account),            "gasPrice": await w3.eth.gas_price,        }    )    signed_tx = w3.eth.account.sign_transaction(tx, private_key=private_key)    print("Deploying Contract...")    tx_hash = await w3.eth.send_raw_transaction(signed_tx.raw_transaction)    tx_receipt = await w3.eth.wait_for_transaction_receipt(tx_hash)    print(f"Contract deployed at {tx_receipt['contractAddress']}")if __name__ == "__main__":    asyncio.run(main())
```

deploy\_contract.py

```
# THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.import asyncioimport osfrom web3 import AsyncHTTPProvider, AsyncWeb3from utils import load_contract_interfaceasync def main() -> None:    account, private_key = os.getenv("ACCOUNT"), os.getenv("ACCOUNT_PRIVATE_KEY")    contract_interface = load_contract_interface("FtsoV2FeedConsumer")    w3 = AsyncWeb3(AsyncHTTPProvider("https://flare-api.flare.network/ext/C/rpc"))    ftso_v2_feed_consumer = w3.eth.contract(        abi=contract_interface["abi"],        bytecode=contract_interface["evm"]["bytecode"]["object"],    )    account = w3.to_checksum_address(account)    tx = await ftso_v2_feed_consumer.constructor().build_transaction(        {            "from": account,            "nonce": await w3.eth.get_transaction_count(account),            "gasPrice": await w3.eth.gas_price,        }    )    signed_tx = w3.eth.account.sign_transaction(tx, private_key=private_key)    print("Deploying Contract...")    tx_hash = await w3.eth.send_raw_transaction(signed_tx.raw_transaction)    tx_receipt = await w3.eth.wait_for_transaction_receipt(tx_hash)    print(f"Contract deployed at {tx_receipt['contractAddress']}")if __name__ == "__main__":    asyncio.run(main())
```

You can now run the `deploy_contract.py` script to deploy the contract. The contract address will be printed once the deployment is successful. You can check the contract address on a Flare Blockchain Explorer, linked on the [Network Configuration](/network/overview#configuration) page.

```
uv run deploy_contract.py 
```

```
python deploy_contract.py 
```

Congratulations! You have now successfully deployed a contract on Flare using Python 🐍.

What's next?

Learn how to interact with Flare's enshrined oracle [FTSOv2 using Python](/ftso/guides/read-feeds-offchain).
