> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baibai.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Python maker example

> Individual spot orders through the unmodified Hyperliquid Python SDK.

Save this as `examples-maker.py` and follow the [quickstart](/makers/quickstart). Set the base URL supplied by Spire. The example places and manages individual orders; it does not choose prices or hedge.

```python theme={null}
"""Individual maker orders through the unmodified Hyperliquid Python SDK.

Install: pip install hyperliquid-python-sdk==0.24.0
Keys come from MM_PRIVATE_KEY; requests use MM_BASE_URL and MM_MASTER_ADDRESS.
"""
import argparse
import json
import os
import sys
import time

from eth_account import Account
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils.types import Cloid


def show(result):
    print(json.dumps(result, indent=2))
    if isinstance(result, dict):
        statuses = result.get("response", {})
        if isinstance(statuses, dict):
            statuses = statuses.get("data", {}).get("statuses", [])
        else:
            statuses = []
        if result.get("status") == "err" or any(
            isinstance(status, dict) and "error" in status for status in statuses
        ):
            raise SystemExit(1)


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--base-url", default=os.environ.get("MM_BASE_URL"))
    parser.add_argument("--master", default=os.environ.get("MM_MASTER_ADDRESS"))
    parser.add_argument("--coin", default="WETH/USDC")
    commands = parser.add_subparsers(dest="command", required=True)
    for name in ("metadata", "open-orders", "fills"):
        commands.add_parser(name)
    for name in ("order", "modify"):
        command = commands.add_parser(name)
        if name == "modify":
            command.add_argument("oid", type=int)
        command.add_argument("--side", choices=("buy", "sell"), required=True)
        command.add_argument("--price", type=float, required=True)
        command.add_argument("--size", type=float, required=True)
        command.add_argument("--tif", choices=("Alo", "Gtc"), default="Alo")
        command.add_argument("--cloid")
    commands.add_parser("cancel").add_argument("oid", type=int)
    commands.add_parser("cancel-by-cloid").add_argument("cloid")
    commands.add_parser("schedule-cancel").add_argument(
        "--after-seconds", type=int, help="Omit to disarm; minimum 5 seconds"
    )
    approve = commands.add_parser("approve-agent")
    approve.add_argument("--name", default="quoting")
    approve.add_argument("--key-file", required=True, help="New private dotenv file; must not exist")
    args = parser.parse_args()
    if not args.base_url:
        parser.error("Set MM_BASE_URL to the adapter URL supplied by Spire")
    if args.command == "metadata":
        show(Info(args.base_url, skip_ws=True).spot_meta())
        return
    if args.command in ("open-orders", "fills"):
        if not args.master:
            parser.error("Set MM_MASTER_ADDRESS")
        info = Info(args.base_url, skip_ws=True)
        show(info.open_orders(args.master) if args.command == "open-orders" else info.user_fills(args.master))
        return
    key = os.environ.get("MM_PRIVATE_KEY")
    if not key:
        parser.error("Load the signing key into MM_PRIVATE_KEY")
    wallet = Account.from_key(key)
    exchange = Exchange(wallet, args.base_url, account_address=args.master or wallet.address)
    if args.command == "approve-agent":
        # Reserve the private output path before approving a key. Do not log the
        # SDK's returned tuple: its second element is the generated private key.
        descriptor = os.open(args.key_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
        with os.fdopen(descriptor, "w") as secret_file:
            result, agent_key = exchange.approve_agent(args.name)
            if result.get("status") != "ok":
                show(result)
            secret_file.write(f"MM_PRIVATE_KEY={agent_key}\n")
            secret_file.flush()
            os.fsync(secret_file.fileno())
        show(result)
        print(f"API-wallet key saved in {args.key_file}", file=sys.stderr)
        return
    if args.command in ("order", "modify"):
        kwargs = dict(name=args.coin, is_buy=args.side == "buy", sz=args.size,
                      limit_px=args.price, order_type={"limit": {"tif": args.tif}},
                      cloid=Cloid.from_str(args.cloid) if args.cloid else None)
        result = exchange.order(**kwargs) if args.command == "order" else exchange.modify_order(args.oid, **kwargs)
    elif args.command == "cancel":
        result = exchange.cancel(args.coin, args.oid)
    elif args.command == "cancel-by-cloid":
        result = exchange.cancel_by_cloid(args.coin, Cloid.from_str(args.cloid))
    else:
        if args.after_seconds is not None and args.after_seconds < 5:
            parser.error("Scheduled cancellation must be at least 5 seconds ahead")
        result = exchange.schedule_cancel(
            int(time.time() * 1000) + args.after_seconds * 1000 if args.after_seconds is not None else None
        )
    show(result)


if __name__ == "__main__":
    main()
```
