{"id":49843544,"url":"https://github.com/stellar/x402-stellar","last_synced_at":"2026-05-14T08:05:39.468Z","repository":{"id":341910533,"uuid":"1171386515","full_name":"stellar/x402-stellar","owner":"stellar","description":"Tools, examples, and references for the [x402 protocol](https://www.x402.org/) on the Stellar network.","archived":false,"fork":false,"pushed_at":"2026-04-27T18:39:44.000Z","size":1253,"stargazers_count":7,"open_issues_count":16,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-27T20:25:43.806Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stellar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-03T07:06:59.000Z","updated_at":"2026-04-27T18:39:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stellar/x402-stellar","commit_stats":null,"previous_names":["stellar/x402-stellar"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/stellar/x402-stellar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellar%2Fx402-stellar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellar%2Fx402-stellar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellar%2Fx402-stellar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellar%2Fx402-stellar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stellar","download_url":"https://codeload.github.com/stellar/x402-stellar/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellar%2Fx402-stellar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33015825,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-14T02:00:06.663Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-14T08:05:34.821Z","updated_at":"2026-05-14T08:05:39.462Z","avatar_url":"https://github.com/stellar.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# x402 Stellar\n\nTools, examples, and references for the [x402 protocol](https://www.x402.org/) on the Stellar network.\n\n## Repository Structure\n\n```\nx402-stellar/\n├── examples/                     # Example applications\n│   ├── facilitator/              # Stellar facilitator service\n│   └── simple-paywall/           # Paywall demo (server + client)\n│       └── docker-compose.yml\n├── Dockerfile                    # Multi-target Dockerfile\n├── package.json\n├── pnpm-workspace.yaml\n├── turbo.json\n└── Makefile\n```\n\n## Prerequisites\n\n- Node.js 22+\n- pnpm 10+\n\n## Quick Start\n\n```bash\n# Clone the repo\ngit clone https://github.com/stellar/x402-stellar.git\ncd x402-stellar\n\n# Install dependencies\npnpm install\n\n# Build all packages\npnpm build\n\n# Copy env template and fill in your values\ncp examples/simple-paywall/server/.env.example examples/simple-paywall/server/.env\n```\n\n### Running the Simple Paywall Example\n\nYou need three terminals:\n\n**Terminal 1 -- Facilitator:**\n\n```bash\ncd examples/facilitator\ncp .env.example .env  # fill in FACILITATOR_STELLAR_PRIVATE_KEY\npnpm dev\n```\n\n**Terminal 2 -- Server:**\n\n```bash\ncd examples/simple-paywall/server\npnpm dev\n```\n\n**Terminal 3 -- Client:**\n\n```bash\ncd examples/simple-paywall/client\npnpm dev\n```\n\nOpen [http://localhost:5173](http://localhost:5173) and navigate through Home → Try It. The page dynamically shows buttons for each configured network (testnet, mainnet, or both) based on which `TESTNET_*` / `MAINNET_*` env vars are set.\n\n### Docker Compose (with ingress rewrite simulation)\n\nTo run the 3-service compose stack plus a local ingress simulator (production-style rewrite behavior):\n\n```bash\ndocker compose \\\n  -f examples/simple-paywall/docker-compose.yml \\\n  -f examples/simple-paywall/docker-compose.ingress-sim.yml \\\n  up -d --build\n```\n\nThen open [http://localhost:8099/x402-demo/try](http://localhost:8099/x402-demo/try).\n\nThis simulator rewrites:\n\n- `/x402-demo(/|$)(.*)` → client `/$2`\n- `/x402-demo/api(/|$)(.*)` → server `/$2`\n\nIt is useful for reproducing ingress-prefix issues locally. Full verification steps (including decoding `PAYMENT-REQUIRED.resource.url`) are in `examples/simple-paywall/INGRESS_SIMULATION.md`.\n\nTo stop:\n\n```bash\ndocker compose \\\n  -f examples/simple-paywall/docker-compose.yml \\\n  -f examples/simple-paywall/docker-compose.ingress-sim.yml \\\n  down\n```\n\n## Examples\n\n| Example            | Path                       | Description                                              |\n| ------------------ | -------------------------- | -------------------------------------------------------- |\n| **Facilitator**    | `examples/facilitator/`    | Stellar facilitator service that processes x402 payments |\n| **Simple Paywall** | `examples/simple-paywall/` | Express API with x402 middleware + React/Vite frontend   |\n\n## Development\n\n```bash\nmake install      # pnpm install\nmake build        # pnpm build (turbo)\nmake dev          # pnpm dev\nmake lint         # pnpm lint\nmake typecheck    # pnpm typecheck\nmake test         # pnpm test\nmake check        # format + lint + typecheck + test\nmake clean        # remove dist/ and node_modules/ from examples\n```\n\n## Deployment\n\nThe Dockerfile is a multi-target build with targets for `facilitator`, `server`, and `client`. See `examples/simple-paywall/docker-compose.yml` for the compose configuration.\n\n## Environment Variables\n\n### Server\n\n| Variable           | Default                          | Description                                 |\n| ------------------ | -------------------------------- | ------------------------------------------- |\n| `PORT`             | `3001`                           | Server port                                 |\n| `NODE_ENV`         | `development`                    | Environment                                 |\n| `LOG_LEVEL`        | `info`                           | Pino log level                              |\n| `CORS_ORIGINS`     | `http://localhost:5173`          | Allowed CORS origins (comma-separated)      |\n| `PAYWALL_DISABLED` | —                                | Set to `true` to disable the paywall        |\n| `PAYMENT_PRICE`    | `0.01`                           | Price for protected content                 |\n| `CLIENT_HOME_URL`  | —                                | Client home page URL for paywall brand link |\n| `TRUST_PROXY`      | `loopback,linklocal,uniquelocal` | Express trust proxy setting                 |\n\n### Per-Network (Testnet / Mainnet)\n\nThe server supports multiple Stellar networks simultaneously. Each network is configured with a `TESTNET_` or `MAINNET_` prefix. Provide at least one set to enable that network's `/protected/\u003cnetwork\u003e` endpoint.\n\n| Variable (replace `\u003cNETWORK\u003e_` with `TESTNET_` or `MAINNET_`) | Default                    | Description                                                                                    |\n| ------------------------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------- |\n| `\u003cNETWORK\u003e_SERVER_STELLAR_ADDRESS`                            | _required per network_     | Stellar address to receive payments                                                            |\n| `\u003cNETWORK\u003e_STELLAR_RPC_URL`                                   | testnet RPC (testnet only) | Custom Soroban RPC URL (required for mainnet)                                                  |\n| `\u003cNETWORK\u003e_FACILITATOR_URL`                                   | —                          | x402 facilitator URL                                                                           |\n| `\u003cNETWORK\u003e_FACILITATOR_API_KEY`                               | —                          | Facilitator API key(s); comma-separate multiple keys for round-robin load balancing (optional) |\n\n### Facilitator\n\n| Variable                              | Default                          | Description                              |\n| ------------------------------------- | -------------------------------- | ---------------------------------------- |\n| `FACILITATOR_STELLAR_PRIVATE_KEY`     | —                                | Facilitator wallet private key           |\n| `FACILITATOR_STELLAR_FEE_BUMP_SECRET` | —                                | Fee-bump signer secret (high-throughput) |\n| `FACILITATOR_STELLAR_CHANNEL_SECRETS` | —                                | Channel account secrets, comma-separated |\n| `TRUST_PROXY`                         | `loopback,linklocal,uniquelocal` | Express trust proxy setting              |\n| `MAX_TRANSACTION_FEE_STROOPS`         | `50000` (library default)        | Max fee in stroops accepted from clients |\n\n### Client\n\n| Variable             | Default                 | Description                                                                              |\n| -------------------- | ----------------------- | ---------------------------------------------------------------------------------------- |\n| `VITE_SERVER_URL`    | `http://localhost:3001` | Server URL for the client SPA (build-time or runtime)                                    |\n| `VITE_APP_NAME`      | `x402 on Stellar`       | App name for the client SPA (build-time or runtime)                                      |\n| `VITE_PAYMENT_PRICE` | `0.01`                  | Payment price shown in the UI (build-time or runtime)                                    |\n| `VITE_BASE_ROUTE`    | `/`                     | Rewrites asset paths and sets the SPA router basename for subpath serving (runtime only) |\n| `VITE_PORT`          | `5173`                  | Dev server port (build-time only)                                                        |\n\n\u003e **Note:** `VITE_SERVER_URL`, `VITE_APP_NAME`, and `VITE_PAYMENT_PRICE` can be overridden at container launch time (via `docker-entrypoint.sh` → `window.__CONFIG__`). `VITE_BASE_ROUTE` is runtime-only: at container startup, the entrypoint rewrites asset paths in `index.html` and injects the SPA router basename so the app works when served under a subpath (e.g. `/x402-demo/`). `VITE_PORT` only affects the Vite dev server and is not used in Docker. These variables are included in the root `.env.example` (commented out); alternatively, set them in the client's own `.env` file or pass them via the environment (e.g. `VITE_PORT=3000 pnpm dev`).\n\n## High-Throughput Facilitator Setup (Recommended)\n\nFor production or high-volume scenarios, the facilitator supports **channel accounts** with a **fee-bump signer**. This is the recommended setup because it allows parallel transaction submission — each channel account maintains its own sequence number, and a dedicated fee-bump signer pays all fees.\n\n### How It Works\n\nOn Stellar, a single account can only submit one transaction at a time because each transaction increments the account's sequence number. With 19 channel accounts + 1 fee-bump signer, the facilitator can submit up to 19 transactions in parallel:\n\n- **Channel accounts** (inner-tx signers): Each holds its own sequence number. The facilitator uses round-robin selection to distribute transactions across them. Created with zero balance via sponsored reserves.\n- **Fee-bump signer**: A separate funded account that wraps each inner transaction in a fee-bump transaction. It pays the network fees but does not manage sequence numbers.\n\n### Setup\n\n1. Generate and fund the accounts on testnet:\n\n```bash\ncd examples/facilitator\npnpm generate-channel-accounts\n```\n\nThis will:\n\n- Create a fee-payer keypair and fund it via Friendbot\n- Generate 19 channel account keypairs\n- Create all channel accounts on-chain with zero balance (using sponsored reserves)\n- Save all keys to a timestamped `.env` file under `scripts/output/`\n- Print the environment variables to add to your `.env`\n\n2. Copy the output into your `.env`:\n\n```bash\n# examples/facilitator/.env\nFACILITATOR_STELLAR_PRIVATE_KEY=S_YOUR_EXISTING_KEY\nFACILITATOR_STELLAR_FEE_BUMP_SECRET=S_FEE_BUMP_SECRET_FROM_SCRIPT\nFACILITATOR_STELLAR_CHANNEL_SECRETS=S_CH1,S_CH2,...,S_CH19\n```\n\n3. Start the facilitator — it auto-detects high-throughput mode:\n\n```bash\npnpm dev\n```\n\nYou should see a log line: `High-throughput mode: fee-bump signer + channel accounts`.\n\nWhen the channel account variables are not set, the facilitator falls back to single-signer mode using `FACILITATOR_STELLAR_PRIVATE_KEY`.\n\n### Testnet Reset Recovery\n\nStellar's public testnet resets periodically, wiping all accounts. Two utility scripts re-fund your accounts without regenerating keys:\n\n```bash\ncd examples/facilitator\n\n# Re-fund accounts from your .env file\npnpm refund-accounts-from-env\n\n# Re-fund all signers registered with x402.org\npnpm refund-accounts-from-remote\n```\n\nBoth scripts skip accounts that are already funded. See `examples/facilitator/README.md` for details.\n\n## Adding a New Example\n\n1. Create a directory under `examples/` (e.g. `examples/my-example/`)\n2. Add a `package.json` with name `@x402-stellar/my-example`\n3. The workspace globs in `pnpm-workspace.yaml` will pick it up automatically\n4. Run `pnpm install` from the root to link it\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstellar%2Fx402-stellar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstellar%2Fx402-stellar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstellar%2Fx402-stellar/lists"}