diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0c45654 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,27 @@ +.git +.gitignore +README.md +docs/ +*.md +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +env +pip-log.txt +pip-delete-this-directory.txt +.tox +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.log +.idea +.vscode +.env +errors.db +cache/ +test_e2e.py \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7ab5e77 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.11-slim + +WORKDIR /app + +COPY . . + +RUN pip install --upgrade pip && pip install . + +RUN mkdir -p /app/cache + +CMD ["python", "-m", "main"] diff --git a/pyproject.toml b/pyproject.toml index dcb87f8..1846520 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,9 @@ dependencies = [ "diskcache==5.6.0", ] +[tool.setuptools] +py-modules = ["main", "router", "providers", "errors", "cache", "http_proxy", "ws_proxy", "normalizer", "cache_policy"] + [project.optional-dependencies] test = [ "pytest>=7.0.0", @@ -22,4 +25,4 @@ test = [ ] [project.scripts] -solana-proxy = "main:main" \ No newline at end of file +solana-proxy = "main:main" diff --git a/stack/README.md b/stack/README.md new file mode 100644 index 0000000..e299ca6 --- /dev/null +++ b/stack/README.md @@ -0,0 +1,3 @@ +# solana-proxy-stack + +[solana-proxy stack documentation](./stack-orchestrator/stack/solana-proxy/README.md) diff --git a/stack/stack-orchestrator/compose/docker-compose-solana-proxy.yml b/stack/stack-orchestrator/compose/docker-compose-solana-proxy.yml new file mode 100644 index 0000000..78c2dbf --- /dev/null +++ b/stack/stack-orchestrator/compose/docker-compose-solana-proxy.yml @@ -0,0 +1,32 @@ +services: + # Builds and serves the solana proxy + solana-proxy: + restart: unless-stopped + image: cerc/solana-proxy:local + environment: + # Provider endpoints and auth (optional) + ALCHEMY_API_KEY: ${ALCHEMY_API_KEY} + HELIUS_API_KEY: ${HELIUS_API_KEY} + QUICKNODE_ENDPOINT: ${QUICKNODE_ENDPOINT} + QUICKNODE_TOKEN: ${QUICKNODE_TOKEN} + + # Proxy settings + CACHE_SIZE_GB: 1 + BACKOFF_MINUTES: 30 + + # Logging + LOG_LEVEL: ${LOG_LEVEL:-INFO} + ERROR_DB_PATH: /app/errors.db + command: ["solana-proxy"] + volumes: + - solana-proxy-data:/app + ports: + - "8545" + healthcheck: + test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8545').read()"] + interval: 30s + timeout: 10s + retries: 3 + +volumes: + solana-proxy-data: diff --git a/stack/stack-orchestrator/container-build/cerc-solana-proxy/build.sh b/stack/stack-orchestrator/container-build/cerc-solana-proxy/build.sh new file mode 100755 index 0000000..35595b7 --- /dev/null +++ b/stack/stack-orchestrator/container-build/cerc-solana-proxy/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# Build cerc/solana-proxy +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh +docker build -t cerc/solana-proxy:local ${build_command_args} ${CERC_REPO_BASE_DIR}/solana-proxy diff --git a/stack/stack-orchestrator/stack/solana-proxy/README.md b/stack/stack-orchestrator/stack/solana-proxy/README.md new file mode 100644 index 0000000..d64f3a3 --- /dev/null +++ b/stack/stack-orchestrator/stack/solana-proxy/README.md @@ -0,0 +1,77 @@ +# solana-proxy + +Instructions for running the `solana-proxy` using [laconic-so](https://git.vdb.to/cerc-io/stack-orchestrator) + +## Setup + +* Clone the stack repo: + + ```bash + laconic-so fetch-stack git.vdb.to/LaconicNetwork/solana-proxy + ``` + +* Build the container image: + + ```bash + laconic-so --stack ~/cerc/solana-proxy/stack/stack-orchestrator/stack/solana-proxy build-containers + ``` + + This should create the `cerc/solana-proxy` image locally + +## Create a deployment + +* Create a spec file for the deployment: + + ```bash + laconic-so --stack ~/cerc/solana-proxy/stack/stack-orchestrator/stack/solana-proxy deploy init --output solana-proxy-spec.yml + ``` + +* Edit `network` in the spec file to map container ports to host ports as required: + + ```bash + network: + ports: + solana-proxy: + - '8545:8545' + ``` + +* Create a deployment from the spec file: + + ```bash + laconic-so --stack ~/cerc/solana-proxy/stack/stack-orchestrator/stack/solana-proxy deploy create --spec-file solana-proxy-spec.yml --deployment-dir solana-proxy-deployment + ``` + +## Configuration + +* Inside the `solana-proxy-deployment` deployment directory, open `config.env` file and set following env variables: + + ```bash + # Optional + ALCHEMY_API_KEY=your_alchemy_key_here + HELIUS_API_KEY=your_helius_key_here + QUICKNODE_ENDPOINT=your_endpoint.quiknode.pro + QUICKNODE_TOKEN=your_quicknode_token_here + LOG_LEVEL=INFO + ``` + + The proxy will work without API keys using free endpoints, but adding them provides access to premium providers with better rate limits. + +## Start the deployment + +```bash +laconic-so deployment --dir solana-proxy-deployment start +``` + +The Solana RPC proxy will be available at: + +* RPC endpoint: + +* WebSocket endpoint: + +## Clean up + +* Stop the deployment: + + ```bash + laconic-so deployment --dir solana-proxy-deployment stop + ``` diff --git a/stack/stack-orchestrator/stack/solana-proxy/stack.yml b/stack/stack-orchestrator/stack/solana-proxy/stack.yml new file mode 100644 index 0000000..51f4ce6 --- /dev/null +++ b/stack/stack-orchestrator/stack/solana-proxy/stack.yml @@ -0,0 +1,7 @@ +version: "1.0" +name: solana-proxy +description: "Solana proxy service" +containers: + - cerc/solana-proxy +pods: + - solana-proxy