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
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.env
.git
.DS_Store
target
web/node_modules
web/dist
web/.env
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DB=lending-indexer
POSTGRES_PORT=5432
DATABASE_URL=postgresql://postgres:password@postgres:5432/lending-indexer
WEB_PORT=80

# Build-time variables for web image
VITE_API_URL=http://localhost/api
VITE_ESPLORA_BASE_URL=https://blockstream.info/liquidtestnet/api
VITE_ESPLORA_EXPLORER_URL=https://blockstream.info/liquidtestnet
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,24 @@ In case the Borrower fails to pay interest before the lending contract expiry, t

## How to use

### Through Docker

From repo root:

```bash
docker compose up --build
```


### Locally (without Docker)

To run the **demo frontend** (web app for borrowers and lenders), you need the **Indexer** API running. The web app talks to it to list and manage offers.

**Quick start (from repo root):**

1. **Indexer** — set up PostgreSQL, configure `crates/indexer` (see [crates/indexer/README.md](crates/indexer/README.md)), then:
```bash
cd creates/indexer && cargo run -p lending-indexer
cd crates/indexer && cargo run -p lending-indexer
```
By default this starts the API (port 8000). For full indexing you also need the indexer worker (`RUN_MODE=indexer`).

Expand Down
37 changes: 37 additions & 0 deletions crates/indexer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
FROM rust:1.90-bookworm AS builder

RUN apt-get update && apt-get install -y --no-install-recommends pkg-config libssl-dev && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY Cargo.toml Cargo.lock ./
COPY .sqlx ./.sqlx
COPY crates ./crates

RUN SQLX_OFFLINE=true cargo build --locked --release -p lending-indexer --bin simplicity-lending-indexer

FROM builder AS sqlx-builder
RUN cargo install --locked sqlx-cli --no-default-features --features rustls,postgres

FROM debian:bookworm-slim AS runtime

RUN apt-get update && apt-get install -y --no-install-recommends bash ca-certificates libssl3 nodejs npm && rm -rf /var/lib/apt/lists/*
RUN npm install --global --no-fund --no-update-notifier bunyan
RUN useradd --system --create-home --uid 10001 appuser

WORKDIR /app
COPY --from=builder /app/target/release/simplicity-lending-indexer /usr/local/bin/simplicity-lending-indexer
COPY crates/indexer/configuration/ configuration/

USER appuser
CMD ["bash", "-o", "pipefail", "-c", "simplicity-lending-indexer 2>&1 | bunyan"]

FROM debian:bookworm-slim AS migrate

RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates libssl3 && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=sqlx-builder /usr/local/cargo/bin/sqlx /usr/local/bin/sqlx
COPY crates/indexer/migrations/ migrations/

CMD ["sqlx", "migrate", "run"]
2 changes: 1 addition & 1 deletion crates/indexer/configuration/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ esplora:
timeout: 10
indexer:
interval: 10000
last_indexed_height: 2309541
last_indexed_height: 2360000
4 changes: 3 additions & 1 deletion crates/indexer/configuration/production.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
application:
host: 0.0.0.0
host: 0.0.0.0
database:
host: postgres
2 changes: 2 additions & 0 deletions crates/indexer/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub fn get_configuration() -> Result<Settings, config::ConfigError> {
.add_source(config::File::from(
configuration_directory.join(environment_filename),
))
// Environment variables override file-based configuration
.add_source(config::Environment::default().separator("__"))
.build()?;

settings.try_deserialize::<Settings>()
Expand Down
89 changes: 89 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
env_file:
- .env
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 5

migrate:
build:
context: .
dockerfile: crates/indexer/Dockerfile
target: migrate
restart: "no"
env_file:
- .env
command: ["sqlx", "migrate", "run"]
depends_on:
postgres:
condition: service_healthy

api:
build:
context: .
dockerfile: crates/indexer/Dockerfile
target: runtime
env_file:
- .env
environment:
APP_ENVIRONMENT: production
RUN_MODE: api
DATABASE__HOST: postgres
DATABASE__PORT: ${POSTGRES_PORT}
DATABASE__USERNAME: ${POSTGRES_USER}
DATABASE__PASSWORD: ${POSTGRES_PASSWORD}
DATABASE__DATABASE_NAME: ${POSTGRES_DB}
depends_on:
migrate:
condition: service_completed_successfully
expose:
- 8000

indexer:
build:
context: .
dockerfile: crates/indexer/Dockerfile
target: runtime
restart: unless-stopped
env_file:
- .env
environment:
APP_ENVIRONMENT: production
RUN_MODE: indexer
DATABASE__HOST: postgres
DATABASE__PORT: ${POSTGRES_PORT}
DATABASE__USERNAME: ${POSTGRES_USER}
DATABASE__PASSWORD: ${POSTGRES_PASSWORD}
DATABASE__DATABASE_NAME: ${POSTGRES_DB}
depends_on:
migrate:
condition: service_completed_successfully

web:
build:
context: .
dockerfile: web/Dockerfile
args:
VITE_API_URL: ${VITE_API_URL}
VITE_ESPLORA_BASE_URL: ${VITE_ESPLORA_BASE_URL}
VITE_ESPLORA_EXPLORER_URL: ${VITE_ESPLORA_EXPLORER_URL}
restart: unless-stopped
ports:
- '${WEB_PORT}:80'
depends_on:
api:
condition: service_started

volumes:
postgres_data:
46 changes: 46 additions & 0 deletions nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
events {}

http {
include /etc/nginx/mime.types;

server {
listen 80;
server_name _;

root /usr/share/nginx/html;
index index.html;

location = /api {
return 308 /api/;
}

location /api/ {
proxy_pass http://api:8000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location = /esplora {
return 308 /esplora/;
}

location /esplora/ {
proxy_pass https://blockstream.info/liquidtestnet/api/;
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_redirect off;
}

location = /runtime-config.js {
add_header Cache-Control "no-store";
try_files /runtime-config.js =404;
}

location / {
try_files $uri $uri/ /index.html;
}
}
}
44 changes: 44 additions & 0 deletions web/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
FROM rust:1.90-bookworm AS lwk-builder

ARG LWK_REF=wasm_0.15.0
ARG LWK_COMMIT=5b015d6548a2e5ce60c5fcaae449248447e4c02d

RUN apt-get update && apt-get install -y --no-install-recommends git pkg-config libssl-dev ca-certificates clang && rm -rf /var/lib/apt/lists/*
RUN rustup target add wasm32-unknown-unknown
RUN cargo install wasm-pack --locked
RUN git clone --depth 1 --branch "${LWK_REF}" https://github.com/Blockstream/lwk.git /tmp/lwk
RUN test "$(git -C /tmp/lwk rev-parse HEAD)" = "${LWK_COMMIT}"
WORKDIR /tmp/lwk/lwk_wasm
RUN RUSTFLAGS='--cfg web_sys_unstable_apis' wasm-pack build --target web --out-dir pkg_web --features simplicity,serial

FROM node:24-alpine AS builder

WORKDIR /app

COPY --from=lwk-builder /tmp/lwk/lwk_wasm/pkg_web /app/lwk_wasm/pkg_web

COPY web/package.json web/package-lock.json ./web/
WORKDIR /app/web
RUN npm install --no-audit --no-fund

# Copy application sources
WORKDIR /app
COPY web ./web
COPY crates/contracts/src ./crates/contracts/src

WORKDIR /app/web
ARG VITE_API_URL
ARG VITE_ESPLORA_BASE_URL
ARG VITE_ESPLORA_EXPLORER_URL
ENV VITE_API_URL=$VITE_API_URL
ENV VITE_ESPLORA_BASE_URL=$VITE_ESPLORA_BASE_URL
ENV VITE_ESPLORA_EXPLORER_URL=$VITE_ESPLORA_EXPLORER_URL
RUN npm run build

FROM nginx:1.27-alpine AS runtime

COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /app/web/dist /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
16 changes: 3 additions & 13 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"test:watch": "vitest"
},
"dependencies": {
"lwk_web": "file:../../../Blockstream/lwk/lwk_wasm/pkg_web",
"lwk_web": "file:../lwk_wasm/pkg_web",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
Expand Down
Loading