Metadata-Version: 2.4
Name: paymos
Version: 0.1.2
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Rust
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: License :: Other/Proprietary License
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial
Classifier: Typing :: Typed
Requires-Dist: httpx>=0.27
Summary: Non-custodial, headless SDK to control a wallet vault: balances, fee-transparent quotes, swaps and on-chain withdrawals over a co-signed 2-of-2 vault.
Keywords: wallet,vault,crypto,payments,sdk,non-custodial,mpc,withdrawals
Author: Paymos
License: Proprietary
Requires-Python: >=3.11
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://wallet.paymos.io

# paymos — Python SDK

Non-custodial, headless control of a wallet vault. Your process holds **one half** of the
signing key; our server holds the other. Neither side alone can move funds — every swap and
withdrawal is co-signed, and we never receive your half.

You talk to it in plain asset terms (`USDC@base`, `ETH@arb`); the SDK hides the routing and the
2-of-2 FROST signing. Amounts you pass are **human decimal strings** (e.g. `"100"`, `"0.5"`) —
never a float; the server scales them to raw, and amounts in responses/dataclasses come back as
raw integer strings. The native signing core ships **inside the wheel** as a compiled
extension, so an end user needs **no Rust toolchain**.

## Install

Wheels are self-contained (the native `paymos._core` extension is bundled), one per platform,
tagged `cp311-abi3` — a single wheel serves CPython **3.11 / 3.12 / 3.13+**:

```powershell
# Windows
pip install paymos-0.1.0-cp311-abi3-win_amd64.whl
```

```bash
# Linux (x86-64)
pip install paymos-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
```

…or, once it's published:

```bash
pip install paymos
```

Only dependency is `httpx` (pulled automatically). Requires Python ≥ 3.11.

## Get a vault secret

The SDK is driven by one `vs_live_…` **vault secret**. You create it in the **wallet Mini App →
Settings → Vault API**:

- a **read** key — view balances and get quotes (no share; cannot sign), and
- a **full** key — everything a read key does, **plus** `swap` and `withdraw` (carries your
  co-signing share).

The secret bundles the API key and, for a full key, your FROST share. The share never leaves your
process and never reaches our server. There is **no CLI provisioner** — the key is minted in the
Mini App (the share is decrypted on your device).

Point the SDK at it with an environment variable:

```powershell
$env:PAYMOS_VAULT_SECRET = "vs_live_…"
# optional — defaults to https://wallet.paymos.io
# $env:PAYMOS_BASE_URL = "https://wallet.paymos.io"
```

## 1-minute usage

```python
import asyncio
from paymos import Wallet

async def main():
    w = Wallet.from_env()                       # reads PAYMOS_VAULT_SECRET

    # Balances — per-asset, raw amount strings + a nullable USD value.
    for b in await w.balances():
        print(b.asset, b.amount_raw, b.usd)

    # Preview a withdraw: a dry, money-safe quote. The headline is the fee breakdown.
    q = await w.quote_withdraw(asset="USDC@base", amount="25", to="0xRecipient…")
    print(q.fees.platform, q.fees.network, q.fees.route, q.fees.total)

    # Move money (full-scope secret only). Amounts are human decimal strings.
    mv = await w.swap(send="USDC@base", receive="ETH@arb", amount="100")
    print(await w.wait(mv.id))                   # poll to a terminal status

    await w.aclose()

asyncio.run(main())
```

Read-only building blocks: `assets()`, `balances()`, `quote_swap(...)`, `quote_withdraw(...)`,
`movement(id)`, `movements(...)`. Money moves (need a full key): `swap(...)`, `withdraw(...)`, and
`wait(id)` to poll a movement to `completed | failed | refunded | expired | cancelled`.

## The fee breakdown

`quote_swap` / `quote_withdraw` always return a **dry** `Quote` (nothing is persisted) whose
`.fees` is the headline: a `Fees` with `platform`, `network`, `total` (raw integer **strings**),
`route` (a `RouteFee` with `.amount` + `.estimate`, or `None` when there's no route leg), and a
nullable `usd` dict. Preview it before you ever sign. `swap` / `withdraw` create the real movement
under a fresh idempotency key and drive the co-sign; `swap` also takes an optional `min_receive`
(human decimal) and raises `SlippageExceeded` — signing nothing — if the guaranteed receive is
below it.

## Security

- A leaked **API key alone cannot move funds** — no share, no signature (and we can revoke the key).
- A leaked **share alone cannot move funds** — no server co-sign.
- Both are needed, on purpose. Treat a full secret like a private key; back up the share.

## Examples

See [`examples/`](examples/) for a clickable local web demo (FastAPI, prod-pointed) that loads
balances, shows the fee breakdown, and — behind a confirm box — does a real swap, plus a minimal
`demo.py` CLI.

