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
22 changes: 22 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.git
.github
.agents
.codex

**/node_modules
**/dist
**/.astro
**/coverage
**/.daml
**/*.log

.env
**/.env
**/.env.local

website
docs
trading
trading-tests
vendor
scripts
34 changes: 33 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ jobs:
run: npm ci
- name: Typecheck
run: npm run typecheck
- name: Typecheck live driver sources (no Canton connection)
run: npm run typecheck:live-scripts
- name: Test
run: npm test

Expand All @@ -77,6 +79,12 @@ jobs:
run: npm test
- name: Build
run: npm run build
- name: Verify production bundle excludes development authority adapters
run: |
if grep -R -E '/v1/wallet/(submit|execute)|VITE_CANTON_AUTH_TOKEN|Direct Canton|Operator Relay' dist; then
echo "development-only wallet authority leaked into the production bundle" >&2
exit 1
fi

docs:
name: Documentation build
Expand All @@ -97,7 +105,7 @@ jobs:
run: npm run build

docker:
name: Docker build smoke
name: Container build + backend runtime smoke
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -108,6 +116,30 @@ jobs:
else
echo "Dockerfile.backend not present on this branch; skipping"
fi
- name: Runtime-smoke backend image
run: |
cid="$(docker run --rm -d -p 127.0.0.1:18082:8080 \
-e DEX_READ_ONLY=1 \
-e CANTON_LEDGER_URL=http://127.0.0.1:1 \
-e CANTON_LEDGER_TOKEN=ci-ledger-token \
-e CANTON_OPERATOR=Operator::ci \
-e CANTON_LP_REGISTRAR=LpRegistrar::ci \
-e CANTON_ADMIN=Admin::ci \
-e 'CANTON_DEX_PACKAGE_ID=#canton-dex-trading' \
canton-dex-backend:ci)"
trap 'docker rm -f "$cid" >/dev/null 2>&1 || true' EXIT
for _ in $(seq 1 30); do
if curl -fsS http://127.0.0.1:18082/v1/status > /tmp/dex-status.json; then
break
fi
sleep 1
done
grep -q '"synced":false' /tmp/dex-status.json
test "$(curl -sS -o /dev/null -w '%{http_code}' -X POST \
-H 'Content-Type: application/json' -d '{}' \
http://127.0.0.1:18082/v1/admin/pairs)" = 401
docker exec "$cid" node -e \
'if (process.getuid?.() === 0) throw new Error("backend runs as root"); const Database=require("better-sqlite3"); const db=new Database(":memory:"); db.exec("select 1"); db.close()'
- name: Build frontend image
run: |
if [ -f Dockerfile.frontend ]; then
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ builder evaluating Canton + Token Standard V2.
and explain any public contract-surface change.
- Backend changes: TypeScript typecheck clean; include a `curl` example
for any new endpoint in the PR description.
- UI changes: at minimum a screenshot of the affected page; if the
change touches data flow, also confirm against testnet.
- UI changes: at minimum a screenshot of the affected page. If the change
touches AMM data flow, run the self-contained DPM sandbox proof documented in
`docs/guides/localnet.md`; controlled-testnet validation is an additional
check when the contributor has access to such an environment.
- Avoid committing secrets, `.env` files, SQLite databases, private keys, or
generated build output. The Token Standard DARs already pinned under
`vendor/splice/dars/` are the intentional exception for binary dependencies.
Expand Down
24 changes: 16 additions & 8 deletions Dockerfile.backend
Original file line number Diff line number Diff line change
@@ -1,35 +1,43 @@
FROM node:20-alpine AS builder
FROM node:24-alpine AS builder

WORKDIR /app

COPY services/registry-client/package.json services/registry-client/
# better-sqlite3 is a native dependency. Prebuilt binaries are used when one
# exists for the current architecture; these tools provide the deterministic
# node-gyp fallback instead of silently skipping its install script.
RUN apk add --no-cache python3 make g++

COPY services/registry-client/package.json services/registry-client/package-lock.json services/registry-client/
COPY services/operator-backend/package.json services/operator-backend/package-lock.json services/operator-backend/

WORKDIR /app/services/registry-client
RUN npm install --ignore-scripts
RUN npm ci --ignore-scripts

WORKDIR /app/services/operator-backend
RUN npm install --ignore-scripts
RUN npm ci

COPY services/registry-client/ /app/services/registry-client/
COPY services/operator-backend/ /app/services/operator-backend/

RUN npx tsc --noEmit

FROM node:20-alpine
FROM node:24-alpine

WORKDIR /app

RUN mkdir -p /app/data
RUN mkdir -p /app/data && chown node:node /app/data

COPY --from=builder /app/services/registry-client /app/services/registry-client
COPY --from=builder /app/services/operator-backend /app/services/operator-backend
COPY --chown=node:node --from=builder /app/services/registry-client /app/services/registry-client
COPY --chown=node:node --from=builder /app/services/operator-backend /app/services/operator-backend

WORKDIR /app/services/operator-backend

ENV NODE_ENV=production
ENV PORT=8080
ENV HOST=0.0.0.0

EXPOSE 8080

USER node

CMD ["node", "--import", "tsx", "src/testnet-server.ts"]
46 changes: 44 additions & 2 deletions Dockerfile.frontend
Original file line number Diff line number Diff line change
@@ -1,11 +1,53 @@
FROM node:20-alpine AS builder
FROM node:24-alpine AS builder

WORKDIR /app

COPY app/web/package.json app/web/package-lock.json ./
RUN npm install --ignore-scripts
RUN npm ci --ignore-scripts

COPY app/web/ .

# Vite reads configuration at build time. Declare every supported safe/public
# build argument explicitly; Docker otherwise ignores Compose's `args:` values.
# A ledger bearer token is intentionally absent because VITE_* is public.
ARG VITE_API_BASE=
ARG VITE_DOCS_URL=https://srikanth-bitdynamics.github.io/Canton-Dex-Reference-Implementation/
ARG VITE_APP_VERSION=v0.6.0
ARG VITE_WC_PROJECT_ID=
ARG VITE_CANTON_NETWORK_ID=canton:devnet
ARG VITE_CANTON_SYNCHRONIZER=
ARG VITE_CANTON_DEX_PACKAGE_ID=#canton-dex-trading
ARG VITE_ENABLE_SDK=0
ARG VITE_WALLET_GATEWAY_URL=
ARG VITE_WALLET_GATEWAY_NAME=
ARG VITE_WALLET_SHOW_FULL_CATALOG=0
ARG VITE_ENABLE_PARTYLAYER=0
ARG VITE_ENABLE_HOSTED_RFQ=0
ARG VITE_PARTYLAYER_APP_NAME=Canton DEX
ARG VITE_PARTYLAYER_NETWORK=canton:devnet
ARG VITE_PARTYLAYER_WALLET_IDS=console,nightly,send
ARG VITE_PARTYLAYER_CONNECT_TIMEOUT_MS=180000
ARG VITE_PARTYLAYER_REGISTRY_URL=
ARG VITE_PARTYLAYER_REGISTRY_CHANNEL=stable
ENV VITE_API_BASE=$VITE_API_BASE \
VITE_DOCS_URL=$VITE_DOCS_URL \
VITE_APP_VERSION=$VITE_APP_VERSION \
VITE_WC_PROJECT_ID=$VITE_WC_PROJECT_ID \
VITE_CANTON_NETWORK_ID=$VITE_CANTON_NETWORK_ID \
VITE_CANTON_SYNCHRONIZER=$VITE_CANTON_SYNCHRONIZER \
VITE_CANTON_DEX_PACKAGE_ID=$VITE_CANTON_DEX_PACKAGE_ID \
VITE_ENABLE_SDK=$VITE_ENABLE_SDK \
VITE_WALLET_GATEWAY_URL=$VITE_WALLET_GATEWAY_URL \
VITE_WALLET_GATEWAY_NAME=$VITE_WALLET_GATEWAY_NAME \
VITE_WALLET_SHOW_FULL_CATALOG=$VITE_WALLET_SHOW_FULL_CATALOG \
VITE_ENABLE_PARTYLAYER=$VITE_ENABLE_PARTYLAYER \
VITE_ENABLE_HOSTED_RFQ=$VITE_ENABLE_HOSTED_RFQ \
VITE_PARTYLAYER_APP_NAME=$VITE_PARTYLAYER_APP_NAME \
VITE_PARTYLAYER_NETWORK=$VITE_PARTYLAYER_NETWORK \
VITE_PARTYLAYER_WALLET_IDS=$VITE_PARTYLAYER_WALLET_IDS \
VITE_PARTYLAYER_CONNECT_TIMEOUT_MS=$VITE_PARTYLAYER_CONNECT_TIMEOUT_MS \
VITE_PARTYLAYER_REGISTRY_URL=$VITE_PARTYLAYER_REGISTRY_URL \
VITE_PARTYLAYER_REGISTRY_CHANNEL=$VITE_PARTYLAYER_REGISTRY_CHANNEL
RUN npm run build

FROM nginx:1.27-alpine
Expand Down
Loading
Loading