Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
42c95df
Docs: agents read docs.sidepit.com as Markdown; deposit address verif…
Oct 27, 2026
f9f7eae
TUI: wallet shows today's P&L and one contract; identity screen can b…
Oct 27, 2026
08e1d42
CI: install proof on Linux, Windows, macOS Intel and Apple Silicon
Oct 28, 2026
418ade4
wallet: pure-Python RIPEMD-160 fallback, drop ripemd-hash
Oct 29, 2026
e266ef6
CI: stock-machine check — fail when any dependency would compile
Oct 29, 2026
60c1e43
tests: key entropy is the OS CSPRNG only; signing is deterministic
Oct 29, 2026
951b331
sidepit 0.1.2: bundled secp256k1 wheels for Windows and Intel macOS
Oct 29, 2026
533b637
CI: build bundled wheels, prove the install on every platform, gate p…
Oct 29, 2026
0f67a27
agent key: Windows has no POSIX mode bits, verify the file by content…
Oct 29, 2026
cd494e5
tests: signing nonce stays RFC 6979
Oct 29, 2026
c375458
Merge branch 'tui-0.1.2' into ci-install-proof
Oct 29, 2026
230f733
trader: poll ACTIVE_PRODUCT without a ticker so the roll is seen afte…
jaybny Sep 23, 2026
03ba0fd
TUI: start on the live market with no identity; add one later
Oct 29, 2026
1a3b604
docs: one-line install per platform, WSL2 path for Windows
Oct 29, 2026
878fb01
keep the BIP39 wordlist byte-exact on Windows checkouts
Oct 29, 2026
31dbfb7
CI: read the version without tomllib so the Python 3.10 legs run
Oct 29, 2026
aaad654
tests: POSIX file-mode checks skip on Windows; read sources as UTF-8
Oct 29, 2026
a4fba46
Merge branch 'docs-agent-reading' into ci-install-proof
Oct 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# byte-exact data: the SDK verifies this file by SHA-256 at runtime, so git must
# never convert its line endings on a Windows checkout
python-client/sidepit_trader/data/bip39_english.txt binary
154 changes: 154 additions & 0 deletions .github/workflows/install-proof.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: Install proof

# Clean-machine proof: build every release artifact once, then `pip install
# sidepit` into a fresh venv on every OS/Python a user might have, pulling
# dependencies from PyPI exactly as a user would. Every leg runs even when
# another fails, so one run shows the whole platform picture. publish.yml
# calls this workflow and refuses to upload unless it is all green.

on:
workflow_dispatch:
workflow_call:
pull_request:
paths:
- ".github/workflows/install-proof.yml"
- "pyproject.toml"
- "setup.py"
- "MANIFEST.in"
- "tools/**"

permissions:
contents: read

env:
# build tools are pinned: the same inputs produce the release every time
BUILD_TOOLS: build==1.6.1 setuptools==80.10.2 wheel==0.48.0 cffi==2.1.1

jobs:
build:
name: pure wheel + sdist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Build
run: |
python -m pip install $BUILD_TOOLS
python -m build --no-isolation
python tools/check_python_dist.py dist/*
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist-pure
path: dist/
if-no-files-found: error

native:
# Platforms where upstream secp256k1 publishes no wheel get the compiled
# module inside sidepit's own platform wheel (setup.py, SIDEPIT_BUNDLE_SECP256K1).
# Built against the stable ABI on 3.10: one wheel per platform serves 3.10+.
name: bundled wheel (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-15-intel]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.10"
- name: Fetch the pinned upstream secp256k1 source
run: |
python -m pip install $BUILD_TOOLS
python tools/vendor_secp256k1.py
- name: Build
env:
SIDEPIT_BUNDLE_SECP256K1: "1"
run: |
python -m build --wheel --no-isolation
python tools/check_python_dist.py dist/*.whl
ls -l dist
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist-native-${{ matrix.os }}
path: dist/
if-no-files-found: error

install:
name: pip install (${{ matrix.os }}, ${{ matrix.python-version }})
needs: [build, native]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
python-version: ["3.10", "3.12", "3.13"]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
pattern: dist-*
path: dist
merge-multiple: true
- name: Fresh venv
run: |
python -m venv "$RUNNER_TEMP/clean"
if [ -d "$RUNNER_TEMP/clean/bin" ]; then
echo "$RUNNER_TEMP/clean/bin" >> "$GITHUB_PATH"
else
echo "$RUNNER_TEMP/clean/Scripts" >> "$GITHUB_PATH"
fi
- name: Describe the machine and the release artifacts
run: |
python -m pip install --quiet --upgrade pip
python -c "import platform, sys; print(platform.platform(), platform.machine(), sys.version)"
python -m pip --version
ls -l dist
python -c "import re; print('VERSION=' + re.search(r'^version = \"([^\"]+)\"', open('pyproject.toml').read(), re.M).group(1))" >> "$GITHUB_ENV"
- name: Stock-machine check — every dependency must come as a prebuilt wheel
# The runner has compilers; a user's machine may not. This resolves the
# whole dependency tree with building forbidden, so anything that would
# compile on a stock machine shows up here even though the real install
# below would succeed on the runner.
id: stock
continue-on-error: true
run: "python -m pip install --dry-run --only-binary=:all: --find-links dist sidepit==$VERSION"
- name: pip install sidepit (release artifacts + dependencies from PyPI, as a user would)
run: python -m pip install --find-links dist "sidepit==$VERSION"
- name: Show what was installed and how
if: always()
run: |
python -m pip list
python -c "import secp256k1, sidepit_trader; print('secp256k1 from', secp256k1.__file__)"
- name: Smoke-test the installed package outside the checkout
working-directory: ${{ runner.temp }}
env:
SIDEPIT_TESTNET: "true"
SIDEPIT_DEPOSIT_ADDRESS: bc1ql3e9pgs3mmwuwrh95fecme0s0qtn2880lsvsd5
SIDEPIT_KEYS_DIR: ${{ runner.temp }}/sidepit-empty-keys
SIDEPIT_STATE_DB: ${{ runner.temp }}/sidepit-empty-state.db
SIDEPIT_HOST: localhost
run: |
sidepit --help
sidepit list
python "$GITHUB_WORKSPACE/tools/smoke_installed_sidepit.py"
- name: Offline test suite against the installed package
run: |
python -m pip install pytest
python -m pytest -q python-client/tests
- name: Verdict — would this have worked on a stock machine?
if: steps.stock.outcome == 'failure'
run: |
echo "::error::a dependency has no prebuilt wheel for this platform; a user without build tools cannot pip install sidepit here"
exit 1
56 changes: 21 additions & 35 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
name: Publish Python package

# Release artifacts come from CI only, never from a developer machine. A tag
# push runs the full install proof (pure wheel + bundled platform wheels,
# pip-installed on Linux, Windows, macOS Intel and Apple Silicon); nothing is
# uploaded unless every leg is green. Upload goes through PyPI Trusted
# Publishing behind the `pypi` environment approval.

on:
push:
tags: ["v*"]
Expand All @@ -15,17 +21,13 @@ permissions:
contents: read

jobs:
build:
check-tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install build tools and test dependencies
run: python -m pip install . build pytest twine
- name: Verify tag matches package version
if: github.event_name == 'push'
run: |
Expand All @@ -36,57 +38,41 @@ jobs:
if tag != f"v{version}":
raise SystemExit(f"tag {tag!r} does not match package version {version!r}")
PY
- name: Test and build
run: |
python -m pytest -q python-client/tests
python -m build
python -m twine check --strict dist/*
python tools/check_python_dist.py dist/*
python -m pip install --force-reinstall --no-deps dist/*.whl
- name: Smoke-test release wheel outside checkout
working-directory: ${{ runner.temp }}
env:
SIDEPIT_TESTNET: "true"
SIDEPIT_DEPOSIT_ADDRESS: bc1ql3e9pgs3mmwuwrh95fecme0s0qtn2880lsvsd5
SIDEPIT_KEYS_DIR: ${{ runner.temp }}/sidepit-empty-keys
SIDEPIT_STATE_DB: ${{ runner.temp }}/sidepit-empty-state.db
SIDEPIT_HOST: localhost
run: |
sidepit --help
sidepit list
python "$GITHUB_WORKSPACE/tools/smoke_installed_sidepit.py"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: python-package
path: dist/
if-no-files-found: error

proof:
needs: check-tag
uses: ./.github/workflows/install-proof.yml

publish-testpypi:
if: github.event_name == 'workflow_dispatch'
needs: build
needs: proof
runs-on: ubuntu-latest
environment: testpypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package
pattern: dist-*
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
merge-multiple: true
- run: ls -l dist
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
with:
repository-url: https://test.pypi.org/legacy/

publish-pypi:
if: github.event_name == 'push'
needs: build
needs: proof
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package
pattern: dist-*
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
merge-multiple: true
- run: ls -l dist
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
.env
/build/
/dist/
/dist-native/
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
**The contract lives in [`Public-API-Data`](Public-API-Data/)** — its README has
the basic facts and every port; `sidepit_api.proto` is every message, exactly as
production speaks it. This file adds the working recipes and trading facts.
The user docs are machine-readable: fetch <https://docs.sidepit.com/llms.txt>
for the index and the linked Markdown pages (any page URL plus `.md`), or
<https://docs.sidepit.com/llms-full.txt> for all of it. Do not scrape the HTML.

Sidepit is a Bitcoin-margined forwards exchange — you are using Bitcoin to
trade USD. Orders match in one-second deterministic auctions (DLOB): the best
Expand Down
14 changes: 10 additions & 4 deletions DISTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# Sidepit distribution record

Status: **v0.1.0 is live on PyPI** as `sidepit`. **v0.1.1 is the release
candidate**: the cockpit TUI no longer triggers whole-order-book snapshot
broadcasts (12129) to refresh its open-orders view; open orders come from the
account's POSITIONS reply. No SDK API changes.
Status: **v0.1.1 is live on PyPI** as `sidepit`. **v0.1.2 is in preparation**
on the `ci-install-proof` branch: `pip install sidepit` works on Linux, macOS
(Apple Silicon and Intel) and Windows with nothing to compile — upstream
`secp256k1` wheels where they exist, sidepit's own platform wheels with
libsecp256k1 compiled in (stable ABI, one per platform) on Windows and Intel
macOS; `ripemd-hash` dropped for a pure-Python fallback. Every release now
passes the four-platform install proof (`.github/workflows/install-proof.yml`)
before it can be uploaded, and release artifacts come from CI only. The cockpit
starts keyless on the live market; identities are added from the doors or
ctrl+a.

This file records the distribution decisions made for the public client. It is
the durable boundary between what works today and what is deliberately next.
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include tools/vendor_secp256k1.py
include tools/secp256k1_ffi.py
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ source .venv/bin/activate
pip install sidepit
```

One line on every desktop, nothing to compile (Python 3.10 or newer):

- **Linux / WSL2:** `pip install sidepit`
- **macOS** (Apple Silicon or Intel): `pip install sidepit` — no Xcode tools, no Homebrew needed.
- **Windows, recommended — WSL2:** in PowerShell `wsl --install`, reboot, open
Ubuntu, then `pip install sidepit`. You get the Linux cockpit, and Claude
Code runs beside it in the same terminal.
- **Windows, native:** `winget install Python.Python.3.12` (or python.org with
"Add python.exe to PATH" ticked), open a **new** terminal, then
`python -m pip install sidepit`. Windows Terminal renders the cockpit best;
keys live in `%USERPROFILE%\.sidepit\keys`.

First run opens on the live market with no identity. Create, import or watch
one from the doors, or press Escape to just look and add a key later with ctrl+a.

Terminal one — the cockpit:

```sh
Expand Down
32 changes: 2 additions & 30 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "sidepit"
version = "0.1.1"
version = "0.1.2"
description = "The official Python SDK and trading terminal for Sidepit."
readme = "README.md"
requires-python = ">=3.10"
Expand All @@ -20,16 +20,7 @@ classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Topic :: Office/Business :: Financial :: Investment",
]
dependencies = [
"protobuf==3.20.1",
"pynng",
"secp256k1",
"base58",
"ripemd-hash>=1.0.1",
"bitcoinlib",
"textual>=8.0",
"qrcode>=7.0",
]
dynamic = ["dependencies"] # see setup.py: pure vs bundled-secp256k1 builds

[project.scripts]
sidepit = "sidepit_tui.__main__:main"
Expand All @@ -38,22 +29,3 @@ sidepit = "sidepit_tui.__main__:main"
Homepage = "https://sidepit.com"
Documentation = "https://docs.sidepit.com"
Source = "https://github.com/sidepit/Public-API"

[tool.setuptools]
packages = [
"sidepit_trader",
"sidepit_trader.examples",
"sidepit_trader.proto",
"sidepit_trader.data",
"sidepit_tui",
]

[tool.setuptools.package-dir]
sidepit_trader = "python-client/sidepit_trader"
"sidepit_trader.examples" = "python-client/sidepit_trader/examples"
"sidepit_trader.proto" = "python-client/proto"
"sidepit_trader.data" = "python-client/sidepit_trader/data"
sidepit_tui = "users-cli/sidepit_tui"

[tool.setuptools.package-data]
sidepit_trader = ["data/*.txt"]
2 changes: 1 addition & 1 deletion python-client/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "sidepit"
version = "0.1.1"
version = "0.1.2"
description = "The official Python SDK for Sidepit — Bitcoin-margined forwards, DLOB one-second deterministic auctions."
readme = "sidepit_trader/README.md"
license = { text = "MIT" }
Expand Down
Loading
Loading