Skip to content

Practicing with our Python SDK

We also have a Python SDK if that's your language of choice. Start by following the steps above under Configuration.

Most systems already have python version 3 installed, available directly through the python command. Make sure by typing the following:

python --version

You should see something similar to this:

Python 3.12.3

If not, you'll need to install it. The official Python documentation provides downloadable installations.

First, create a new folder to hold you project:

mkdir golem-python-practice
cd golem-python-practice

Next, create and activate a virtual environment.

python3 -m venv venv

This creates a virtual environment. Note: If you get an error message regarding "ensurepip not being available" type the following to add the python3-venv package:

sudo apt install python3.12-venv

and then repeat the python3 -m venv venv command.

Now activate the virtual environment. On Mac and Linux, type:

source venv/bin/activate 

Now install the GolemBase SDK and some additional libraries you'll need:

pip install golem-base-sdk eth-account anyio

Code to create a private.key file

Now we'll create a python app that can create a wallet stored in a private.key file. Create a file called wallet.py and add the following to it:

import os
from eth_account import Account

key_path = 'private.key'

if os.path.exists(key_path):
    print(f'File "{key_path}" already exists. Aborting.')
    exit(0)

acct = Account.create()

with open(key_path, 'wb') as f:
    f.write(bytes.fromhex(acct.key.hex()))

print('Address:', acct.address)

Then run the above by typing:

python wallet.py

You should see output similar to the following:

Address: 0x10882A8BD4C79ED56Fca4Cd9AD73E3D234365547

This is the address portion of the private key you just created. Copy this to your clipboard, as you'll need it in the next step.

Adding Funds

Open your browser and go to this link, which is the for Kaolin:

https://kaolin.holesky.golem-base.io/faucet/

Paste your account Address in and click Request Funds. After a moment, your account will have a couple Eth available in our testnet.

Creating entities in Golem-base

Now create a file called main.py and insert the following into it:

"""GolemBase Python SDK."""

import argparse
import asyncio
import logging
import logging.config

import anyio
from golem_base_sdk import (
    Annotation,
    GolemBaseClient,
    GolemBaseCreate,
    GolemBaseDelete,
    GolemBaseExtend,
    GolemBaseUpdate,
)

logging.config.dictConfig(
    {
        "version": 1,
        "formatters": {
            "default": {
                "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s",
            }
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "default",
                "level": "DEBUG",
                "stream": "ext://sys.stdout",
            }
        },
        "loggers": {
            # "": {"level": "DEBUG", "handlers": ["console"]},
            "": {"level": "INFO", "handlers": ["console"]},
        },
        # Avoid pre-existing loggers from imports being disabled
        "disable_existing_loggers": False,
    }
)
logger = logging.getLogger(__name__)

INSTANCE_URLS = {
    "demo": {
        "rpc": "https://api.golembase.demo.golem-base.io",
    },
    "local": {
        "rpc": "http://localhost:8545",
        "ws": "ws://localhost:8545",
    },
    "kaolin": {
        "rpc": "https://rpc.kaolin.holesky.golem-base.io",
        "ws": "wss://ws.rpc.kaolin.holesky.golem-base.io",
    },
}


async def run_example(instance: str) -> None:  # noqa: PLR0915
    """Run the example."""
    async with await anyio.open_file(
        "./private.key",
        "rb",
    ) as private_key_file:
        key_bytes = await private_key_file.read(32)

    client = await GolemBaseClient.create(
        rpc_url=INSTANCE_URLS[instance]["rpc"],
        ws_url=INSTANCE_URLS[instance]["ws"],
        private_key=key_bytes,
    )

    watch_logs_handle = await client.watch_logs(
        label="first",
        create_callback=lambda create: logger.info(
            """\n
Got create event: %s
        """,
            create,
        ),
        update_callback=lambda update: logger.info(
            """\n
Got update event: %s
        """,
            update,
        ),
    )

    await client.watch_logs(
        label="second",
        delete_callback=lambda deleted_key: logger.info(
            """\n
Got delete event: %s
        """,
            deleted_key,
        ),
        extend_callback=lambda extension: logger.info(
            """\n
Got extend event: %s
        """,
            extension,
        ),
    )

    if await client.is_connected():
        logger.info("""\n
        *****************************
        * Checking basic methods... *
        *****************************
        """)

        block = await client.http_client().eth.get_block("latest")
        logger.info("Retrieved block %s", block["number"])

        logger.info("entity count: %s", await client.get_entity_count())

        logger.info("""\n
        *************************
        * Creating an entity... *
        *************************
        """)

        create_receipt = await client.create_entities(
            [GolemBaseCreate(b"hello", 60, [Annotation("app", "demo")], [])]
        )
        entity_key = create_receipt[0].entity_key
        logger.info("receipt: %s", create_receipt)
        logger.info("entity count: %s", await client.get_entity_count())

        logger.info("created entity with key %s", entity_key)
        logger.info("storage value: %s", await client.get_storage_value(entity_key))
        metadata = await client.get_entity_metadata(entity_key)
        logger.info("entity metadata: %s", metadata)

        logger.info("""\n
        ***********************************
        * Extend the BTL of the entity... *
        ***********************************
        """)

        logger.info(
            "entities to expire at block %s: %s",
            metadata.expires_at_block,
            await client.get_entities_to_expire_at_block(metadata.expires_at_block),
        )

        [extend_receipt] = await client.extend_entities(
            [GolemBaseExtend(entity_key, 60)]
        )
        logger.info("receipt: %s", extend_receipt)

        logger.info(
            "entities to expire at block %s: %s",
            metadata.expires_at_block,
            await client.get_entities_to_expire_at_block(metadata.expires_at_block),
        )
        logger.info(
            "entities to expire at block %s: %s",
            extend_receipt.new_expiration_block,
            await client.get_entities_to_expire_at_block(
                extend_receipt.new_expiration_block
            ),
        )
        logger.info("entity metadata: %s", await client.get_entity_metadata(entity_key))

        logger.info("""\n
        ************************
        * Update the entity... *
        ************************
        """)

        logger.info(
            "block number: %s", await client.http_client().eth.get_block_number()
        )
        [update_receipt] = await client.update_entities(
            [GolemBaseUpdate(entity_key, b"hello", 60, [Annotation("app", "demo")], [])]
        )
        logger.info("receipt: %s", update_receipt)
        entity_key = update_receipt.entity_key

        logger.info("entity metadata: %s", await client.get_entity_metadata(entity_key))

        logger.info("""\n
        *************************
        * Query for entities... *
        *************************
        """)

        query_result = await client.query_entities('app = "demo"')
        logger.info("Query result: %s", query_result)

        logger.info("""\n
        ************************
        * Delete the entity... *
        ************************
        """)

        logger.info("entity metadata: %s", await client.get_entity_metadata(entity_key))
        logger.info(
            "block number: %s", await client.http_client().eth.get_block_number()
        )

        receipt = await client.delete_entities([GolemBaseDelete(entity_key)])
        logger.info("receipt: %s", receipt)

        logger.info(
            "My entities: %s",
            await client.get_entities_of_owner(client.get_account_address()),
        )

        logger.info(
            "All entities: %s",
            await client.get_all_entity_keys(),
        )

        await watch_logs_handle.unsubscribe()

        logger.info("""\n
        *********************************************
        * Creating an entity to test unsubscribe... *
        *********************************************
        """)

        create_receipt = await client.create_entities(
            [GolemBaseCreate(b"hello", 60, [Annotation("app", "demo")], [])]
        )
        entity_key = create_receipt[0].entity_key
        logger.info("receipt: %s", create_receipt)
        logger.info("entity count: %s", await client.get_entity_count())

        logger.info("created entity with key %s", entity_key)
        logger.info("storage value: %s", await client.get_storage_value(entity_key))
        metadata = await client.get_entity_metadata(entity_key)
        logger.info("entity metadata: %s", metadata)

        await client.delete_entities([GolemBaseDelete(entity_key)])
    else:
        logger.warning("Could not connect to the API...")

    await client.disconnect()


def main() -> None:
    """Run the example."""
    parser = argparse.ArgumentParser(description="GolemBase Python SDK Example")
    parser.add_argument(
        "--instance",
        choices=INSTANCE_URLS.keys(),
        default="kaolin",
        help="Which instance to connect to (default: kaolin)",
    )
    args = parser.parse_args()
    logger.info("Starting main loop")
    asyncio.run(run_example(args.instance))


if __name__ == "__main__":
    main()

Note that this example includes a command line option to choose between different nodes:

  • A local node running in a container

  • Our testnet server

The testnet server is the default, which is what we want. So run the file by simply typing:

python main.py

To see more examples and learn about our Python SDK, visit our Python SDK's repo on GitHub.

  • Wish to learn more?


    Golem Base introduces a novel architectural model for decentralized data infrastructure — designed to be modular, Ethereum-native, and accessible across both Web2 and Web3.

    For a complete overview:
    Read the Litepaper (PDF)

    It covers:

    • The structure and role of DB-Chains
    • How Golem Base aligns with Ethereum Layer 2/3 philosophy
    • Potential real-world use cases

    Golem Base Origins

    Golem Base was born from a need inside Golem Network — and grew into its own thing. Built by an independent team committed to the idea that data autonomy should be the norm, not the exception. Read more

  • Join the Community


    Stay connected and get help as you explore Golem Base.

    • Discord — Chat with the team and other developers in real time.
    • GitHub — Ask questions, share feedback, or explore new ideas.
    • Twitter (X) — Follow us for announcements, updates, and ecosystem highlights.
    • Blog — Read technical deep dives, tutorials, and project news.


      Need Help?