Add contributing guide with LLM quick start instructions#563
Add contributing guide with LLM quick start instructions#563leofelix077 wants to merge 6 commits intostellar:developfrom
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a contributor-focused setup guide, including an LLM-oriented “quick start”, to help developers validate prerequisites, configure environment variables, and run the wallet-backend locally.
Changes:
- Added
LLM-QUICK-START.mdwith step-by-step environment checks, env var guidance, and run/verify instructions. - Expanded
CONTRIBUTING.mdwith prerequisites, local dev paths (Docker Compose vs local Go), testing guidance, and repo context.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 18 comments.
| File | Description |
|---|---|
LLM-QUICK-START.md |
New LLM-driven local setup checklist and instructions. |
CONTRIBUTING.md |
Rewritten contributing guide with setup, env var, testing, and workflow guidance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Go >= 1.24.0 | ||
| go version 2>&1 || which go |
There was a problem hiding this comment.
The quick start requires Go >= 1.24.0, but the repo is pinned to Go 1.23.2 (see go.mod and .github/workflows/go.yaml). Update the stated requirement (and the example output in Step 2) to match the repo’s supported Go version.
| - **golangci-lint**: `brew install golangci-lint` (macOS) or | ||
| `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest` |
There was a problem hiding this comment.
The suggested go install path for golangci-lint installs the v1 module path. This repo’s .golangci.yml uses config version: "2" and CI installs github.com/golangci/golangci-lint/v2/..., so the documented install command should use the /v2/ module path (ideally pinned to the CI version).
| These are set automatically by `docker-compose.yaml` for containerized services, | ||
| but if running `go run main.go` directly, add them to `.env` or export in shell: | ||
|
|
||
| | Variable | Value for local dev | | ||
| | -------------------- | ---------------------------------------------------------------------- | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | ||
| | `NETWORK` | `testnet` (recommended for dev) or `pubnet` | | ||
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | ||
| | `RPC_URL` | `http://localhost:8000` (default Docker Compose Stellar RPC port) | |
There was a problem hiding this comment.
This section says these variables are set automatically by docker-compose.yaml, but docker-compose.yaml requires NETWORK via ${NETWORK} (no default). Clarify that NETWORK must be set for Docker Compose too, and consider warning that setting RPC_URL=http://localhost:8000 in .env can break the containerized api/ingest services (they default to http://stellar-rpc:8000 inside the network).
| These are set automatically by `docker-compose.yaml` for containerized services, | |
| but if running `go run main.go` directly, add them to `.env` or export in shell: | |
| | Variable | Value for local dev | | |
| | -------------------- | ---------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended for dev) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| | `RPC_URL` | `http://localhost:8000` (default Docker Compose Stellar RPC port) | | |
| For containerized services, `docker-compose.yaml` supplies some of these values, | |
| but `NETWORK` must still be set for Docker Compose as well (it is referenced as | |
| `${NETWORK}` with no default). If running `go run main.go` directly on the host, | |
| add these to `.env` or export them in your shell: | |
| | Variable | Value for local dev | | |
| | -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended for dev) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| | `RPC_URL` | `http://localhost:8000` for `go run main.go` on the host. Do **not** set this in `.env` for containerized `api`/`ingest` services; inside Docker they use `http://stellar-rpc:8000`. | |
| docker compose up | ||
| ``` | ||
|
|
||
| This starts everything: TimescaleDB, Stellar RPC, API server, and ingestion. |
There was a problem hiding this comment.
docker-compose.yaml uses a plain Postgres container (postgres:14-alpine), not TimescaleDB. Update this sentence to avoid calling the DB service “TimescaleDB”.
| This starts everything: TimescaleDB, Stellar RPC, API server, and ingestion. | |
| This starts everything: Postgres, Stellar RPC, API server, and ingestion. |
| # Start dependencies | ||
| docker compose up -d db stellar-rpc-testnet | ||
|
|
There was a problem hiding this comment.
docker-compose.yaml defines the RPC service as stellar-rpc (not stellar-rpc-testnet). The documented compose command will fail as written; update the service name to match the compose file.
| Copy `.env.example` to `.env`. Required variables: | ||
|
|
||
| | Variable | How to set up | | ||
| | ----------------------------------------- | ------------------------------------------------------------------------ | | ||
| | `CLIENT_AUTH_PUBLIC_KEYS` | Generate a Stellar keypair and use the public key | | ||
| | `DISTRIBUTION_ACCOUNT_PUBLIC_KEY` | Generate a Stellar keypair for the distribution account | | ||
| | `DISTRIBUTION_ACCOUNT_PRIVATE_KEY` | Private key for the distribution account (use `ENV` signature provider) | | ||
| | `DISTRIBUTION_ACCOUNT_SIGNATURE_PROVIDER` | `ENV` for local dev (uses env var above). `KMS` for production | | ||
| | `CHANNEL_ACCOUNT_ENCRYPTION_PASSPHRASE` | Any passphrase for encrypting channel account keys | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` (default Docker Compose) | | ||
| | `NETWORK` | `testnet` or `pubnet` | | ||
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) or `Public Global Stellar Network ; September 2015` (pubnet) | | ||
| | `RPC_URL` | `http://localhost:8000` (default Docker Compose RPC) | | ||
|
|
||
| **Not in `.env.example` but needed for local Go binary dev** (Docker Compose | ||
| sets these internally for containerized services): | ||
|
|
||
| | Variable | Value for local dev | | ||
| | -------------------- | ------------------------------------------------------------------- | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | ||
| | `NETWORK` | `testnet` (recommended) or `pubnet` | | ||
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | |
There was a problem hiding this comment.
This section says “Copy .env.example to .env. Required variables:” but the table includes variables that are not present in .env.example (e.g., DATABASE_URL/NETWORK/RPC_URL), and then repeats them again under “Not in .env.example…”. Consider splitting into two non-duplicated lists: (1) variables present in .env.example and (2) additional variables contributors must add/export for local runs.
| Copy `.env.example` to `.env`. Required variables: | |
| | Variable | How to set up | | |
| | ----------------------------------------- | ------------------------------------------------------------------------ | | |
| | `CLIENT_AUTH_PUBLIC_KEYS` | Generate a Stellar keypair and use the public key | | |
| | `DISTRIBUTION_ACCOUNT_PUBLIC_KEY` | Generate a Stellar keypair for the distribution account | | |
| | `DISTRIBUTION_ACCOUNT_PRIVATE_KEY` | Private key for the distribution account (use `ENV` signature provider) | | |
| | `DISTRIBUTION_ACCOUNT_SIGNATURE_PROVIDER` | `ENV` for local dev (uses env var above). `KMS` for production | | |
| | `CHANNEL_ACCOUNT_ENCRYPTION_PASSPHRASE` | Any passphrase for encrypting channel account keys | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` (default Docker Compose) | | |
| | `NETWORK` | `testnet` or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) or `Public Global Stellar Network ; September 2015` (pubnet) | | |
| | `RPC_URL` | `http://localhost:8000` (default Docker Compose RPC) | | |
| **Not in `.env.example` but needed for local Go binary dev** (Docker Compose | |
| sets these internally for containerized services): | |
| | Variable | Value for local dev | | |
| | -------------------- | ------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| Copy `.env.example` to `.env`. | |
| **Variables in `.env.example`:** | |
| | Variable | How to set up | | |
| | ----------------------------------------- | ----------------------------------------------------------------------- | | |
| | `CLIENT_AUTH_PUBLIC_KEYS` | Generate a Stellar keypair and use the public key | | |
| | `DISTRIBUTION_ACCOUNT_PUBLIC_KEY` | Generate a Stellar keypair for the distribution account | | |
| | `DISTRIBUTION_ACCOUNT_PRIVATE_KEY` | Private key for the distribution account (use `ENV` signature provider) | | |
| | `DISTRIBUTION_ACCOUNT_SIGNATURE_PROVIDER` | `ENV` for local dev (uses env var above). `KMS` for production | | |
| | `CHANNEL_ACCOUNT_ENCRYPTION_PASSPHRASE` | Any passphrase for encrypting channel account keys | | |
| **Additional variables for local Go binary dev** (Docker Compose sets these | |
| internally for containerized services): | |
| | Variable | Value for local dev | | |
| | -------------------- | ------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) or `Public Global Stellar Network ; September 2015` (pubnet) | |
| ```bash | ||
| make check # Run all quality checks (lint, fmt, vet, generate, etc.) | ||
| make unit-test # Run unit tests | ||
| make integration-test # Run integration tests (requires Docker services) | ||
| go run main.go serve # Start API server | ||
| go run main.go ingest # Start ingestion service | ||
| go run main.go migrate up # Run database migrations | ||
| ``` | ||
|
|
||
| See `Makefile` for the complete list of targets. |
There was a problem hiding this comment.
These make targets aren’t present in the repo’s Makefile (it only includes docker-build/docker-push/go-install). Update this section to reference the actual commands used by CI (see .github/workflows/go.yaml) or add the documented Make targets.
| - **Formatting:** `gofmt` and `gofumpt`. Run `make fmt` to check. | ||
| - **Linting:** `golangci-lint`. Config in `.golangci.yml`. | ||
| - **Imports:** Organized by `goimports`. Run `make goimports` to check. | ||
| - **GraphQL:** Schema in `internal/serve/graphql/`. Run `make gql-generate` | ||
| after schema changes. |
There was a problem hiding this comment.
make fmt, make goimports, and make gql-generate aren’t defined in the Makefile. Also, internal/serve/graphql/ doesn’t exist in this repo. Please update the conventions to match the current codebase/tooling (or add the missing targets/paths if they’re intended).
| - **Formatting:** `gofmt` and `gofumpt`. Run `make fmt` to check. | |
| - **Linting:** `golangci-lint`. Config in `.golangci.yml`. | |
| - **Imports:** Organized by `goimports`. Run `make goimports` to check. | |
| - **GraphQL:** Schema in `internal/serve/graphql/`. Run `make gql-generate` | |
| after schema changes. | |
| - **Formatting:** Use standard Go formatting tools such as `gofmt` and | |
| `gofumpt`. Run `make check` to validate formatting and other quality gates. | |
| - **Linting:** `golangci-lint`. Config in `.golangci.yml`. | |
| - **Imports:** Keep imports organized consistently with standard Go tooling. | |
| Use the checks defined in the `Makefile` to verify import/style compliance. | |
| - **GraphQL:** If you change GraphQL schema or generated code, use the current | |
| schema/codegen locations and generation commands defined in this repository | |
| and its `Makefile`. |
| **Unit tests:** Require `DATABASE_URL` to be set. | ||
|
|
||
| ```bash | ||
| make unit-test |
There was a problem hiding this comment.
make unit-test isn’t defined in the Makefile. Either change this to the repo’s actual unit-test command (e.g., the go test/gotestsum invocation used in CI) or add a unit-test target to the Makefile.
| make unit-test | |
| go test -v ./... |
|
|
||
| - **Never log private keys** or encryption passphrases | ||
| - **Use `ENV` signature provider** for local dev only — production uses KMS | ||
| - **Validate all GraphQL inputs** — the API is exposed to wallet clients |
There was a problem hiding this comment.
This repo does not appear to use GraphQL endpoints/inputs (README points to Swagger/OpenAPI and the server uses chi HTTP handlers). Replace “GraphQL inputs” with the correct API surface (HTTP/JSON request validation) to avoid misleading security guidance.
| - **Validate all GraphQL inputs** — the API is exposed to wallet clients | |
| - **Validate all HTTP/JSON request inputs** — the API is exposed to wallet clients |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| golangci-lint --version 2>&1 || which golangci-lint | ||
|
|
||
| # Make | ||
| make --version 2>&1 | head -1 || which make |
There was a problem hiding this comment.
The make prerequisite check uses a pipeline (make --version | head -1 || which make). Without set -o pipefail, this will exit successfully even when make is missing (e.g., the error text is piped to head). Prefer a non-piped check or explicitly enable/handle pipefail so missing make is detected correctly.
| make --version 2>&1 | head -1 || which make | |
| make --version 2>&1 || which make |
| | Variable | Value or setup | | ||
| | ----------------------------------------- | ------------------------------------------------------------------------ | | ||
| | `CLIENT_AUTH_PUBLIC_KEYS` | Generate a Stellar keypair (e.g., via `stellar-sdk` or Stellar Laboratory) and use the public key | |
There was a problem hiding this comment.
Markdown table syntax here starts rows with || (double pipes), which renders as an extra empty column in many Markdown renderers. Use single leading/trailing pipes (e.g., | Variable | ... |) for correct table formatting.
| | Variable | Value for local dev | | ||
| | -------------------- | ---------------------------------------------------------------------- | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | |
There was a problem hiding this comment.
Same table-formatting issue as above: this table also starts with || (double pipes), which introduces an empty column. Switch to standard Markdown table rows with single | delimiters.
| | Variable | How to set up | | ||
| | ----------------------------------------- | ------------------------------------------------------------------------ | | ||
| | `CLIENT_AUTH_PUBLIC_KEYS` | Generate a Stellar keypair and use the public key | | ||
| | `DISTRIBUTION_ACCOUNT_PUBLIC_KEY` | Generate a Stellar keypair for the distribution account | |
There was a problem hiding this comment.
This environment-variable table also uses || (double pipes), which renders as an extra empty column. Update it to standard Markdown table syntax (| ... |).
| | Variable | Value for local dev | | ||
| | -------------------- | ------------------------------------------------------------------- | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | ||
| | `NETWORK` | `testnet` (recommended) or `pubnet` | | ||
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | ||
| | `RPC_URL` | `http://localhost:8000` (Docker Compose default) | | ||
|
|
There was a problem hiding this comment.
RPC_URL is documented as http://localhost:8000 and labeled “Docker Compose default”, but docker-compose.yaml defaults RPC_URL to http://stellar-rpc:8000 inside containers. Setting RPC_URL=http://localhost:8000 in .env will override Compose and break api/ingest (since localhost is the container). Clarify that http://localhost:8000 is for host-side go run only, and avoid setting it when running the full Docker Compose stack (or document the container value explicitly).
| | Variable | Value for local dev | | |
| | -------------------- | ------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| | `RPC_URL` | `http://localhost:8000` (Docker Compose default) | | |
| | Variable | Value for local dev | | |
| | -------------------- | ----------------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| | `RPC_URL` | `http://localhost:8000` (for host-side `go run`; not the container default) | | |
| When running the full Docker Compose stack, do **not** set `RPC_URL` in | |
| `.env` to `http://localhost:8000`. Containerized services use the internal | |
| Docker Compose address `http://stellar-rpc:8000`. |
| **Integration tests:** Require `db` and `stellar-rpc` Docker services running. | ||
|
|
||
| ```bash | ||
| ENABLE_INTEGRATION_TESTS=true go test -v ./internal/integrationtests/... -timeout 30m |
There was a problem hiding this comment.
The integration-test instructions reference ENABLE_INTEGRATION_TESTS=true and go test -v ./internal/integrationtests/..., but ENABLE_INTEGRATION_TESTS is not used anywhere in the codebase, and the repo’s documented/CI path runs integration tests via the CLI command (go run main.go integration-tests / ./wallet-backend integration-tests). Update this section to match the supported command and remove the unused env var to avoid misleading contributors.
| ENABLE_INTEGRATION_TESTS=true go test -v ./internal/integrationtests/... -timeout 30m | |
| go run main.go integration-tests |
| | Variable | Value for local dev | | ||
| | -------------------- | ------------------------------------------------------------------- | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | |
There was a problem hiding this comment.
This second environment-variable table also starts rows with || (double pipes), which produces an extra empty column in Markdown rendering. Use single | delimiters for the table.
| but `NETWORK` must still be set for Docker Compose as well (it is referenced as | ||
| `${NETWORK}` with no default). If running `go run main.go` directly on the host, | ||
| add these to `.env` or export them in your shell: | ||
|
|
||
| | Variable | Value for local dev | | ||
| | -------------------- | ---------------------------------------------------------------------- | | ||
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | ||
| | `NETWORK` | `testnet` (recommended for dev) or `pubnet` | | ||
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | ||
| | `RPC_URL` | `http://localhost:8000` for host-side `go run`. Do **not** set this in `.env` for containerized services; inside Docker they use `http://stellar-rpc:8000`. | |
There was a problem hiding this comment.
The docs list extra env vars needed beyond .env.example, but they omit STELLAR_ENVIRONMENT. This value is required by the CLI config (see cmd/utils/global_options.go where stellar-environment is Required: true) and docker-compose.yaml passes it through as ${STELLAR_ENVIRONMENT} with no default. Add STELLAR_ENVIRONMENT (e.g., development for local dev) to the required/extra variables to prevent startup failures.
| but `NETWORK` must still be set for Docker Compose as well (it is referenced as | |
| `${NETWORK}` with no default). If running `go run main.go` directly on the host, | |
| add these to `.env` or export them in your shell: | |
| | Variable | Value for local dev | | |
| | -------------------- | ---------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended for dev) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| | `RPC_URL` | `http://localhost:8000` for host-side `go run`. Do **not** set this in `.env` for containerized services; inside Docker they use `http://stellar-rpc:8000`. | | |
| but `NETWORK` and `STELLAR_ENVIRONMENT` must still be set for Docker Compose as | |
| well (they are referenced as `${NETWORK}` and `${STELLAR_ENVIRONMENT}` with no | |
| default). If running `go run main.go` directly on the host, add these to `.env` | |
| or export them in your shell: | |
| | Variable | Value for local dev | | |
| | ----------------------- | ---------------------------------------------------------------------- | | |
| | `DATABASE_URL` | `postgres://postgres@localhost:5432/wallet-backend?sslmode=disable` | | |
| | `NETWORK` | `testnet` (recommended for dev) or `pubnet` | | |
| | `NETWORK_PASSPHRASE` | `Test SDF Network ; September 2015` (testnet) | | |
| | `STELLAR_ENVIRONMENT` | `development` | | |
| | `RPC_URL` | `http://localhost:8000` for host-side `go run`. Do **not** set this in `.env` for containerized services; inside Docker they use `http://stellar-rpc:8000`. | |
Use a more human-readable filename and update references in CONTRIBUTING.md.
Skill Eval:
wallet-backend-dev-setup— Benchmark ReportDate: 2026-04-08
Iterations: 4
Repo: stellar/wallet-backend
Model: Claude Opus 4.6
Prompt: "I just cloned wallet-backend and want to run it locally."
Summary
The gap is smaller than other repos because Go project conventions (
go.mod,Makefile,docker-compose.yaml) make the baseline more self-sufficient.Assertion Results (aggregated across 4 iterations)
Analysis
The skill's main value is documenting the extra env vars needed for local Go
binary dev (
DATABASE_URL,NETWORK,NETWORK_PASSPHRASE,RPC_URL) thatare set automatically by Docker Compose but missing from
.env.example. Thebaseline found these only 25% of the time.