diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..b9eee7c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,62 @@ +## Summary + + + +Closes # + +--- + +## Type of change + + + +- [ ] `feat` — new page or substantial content addition +- [ ] `fix` — corrects a factual error, broken link, or bad code example +- [ ] `docs` — changes to meta-docs (CONTRIBUTING.md, README.md, templates) +- [ ] `chore` — tooling, CI, config, or dependency update +- [ ] `refactor` — content restructuring without meaning changes +- [ ] `style` — formatting only + +--- + +## Branch checklist + +> Common mistakes that cause PRs to be redirected. Please verify before opening. + +- [ ] I branched from `develop`, not `main` +- [ ] This PR targets `develop`, not `main` +- [ ] My PR title follows conventional commits format (e.g., `feat(guides): add stellar multisig guide`) + +--- + +## Content checklist + +- [ ] All new or modified pages have at least one code example (if applicable) +- [ ] Code examples use TypeScript, `@wraith-protocol/sdk`, and the `Chain` enum — not raw strings +- [ ] No marketing copy — descriptions explain what, not how great + +--- + +## Snippet checklist + + + +- [ ] I ran `pnpm run check:snippets` locally and it passes +- [ ] All new TypeScript/JavaScript fences compile without errors +- [ ] I used `no-check` only for intentionally illustrative pseudocode that cannot be made runnable + + + +--- + +## Screenshots or previews + + + +--- + +## Additional notes + + diff --git a/.github/workflows/guard-main.yml b/.github/workflows/guard-main.yml new file mode 100644 index 0000000..176e7e1 --- /dev/null +++ b/.github/workflows/guard-main.yml @@ -0,0 +1,25 @@ +name: PR target branch guard + +on: + pull_request: + branches: + - main + +jobs: + block-direct-main-pr: + name: Block PRs targeting main + runs-on: ubuntu-latest + steps: + - name: Reject PR targeting main + run: | + echo "::error::PRs must target 'develop', not 'main'." + echo "" + echo " 'main' is the release branch and is only updated by" + echo " maintainers via controlled merges from 'develop'." + echo "" + echo " Please retarget your PR to 'develop':" + echo " 1. Close this PR." + echo " 2. Open a new PR with base set to 'develop'." + echo "" + echo " See CONTRIBUTING.md for the full branch model." + exit 1 diff --git a/.github/workflows/pr-title-lint.yml b/.github/workflows/pr-title-lint.yml new file mode 100644 index 0000000..81f6ceb --- /dev/null +++ b/.github/workflows/pr-title-lint.yml @@ -0,0 +1,42 @@ +name: PR title lint + +on: + pull_request: + types: + - opened + - edited + - synchronize + - reopened + +jobs: + lint-pr-title: + name: Validate conventional commit title + runs-on: ubuntu-latest + steps: + - name: Check PR title format + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + # Pattern: (): + # Allowed types: feat fix docs chore refactor style + PATTERN='^(feat|fix|docs|chore|refactor|style)(\([a-z0-9/,. -]+\))?: .{1,100}$' + + if echo "$PR_TITLE" | grep -qE "$PATTERN"; then + echo "PR title is valid: $PR_TITLE" + else + echo "::error::PR title does not follow Conventional Commits format." + echo "" + echo " Got: $PR_TITLE" + echo "" + echo " Expected format: (): " + echo " Allowed types: feat | fix | docs | chore | refactor | style" + echo "" + echo " Examples:" + echo " feat(guides): add stellar multisig withdrawal guide" + echo " fix(sdk): correct Chain enum example" + echo " docs: expand CONTRIBUTING with branch model" + echo " chore(ci): pin actions/checkout to v4" + echo "" + echo " See CONTRIBUTING.md for the full commit message guide." + exit 1 + fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1ba8c3a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,282 @@ +# Contributing to Wraith Protocol Docs + +Thanks for helping improve the Wraith Protocol documentation. This guide covers +everything you need to contribute — from branching strategy to getting your PR merged. + +--- + +## Table of contents + +1. [Branch model](#branch-model) +2. [Getting started](#getting-started) +3. [Making changes](#making-changes) +4. [Commit messages](#commit-messages) +5. [Opening a pull request](#opening-a-pull-request) +6. [Code and snippet standards](#code-and-snippet-standards) +7. [CI checks](#ci-checks) +8. [Review process](#review-process) + +--- + +## Branch model + +> **The most common mistake new contributors make is branching from `main` and +> targeting `main` in their PR. Please read this section carefully.** + +| Branch | Purpose | +| --------- | ----------------------------------------------------------------------- | +| `develop` | **Trunk.** All work branches off here. All PRs target here. | +| `main` | **Release.** Reflects what is live in production. Never push directly. | + +``` +main ──────────────────────────────────────► (live / released) + ↑ periodic release merges +develop ──────────────────────────────────────► (trunk) + ↑ your PRs merge here +feature/ ──────────────────────► +fix/ ──────────────────────► +docs/ ──────────────────────► +``` + +**Always branch from `develop`. Always target `develop` in your PR.** + +`main` is updated only via controlled releases by maintainers. A PR targeting +`main` will be redirected or closed. + +--- + +## Getting started + +### Prerequisites + +- Node.js 22+ +- [pnpm](https://pnpm.io/) 10+ + +### Fork and clone + +```bash +# Fork the repo on GitHub, then: +git clone https://github.com//docs.git +cd docs + +# Add upstream remote +git remote add upstream https://github.com/wraith-protocol/docs.git +``` + +### Install dependencies + +```bash +pnpm install +``` + +### Sync with upstream before starting work + +```bash +git fetch upstream +git checkout develop +git merge upstream/develop +``` + +### Create a branch + +Branch names should use one of these prefixes: + +| Prefix | When to use | +| ---------- | ------------------------------------------------------- | +| `feat/` | New page or substantial new section | +| `fix/` | Correcting a factual error, broken link, or bad example | +| `docs/` | Meta-docs changes (this file, README, templates) | +| `chore/` | Config, CI, tooling, dependency updates | +| `refactor/`| Restructuring content without changing meaning | + +```bash +git checkout -b feat/stellar-multisig-guide +``` + +--- + +## Making changes + +### File structure + +Pages live at the repo root in their logical subdirectory. All content files are +`.mdx`. Internal docs (like this file) are `.md`. + +``` +CONTRIBUTING.md +README.md +getting-started.mdx +sdk/ +guides/ +architecture/ +contracts/ +api-reference/ +``` + +See `CLAUDE.md` for the full content map. + +### Writing style + +- Short sentences. Active voice. +- Technical but approachable — assume TypeScript knowledge, not stealth-address + cryptography knowledge. +- Every conceptual page needs at least one working code example. +- Use `@wraith-protocol/sdk` as the package name. Reference the `Chain` enum, + not raw strings. All code examples must be TypeScript. +- No marketing copy. Describe what things do, not how great they are. + +### MDX conventions + +- Use `.mdx` extension for all public-facing docs. +- Keep frontmatter minimal — `title` and `description` are sufficient for most + pages. +- Code fences must specify a language tag (e.g., ` ```typescript `). +- Use `no-check` only for intentionally non-runnable pseudocode (see + [snippet standards](#code-and-snippet-standards) below). + +--- + +## Commit messages + +All commits must follow [Conventional Commits](https://www.conventionalcommits.org/). + +### Format + +``` +(): + +[optional body] + +[optional footer(s)] +``` + +### Types + +| Type | When to use | +| ---------- | --------------------------------------------------------- | +| `feat` | A new page, section, or meaningful content addition | +| `fix` | Corrects an error — factual, typographical, or code-based | +| `docs` | Changes to meta-docs (CONTRIBUTING.md, README.md, etc.) | +| `chore` | Tooling, CI, config, dependency updates | +| `refactor` | Content restructuring without meaning changes | +| `style` | Formatting only (whitespace, punctuation) | + +### Examples + +``` +feat(guides): add stellar multisig withdrawal guide +fix(sdk): correct Chain enum example in agent-client reference +docs: expand CONTRIBUTING with branch model +chore(ci): pin actions/checkout to v4 +refactor(architecture): reorganise TEE section headings +``` + +### Rules + +- Subject line: 72 characters max, lowercase, no trailing period. +- Use the imperative mood — "add guide" not "added guide" or "adds guide". +- Reference issues in the footer: `Closes #91` +- **Do not** add `Co-Authored-By` lines. + +--- + +## Opening a pull request + +1. Push your branch to your fork: + + ```bash + git push -u origin feat/your-branch-name + ``` + +2. Open a PR on GitHub. Set: + - **Base branch:** `develop` ← your branch + - **Title:** Follow the conventional commits format (e.g., + `feat(guides): add stellar multisig withdrawal guide`) + +3. Fill in the PR template completely. Incomplete templates slow down review. + +4. A maintainer will review within a few business days. Address feedback with + new commits — do not force-push after a review has started. + +### Common PR mistakes to avoid + +| Mistake | Correct approach | +| ----------------------------------- | ------------------------------------- | +| Branching from `main` | Always branch from `develop` | +| Targeting `main` in the PR | Always target `develop` | +| No conventional-commit prefix in title | Use `feat:`, `fix:`, `docs:`, etc. | +| Snippet check failing | Run `pnpm run check:snippets` locally first | +| Opting out snippets with `no-check` when they could compile | Prefer making snippets compile | + +--- + +## Code and snippet standards + +All TypeScript and JavaScript code fences in `.mdx` files are validated by the +snippet checker on every PR. + +### Running the snippet check locally + +```bash +pnpm run check:snippets +``` + +The checker extracts every ` ```ts `, ` ```tsx `, ` ```typescript `, ` ```js `, +and ` ```javascript ` fence, writes it to a temp file, and runs `tsc --noEmit` +against it. This catches syntax errors and malformed TypeScript before CI does. + +### When a snippet fails + +1. Fix the snippet so it compiles. This is the preferred path. +2. If the snippet is intentionally illustrative pseudocode that is not meant to + run, add `no-check` after the language tag: + + ````mdx + ```typescript no-check + // This is pseudocode illustrating the concept only. + const result = await someHypotheticalMethod(); + ``` + ```` + + Use `no-check` sparingly. A snippet that can be made to compile should be. + +### Stellar testnet snippets + +A separate non-blocking CI job validates Stellar-specific snippets against the +live testnet. This job uses `continue-on-error: true` and will not block your +PR from merging. If it fails, a maintainer will investigate separately. + +--- + +## CI checks + +| Check | Blocking | Description | +| ---------------------------------- | -------- | ------------------------------------------------------------------ | +| Compile docs snippets | ✅ Yes | Runs `pnpm run check:snippets` on every PR | +| PR title lint | ✅ Yes | Enforces conventional commit format on PR title | +| PR target branch guard | ✅ Yes | Rejects PRs targeting `main` — retarget to `develop` | +| Stellar snippet testnet validation | ❌ No | End-to-end validation against Stellar testnet (non-blocking) | + +The blocking checks must all pass before a PR can be merged. Check status is visible in the **Checks** tab of your PR. + +The blocking check must pass before a PR can be merged. You can see check +status in the **Checks** tab of your PR. + +--- + +## Review process + +- Maintainers aim to review within **2 business days**. +- All feedback should be addressed in new commits, not by rewriting history + after review has started. +- Once approved, a maintainer will squash-merge your PR into `develop`. +- Squash message will follow conventional commits format, referencing your PR. +- Periodic batches of `develop` → `main` are performed by maintainers as + releases. + +--- + +## Questions + +Open an issue or start a discussion on GitHub. Tag it `question` so it gets +routed to the right people. diff --git a/contributing.mdx b/contributing.mdx new file mode 100644 index 0000000..028aca4 --- /dev/null +++ b/contributing.mdx @@ -0,0 +1,79 @@ +--- +title: "Contributing" +description: "How to contribute to the Wraith Protocol documentation — branch model, conventional commits, snippet checks, and the review process." +--- + +The Wraith Protocol docs are open source and live at [github.com/wraith-protocol/docs](https://github.com/wraith-protocol/docs). Contributions of all kinds are welcome: fixing typos, improving code examples, adding guides, or expanding reference pages. + +The full contributing guide is in [CONTRIBUTING.md](https://github.com/wraith-protocol/docs/blob/develop/CONTRIBUTING.md) at the root of the repository. The sections below summarise the most important points. + +--- + +## Branch model + +| Branch | Purpose | +| --------- | ------------------------------------- | +| `develop` | Trunk — all work branches off here | +| `main` | Release — merged from `develop` only | + +Always branch from `develop`. PRs targeting `main` directly will be closed. + +```bash +git checkout develop +git pull origin develop +git checkout -b docs/my-improvement +``` + +--- + +## Conventional commits + +Every commit and PR title must follow the [Conventional Commits](https://www.conventionalcommits.org/) format: + +``` +(): +``` + +Common types for this repo: `docs`, `fix`, `feat`, `refactor`, `chore`, `style`. + +```bash +# Examples +docs(stellar): add passkey signing guide +fix(snippets): correct XLM transfer fee calculation +feat(guides): add Soroswap integration walkthrough +``` + +--- + +## Code snippet checks + +All TypeScript and JavaScript fences in `.mdx` files are compiled by `tsc --noEmit` in CI. Run the check locally before pushing: + +```bash +pnpm run check:snippets +``` + +If a snippet is intentional pseudocode, annotate it with `no-check`: + +````mdx +```typescript no-check +// Illustrative — not meant to compile. +``` +```` + +Prefer making snippets compile over opting them out. + +--- + +## Opening a pull request + +1. Target `develop`. +2. Use the PR template that appears automatically on GitHub. +3. Complete all checklist items relevant to your change. +4. Keep PRs focused — one logical change per PR. + +A maintainer will review within 2 business days. Automated snippet and link checks must pass before human review begins. + + + See [CONTRIBUTING.md](https://github.com/wraith-protocol/docs/blob/develop/CONTRIBUTING.md) for the complete guide, including setup instructions and the full review process. + diff --git a/docs.json b/docs.json index 6050cc4..d65015c 100644 --- a/docs.json +++ b/docs.json @@ -76,7 +76,7 @@ "groups": [ { "group": "Overview", - "pages": ["introduction", "getting-started", "roadmap"] + "pages": ["introduction", "getting-started", "roadmap", "contributing"] }, { "group": "Architecture", diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 597665e..d44ffa7 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,34 +1,11 @@ # Contributing -Thanks for helping improve the Wraith Protocol docs. +The contributing guide has moved to [CONTRIBUTING.md](../CONTRIBUTING.md) at the root of the repository. -## Snippet checks +Please read that file for the full guide, including: -All TypeScript and JavaScript code fences in `.mdx` files are checked by: - -```bash -npm run check:snippets -``` - -The checker extracts each `ts`, `tsx`, `typescript`, `js`, and `javascript` fence, -writes it to a temporary file, and runs `tsc --noEmit` against that snippet. The -initial gate is intentionally syntax-focused because many current docs snippets -are fragments meant to illustrate API shapes rather than complete programs. It -still catches malformed TypeScript and keeps the docs ready for stricter runtime -validation over time. - -Use `no-check` only for intentionally illustrative pseudocode: - -````mdx -```typescript no-check -// Pseudocode that is not copy-paste runnable. -``` -```` - -Prefer making snippets compile over opting them out. - -## CI - -Every pull request runs the snippet checker through GitHub Actions. A separate -non-blocking Stellar testnet job is reserved for end-to-end snippet validation -that depends on network availability. +- Branch model (`develop` = trunk, `main` = release) +- Conventional commit format +- Snippet checks and the `no-check` escape hatch +- How to open a pull request +- Review process diff --git a/package.json b/package.json index e364273..53cd847 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@wraith-protocol/docs", "private": true, "type": "module", + "packageManager": "pnpm@10.0.0", "scripts": { "check:snippets": "tsx scripts/check-snippets.ts", "check:stellar-testnet": "tsx scripts/check-stellar-testnet-snippets.ts", diff --git a/reference/stellar-event-schemas.mdx b/reference/stellar-event-schemas.mdx new file mode 100644 index 0000000..408ee00 --- /dev/null +++ b/reference/stellar-event-schemas.mdx @@ -0,0 +1,109 @@ +--- +title: "Stellar Event Schemas (v2)" +description: "Soroban event topic schemas for stealth address announcements" +keywords: "Stellar, soroban, freighter, xlm, lumen, friendbot, stellar.expert, path payment, meta-address" +--- + +The `stealth-announcer` contract emits events to notify indexers and clients about new stealth payments. In v2, the event topic schema has been updated to include indexed fields that allow clients to efficiently filter events before downloading the full metadata. + +This reference guide documents the v2 event schema, how it differs from v1, and how to query it. + +## v1 vs v2 Event Topic Comparison + +### v1 Schema (Legacy) + +In v1, the event emitted a single topic, requiring indexers to parse the data payload to extract routing information. + +- **Topic Layout**: `("announce")` +- **Data Layout**: `(caller, scheme_id, stealth_address, ephemeral_pub_key, metadata)` + +### v2 Schema (Current) + +In v2, key routing fields have been moved to the event topics to enable native filtering via the Soroban RPC `getEvents` method. + +- **Topic Layout**: `("announce", scheme_id, view_tag_bucket, metadata_kind)` +- **Data Layout**: `(caller, stealth_address, ephemeral_pub_key, metadata)` + +## v2 Topic Layout Details + +The v2 event emits exactly four topics: + +1. **`"announce"`**: The literal string identifier for the event. +2. **`scheme_id`** (u32): The stealth address scheme being used (e.g., `1` for the standard ed25519 scheme). +3. **`view_tag_bucket`** (u32): A deterministic bucket derived from the view tag to allow prefix filtering. +4. **`metadata_kind`** (u32): The type of metadata attached to the event. + +### `view_tag_bucket` Derivation Rule + +To reduce false positives when scanning announcements, clients can filter by the `view_tag_bucket`. + +- **Rule**: The bucket is derived directly from the first byte of the metadata (`metadata[0]`). +- **Stability**: This derivation is stable and guaranteed not to change for a given `metadata_kind`. + +When querying the RPC, indexers can specify their expected `view_tag_bucket` to dramatically reduce the number of events they need to fetch and process. + +### `metadata_kind` Values & Forward-Compat + +The `metadata_kind` field ensures forward compatibility for future upgrades to the announcement payload. + +- **`0`**: Standard stealth payment metadata (view tag included). +- **`1+`**: Reserved for future use (e.g., encrypted amounts, multi-asset routing). + +**Forward-Compat Semantics**: Indexers and clients *must* gracefully ignore events with a `metadata_kind` they do not recognise. This allows new metadata formats to be deployed without breaking existing indexers. + +## Example `getEvents` Filter Queries + +You can use the Soroban RPC `getEvents` endpoint to filter for specific topics. + +### 1. Fetch all v2 announcements for Scheme 1 + +```json +{ + "startLedger": 123456, + "filters": [ + { + "type": "contract", + "contractIds": [""], + "topics": [ + ["announce"], + ["1"], + ["*"], + ["*"] + ] + } + ], + "pagination": { "limit": 100 } +} +``` + +### 2. Filter by `view_tag_bucket` (e.g., Bucket 42) + +This is the recommended query for clients looking for their own transactions. + +```json +{ + "startLedger": 123456, + "filters": [ + { + "type": "contract", + "contractIds": [""], + "topics": [ + ["announce"], + ["1"], + ["42"], + ["0"] + ] + } + ], + "pagination": { "limit": 100 } +} +``` + +## Migration & Indexer Recommendations + +The transition from v1 to v2 involves a new deployment of the `stealth-announcer` contract. + +- **Migration Timing**: v1 events remain readable and will not be deleted. v2 is a strictly new deployment with a new contract ID. +- **Indexer Recommendations**: During the transition period, indexers and wallets *must* listen to both the v1 and v2 contract IDs to ensure no announcements are missed. + +You can query both simultaneously by including both contract IDs in your `getEvents` filter, or by running parallel queries for the different topic structures.