Skip to content
Open
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
1,054 changes: 527 additions & 527 deletions .env.example

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Normalise line endings in text artifacts so tooling that byte-compares them
# does not depend on a contributor's git config. In particular,
# tests/openapi.test.ts compares openapi.json byte-for-byte, which fails on
# Windows with core.autocrlf=true unless the checkout is forced to LF.
*.json text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
# tests/historical.golden.test.ts byte-compares these against the CSV export.
*.csv text eol=lf
# src/__tests__/graphqlSchemaDrift.test.ts byte-compares schema.graphql against
# `printSchema()` output, which is always LF. Without this a Windows checkout
# gets CRLF and the drift guard fails on a file that has not drifted at all.
*.graphql text eol=lf
# prisma/migrations/*/migration.sql is compared against `prisma migrate diff`
# output (tests/prisma-migrations.test.ts), which is always LF. The comparison
# normalises trailing whitespace so CRLF would survive it today — pinned anyway,
# because the file is a generated artifact and the four guards above all learned
# this the hard way.
*.sql text eol=lf
# Normalise line endings in text artifacts so tooling that byte-compares them
# does not depend on a contributor's git config. In particular,
# tests/openapi.test.ts compares openapi.json byte-for-byte, which fails on
# Windows with core.autocrlf=true unless the checkout is forced to LF.
*.json text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
# tests/historical.golden.test.ts byte-compares these against the CSV export.
*.csv text eol=lf
# src/__tests__/graphqlSchemaDrift.test.ts byte-compares schema.graphql against
# `printSchema()` output, which is always LF. Without this a Windows checkout
# gets CRLF and the drift guard fails on a file that has not drifted at all.
*.graphql text eol=lf
# prisma/migrations/*/migration.sql is compared against `prisma migrate diff`
# output (tests/prisma-migrations.test.ts), which is always LF. The comparison
# normalises trailing whitespace so CRLF would survive it today — pinned anyway,
# because the file is a generated artifact and the four guards above all learned
# this the hard way.
*.sql text eol=lf
16 changes: 8 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
node_modules/
dist/
.env
*.tsbuildinfo

# Soroban build artifacts for the SEP-40 oracle contract (oracle/contract)
oracle/contract/target/
oracle/contract/test_snapshots/
node_modules/
dist/
*.tsbuildinfo
# Soroban build artifacts for the SEP-40 oracle contract (oracle/contract)
oracle/contract/target/
oracle/contract/test_snapshots/
config.bat
240 changes: 120 additions & 120 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,120 +1,120 @@
# Contributing to Lens

Lens is a unified Stellar price oracle aggregating SDEX and AMM prices, gated behind x402 micropayments. Contributions welcome — docs, tests, new endpoints, ingestion improvements.

## Ways to contribute

- **Good first issues** — [`good first issue`](https://github.com/Miracle656/Lens/labels/good%20first%20issue)
- **Bug reports** — use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md)
- **Feature requests** — use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.md)
- **Tests** — see [`area:tests`](https://github.com/Miracle656/Lens/labels/area%3Atests)

## Repository layout

```
lens/
├── src/
│ ├── index.ts # Fastify entry point
│ ├── config.ts # Per-network config (STELLAR_NETWORK + overrides)
│ ├── db.ts # Postgres pool / Prisma client
│ ├── api/ # REST + GraphQL route implementations
│ ├── routes/ # Additional REST route modules
│ ├── ingesters/ # SDEX + AMM ingester loops
│ ├── ingest/ # Venue/oracle adapters (Horizon AMM, Aquarius, Reflector)
│ ├── publish/ # SEP-40 publisher: encoding, publication policy, on-chain feed
│ ├── aggregator/ # VWAP + best-route calculation
│ ├── pricing/ # TWAP, depth and aggregate helpers
│ ├── middleware/ # Network selector, x402, auth, metrics
│ └── x402/ # x402 facilitator client + metering
├── oracle/
│ └── contract/ # Soroban SEP-40 price feed contract (Rust, `cargo test --lib`)
├── prisma/
│ └── schema.prisma # Network-discriminated data models
├── tests/ # Integration, load and property suites
└── docs/ # Architecture, ops and design docs
```

## Development setup

### Prerequisites
- **Node.js 20+**
- **PostgreSQL** (local or Supabase)
- **Redis** (optional — for BullMQ workers)
- A Stellar testnet account for x402 payments (if testing paid endpoints)

### Clone and install

```bash
git clone https://github.com/Miracle656/Lens.git
cd Lens
npm install
cp .env.example .env # fill in DATABASE_URL, REDIS_URL, WATCHED_PAIRS
npm run db:migrate # apply committed migrations (prisma migrate dev) — do NOT `db push`
npm run dev
```

API runs on `http://localhost:3002`.

### Environment variables
- `DATABASE_URL` — Postgres connection string (Supabase or local)
- `REDIS_URL` — optional, enables aggregate refresh worker
- `WATCHED_PAIRS` — comma-separated `CODE:ISSUER/CODE:ISSUER` (e.g. `XLM:native/USDC:GBBD...`)
- `STELLAR_NETWORK` — this instance's default network, `testnet` or `mainnet` (default: `testnet`)
- `ENABLED_NETWORKS` — optional, comma-separated networks to ingest (`testnet,mainnet`); falls back to `STELLAR_NETWORK`

Per-network overrides use a `_TESTNET` / `_MAINNET` suffix (e.g. `HORIZON_URL_MAINNET`, `WATCHED_PAIRS_TESTNET`); see `.env.example` for the full list.

## Commit conventions

- `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `chore:`
- Keep PRs focused

## Before opening a PR

```bash
npx prisma generate
npx tsc --noEmit
npm run build
npm test --if-present
```

## Testing

Tests run under [Vitest](https://vitest.dev):

```bash
npm test # full suite (vitest run)
npx vitest run path/to/file.test.ts # a single file
```

The suite is ~53 files / ~520 tests covering route handlers, price math
(including property-based tests with [fast-check](https://fast-check.dev)),
the x402 flow, per-network config and ingesters, HTTP metrics, and integration
scenarios under `tests/`. Open test work is tracked under
[`area:tests`](https://github.com/Miracle656/Lens/labels/area%3Atests).

## Releases

Lens uses [changesets](https://github.com/changesets/changesets) for versioning and changelog generation.

### Adding a changeset

When you make a change that should appear in the changelog (a feature, fix, or any user-facing change), add a changeset in the same PR:

```bash
npx changeset
```

Pick the bump type (`patch` / `minor` / `major`) and write a short summary. This creates a markdown file under `.changeset/` — commit it alongside your change.

### How a release happens

1. When PRs with changesets are merged into `main`, the release workflow (`.github/workflows/release.yml`) opens (or updates) a **"Version Packages"** PR.
2. That PR consumes the pending changeset files, bumps the version in `package.json`, and updates `CHANGELOG.md`.
3. Merging the Version Packages PR bumps the version and creates a matching git tag and GitHub release.

Lens is not published to a registry, so there is no publish step — releases are tag-only (`changeset tag`).

## Questions

Open an [issue](https://github.com/Miracle656/Lens/issues) or start a [discussion](https://github.com/Miracle656/Lens/discussions).
# Contributing to Lens
Lens is a unified Stellar price oracle aggregating SDEX and AMM prices, gated behind x402 micropayments. Contributions welcome — docs, tests, new endpoints, ingestion improvements.
## Ways to contribute
- **Good first issues** — [`good first issue`](https://github.com/Miracle656/Lens/labels/good%20first%20issue)
- **Bug reports** — use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md)
- **Feature requests** — use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.md)
- **Tests** — see [`area:tests`](https://github.com/Miracle656/Lens/labels/area%3Atests)
## Repository layout
```
lens/
├── src/
│ ├── index.ts # Fastify entry point
│ ├── config.ts # Per-network config (STELLAR_NETWORK + overrides)
│ ├── db.ts # Postgres pool / Prisma client
│ ├── api/ # REST + GraphQL route implementations
│ ├── routes/ # Additional REST route modules
│ ├── ingesters/ # SDEX + AMM ingester loops
│ ├── ingest/ # Venue/oracle adapters (Horizon AMM, Aquarius, Reflector)
│ ├── publish/ # SEP-40 publisher: encoding, publication policy, on-chain feed
│ ├── aggregator/ # VWAP + best-route calculation
│ ├── pricing/ # TWAP, depth and aggregate helpers
│ ├── middleware/ # Network selector, x402, auth, metrics
│ └── x402/ # x402 facilitator client + metering
├── oracle/
│ └── contract/ # Soroban SEP-40 price feed contract (Rust, `cargo test --lib`)
├── prisma/
│ └── schema.prisma # Network-discriminated data models
├── tests/ # Integration, load and property suites
└── docs/ # Architecture, ops and design docs
```
## Development setup
### Prerequisites
- **Node.js 20+**
- **PostgreSQL** (local or Supabase)
- **Redis** (optional — for BullMQ workers)
- A Stellar testnet account for x402 payments (if testing paid endpoints)
### Clone and install
```bash
git clone https://github.com/Miracle656/Lens.git
cd Lens
npm install
cp .env.example .env # fill in DATABASE_URL, REDIS_URL, WATCHED_PAIRS
npm run db:migrate # apply committed migrations (prisma migrate dev) — do NOT `db push`
npm run dev
```
API runs on `http://localhost:3002`.
### Environment variables
- `DATABASE_URL` — Postgres connection string (Supabase or local)
- `REDIS_URL` — optional, enables aggregate refresh worker
- `WATCHED_PAIRS` — comma-separated `CODE:ISSUER/CODE:ISSUER` (e.g. `XLM:native/USDC:GBBD...`)
- `STELLAR_NETWORK` — this instance's default network, `testnet` or `mainnet` (default: `testnet`)
- `ENABLED_NETWORKS` — optional, comma-separated networks to ingest (`testnet,mainnet`); falls back to `STELLAR_NETWORK`
Per-network overrides use a `_TESTNET` / `_MAINNET` suffix (e.g. `HORIZON_URL_MAINNET`, `WATCHED_PAIRS_TESTNET`); see `.env.example` for the full list.
## Commit conventions
- `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `chore:`
- Keep PRs focused
## Before opening a PR
```bash
npx prisma generate
npx tsc --noEmit
npm run build
npm test --if-present
```
## Testing
Tests run under [Vitest](https://vitest.dev):
```bash
npm test # full suite (vitest run)
npx vitest run path/to/file.test.ts # a single file
```
The suite is ~53 files / ~520 tests covering route handlers, price math
(including property-based tests with [fast-check](https://fast-check.dev)),
the x402 flow, per-network config and ingesters, HTTP metrics, and integration
scenarios under `tests/`. Open test work is tracked under
[`area:tests`](https://github.com/Miracle656/Lens/labels/area%3Atests).
## Releases
Lens uses [changesets](https://github.com/changesets/changesets) for versioning and changelog generation.
### Adding a changeset
When you make a change that should appear in the changelog (a feature, fix, or any user-facing change), add a changeset in the same PR:
```bash
npx changeset
```
Pick the bump type (`patch` / `minor` / `major`) and write a short summary. This creates a markdown file under `.changeset/` — commit it alongside your change.
### How a release happens
1. When PRs with changesets are merged into `main`, the release workflow (`.github/workflows/release.yml`) opens (or updates) a **"Version Packages"** PR.
2. That PR consumes the pending changeset files, bumps the version in `package.json`, and updates `CHANGELOG.md`.
3. Merging the Version Packages PR bumps the version and creates a matching git tag and GitHub release.
Lens is not published to a registry, so there is no publish step — releases are tag-only (`changeset tag`).
## Questions
Open an [issue](https://github.com/Miracle656/Lens/issues) or start a [discussion](https://github.com/Miracle656/Lens/discussions).
88 changes: 44 additions & 44 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
# Stage 1: Build
FROM node:20-slim AS builder

WORKDIR /app

# Install dependencies
COPY package*.json ./
COPY prisma ./prisma/
RUN npm install

# Copy source and build
COPY . .
RUN npm run build

# Stage 2: Run
FROM node:20-slim

WORKDIR /app

# Install curl for healthcheck
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*

# Copy production dependencies
COPY package*.json ./
COPY prisma ./prisma/
RUN npm install --omit=dev

# Copy built assets
COPY --from=builder /app/dist ./dist
# Prisma engine and generated client are needed
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
# Need prisma for the auto-migration in src/index.ts
COPY --from=builder /app/node_modules/prisma ./node_modules/prisma

# Set environment variables
ENV NODE_ENV=production
ENV PORT=3002
ENV HOST=0.0.0.0

EXPOSE 3002

# Startup script ensures DB is ready (handled in src/index.ts via execSync)
CMD ["npm", "start"]
# Stage 1: Build
FROM node:20-slim AS builder
WORKDIR /app
# Install dependencies
COPY package*.json ./
COPY prisma ./prisma/
RUN npm install
# Copy source and build
COPY . .
RUN npm run build
# Stage 2: Run
FROM node:20-slim
WORKDIR /app
# Install curl for healthcheck
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
# Copy production dependencies
COPY package*.json ./
COPY prisma ./prisma/
RUN npm install --omit=dev
# Copy built assets
COPY --from=builder /app/dist ./dist
# Prisma engine and generated client are needed
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
# Need prisma for the auto-migration in src/index.ts
COPY --from=builder /app/node_modules/prisma ./node_modules/prisma
# Set environment variables
ENV NODE_ENV=production
ENV PORT=3002
ENV HOST=0.0.0.0
EXPOSE 3002
# Startup script ensures DB is ready (handled in src/index.ts via execSync)
CMD ["npm", "start"]
Loading
Loading