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

# Gasless Wallets — Python

> Create a wallet and look it up with the chipi-stack Python SDK. Code lifted from the Chipi staging smoke test that runs in CI.

<Info>
  **Production apps should pair this with a passkey on the browser side.** This
  page uses a string `encrypt_key` for the smoke-test scenario, which is the
  simplest possible flow. For shipping integrations, the `encrypt_key`
  should come from a platform passkey via the browser-side flow — see the
  [passkey quickstart](/sdk/passkeys/quickstart). The Python pieces below
  are identical either way.
</Info>

This page shows wallet creation and retrieval with `chipi-stack` on PyPI, using code lifted verbatim from `python/tests/test_staging_smoke.py`.

<Note>
  The Python SDK is published as **`chipi-stack`** on PyPI — matching the `@chipi-stack/*` npm scope. (The legacy `chipi-python` package is deprecated.)
</Note>

## Install

<CodeGroup>
  ```bash pip theme={null}
  pip install chipi-stack
  ```

  ```bash uv theme={null}
  uv add chipi-stack
  ```

  ```bash poetry theme={null}
  poetry add chipi-stack
  ```
</CodeGroup>

Requires Python 3.11+.

<Note>
  **Install vs import:** the PyPI package is `chipi-stack` but the Python module is `chipi_sdk`. After `pip install chipi-stack`, import with `from chipi_sdk import ...` (not `chipi_stack`).
</Note>

## Initialise the SDK

```python theme={null}
import os
from chipi_sdk import ChipiSDK, ChipiSDKConfig

sdk = ChipiSDK(
    config=ChipiSDKConfig(
        api_public_key=os.environ["CHIPI_PUBLIC_KEY"],
        api_secret_key=os.environ["CHIPI_SECRET_KEY"],
        # alpha_url is only needed for staging or self-hosted backends
        alpha_url=os.environ.get("CHIPI_BASE_URL"),  # omit for production
    )
)
```

## Create a wallet

`create_wallet` provisions a fresh Starknet account, encrypts the private key with the `encrypt_key` you provide, and returns a flat response (no nested `.wallet` field — `public_key` and `encrypted_private_key` are at the root).

```python theme={null}
from uuid import uuid4
from chipi_sdk import CreateWalletParams, WalletType

external_user_id = f"user-{uuid4().hex[:12]}"

result = sdk.create_wallet(
    params=CreateWalletParams(
        encrypt_key="user-chosen-pin",
        external_user_id=external_user_id,
        wallet_type=WalletType.CHIPI,
    ),
    bearer_token=os.environ["CHIPI_SECRET_KEY"],
)

print(result.public_key)            # 0x...
print(result.wallet_type)           # WalletType.CHIPI
print(result.chain)                 # Chain.STARKNET
print(result.is_deployed)           # False initially; flips to True once the deploy tx confirms

# result.encrypted_private_key is sensitive — store it in your user record
# (e.g. Postgres) alongside the externalUserId. Never log it.
store_in_db(external_user_id, result.encrypted_private_key)
```

## Get a wallet

Look it up later by your own user ID:

```python theme={null}
from chipi_sdk import GetWalletParams

retrieved = sdk.get_wallet(
    params=GetWalletParams(external_user_id=external_user_id),
    bearer_token=os.environ["CHIPI_SECRET_KEY"],
)

assert retrieved.public_key == result.public_key
assert retrieved.encrypted_private_key == result.encrypted_private_key
```

The response is the same flat shape — `public_key`, `encrypted_private_key`, `wallet_type`, `chain`, `is_deployed`, `id`, `external_user_id`, `created_at`, `updated_at` are all on the root object.

## Putting it together

```python theme={null}
import os
from uuid import uuid4
from chipi_sdk import (
    ChipiSDK,
    ChipiSDKConfig,
    CreateWalletParams,
    GetWalletParams,
    WalletType,
)


def main():
    sdk = ChipiSDK(
        config=ChipiSDKConfig(
            api_public_key=os.environ["CHIPI_PUBLIC_KEY"],
            api_secret_key=os.environ["CHIPI_SECRET_KEY"],
        )
    )
    bearer = os.environ["CHIPI_SECRET_KEY"]

    external_user_id = f"user-{uuid4().hex[:12]}"

    # 1. Create
    created = sdk.create_wallet(
        params=CreateWalletParams(
            encrypt_key=os.environ["USER_PIN"],
            external_user_id=external_user_id,
            wallet_type=WalletType.CHIPI,
        ),
        bearer_token=bearer,
    )

    # 2. Look it up by your own user ID
    retrieved = sdk.get_wallet(
        params=GetWalletParams(external_user_id=external_user_id),
        bearer_token=bearer,
    )

    print({"public_key": created.public_key, "match": retrieved.public_key == created.public_key})


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

> ✅ Verified against the live API on **2026-05-11**.

## What's next

Transfers, balance reads, PIN rotation, and session keys are exposed through the same SDK — coverage in the Python guide expands as we port more smoke tests. For the Node-equivalent flow today, see the [Node guide](/services/gasless/node).
