Skip to content

Commit

Permalink
feat: lmax connector service (#239)
Browse files Browse the repository at this point in the history
* feat: lmax connector first draft

* fix: config and shutdown

* feat: working connection!

* Update README.md

* fix: send request

* fix: kinda works

* fix: receiving snapshots

* fix: field error

* fix: publishing works!

* fix: linter

* fix: lint

* ♻️ streamline admin message handling

* 🔧 update quickfix dependency to quickfix-py

* 📝 update README with Docker usage instructions

* ✨ add Dockerfile for lmax-connector setup

* 🚀 add lmax-connector to Docker build and test workflows

* 🐛 reconfigure Stunnel to work as Entry Point

* 🚀 add g++, libssl-dev, and swig to lmax-connector Dockerfile

* 🚀 add pkg-config to lmax-connector Dockerfile

* ✨ add Infra configuration for lmax-connector

* ♻️ fix formatting & linting issue

* 🐛 fix Stunnel execution in entrypoint and Dockerfile

* 🚀 install stunnel4 in Dockerfile and update entrypoint script execution

* ✨ update lmax-connector Dockerfile to include stunnel and add Fix44 configuration file

* ♻️ remove unused Fix44 configuration file from Dockerfile

* ✨ add Fix44 configuration file to lmax-connector Dockerfile

* ♻️ correct case of Fix44 configuration file path in Dockerfile

---------

Co-authored-by: Yasser Tahiri <yasserth19@gmail.com>
  • Loading branch information
EvolveArt and yezz123 authored Jan 15, 2025
1 parent ae63782 commit 923e145
Show file tree
Hide file tree
Showing 19 changed files with 2,179 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
package:
[pragma-sdk, price-pusher, vrf-listener, checkpointer, merkle-maker]
[pragma-sdk, price-pusher, vrf-listener, checkpointer, merkle-maker, lmax-connector]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
build_containers:
strategy:
matrix:
package: [pragma-sdk, price-pusher, vrf-listener, checkpointer]
package: [pragma-sdk, price-pusher, vrf-listener, checkpointer, lmax-connector]
runs-on: ubuntu-latest
permissions:
checks: write
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ devnet.pkl

# Mac
.DS_STORE

# Lmax connector metadata
lmax-connector/log/
lmax-connector/store/
lmax-connector/config/fix_settings.cfg
43 changes: 43 additions & 0 deletions infra/lmax-connector/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
FROM python:3.12-slim AS base

ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100

ENV PATH="/root/.local/bin:${PATH}"

FROM base as builder

RUN apt-get update && \
apt-get install --no-install-recommends -y \
gcc \
g++ \
libssl-dev \
swig \
libgmp3-dev \
pkg-config \
pipx \
stunnel4

RUN apt-get update && apt-get install -y bash curl && curl -1sLf \
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | bash \
&& apt-get update && apt-get install -y infisical

RUN pipx install uv
COPY pragma-sdk/ /opt/pragma-sdk/
COPY lmax-connector/ /opt/lmax-connector/
COPY lmax-connector/config/Fix44.xml /opt/lmax-connector/config/Fix44.xml
WORKDIR /opt/lmax-connector
RUN uv sync

FROM base as final

COPY --from=builder /usr/bin/infisical /usr/bin/infisical
COPY --from=builder /usr/bin/stunnel /usr/bin/stunnel
COPY --from=builder /usr/lib /usr/lib
COPY --from=builder /opt /opt
COPY infra/lmax-connector/entrypoint.sh /opt/lmax-connector/
WORKDIR /opt/lmax-connector
ENTRYPOINT ["bash","/opt/lmax-connector/entrypoint.sh"]
29 changes: 29 additions & 0 deletions infra/lmax-connector/buildspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws --version
- aws ecr get-login-password --region $ECR_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$ECR_REGION.amazonaws.com
- REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$ECR_REGION.amazonaws.com/$ECR_REPOSITORY_NAME
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- ls -ltr
- docker build -f infra/lmax-connector/Dockerfile -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- echo Writing image definitions file...
- printf '[{"name":"%s","imageUri":"%s"}]' $ECS_CONTAINER_NAME $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
- infra/lmax-connector/config.yml
discard-paths: yes
9 changes: 9 additions & 0 deletions infra/lmax-connector/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
path: "/"
container_port: 8080
health_check_path: "/"
container_environment:
- region: "eu-west-3"
- prefix: "/conf/{{ SERVICE_NAME }}/{{ RUN_ENV }}"
- keys:
- INFISICAL_ENV
- INFISICAL_APP_PATH
15 changes: 15 additions & 0 deletions infra/lmax-connector/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

set -euo pipefail

export INFISICAL_TOKEN=$(infisical login --method=universal-auth --client-id=${INFISICAL_CLIENT_ID} --client-secret=${INFISICAL_CLIENT_SECRET} --silent --plain)
infisical export --projectId=${INFISICAL_PROJECT_ID} --env=${INFISICAL_ENV} --path=${INFISICAL_APP_PATH} > .env
source .env

# Execute Stunnel
/usr/bin/stunnel stunnel.conf &

sleep 5

# Execute LMAX Connector
exec /opt/lmax-connector/.venv/bin/python3.12 -m lmax_connector
13 changes: 13 additions & 0 deletions lmax-connector/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# LMAX FIX Connection Settings
LMAX_SENDER_COMP_ID=your_sender_id
LMAX_TARGET_COMP_ID=LMXBLM
LMAX_HOST=fix-md.lmaxtrader.com
LMAX_PORT=443
LMAX_PASSWORD=your_fix_password

# Pragma API Settings
PRAGMA_API_KEY=your_api_key
PRAGMA_PUBLISHER_ID=your_publisher_id
PRAGMA_API_BASE_URL=https://api.dev.pragma.build
PRAGMA_ACCOUNT_PRIVATE_KEY=your_account_private_key
PRAGMA_ACCOUNT_CONTRACT_ADDRESS=your_account_contract_address
47 changes: 47 additions & 0 deletions lmax-connector/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
FROM python:3.12-slim AS base

ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100

ENV PATH="/root/.local/bin:${PATH}"

FROM base AS builder

RUN apt-get update && \
apt-get install --no-install-recommends -y \
gcc \
g++ \
libssl-dev \
swig \
libgmp3-dev \
pkg-config \
pipx \
stunnel4

RUN pipx install uv
COPY pragma-sdk/ /opt/pragma-sdk/
COPY lmax-connector/ /opt/lmax-connector/
WORKDIR /opt/lmax-connector
RUN uv sync

FROM base AS final
RUN apt-get update && \
apt-get install --no-install-recommends -y stunnel4 && \
rm -rf /var/lib/apt/lists/*

COPY --from=builder /opt /opt
VOLUME /opt/lmax-connector/config/

WORKDIR /opt/lmax-connector

# Create startup script
RUN echo '#!/bin/bash\n\
exec /usr/bin/stunnel stunnel.conf &\n\
sleep 2\n\
exec /opt/lmax-connector/.venv/bin/python3.12 -m lmax_connector' > /start.sh && \
chmod +x /start.sh

ENTRYPOINT ["/start.sh"]
105 changes: 105 additions & 0 deletions lmax-connector/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# LMAX Connector

A service that connects to LMAX Exchange via FIX 4.4 protocol and pushes EUR/USD market data to Pragma.

## Prerequisites

- Python 3.11+
- stunnel (for SSL/TLS connection to LMAX)
- LMAX Exchange account credentials
- uv for dependency management

## Installation

1. Install stunnel:

```bash
# macOS
brew install stunnel

# Ubuntu/Debian
apt-get install stunnel4
```

2. Install the package:

```bash
uv sync
```

## Configuration

1. Copy `.env.example` to `.env` and fill in your credentials:

```bash
cp .env.example .env
```

2. Configure stunnel by modifying `stunnel.conf`:

```ini
; Stunnel configuration for LMAX FIX connection
debug = 7
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
fips = no

[Production-MarketData]
client = yes
accept = 127.0.0.1:40003
connect = fix-md.lmaxtrader.com:443
sslVersion = TLSv1.2
verify = 0
delay = no
TIMEOUTclose = 0
```

## Running the Service

1. Start stunnel:

```bash
cd lmax-connector
stunnel stunnel.conf
```

2. Then, start the connector:

```bash
python -m lmax_connector
```

The service will:

1. Connect to LMAX via FIX 4.4 protocol
2. Subscribe to EUR/USD market data
3. Push prices to Pragma API

## Environment Variables

- `LMAX_SENDER_COMP_ID`: Your LMAX username
- `LMAX_TARGET_COMP_ID`: LMXBLM (for production)
- `LMAX_PASSWORD`: Your LMAX password
- `PRAGMA_API_KEY`: Your Pragma API key
- `PRAGMA_ACCOUNT_PRIVATE_KEY`: Your Pragma account private key
- `PRAGMA_ACCOUNT_CONTRACT_ADDRESS`: Your Pragma account contract address

## Using Docker

1. Build the Docker image:

```bash
ddocker build -t lmax-connector:latest -f lmax-connector/Dockerfile .
```

2. Run the Docker container:

```bash
docker run -v ./config:/opt/lmax-connector/config --env-file .env lmax-connector
```

## Troubleshooting

1. If you see SSL/TLS connection errors, make sure stunnel is running and the configuration is correct.
2. If you see authentication errors, verify your LMAX credentials in the `.env` file.
3. Check the logs in `log/` directory for detailed error messages.
Loading

0 comments on commit 923e145

Please sign in to comment.