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

# Walley Python SDK Quickstart: Sign In and Transact

> Install walley-sdk, sign in with your wallet's key file, check balances, and send your first transaction from Python.

This guide takes you from `pip install` to a committed transaction. It assumes you already have a Walley wallet - if not, [create one](/getting-started/create-wallet) in the app first and back up its recovery phrase.

## Install

```bash theme={null}
pip install walley-sdk
```

## Store your key in a file

Put the wallet's 24-word recovery phrase (or an exported PKCS#8 PEM) in a file only your process can read:

```bash theme={null}
install -m 600 /dev/null ~/.config/walley/alice.key
# paste the 24 words (or PEM) into it
```

The SDK detects the format — PEM, mnemonic, or a hex/base64 raw key — so there is nothing to configure.

<Warning>
  The key file **is** the wallet. Anyone who reads it controls the party and its funds. Keep it out of source control and CI logs; prefer a secrets manager in production.
</Warning>

## Sign in

```python theme={null}
from walley import Walley

w = Walley(
    key_file="~/.config/walley/alice.key",
    party_hint="walley-alice",        # or the full party_id
)
print(w.party_id)                     # walley-alice::1220...
```

The party id is derived from the key's fingerprint, so a wrong key for a given `party_id` is rejected before any request is made. Configuration can also come from the environment — `WALLEY_KEY_FILE`, `WALLEY_PARTY_HINT`, and `WALLEY_API_URL` — which keeps scripts credential-free.

## Look around

```python theme={null}
for balance in w.balances:            # every instrument the party holds
    print(balance.instrument_id, balance.total_balance)

w.balances["Amulet"].unlocked_balance # indexable by instrument id

for h in w.holdings.list(instrument_id="Amulet"):
    print(h.contract_id, h.amount)    # the on-ledger contracts behind a balance
```

Reads authenticate automatically with your key — no passwords, API keys, or tokens to manage.

## Send a transaction

The built-in transfer flow prepares the commands, quotes the network fee, signs locally, submits, and waits for finality:

```python theme={null}
result = w.transfers.send(
    receiver="walley-bob::1220...",
    amount="2.5",
    reason="lunch",
)
print(result.update_id, result.fee)
```

Or run your dApp's own commands through the same machinery:

```python theme={null}
result = w.transactions.execute(commands)   # dict or raw JSON string
```

## Next steps

<CardGroup cols={2}>
  <Card title="Transactions & Fees" icon="arrow-right-arrow-left" href="/python-sdk/transactions">
    Fee quotes before you sign, and how deferred fees settle.
  </Card>

  <Card title="Ledger API" icon="database" href="/python-sdk/ledger">
    Read active contracts and other ledger state directly.
  </Card>
</CardGroup>
