Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
BasedOnStyle: LLVM
IndentWidth: 4
NamespaceIndentation: All
BreakBeforeBraces: Allman
PointerAlignment: Right
ColumnLimit: 100
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: WithoutElse
SortIncludes: Never
14 changes: 14 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Checks: >-
-*,
bugprone-dangling-handle,
bugprone-sizeof-expression,
bugprone-suspicious-memset-usage,
bugprone-unused-raii,
bugprone-use-after-move,
performance-*,
readability-identifier-naming
WarningsAsErrors: '*'
HeaderFilterRegex: '.*'
CheckOptions:
readability-identifier-naming.VariableCase: lower_case
readability-identifier-naming.ParameterCase: lower_case
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space

[*.{cpp,h,hpp}]
indent_size = 4

[*.{md,json,yml,yaml}]
indent_size = 2
14 changes: 9 additions & 5 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
## Summary

-
Describe the concrete problem and resulting behavior.

## Verification

- [ ] Tested with the narrowest relevant command
- [ ] Not run; reason:
Commands run and their actual results:

## Notes
Checks not run and the reason (or none):

Compatibility concerns, API surface changes, or release notes.
## Compatibility and evidence

Public API, binary compatibility, or release implications (or none):

For protocol changes: official docs links and the Python SDK commit or fixture source.
For live checks: distinguish observed outcomes from local fixture coverage.
29 changes: 28 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ name: build

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

concurrency:
group: build-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
build-test:
name: ${{ matrix.os }} ${{ matrix.build_type }}
Expand All @@ -19,8 +24,21 @@ jobs:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- name: Check PR title
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-22.04' && matrix.build_type == 'Release'
shell: bash
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
pattern='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-zA-Z0-9_./-]+\))?!?: .+'
if [[ ! "$PR_TITLE" =~ $pattern ]]; then
echo 'Use type(scope): description or type: description for the PR title.' >&2
exit 1
fi

- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
Expand All @@ -41,11 +59,20 @@ jobs:
"${deployment_args[@]}"

- name: Build
run: cmake --build build --parallel --config ${{ matrix.build_type }}
run: cmake --build build --parallel 2 --config ${{ matrix.build_type }}

- name: Test
run: ctest --test-dir build --output-on-failure --build-config ${{ matrix.build_type }} -LE live

- name: Check formatting and C++ lint
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-22.04' && matrix.build_type == 'Release'
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
python3 -m pip install clang-format==21.1.6 clang-tidy==21.1.6
python3 scripts/test_quality.py
python3 scripts/quality.py "$BASE_SHA" --build-dir build

- name: Optional live smoke
if: vars.POLYMARKET_RUN_LIVE_SMOKE == '1'
run: |
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
package_version="${version%%-*}"
grep -Eq "project\(polymarket_cpp_client VERSION ${package_version//./\\.} LANGUAGES" CMakeLists.txt
grep -Fq "#define POLYMARKET_CLIENT_VERSION \"$package_version\"" include/polymarket/version.hpp
test -s "docs/releases/$tag.md"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "commit=$commit" >> "$GITHUB_OUTPUT"

Expand All @@ -69,7 +70,7 @@ jobs:
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/install

- name: Build
run: cmake --build build --parallel --config Release
run: cmake --build build --parallel 2 --config Release

- name: Test
run: ctest --test-dir build --output-on-failure --build-config Release -LE live
Expand Down Expand Up @@ -125,7 +126,7 @@ jobs:
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/install

- name: Build
run: cmake --build build --parallel --config Release
run: cmake --build build --parallel 2 --config Release

- name: Test
run: ctest --test-dir build --output-on-failure --build-config Release -LE live
Expand Down Expand Up @@ -171,7 +172,7 @@ jobs:
name: Release ${{ needs.validate.outputs.tag }}
draft: false
prerelease: ${{ contains(needs.validate.outputs.tag, '-') }}
generate_release_notes: true
body_path: docs/releases/${{ needs.validate.outputs.tag }}.md
files: |
artifacts/macos-arm64/polymarket-cpp-client-macos-arm64.tar.gz
artifacts/linux-x64/polymarket-cpp-client-linux-x64.tar.gz
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ node_modules/

# Project-local agent learnings
.learnings/

# Local quality tools
.venv-quality/
__pycache__/
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build/
work/
node_modules/
.learnings/
.journal/
4 changes: 4 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"proseWrap": "preserve",
"printWidth": 100
}
40 changes: 40 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Working in this repository

Read [CONTRIBUTING.md](CONTRIBUTING.md) before changing code or preparing commits.
It defines coding rules, commit names, validation, and the completion criteria.

## Start here

1. Check the current branch, diff, and untracked files. Preserve other work.
2. State the working assumption and success check for larger or ambiguous tasks.
3. Read the affected public headers under `include/polymarket/`, implementation, and existing tests before editing.
4. Keep the diff within the requested scope and match the surrounding C++ style.
5. Run the narrowest meaningful check, then report the command and actual result.

Concurrent work is common. Continue around unrelated changes without resetting,
removing, or reformatting them. When asked to commit all work, review every tracked
and untracked change and create logical commit groups.

## Load these references when relevant

- Protocol, signing, transactions, numeric parsing, or stream lifecycle changes:
read [docs/protocol-development.md](docs/protocol-development.md).
- Position operations or wallet support: also read
[docs/position-operations.md](docs/position-operations.md).
- Versions, tags, release packages, or publication: read
[docs/releasing.md](docs/releasing.md) and `.github/workflows/release.yml`.
- Test registration and example targets: inspect `cmake/PolymarketTests.cmake`
and `cmake/PolymarketExamples.cmake`.

## Authorization and reporting

A request to investigate or draft permits local preparation. Publishing comments,
pushing commits, merging PRs, and publishing releases require authorization from
the user. Carry forward authorization already given in the conversation.

Live orders, approvals, and funded transactions require explicit authorization.
Use deterministic tests and read-only inspection for routine validation.

Distinguish prepared changes, passing local checks, passing CI, and published
artifacts. Report skipped checks and the precise reason. Keep contributor
messages natural and concise. Do not use em dashes.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()

project(polymarket_cpp_client VERSION 2.0.0 LANGUAGES CXX C)
project(polymarket_cpp_client VERSION 3.0.0 LANGUAGES CXX C)

if(PROJECT_IS_TOP_LEVEL)
set(CMAKE_CXX_STANDARD 20)
Expand Down
126 changes: 126 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Contributing

## Coding rules

- Prefer clear domain names such as `submitted_hashes` and `poll_interval`.
Use the existing snake_case convention for variables and parameters.
- Keep hot paths efficient. Avoid needless copies, repeated parsing, unbounded
queues, and allocations inside loops. Measure performance changes with the
relevant existing benchmark and report workload, build type, and comparison.
Prefer a small direct implementation over extra abstractions.
- Use C++20 and match the existing naming, indentation, and brace style.
- Keep new or substantially changed files near 300 lines or fewer. This is a
soft limit: split by responsibility, not arbitrary line counts. Explain an
exception in the PR instead of creating meaningless wrappers.
- Keep public interfaces in `include/polymarket/` and implementation details in `src/`.
Reuse existing numeric, transport, signing, and error helpers.
- Keep changes surgical. Avoid unrelated cleanup, dependency upgrades, and
formatting changes. Add configuration or features only when requested.
- Validate inputs at the boundary. Return or throw useful errors with the
original cause and relevant transaction or request identifiers.
- Handle failure explicitly. Do not hide it with fallback behavior or fabricated
production data. Deterministic fixtures and local servers belong in tests.
- Use RAII for resources and state ownership. Make callback lifetime, shutdown,
locking, and concurrent access explicit when changing asynchronous code.
- Treat public type layout and behavior as compatibility concerns. Explain
changes that require consumers to rebuild or adapt.

Protocol and lifecycle changes also follow
[docs/protocol-development.md](docs/protocol-development.md).

Use prefixed public includes such as `<polymarket/http_client.hpp>`. Keep generic
header names out of the install prefix root.

## Commits and pull requests

Use `type(scope): description` or `type: description`. Write a short imperative
subject and group changes by purpose. Common types are `feat`, `fix`, `docs`,
`refactor`, `test`, `perf`, `build`, `ci`, and `chore`. Use `!` and a
`BREAKING CHANGE:` footer when a change requires a migration.

Examples:

- `fix(position): preserve hashes after partial batch failure`
- `test(user-stream): cover authentication rejection`
- `docs: explain agent workflow and coding rules`
- `chore(release): prepare v3.0.0`

PR titles use the same format and are checked in CI. Describe the concrete
problem and resulting behavior, then give the relevant validation. For protocol
changes, include official documentation links and the SDK commit or fixture
source used. Separate observed live results from deterministic test coverage.

Review all tracked and untracked changes before committing. Stage explicit files
or hunks and keep unrelated work in separate commits when its inclusion is
requested. Keep credentials, local environment files, and build artifacts out
of commits.

## Validation

Configure an isolated build directory for the task:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DPOLYMARKET_CLIENT_BUILD_EXAMPLES=ON \
-DPOLYMARKET_CLIENT_BUILD_TESTS=ON
cmake --build build --parallel 2
ctest --test-dir build --output-on-failure -LE live
```

For a small fix, build the affected target and select the relevant tests with
`ctest --test-dir build --output-on-failure -R '<test-name-pattern>' -LE live`.
Add a focused regression for changed behavior. Check that it exposes the failure
before the fix where practical. Assertions must remain effective in Release
builds; use explicit checks such as `tests/check_support.hpp`, not C `assert`
for new tests.

For public headers, dependency exports, or installation changes, run
`test_package_consumer`. It installs the package, builds an external consumer and
shared plugin, and checks subproject configuration. Match the full CI matrix
before releasing: Linux and macOS, Debug and Release. The workflow files define
the authoritative build options and live-test policy.

A successful fake-server test proves the local request and response contract.
It does not prove a transaction succeeded on mainnet. Report the distinction.

## Formatting and linting

Install the pinned development tools separately from the library:

```bash
python3 -m venv .venv-quality
. .venv-quality/bin/activate
python3 -m pip install clang-format==21.1.6 clang-tidy==21.1.6
# Requires Node.js and npm for pinned Prettier 3.6.2.
# Run test_package_consumer first when its source changes.
python3 scripts/quality.py origin/main --build-dir build
python3 scripts/quality.py origin/main --fix
```

On macOS, make the SDK explicit in the compile database before running clang-tidy:

```bash
cmake -S . -B build -DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)"
```

clang-format follows `.clang-format`; clang-tidy checks correctness, performance,
and variable naming through `.clang-tidy`. Prettier formats Markdown, YAML, and
JSON. `--fix` changes formatting only; inspect the diff before keeping it.

CI checks changed C++ lines and rejects new Prettier formatting debt in touched
files. Existing formatting is the baseline, so unrelated code stays untouched.
Linux Release runs these checks against its existing build and installed
consumer, avoiding a separate library build for linting.
Header-only changes lint first-party translation units against the changed
header lines. New files are checked in full. Use the configured compile database
for linting, and keep static analysis warnings actionable. Duplicate logic and
unnecessary abstractions remain explicit code review checks; the linter does
not prove architectural quality or runtime efficiency.

## Done means

The requested behavior is implemented, relevant checks pass, and the diff
contains only the intended work. The PR names compatibility changes, evidence,
and checks that were not run. Report blockers instead of claiming completion.

For releases, follow [docs/releasing.md](docs/releasing.md).
Loading
Loading