Compare commits

..
Author SHA1 Message Date
roysc f8f5030976 change imports 2023-10-07 12:22:40 +08:00
roysc b686540512 rename app module, nest cli in app 2023-10-07 12:22:30 +08:00
76 changed files with 336 additions and 1441 deletions
@@ -2,10 +2,7 @@ name: Fixturenet-Eth-Plugeth-Test
on: on:
push: push:
branches: '*' branches: 'ci-test'
paths:
- '!**'
- '.gitea/workflows/triggers/fixturenet-eth-plugeth-test'
# Needed until we can incorporate docker startup into the executor container # Needed until we can incorporate docker startup into the executor container
env: env:
@@ -19,16 +16,8 @@ jobs:
steps: steps:
- name: "Clone project repository" - name: "Clone project repository"
uses: actions/checkout@v3 uses: actions/checkout@v3
# At present the stock setup-python action fails on Linux/aarch64 - name: "Install Python"
# Conditional steps below workaroud this by using deadsnakes for that case only uses: cerc-io/setup-python@v4
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: '3.8'
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4
with: with:
python-version: '3.8' python-version: '3.8'
- name: "Print Python version" - name: "Print Python version"
+2 -13
View File
@@ -2,10 +2,7 @@ name: Fixturenet-Eth-Test
on: on:
push: push:
branches: '*' branches: 'ci-test'
paths:
- '!**'
- '.gitea/workflows/triggers/fixturenet-eth-test'
# Needed until we can incorporate docker startup into the executor container # Needed until we can incorporate docker startup into the executor container
env: env:
@@ -19,15 +16,7 @@ jobs:
steps: steps:
- name: "Clone project repository" - name: "Clone project repository"
uses: actions/checkout@v3 uses: actions/checkout@v3
# At present the stock setup-python action fails on Linux/aarch64 - name: "Install Python"
# Conditional steps below workaroud this by using deadsnakes for that case only
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: '3.8'
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: '3.8' python-version: '3.8'
@@ -1,48 +0,0 @@
name: Fixturenet-Payments-Test
on:
push:
branches: '*'
paths:
- '!**'
- '.gitea/workflows/triggers/fixturenet-payments-test'
# Needed until we can incorporate docker startup into the executor container
env:
DOCKER_HOST: unix:///var/run/dind.sock
jobs:
test:
name: "Run a payments fixturenet test"
runs-on: ubuntu-latest
steps:
- name: "Clone project repository"
uses: actions/checkout@v3
# At present the stock setup-python action fails on Linux/aarch64
# Conditional steps below workaroud this by using deadsnakes for that case only
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: '3.8'
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4
with:
python-version: '3.8'
- name: "Print Python version"
run: python3 --version
- name: "Install shiv"
run: pip install shiv
- name: "Generate build version file"
run: ./scripts/create_build_tag_file.sh
- name: "Build local shiv package"
run: ./scripts/build_shiv_package.sh
- name: Start dockerd # Also needed until we can incorporate into the executor
run: |
dockerd -H $DOCKER_HOST --userland-proxy=false &
sleep 5
- name: "Run fixturenet-payments tests"
run: ./tests/fixturenet-payments/run-test.sh
+1 -11
View File
@@ -5,8 +5,6 @@ on:
branches: branches:
- main - main
- publish-test - publish-test
paths-ignore:
- '.gitea/workflows/triggers/*'
jobs: jobs:
publish: publish:
@@ -20,15 +18,7 @@ jobs:
run: | run: |
build_tag=$(./scripts/create_build_tag_file.sh) build_tag=$(./scripts/create_build_tag_file.sh)
echo "build-tag=v${build_tag}" >> $GITHUB_OUTPUT echo "build-tag=v${build_tag}" >> $GITHUB_OUTPUT
# At present the stock setup-python action fails on Linux/aarch64 - name: "Install Python"
# Conditional steps below workaroud this by using deadsnakes for that case only
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: '3.8'
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: '3.8' python-version: '3.8'
+1 -11
View File
@@ -7,8 +7,6 @@ on:
branches: branches:
- main - main
- ci-test - ci-test
paths-ignore:
- '.gitea/workflows/triggers/*'
# Needed until we can incorporate docker startup into the executor container # Needed until we can incorporate docker startup into the executor container
env: env:
@@ -21,15 +19,7 @@ jobs:
steps: steps:
- name: "Clone project repository" - name: "Clone project repository"
uses: actions/checkout@v3 uses: actions/checkout@v3
# At present the stock setup-python action fails on Linux/aarch64 - name: "Install Python"
# Conditional steps below workaroud this by using deadsnakes for that case only
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: '3.8'
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: '3.8' python-version: '3.8'
+1 -12
View File
@@ -7,8 +7,6 @@ on:
branches: branches:
- main - main
- ci-test - ci-test
paths-ignore:
- '.gitea/workflows/triggers/*'
# Needed until we can incorporate docker startup into the executor container # Needed until we can incorporate docker startup into the executor container
env: env:
@@ -21,15 +19,7 @@ jobs:
steps: steps:
- name: "Clone project repository" - name: "Clone project repository"
uses: actions/checkout@v3 uses: actions/checkout@v3
# At present the stock setup-python action fails on Linux/aarch64 - name: "Install Python"
# Conditional steps below workaroud this by using deadsnakes for that case only
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: '3.8'
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: '3.8' python-version: '3.8'
@@ -48,4 +38,3 @@ jobs:
- name: "Run smoke tests" - name: "Run smoke tests"
run: ./tests/smoke-test/run-smoke-test.sh run: ./tests/smoke-test/run-smoke-test.sh
@@ -1,2 +0,0 @@
Change this file to trigger running the fixturenet-eth-plugeth-test CI job
trigger
@@ -1,2 +0,0 @@
Change this file to trigger running the fixturenet-eth-test CI job
trigger
@@ -1,2 +0,0 @@
Change this file to trigger running the fixturenet-payments-test CI job
-30
View File
@@ -1,30 +0,0 @@
name: Fixturenet-Payments Test
on:
pull_request:
branches: '*'
push:
branches: '*'
jobs:
test:
name: "Run basic test suite"
runs-on: ubuntu-latest
steps:
- name: "Clone project repository"
uses: actions/checkout@v3
- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: '3.8'
- name: "Print Python version"
run: python3 --version
- name: "Install shiv"
run: pip install shiv
- name: "Generate build version file"
run: ./scripts/create_build_tag_file.sh
- name: "Build local shiv package"
run: ./scripts/build_shiv_package.sh
- name: "Run fixturenet-payments tests"
run: ./tests/fixturenet-payments/run-test.sh
+1 -1
View File
@@ -52,7 +52,7 @@ Version: 1.1.0-7a607c2-202304260513
Save the distribution url to `~/.laconic-so/config.yml`: Save the distribution url to `~/.laconic-so/config.yml`:
```bash ```bash
mkdir ~/.laconic-so mkdir ~/.laconic-so
echo "distribution-url: https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so" > ~/.laconic-so/config.yml echo "distribution-url: https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so" > ~/.laconic-so/config.yml"
``` ```
### Update ### Update
+1 -1
View File
@@ -15,8 +15,8 @@
import os import os
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from app.deploy import get_stack_status
from decouple import config from decouple import config
from .deploy import get_stack_status
def get_stack(config, stack): def get_stack(config, stack):
+3 -3
View File
@@ -27,8 +27,8 @@ import subprocess
import click import click
import importlib.resources import importlib.resources
from pathlib import Path from pathlib import Path
from app.util import include_exclude_check, get_parsed_stack_config from .util import include_exclude_check, get_parsed_stack_config
from app.base import get_npm_registry_url from .base import get_npm_registry_url
# TODO: find a place for this # TODO: find a place for this
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)" # epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
@@ -67,7 +67,7 @@ def command(ctx, include, exclude, force_rebuild, extra_build_args):
print('Dev root directory doesn\'t exist, creating') print('Dev root directory doesn\'t exist, creating')
# See: https://stackoverflow.com/a/20885799/1701505 # See: https://stackoverflow.com/a/20885799/1701505
from app import data from . import data
with importlib.resources.open_text(data, "container-image-list.txt") as container_list_file: with importlib.resources.open_text(data, "container-image-list.txt") as container_list_file:
all_containers = container_list_file.read().splitlines() all_containers = container_list_file.read().splitlines()
+3 -3
View File
@@ -25,8 +25,8 @@ from decouple import config
import click import click
import importlib.resources import importlib.resources
from python_on_whales import docker, DockerException from python_on_whales import docker, DockerException
from app.base import get_stack from .base import get_stack
from app.util import include_exclude_check, get_parsed_stack_config from .util import include_exclude_check, get_parsed_stack_config
builder_js_image_name = "cerc/builder-js:local" builder_js_image_name = "cerc/builder-js:local"
@@ -83,7 +83,7 @@ def command(ctx, include, exclude, force_rebuild, extra_build_args):
os.makedirs(build_root_path) os.makedirs(build_root_path)
# See: https://stackoverflow.com/a/20885799/1701505 # See: https://stackoverflow.com/a/20885799/1701505
from app import data from . import data
with importlib.resources.open_text(data, "npm-package-list.txt") as package_list_file: with importlib.resources.open_text(data, "npm-package-list.txt") as package_list_file:
all_packages = package_list_file.read().splitlines() all_packages = package_list_file.read().splitlines()
+8 -8
View File
@@ -15,14 +15,14 @@
import click import click
from app.command_types import CommandOptions from .command_types import CommandOptions
from app import setup_repositories from . import setup_repositories
from app import build_containers from . import build_containers
from app import build_npms from . import build_npms
from app import deploy from . import deploy
from app import version from . import version
from app import deployment from . import deployment
from app import update from . import update
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@@ -70,7 +70,6 @@ services:
command: "/run-op-geth.sh" command: "/run-op-geth.sh"
ports: ports:
- "0.0.0.0:8545:8545" - "0.0.0.0:8545:8545"
- "0.0.0.0:8546:8546"
healthcheck: healthcheck:
test: ["CMD", "nc", "-vz", "localhost:8545"] test: ["CMD", "nc", "-vz", "localhost:8545"]
interval: 30s interval: 30s
+17 -10
View File
@@ -11,13 +11,10 @@ services:
condition: service_completed_successfully condition: service_completed_successfully
environment: environment:
CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546} CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546}
CERC_NITRO_PK: ${CERC_NITRO_PK:-f36f6dd450892224ee113899195ef922a4795d41c32cafb386d9aab6e0b7b0c6} CERC_NITRO_PK: ${CERC_NITRO_PK:-2d999770f7b5d49b694080f987b82bbc9fc9ac2b4dcc10b0f8aba7d700f69c6d}
CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK:-888814df89c4358d7ddb3fa4b0213e7331239a80e1f013eaa7b2deca2a41a218} CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK:-570b909da9669b2f35a0b1ac70b8358516d55ae1b5b3710e95e9a94395090597}
CERC_NITRO_USE_DURABLE_STORE: ${CERC_NITRO_USE_DURABLE_STORE:-true} CERC_NITRO_USE_DURABLE_STORE: ${CERC_NITRO_USE_DURABLE_STORE:-true}
CERC_NITRO_DURABLE_STORE_FOLDER: ${CERC_NITRO_DURABLE_STORE_FOLDER:-/app/data/nitro-store} CERC_NITRO_DURABLE_STORE_FOLDER: ${CERC_NITRO_DURABLE_STORE_FOLDER:-/app/data/nitro-store}
CERC_NITRO_MSG_PORT: ${CERC_NITRO_MSG_PORT:-3006}
CERC_NITRO_WS_MSG_PORT: ${CERC_NITRO_WS_MSG_PORT:-5006}
CERC_NITRO_RPC_PORT: ${CERC_NITRO_RPC_PORT:-4006}
CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} CERC_NA_ADDRESS: ${CERC_NA_ADDRESS}
CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS}
CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} CERC_CA_ADDRESS: ${CERC_CA_ADDRESS}
@@ -27,15 +24,25 @@ services:
- nitro_deployment:/app/deployment - nitro_deployment:/app/deployment
- ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh - ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh
healthcheck: healthcheck:
test: ["CMD", "nc", "-vz", "localhost", "4006"] test: ["CMD", "nc", "-vz", "localhost", "4005"]
interval: 30s interval: 10s
timeout: 5s timeout: 5s
retries: 10 retries: 10
start_period: 10s start_period: 10s
ports: ports:
- "3006:3006" - "3005"
- "4006:4006" - "4005:4005"
- "5006:5006" - "5005:5005"
nitro-rpc-client:
image: cerc/nitro-rpc-client:local
hostname: nitro-rpc-client
restart: on-failure
depends_on:
# Wait for the go-nitro node to start
go-nitro:
condition: service_healthy
command: ["bash", "-c", "tail -f /dev/null"]
volumes: volumes:
go_nitro_data: go_nitro_data:
@@ -1,111 +0,0 @@
version: "3.2"
services:
ipld-eth-server-1:
restart: unless-stopped
depends_on:
ipld-eth-db:
condition: service_healthy
image: cerc/ipld-eth-server:local
environment:
SERVER_HTTP_PATH: 0.0.0.0:8081
SERVER_GRAPHQL: "true"
SERVER_GRAPHQLPATH: 0.0.0.0:8082
VDB_COMMAND: "serve"
ETH_CHAIN_CONFIG: "/tmp/chain.json"
DATABASE_NAME: cerc_testing
DATABASE_HOSTNAME: ipld-eth-db
DATABASE_PORT: 5432
DATABASE_USER: "vdbm"
DATABASE_PASSWORD: "password"
ETH_CHAIN_ID: 99
ETH_FORWARD_ETH_CALLS: "false"
ETH_FORWARD_GET_STORAGE_AT: "false"
ETH_PROXY_ON_ERROR: "false"
METRICS: "true"
PROM_HTTP: "true"
PROM_HTTP_ADDR: "0.0.0.0"
PROM_HTTP_PORT: "8090"
LOG_LEVEL: "debug"
CERC_REMOTE_DEBUG: ${CERC_REMOTE_DEBUG:-true}
NITRO_RUN_NODE_IN_PROCESS: ${CERC_NITRO_RUN_NODE_IN_PROCESS:-true}
NITRO_PK: ${CERC_NITRO_PK:-2d999770f7b5d49b694080f987b82bbc9fc9ac2b4dcc10b0f8aba7d700f69c6d}
NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK:-570b909da9669b2f35a0b1ac70b8358516d55ae1b5b3710e95e9a94395090597}
NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546}
NITRO_USE_DURABLE_STORE: ${CERC_NITRO_USE_DURABLE_STORE:-true}
NITRO_DURABLE_STORE_FOLDER: ${CERC_NITRO_DURABLE_STORE_FOLDER:-/app/nitro-data/nitro-store}
CERC_NA_ADDRESS: ${CERC_NA_ADDRESS}
CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS}
CERC_CA_ADDRESS: ${CERC_CA_ADDRESS}
entrypoint: ["bash", "-c", "/app/entrypoint.sh"]
volumes:
- type: bind
source: ../config/ipld-eth-server/chain.json
target: /tmp/chain.json
- eth_server_nitro_data:/app/nitro-data
- nitro_deployment:/app/deployment
- ../config/ipld-eth-server/entrypoint.sh:/app/entrypoint.sh
ports:
- "8081"
- "8082"
- "8090"
- "40000"
- "3005:3005"
- "4005:4005"
- "5005:5005"
healthcheck:
test: ["CMD", "nc", "-v", "localhost", "8081"]
interval: 20s
timeout: 5s
retries: 15
start_period: 5s
ipld-eth-server-2:
restart: unless-stopped
depends_on:
ipld-eth-db:
condition: service_healthy
image: cerc/ipld-eth-server:local
environment:
SERVER_HTTP_PATH: 0.0.0.0:8081
SERVER_GRAPHQL: "true"
SERVER_GRAPHQLPATH: 0.0.0.0:8082
VDB_COMMAND: "serve"
ETH_CHAIN_CONFIG: "/tmp/chain.json"
DATABASE_NAME: cerc_testing
DATABASE_HOSTNAME: ipld-eth-db
DATABASE_PORT: 5432
DATABASE_USER: "vdbm"
DATABASE_PASSWORD: "password"
ETH_CHAIN_ID: 99
ETH_FORWARD_ETH_CALLS: "false"
ETH_FORWARD_GET_STORAGE_AT: "false"
ETH_PROXY_ON_ERROR: "false"
METRICS: "true"
PROM_HTTP: "true"
PROM_HTTP_ADDR: "0.0.0.0"
PROM_HTTP_PORT: "8090"
LOG_LEVEL: "debug"
CERC_REMOTE_DEBUG: ${CERC_REMOTE_DEBUG:-true}
NITRO_RUN_NODE_IN_PROCESS: ${CERC_NITRO_RUN_NODE_IN_PROCESS:-false}
NITRO_ENDPOINT: ${CERC_NITRO_ENDPOINT:-go-nitro:4006/api/v1}
entrypoint: ["bash", "-c", "/app/entrypoint.sh"]
volumes:
- type: bind
source: ../config/ipld-eth-server/chain.json
target: /tmp/chain.json
- ../config/ipld-eth-server/entrypoint.sh:/app/entrypoint.sh
ports:
- "8081"
- "8082"
- "8090"
- "40000"
healthcheck:
test: ["CMD", "nc", "-v", "localhost", "8081"]
interval: 20s
timeout: 5s
retries: 15
start_period: 5s
volumes:
eth_server_nitro_data:
nitro_deployment:
@@ -1,8 +0,0 @@
version: "3.2"
services:
laconic-dot-com:
image: cerc/laconic-dot-com:local
restart: always
ports:
- "3000"
@@ -0,0 +1,27 @@
version: '3.7'
services:
nitro-reverse-payment-proxy:
image: cerc/go-nitro:local
hostname: nitro-reverse-payment-proxy
restart: on-failure
depends_on:
# Wait for the go-nitro node to start
go-nitro:
condition: service_healthy
environment:
CERC_PROXY_ADDRESS: 0.0.0.0:8081
CERC_PROXY_NITRO_ENDPOINT: ${CERC_PROXY_NITRO_ENDPOINT:-go-nitro:4005/api/v1}
CERC_PROXY_DESTINATION_URL: ${CERC_PROXY_DESTINATION_URL:-http://ipld-eth-server:8081}
CERC_PROXY_COST_PER_BYTE: ${CERC_PROXY_COST_PER_BYTE:-1}
entrypoint: ["bash", "-c", "/app/run-reverse-payment-proxy.sh"]
volumes:
- ../config/go-nitro/run-reverse-payment-proxy.sh:/app/run-reverse-payment-proxy.sh
healthcheck:
test: ["CMD", "nc", "-vz", "localhost", "8081"]
interval: 10s
timeout: 5s
retries: 10
start_period: 10s
ports:
- "8081:8081"
@@ -1,7 +0,0 @@
version: '3.7'
services:
nitro-rpc-client:
image: cerc/nitro-rpc-client:local
hostname: nitro-rpc-client
restart: on-failure
command: ["bash", "-c", "tail -f /dev/null"]
@@ -1,80 +0,0 @@
version: '3.7'
services:
ponder-er20-contracts:
image: cerc/watcher-erc20:local
restart: on-failure
environment:
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT:-http://fixturenet-eth-geth-1:8545}
CERC_PRIVATE_KEY_DEPLOYER: ${CERC_PRIVATE_KEY_DEPLOYER:-0x888814df89c4358d7ddb3fa4b0213e7331239a80e1f013eaa7b2deca2a41a218}
volumes:
- ../config/ponder/deploy-erc20-contract.sh:/app/deploy-erc20-contract.sh
- erc20_deployment:/app/deployment
command: ["bash", "-c", "/app/deploy-erc20-contract.sh"]
extra_hosts:
- "host.docker.internal:host-gateway"
ponder-app-indexer-1:
hostname: ponder-app-indexer-1
restart: unless-stopped
image: cerc/ponder:local
working_dir: /app/examples/token-erc20
environment:
CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99}
CERC_PONDER_RPC_URL_1: ${PONDER_RPC_URL_1:-http://ipld-eth-server-2:8081}
CERC_PONDER_NITRO_PK: ${CERC_PONDER_INDEXER_NITRO_PK_1:-58368d20ff12f17669c06158c21d885897aa56f9be430edc789614bf9851d53f}
CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_INDEXER_NITRO_CHAIN_PK_1:-fb1e9af328c283ca3e2486e7c24d13582b7912057d8b9542ff41503c85bc05c0}
CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546}
CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR}
CERC_UPSTREAM_NITRO_ADDRESS: ${CERC_UPSTREAM_NITRO_ADDRESS:-0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e}
CERC_UPSTREAM_NITRO_MULTIADDR: ${CERC_UPSTREAM_NITRO_MULTIADDR:-/dns4/go-nitro/tcp/5006/ws/p2p/16Uiu2HAmNUiX7bpCpbo5JdqEebp85ptGU2Vk2AT9E3BykvbwQ3F9}
CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-100}
command: ["bash", "./ponder-start.sh"]
volumes:
- ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh
- ../config/ponder/ponder.indexer-1.config.ts:/app/examples/token-erc20/ponder.config.ts
- ../config/ponder/base-rates-config.json:/app/examples/token-erc20/base-rates-config.json
- peers_ids:/peers
- nitro_deployment:/nitro
- erc20_deployment:/erc20
- ponder_indexer_1_nitro_data:/app/examples/token-erc20/.ponder/nitro-db
ports:
- "127.0.0.1:42070:42070"
extra_hosts:
- "host.docker.internal:host-gateway"
ponder-app-indexer-2:
hostname: ponder-app-indexer-2
restart: unless-stopped
image: cerc/ponder:local
working_dir: /app/examples/token-erc20
environment:
CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99}
CERC_INDEXER_GQL_ENDPOINT: ${CERC_INDEXER_GQL_ENDPOINT:-http://ponder-app-indexer-1:42070/graphql}
CERC_PONDER_NITRO_PK: ${CERC_PONDER_INDEXER_NITRO_PK_2:-0aca28ba64679f63d71e671ab4dbb32aaa212d4789988e6ca47da47601c18fe2}
CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_INDEXER_NITRO_CHAIN_PK_2:-6177345b77c4069ac4d553f8b43cf68a799ca4bb63eac93d6cf796d63694ebf0}
CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546}
CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR}
CERC_INDEXER_NITRO_ADDRESS: ${CERC_INDEXER_NITRO_ADDRESS:-0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d}
CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-100}
command: ["bash", "./ponder-start.sh"]
volumes:
- ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh
- ../config/ponder/ponder.indexer-2.config.ts:/app/examples/token-erc20/ponder.config.ts
- ../config/ponder/base-rates-config.json:/app/examples/token-erc20/base-rates-config.json
- peers_ids:/peers
- nitro_deployment:/nitro
- erc20_deployment:/erc20
- ponder_indexer_2_nitro_data:/app/examples/token-erc20/.ponder/nitro-db
ports:
- "127.0.0.1:42071:42070"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
peers_ids:
nitro_deployment:
erc20_deployment:
ponder_indexer_1_nitro_data:
ponder_indexer_2_nitro_data:
@@ -1,39 +0,0 @@
version: '3.7'
services:
ponder-app-watcher:
hostname: ponder-app-watcher
depends_on:
- ponder-app-indexer-1
restart: unless-stopped
image: cerc/ponder:local
working_dir: /app/examples/token-erc20
environment:
CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99}
CERC_PONDER_NITRO_PK: ${CERC_PONDER_WATCHER_NITRO_PK:-febb3b74b0b52d0976f6571d555f4ac8b91c308dfa25c7b58d1e6a7c3f50c781}
CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_WATCHER_NITRO_CHAIN_PK:-be4aa664815ea3bc3d63118649a733f6c96b243744310806ecb6d96359ab62cf}
CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546}
CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR}
CERC_INDEXER_GQL_ENDPOINT: ${CERC_INDEXER_GQL_ENDPOINT:-http://ponder-app-indexer-2:42070/graphql}
CERC_INDEXER_NITRO_ADDRESS: ${CERC_INDEXER_NITRO_ADDRESS:-0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01}
CERC_INDEXER_NITRO_PAY_AMOUNT: ${CERC_INDEXER_NITRO_PAY_AMOUNT:-50}
command: ["bash", "./ponder-start.sh"]
volumes:
- ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh
- ../config/ponder/ponder.watcher.config.ts:/app/examples/token-erc20/ponder.config.ts
- ../config/ponder/base-rates-config.json:/app/examples/token-erc20/base-rates-config.json
- peers_ids:/peers
- nitro_deployment:/nitro
- erc20_deployment:/erc20
- ponder_watcher_nitro_data:/app/examples/token-erc20/.ponder/nitro-db
ports:
- "127.0.0.1:42069:42069"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
peers_ids:
nitro_deployment:
erc20_deployment:
ponder_watcher_nitro_data:
@@ -0,0 +1,31 @@
version: '3.7'
services:
ponder-app:
restart: unless-stopped
image: cerc/ponder:local
working_dir: /app/examples/token-erc20
environment:
CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99}
CERC_PONDER_RPC_URL_1: ${PONDER_RPC_URL_1:-http://nitro-reverse-payment-proxy:8081}
CERC_PONDER_NITRO_PK: ${CERC_PONDER_NITRO_PK:-58368d20ff12f17669c06158c21d885897aa56f9be430edc789614bf9851d53f}
CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_NITRO_CHAIN_PK:-fb1e9af328c283ca3e2486e7c24d13582b7912057d8b9542ff41503c85bc05c0}
CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546}
CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR}
CERC_UPSTREAM_NITRO_ADDRESS: ${CERC_UPSTREAM_NITRO_ADDRESS:-0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE}
CERC_UPSTREAM_NITRO_MULTIADDR: ${CERC_UPSTREAM_NITRO_MULTIADDR:-/dns4/go-nitro/tcp/5005/ws/p2p/16Uiu2HAmSjXJqsyBJgcBUU2HQmykxGseafSatbpq5471XmuaUqyv}
CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-5000}
command: ["bash", "./ponder-start.sh"]
volumes:
- ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh
- ../config/ponder/ponder.config.ts:/app/examples/token-erc20/ponder.config.ts
- peers_ids:/peers
- nitro_deployment:/nitro
- ponder_nitro_data:/app/examples/token-erc20/.ponder/nitro-db
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
peers_ids:
nitro_deployment:
ponder_nitro_data:
@@ -34,7 +34,7 @@ services:
- ETH_RPC_URL=http://go-ethereum:8545 - ETH_RPC_URL=http://go-ethereum:8545
command: ["sh", "-c", "yarn server"] command: ["sh", "-c", "yarn server"]
volumes: volumes:
- ../config/watcher-erc20/erc20-watcher.toml:/app/environments/local.toml - ../config/watcher-erc20/erc20-watcher.toml:/app/packages/erc20-watcher/environments/local.toml
ports: ports:
- "0.0.0.0:3002:3001" - "0.0.0.0:3002:3001"
- "0.0.0.0:9002:9001" - "0.0.0.0:9002:9001"
@@ -89,8 +89,8 @@ services:
CERC_PEER_ID: ${CERC_PEER_ID} CERC_PEER_ID: ${CERC_PEER_ID}
CERC_ENABLE_UPSTREAM_PAYMENTS: ${CERC_ENABLE_UPSTREAM_PAYMENTS} CERC_ENABLE_UPSTREAM_PAYMENTS: ${CERC_ENABLE_UPSTREAM_PAYMENTS}
CERC_UPSTREAM_NITRO_ADDRESS: ${CERC_UPSTREAM_NITRO_ADDRESS:-0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE} CERC_UPSTREAM_NITRO_ADDRESS: ${CERC_UPSTREAM_NITRO_ADDRESS:-0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE}
CERC_UPSTREAM_NITRO_MULTIADDR: ${CERC_UPSTREAM_NITRO_MULTIADDR:-/dns4/ipld-eth-server-1/tcp/5005/ws/p2p/16Uiu2HAmSjXJqsyBJgcBUU2HQmykxGseafSatbpq5471XmuaUqyv} CERC_UPSTREAM_NITRO_MULTIADDR: ${CERC_UPSTREAM_NITRO_MULTIADDR:-/dns4/go-nitro/tcp/5005/ws/p2p/16Uiu2HAmSjXJqsyBJgcBUU2HQmykxGseafSatbpq5471XmuaUqyv}
CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-100} CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-5000}
command: ["bash", "./start-server.sh"] command: ["bash", "./start-server.sh"]
volumes: volumes:
- ../config/watcher-mobymask-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml - ../config/watcher-mobymask-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml
+4 -5
View File
@@ -29,13 +29,12 @@ fi
echo "Running Nitro node" echo "Running Nitro node"
# Assuming CERC_NITRO_CHAIN_URL is of format <ws|http>://host:port
ws_host=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 1)
ws_port=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 2)
# Wait till chain endpoint is available # Wait till chain endpoint is available
retry_interval=5 retry_interval=5
while true; do while true; do
# Assuming CERC_NITRO_CHAIN_URL is of format <ws|http>://host:port
ws_host=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 1)
ws_port=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 2)
nc -z -w 1 "$ws_host" "$ws_port" nc -z -w 1 "$ws_host" "$ws_port"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
@@ -47,4 +46,4 @@ while true; do
sleep $retry_interval sleep $retry_interval
done done
./nitro -chainurl ${CERC_NITRO_CHAIN_URL} -msgport ${CERC_NITRO_MSG_PORT} -rpcport ${CERC_NITRO_RPC_PORT} -wsmsgport ${CERC_NITRO_WS_MSG_PORT} -publicip "0.0.0.0" -pk ${CERC_NITRO_PK} -chainpk ${CERC_NITRO_CHAIN_PK} -naaddress ${NA_ADDRESS} -vpaaddress ${VPA_ADDRESS} -caaddress ${CA_ADDRESS} -usedurablestore ${CERC_NITRO_USE_DURABLE_STORE} -durablestorefolder ${CERC_NITRO_DURABLE_STORE_FOLDER} -tlscertfilepath "" -tlsKeyFilepath "" ./nitro -chainurl ${CERC_NITRO_CHAIN_URL} -msgport 3005 -rpcport 4005 -wsmsgport 5005 -pk ${CERC_NITRO_PK} -chainpk ${CERC_NITRO_CHAIN_PK} -naaddress ${NA_ADDRESS} -vpaaddress ${VPA_ADDRESS} -caaddress ${CA_ADDRESS} -usedurablestore ${CERC_NITRO_USE_DURABLE_STORE} -durablestorefolder ${CERC_NITRO_DURABLE_STORE_FOLDER}
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
echo "Running Nitro reverse payment proxy"
echo "Using CERC_PROXY_ADDRESS ${CERC_PROXY_ADDRESS}"
echo "Using CERC_PROXY_NITRO_ENDPOINT ${CERC_PROXY_NITRO_ENDPOINT}"
echo "Using CERC_PROXY_DESTINATION_URL ${CERC_PROXY_DESTINATION_URL}"
echo "Using CERC_PROXY_COST_PER_BYTE ${CERC_PROXY_COST_PER_BYTE}"
./proxy -proxyaddress ${CERC_PROXY_ADDRESS} -nitroendpoint=${CERC_PROXY_NITRO_ENDPOINT} -destinationurl=${CERC_PROXY_DESTINATION_URL} -costperbyte ${CERC_PROXY_COST_PER_BYTE} -enablepaidrpcmethods
@@ -1,71 +0,0 @@
#!/bin/sh
read_nitro_addresses() {
nitro_addresses_file="/app/deployment/nitro-addresses.json"
# Check if CERC_NA_ADDRESS environment variable is set
if [ -n "$CERC_NA_ADDRESS" ]; then
echo "CERC_NA_ADDRESS is set to '$CERC_NA_ADDRESS'"
echo "CERC_VPA_ADDRESS is set to '$CERC_VPA_ADDRESS'"
echo "CERC_CA_ADDRESS is set to '$CERC_CA_ADDRESS'"
echo "Using the above Nitro addresses"
export NITRO_NA_ADDRESS=${CERC_NA_ADDRESS}
export NITRO_VPA_ADDRESS=${CERC_VPA_ADDRESS}
export NITRO_CA_ADDRESS=${CERC_CA_ADDRESS}
else
# Read addresses from a file
# Keep retrying until found
echo "Reading Nitro addresses from ${nitro_addresses_file}"
retry_interval=5
while true; do
if [[ -e "$nitro_addresses_file" ]]; then
export NITRO_NA_ADDRESS=$(jq -r '.nitroAdjudicatorAddress' ${nitro_addresses_file})
export NITRO_VPA_ADDRESS=$(jq -r '.virtualPaymentAppAddress' ${nitro_addresses_file})
export NITRO_CA_ADDRESS=$(jq -r '.consensusAppAddress' ${nitro_addresses_file})
break
else
echo "File not yet available, retrying in $retry_interval seconds..."
sleep $retry_interval
fi
done
fi
}
wait_for_nitro_endpoint() {
retry_interval=5
while true; do
curl -I -s -o /dev/null $NITRO_ENDPOINT/health
if [ $? -eq 0 ]; then
echo "Nitro endpoint is up"
break
else
echo "Nitro endpoint not available yet, retrying in $retry_interval seconds..."
sleep $retry_interval
fi
done
}
if [ "$NITRO_RUN_NODE_IN_PROCESS" = "true" ]; then
read_nitro_addresses
else
wait_for_nitro_endpoint
fi
echo "Beginning the ipld-eth-server process"
START_CMD="./ipld-eth-server"
if [ "true" == "$CERC_REMOTE_DEBUG" ] && [ -x "/usr/local/bin/dlv" ]; then
START_CMD="/usr/local/bin/dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient exec `pwd`/ipld-eth-server --continue --"
fi
echo running: $START_CMD ${VDB_COMMAND} --config=`pwd`/config.toml
$START_CMD ${VDB_COMMAND} --config=`pwd`/config.toml
rv=$?
if [ $rv != 0 ]; then
echo "ipld-eth-server startup failed"
exit 1
fi
@@ -1,10 +0,0 @@
{
"freeQueriesLimit": 10,
"freeQueriesList": [],
"queries": {
"getLogEvents": "50",
"getEthLogs": "50",
"getEthBlock": "50"
},
"mutations": {}
}
@@ -1,57 +0,0 @@
#!/bin/bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
erc20_address_file="/app/deployment/erc20-address.json"
echo ETH_RPC_URL=${CERC_ETH_RPC_ENDPOINT} > .env
echo ACCOUNT_PRIVATE_KEY=${CERC_PRIVATE_KEY_DEPLOYER} >> .env
# Check and keep container running if a deployment already exists (on restarts)
if [ -f ${erc20_address_file} ]; then
echo "${erc20_address_file} already exists, skipping ERC20 contract deployment"
cat ${erc20_address_file}
# Keep the container running
tail -f
fi
wait_for_chain_endpoint() {
# Wait till ETH RPC endpoint is available with block number > 1
retry_interval=5
while true; do
block_number_hex=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' ${CERC_ETH_RPC_ENDPOINT} | jq -r '.result')
# Check if the request call was successful
if [ $? -ne 0 ]; then
echo "RPC endpoint ${CERC_ETH_RPC_ENDPOINT} not yet available, retrying in $retry_interval seconds..."
sleep $retry_interval
continue
fi
# Convert hex to decimal
block_number_dec=$(printf %u ${block_number_hex})
# Check if block number is > 1 to avoid failures in the deployment
if [ "$block_number_dec" -ge 1 ]; then
echo "RPC endpoint ${CERC_ETH_RPC_ENDPOINT} is up"
break
else
echo "RPC endpoint ${CERC_ETH_RPC_ENDPOINT} not yet available, retrying in $retry_interval seconds..."
sleep $retry_interval
continue
fi
done
}
wait_for_chain_endpoint
echo "Using CERC_PRIVATE_KEY_DEPLOYER from env"
yarn token:deploy:docker --file ${erc20_address_file}
# Keep the container running
tail -f
-19
View File
@@ -31,21 +31,6 @@ else
exit 1 exit 1
fi fi
# Read ERC20 address from a file
# Keep retrying until found
erc20_address_file="/erc20/erc20-address.json"
echo "Reading ERC20 address from ${erc20_address_file}"
retry_interval=5
while true; do
if [[ -e "$erc20_address_file" ]]; then
ERC20_CONTRACT=$(jq -r '.address' ${erc20_address_file})
break
else
echo "File not yet available, retrying in $retry_interval seconds..."
sleep $retry_interval
fi
done
echo "Using CERC_PONDER_NITRO_PK from env for Nitro account" echo "Using CERC_PONDER_NITRO_PK from env for Nitro account"
echo "Using CERC_PONDER_NITRO_CHAIN_PK (account with funds) from env for sending Nitro txs" echo "Using CERC_PONDER_NITRO_CHAIN_PK (account with funds) from env for sending Nitro txs"
echo "Using ${CERC_PONDER_NITRO_CHAIN_URL} as the RPC endpoint for Nitro txs" echo "Using ${CERC_PONDER_NITRO_CHAIN_URL} as the RPC endpoint for Nitro txs"
@@ -68,10 +53,6 @@ echo "RELAY_MULTIADDR=\"$CERC_RELAY_MULTIADDR\"" >> "$env_file"
echo "UPSTREAM_NITRO_ADDRESS=\"$CERC_UPSTREAM_NITRO_ADDRESS\"" >> "$env_file" echo "UPSTREAM_NITRO_ADDRESS=\"$CERC_UPSTREAM_NITRO_ADDRESS\"" >> "$env_file"
echo "UPSTREAM_NITRO_MULTIADDR=\"$CERC_UPSTREAM_NITRO_MULTIADDR\"" >> "$env_file" echo "UPSTREAM_NITRO_MULTIADDR=\"$CERC_UPSTREAM_NITRO_MULTIADDR\"" >> "$env_file"
echo "UPSTREAM_NITRO_PAY_AMOUNT=\"$CERC_UPSTREAM_NITRO_PAY_AMOUNT\"" >> "$env_file" echo "UPSTREAM_NITRO_PAY_AMOUNT=\"$CERC_UPSTREAM_NITRO_PAY_AMOUNT\"" >> "$env_file"
echo "INDEXER_GQL_ENDPOINT=\"$CERC_INDEXER_GQL_ENDPOINT\"" >> "$env_file"
echo "INDEXER_NITRO_ADDRESS=\"$CERC_INDEXER_NITRO_ADDRESS\"" >> "$env_file"
echo "INDEXER_NITRO_PAY_AMOUNT=\"$CERC_INDEXER_NITRO_PAY_AMOUNT\"" >> "$env_file"
echo "ERC20_CONTRACT=\"$ERC20_CONTRACT\"" >> "$env_file"
cat "$env_file" cat "$env_file"
@@ -1,6 +1,6 @@
import { type Config, AppMode } from "@ponder/core"; import type { Config } from "@ponder/core";
import contractAddresses from "./nitro-addresses.json" assert { type: "json" }; import contractAddresses from "./nitro-addresses.json";
export const config: Config = { export const config: Config = {
networks: [ networks: [
@@ -34,14 +34,11 @@ export const config: Config = {
name: "AdventureGold", name: "AdventureGold",
network: "fixturenet", network: "fixturenet",
abi: "./abis/AdventureGold.json", abi: "./abis/AdventureGold.json",
address: process.env.ERC20_CONTRACT, address: "0x32353A6C91143bfd6C7d363B546e62a9A2489A20",
startBlock: 1, startBlock: 5,
maxBlockRange: 100, maxBlockRange: 100,
}, },
], ],
options: {
mode: AppMode.Indexer,
},
nitro: { nitro: {
privateKey: process.env.PONDER_NITRO_PK!, privateKey: process.env.PONDER_NITRO_PK!,
chainPrivateKey: process.env.PONDER_NITRO_CHAIN_PK!, chainPrivateKey: process.env.PONDER_NITRO_CHAIN_PK!,
@@ -49,17 +46,5 @@ export const config: Config = {
contractAddresses, contractAddresses,
relayMultiAddr: process.env.RELAY_MULTIADDR!, relayMultiAddr: process.env.RELAY_MULTIADDR!,
store: "./.ponder/nitro-db", store: "./.ponder/nitro-db",
payments: {
cache: {
maxAccounts: 1000,
accountTTLInSecs: 1800,
maxVouchersPerAccount: 1000,
voucherTTLInSecs: 300,
maxPaymentChannels: 10000,
paymentChannelTTLInSecs: 1800,
},
ratesFile: "./base-rates-config.json",
requestTimeoutInSecs: 10,
},
}, },
}; };
@@ -1,64 +0,0 @@
import { type Config, AppMode } from "@ponder/core";
import contractAddresses from "./nitro-addresses.json" assert { type: "json" };
export const config: Config = {
networks: [
{
name: "fixturenet",
chainId: Number(process.env.PONDER_CHAIN_ID),
indexerUrl: process.env.INDEXER_GQL_ENDPOINT,
maxRpcRequestConcurrency: 1,
pollingInterval: 5000,
payments: {
nitro: {
address: process.env.INDEXER_NITRO_ADDRESS!,
fundingAmounts: {
// TODO: Pass amounts from env
directFund: "1000000000000",
virtualFund: "1000000000",
},
},
paidRPCMethods: [
"eth_getLogs",
"eth_getBlockByNumber",
"eth_getBlockByHash",
],
amount: process.env.UPSTREAM_NITRO_PAY_AMOUNT!,
},
},
],
contracts: [
{
name: "AdventureGold",
network: "fixturenet",
abi: "./abis/AdventureGold.json",
address: process.env.ERC20_CONTRACT,
startBlock: 1,
maxBlockRange: 100,
},
],
options: {
mode: AppMode.Indexer,
},
nitro: {
privateKey: process.env.PONDER_NITRO_PK!,
chainPrivateKey: process.env.PONDER_NITRO_CHAIN_PK!,
chainUrl: process.env.PONDER_NITRO_CHAIN_URL!,
contractAddresses,
relayMultiAddr: process.env.RELAY_MULTIADDR!,
store: "./.ponder/nitro-db",
payments: {
cache: {
maxAccounts: 1000,
accountTTLInSecs: 1800,
maxVouchersPerAccount: 1000,
voucherTTLInSecs: 300,
maxPaymentChannels: 10000,
paymentChannelTTLInSecs: 1800,
},
ratesFile: "./base-rates-config.json",
requestTimeoutInSecs: 10,
},
},
};
@@ -1,58 +0,0 @@
import { type Config, AppMode } from "@ponder/core";
import contractAddresses from "./nitro-addresses.json" assert { type: "json" };
export const config: Config = {
networks: [
{
name: "fixturenet",
chainId: Number(process.env.PONDER_CHAIN_ID),
},
],
contracts: [
{
name: "AdventureGold",
network: "fixturenet",
abi: "./abis/AdventureGold.json",
address: process.env.ERC20_CONTRACT,
startBlock: 1,
maxBlockRange: 100,
},
],
options: {
mode: AppMode.Watcher,
},
indexer: {
gqlEndpoint: process.env.INDEXER_GQL_ENDPOINT,
payments: {
nitro: {
address: process.env.INDEXER_NITRO_ADDRESS,
fundingAmounts: {
directFund: "1000000000000",
virtualFund: "1000000000",
},
},
amount: process.env.INDEXER_NITRO_PAY_AMOUNT,
},
},
nitro: {
privateKey: process.env.PONDER_NITRO_PK!,
chainPrivateKey: process.env.PONDER_NITRO_CHAIN_PK!,
chainUrl: process.env.PONDER_NITRO_CHAIN_URL!,
contractAddresses,
relayMultiAddr: process.env.RELAY_MULTIADDR!,
store: "./.ponder/nitro-db",
payments: {
cache: {
maxAccounts: 1000,
accountTTLInSecs: 1800,
maxVouchersPerAccount: 1000,
voucherTTLInSecs: 300,
maxPaymentChannels: 10000,
paymentChannelTTLInSecs: 1800,
},
ratesFile: "./base-rates-config.json",
requestTimeoutInSecs: 10,
},
}
};
@@ -4,7 +4,7 @@
DEFAULT_CERC_ETH_RPC_ENDPOINT="http://fixturenet-eth-geth-1:8545" DEFAULT_CERC_ETH_RPC_ENDPOINT="http://fixturenet-eth-geth-1:8545"
# ETH RPC endpoint used for queries in the watcher # ETH RPC endpoint used for queries in the watcher
DEFAULT_CERC_ETH_RPC_QUERY_ENDPOINT="http://ipld-eth-server-1:8081" DEFAULT_CERC_ETH_RPC_QUERY_ENDPOINT="http://nitro-reverse-payment-proxy:8081"
# ETH RPC endpoint used for mutations in the watcher # ETH RPC endpoint used for mutations in the watcher
DEFAULT_CERC_ETH_RPC_MUTATION_ENDPOINT="http://fixturenet-eth-geth-1:8545" DEFAULT_CERC_ETH_RPC_MUTATION_ENDPOINT="http://fixturenet-eth-geth-1:8545"
@@ -20,24 +20,21 @@ if [[ $? -ne 0 ]]; then
exit 1 exit 1
fi fi
# Stop geth.
echo -n "Exporting ethdb.... "
GETH_CONTAINER=`docker ps -q -f "name=${CERC_SO_COMPOSE_PROJECT}-fixturenet-eth-geth-2-1"` GETH_CONTAINER=`docker ps -q -f "name=${CERC_SO_COMPOSE_PROJECT}-fixturenet-eth-geth-2-1"`
if [[ -z "$GETH_CONTAINER" ]]; then if [[ -z "$GETH_CONTAINER" ]]; then
echo "not found" echo "not found"
exit 1 exit 1
fi fi
# Make sure we have the necessary tools
docker exec $GETH_CONTAINER sh -c 'apk add --no-cache jq curl'
# Gather metadata.
docker exec $GETH_CONTAINER sh -c 'rm -rf /root/tmp && mkdir -p /root/tmp/export' docker exec $GETH_CONTAINER sh -c 'rm -rf /root/tmp && mkdir -p /root/tmp/export'
docker exec $GETH_CONTAINER sh -c 'ln -s /opt/testnet/build/el/geth.json /root/tmp/export/genesis.json && ln -s /root/ethdata /root/tmp/export/' docker exec $GETH_CONTAINER sh -c 'ln -s /opt/testnet/build/el/geth.json /root/tmp/export/genesis.json && ln -s /root/ethdata /root/tmp/export/'
docker exec $GETH_CONTAINER sh -c 'cat /root/tmp/export/genesis.json | jq ".config" > /root/tmp/export/genesis.config.json' docker exec $GETH_CONTAINER sh -c 'cat /root/tmp/export/genesis.json | jq ".config" > /root/tmp/export/genesis.config.json'
docker exec $GETH_CONTAINER sh -c 'curl -s --location "localhost:8545" --header "Content-Type: application/json" --data "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockByNumber\", \"params\": [\"0x0\", false]}" > /root/tmp/export/eth_getBlockByNumber_0x0.json'
docker exec $GETH_CONTAINER sh -c 'curl -s --location "localhost:8545" --header "Content-Type: application/json" --data "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_blockNumber\", \"params\": []}" > /root/tmp/export/eth_blockNumber.json'
# Stop geth and zip up ethdb. # Stop geth and zip up ethdb.
echo -n "Exporting ethdb.... " docker exec $GETH_CONTAINER sh -c 'curl -s --location "localhost:8545" --header "Content-Type: application/json" --data "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockByNumber\", \"params\": [\"0x0\", false]}" > /root/tmp/export/eth_getBlockByNumber_0x0.json'
docker exec $GETH_CONTAINER sh -c 'curl -s --location "localhost:8545" --header "Content-Type: application/json" --data "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_blockNumber\", \"params\": []}" > /root/tmp/export/eth_blockNumber.json'
docker exec $GETH_CONTAINER sh -c "killall geth && sleep 2 && tar chzf /root/tmp/ethdb.tgz -C /root/tmp/export ." docker exec $GETH_CONTAINER sh -c "killall geth && sleep 2 && tar chzf /root/tmp/ethdb.tgz -C /root/tmp/export ."
# Copy ethdb to host. # Copy ethdb to host.
@@ -1,16 +0,0 @@
FROM golang:1.21-bullseye AS builder
# Copy files into image
WORKDIR /app
COPY . .
# Build the binary
RUN go build -v -o nitro .
# Reduce image size
FROM debian:bullseye-slim
RUN apt-get update
RUN apt-get install -y ca-certificates jq netcat
RUN rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /app/nitro .
@@ -3,6 +3,4 @@
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) docker build -t cerc/go-nitro:local -f ${CERC_REPO_BASE_DIR}/go-nitro/docker/local/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/go-nitro
docker build -t cerc/go-nitro:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/go-nitro
@@ -1,4 +0,0 @@
#!/usr/bin/env bash
# Build the laconic.com image
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
docker build -t cerc/laconic-dot-com:local -f ${CERC_REPO_BASE_DIR}/laconic.com/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/laconic.com
@@ -1,8 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Build cerc/plugeth-statediff # Build cerc/plugeth-statediff
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
# Pass Go auth token if present # This container build currently requires access to private dependencies in gitea
if [[ -n "${CERC_GO_AUTH_TOKEN}" ]]; then # so we check that the necessary access token has been supplied here, then pass it o the build
build_command_args="${build_command_args} --build-arg GIT_VDBTO_TOKEN=${CERC_GO_AUTH_TOKEN}" if [[ -z "${CERC_GO_AUTH_TOKEN}" ]]; then
echo "ERROR: CERC_GO_AUTH_TOKEN is not set" >&2
exit 1
fi fi
docker build -t cerc/plugeth-statediff:local ${build_command_args} ${CERC_REPO_BASE_DIR}/plugeth-statediff docker build -t cerc/plugeth-statediff:local ${build_command_args} --build-arg GIT_VDBTO_TOKEN=${CERC_GO_AUTH_TOKEN} ${CERC_REPO_BASE_DIR}/plugeth-statediff
@@ -1,8 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Build cerc/plugeth # Build cerc/plugeth
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
# Pass Go auth token if present # This container build currently requires access to private dependencies in gitea
if [[ -n "${CERC_GO_AUTH_TOKEN}" ]]; then # so we check that the necessary access token has been supplied here, then pass it o the build
build_command_args="${build_command_args} --build-arg GIT_VDBTO_TOKEN=${CERC_GO_AUTH_TOKEN}" if [[ -z "${CERC_GO_AUTH_TOKEN}" ]]; then
echo "ERROR: CERC_GO_AUTH_TOKEN is not set" >&2
exit 1
fi fi
docker build -t cerc/plugeth:local ${build_command_args} ${CERC_REPO_BASE_DIR}/plugeth docker build -t cerc/plugeth:local ${build_command_args} --build-arg GIT_VDBTO_TOKEN=${CERC_GO_AUTH_TOKEN} ${CERC_REPO_BASE_DIR}/plugeth
@@ -1,10 +1,13 @@
FROM node:16.17.1-alpine3.16 FROM node:16.17.1-alpine3.16
RUN apk --update --no-cache add git python3 alpine-sdk bash curl jq RUN apk --update --no-cache add git python3 alpine-sdk
WORKDIR /app WORKDIR /app
COPY . . COPY . .
RUN echo "Building erc20-watcher-ts" && \ RUN echo "Building watcher-ts" && \
git checkout v0.2.19 && \
yarn && yarn build yarn && yarn build
WORKDIR /app/packages/erc20-watcher
@@ -6,4 +6,4 @@ source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
# See: https://stackoverflow.com/a/246128/1701505 # See: https://stackoverflow.com/a/246128/1701505
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
docker build -t cerc/watcher-erc20:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/erc20-watcher-ts docker build -t cerc/watcher-erc20:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/watcher-ts
@@ -1,4 +1,4 @@
FROM node:18.17.1-alpine3.17 FROM node:18.17.1-alpine3.18
RUN apk --update --no-cache add git python3 alpine-sdk jq RUN apk --update --no-cache add git python3 alpine-sdk jq
-1
View File
@@ -14,7 +14,6 @@ cerc/laconic-registry-cli
cerc/laconic-console-host cerc/laconic-console-host
cerc/fixturenet-eth-geth cerc/fixturenet-eth-geth
cerc/fixturenet-eth-lighthouse cerc/fixturenet-eth-lighthouse
cerc/fixturenet-eth-genesis
cerc/watcher-ts cerc/watcher-ts
cerc/watcher-mobymask cerc/watcher-mobymask
cerc/watcher-erc20 cerc/watcher-erc20
+1 -2
View File
@@ -38,8 +38,7 @@ fixturenet-sushiswap-subgraph-v3
watcher-mobymask-v3 watcher-mobymask-v3
mobymask-app-v3 mobymask-app-v3
go-nitro go-nitro
nitro-rpc-client
nitro-contracts nitro-contracts
nitro-reverse-payment-proxy
mobymask-snap mobymask-snap
ponder ponder
ipld-eth-server-payments
+1 -1
View File
@@ -4,8 +4,8 @@ repos:
- git.vdb.to/cerc-io/go-ethereum@v1.11.6-statediff-v5 - git.vdb.to/cerc-io/go-ethereum@v1.11.6-statediff-v5
- git.vdb.to/cerc-io/ipld-eth-db@v5 - git.vdb.to/cerc-io/ipld-eth-db@v5
- git.vdb.to/cerc-io/ipld-eth-server@v1.11.6-statediff-v5 - git.vdb.to/cerc-io/ipld-eth-server@v1.11.6-statediff-v5
- github.com/cerc-io/watcher-ts
- github.com/dboreham/foundry - github.com/dboreham/foundry
- github.com/cerc-io/erc20-watcher-ts
containers: containers:
- cerc/foundry - cerc/foundry
- cerc/go-ethereum - cerc/go-ethereum
@@ -2,14 +2,14 @@ version: "1.1"
name: fixturenet-laconic-loaded name: fixturenet-laconic-loaded
description: "A full featured laconic fixturenet" description: "A full featured laconic fixturenet"
repos: repos:
- git.vdb.to/cerc-io/laconicd - github.com/cerc-io/laconicd
- github.com/lirewine/debug - github.com/lirewine/debug
- github.com/lirewine/crypto - github.com/lirewine/crypto
- github.com/lirewine/gem - github.com/lirewine/gem
- github.com/lirewine/sdk - github.com/lirewine/sdk
- git.vdb.to/cerc-io/laconic-sdk - github.com/cerc-io/laconic-sdk
- git.vdb.to/cerc-io/laconic-registry-cli - github.com/cerc-io/laconic-registry-cli
- git.vdb.to/cerc-io/laconic-console - github.com/cerc-io/laconic-console
npms: npms:
- laconic-sdk - laconic-sdk
- laconic-registry-cli - laconic-registry-cli
@@ -2,9 +2,9 @@ version: "1.0"
name: fixturenet-laconicd name: fixturenet-laconicd
description: "A laconicd fixturenet" description: "A laconicd fixturenet"
repos: repos:
- git.vdb.to/cerc-io/laconicd - github.com/cerc-io/laconicd
- git.vdb.to/cerc-io/laconic-sdk - github.com/cerc-io/laconic-sdk
- git.vdb.to/cerc-io/laconic-registry-cli - github.com/cerc-io/laconic-registry-cli
npms: npms:
- laconic-sdk - laconic-sdk
- laconic-registry-cli - laconic-registry-cli
+7 -34
View File
@@ -1,6 +1,6 @@
# fixturenet-payments # fixturenet-payments
Instructions to setup and deploy an end-to-end fixturenet-payments stack, on a local machine. Some tips are included for running on a remote cloud machine. Instructions to setup and deploy an end-to-end fixturenet-payments stack
## Setup ## Setup
@@ -22,48 +22,21 @@ Deploy the stack:
```bash ```bash
laconic-so --stack fixturenet-payments deploy --cluster payments up laconic-so --stack fixturenet-payments deploy --cluster payments up
```
```bash
# Exposed on host ports: # Exposed on host ports:
# 32***: geth in statediffing mode and ipld-eth-server(s) # 4005: go-nitro node's RPC endpoint
# 4005: in-process go-nitro node's RPC endpoint # 5005: go-nitro node's p2p endpoint
# 3005: in-process go-nitro node's p2p TCP endpoint # 8081: reverse payment proxy's RPC endpoint
# 5005: in-process go-nitro node's p2p WS endpoint
# 4006: out-of-process go-nitro node's RPC endpoint
# 3006: out-of-process go-nitro node's p2p TCP endpoint
# 5006: out-of-process go-nitro node's p2p WS endpoint
# 15432: MobyMask v3 watcher's db endpoint # 15432: MobyMask v3 watcher's db endpoint
# 3001: MobyMask v3 watcher endpoint # 3001: MobyMask v3 watcher endpoint
# 9090: MobyMask v3 watcher relay node endpoint # 9090: MobyMask v3 watcher relay node endpoint
# 8080: MobyMask snap # 8080: MobyMask snap
# 3004: MobyMask v3 app # 3004: MobyMask v3 app
# 42070: Ponder indexer-1
# 42071: Ponder indexer-2
# 42069: Ponder watcher
``` ```
If running in the cloud, ensure all the of the above ports are open. The geth port can be retrieved with:
```bash
docker port payments-fixturenet-eth-geth-1-1 8545
```
Then for every port above, run each line in a new terminal window (or use `screen`):
```bash
ssh -L 4005:localhost:4005 user@<your-ip>
ssh -L 5005:localhost:5005 user@<your-ip>
ssh -L 8081:localhost:8081 user@<your-ip>
# ... and so on for every port
```
This will allow you to access the entirety of the app as if it were running locally.
## Demo ## Demo
- Follow the [mobymask-demo](./mobymask-demo.md) to try out MobyMask end-to-end payments. Follow the [demo](./demo.md) to try out end-to-end payments
- Follow the [ponder-demo](./ponder-demo.md) to try out Ponder end-to-end payments.
## Clean up ## Clean up
@@ -77,8 +50,8 @@ Clear volumes created by this stack:
```bash ```bash
# List all relevant volumes # List all relevant volumes
docker volume ls -q --filter "name=payments" docker volume ls -q --filter "name=[payments"
# Remove all the listed volumes # Remove all the listed volumes
docker volume rm $(docker volume ls -q --filter "name=payments") docker volume rm $(docker volume ls -q --filter "name=[payments")
``` ```
@@ -3,14 +3,16 @@
Stack components: Stack components:
* `ipld-eth-db` database for statediffed data * `ipld-eth-db` database for statediffed data
* Local geth + lighthouse blockchain "fixturenet" running in statediffing mode * Local geth + lighthouse blockchain "fixturenet" running in statediffing mode
* `ipld-eth-server-1` which runs an ETH RPC API and a GQL server; they both serve data from `ipld-eth-db` * `ipld-eth-server` which runs an ETH RPC API and a GQL server; serves data from `ipld-eth-db`
* It runs an in-process go-nitro node for payments required for configured RPC requests * A go-nitro deployment acting as the Nitro node for `ipld-eth-server`
* A MobyMask v3 watcher that pays the `ipld-eth-server-1` for ETH RPC requests * A modified reverse payment proxy server (based on the one from go-nitro) that proxies requests to `ipld-eth-server`'s RPC endpoint; it talks to `ipld-eth-server`'s Nitro node to accept and validate payments required for configured RPC requests
* A MobyMask v3 watcher that pays the `ipld-eth-server` for ETH RPC requests
* A MobyMask v3 app that pays the watcher for reads (GQL queries) and writes * A MobyMask v3 app that pays the watcher for reads (GQL queries) and writes
* An example ERC20 Ponder app that pays the `ipld-eth-server` for ETH RPC requests
## Setup ## Setup
* On starting the stack, MobyMask watcher creates a payment channel with the `ipld-eth-server-1`'s (in-process) Nitro node. Check watcher logs and wait for the same: * On starting the stack, MobyMask watcher creates a payment channel with the `ipld-eth-server`'s Nitro node. Check watcher logs and wait for the same:
```bash ```bash
docker logs -f $(docker ps -aq --filter name="mobymask-watcher-server") docker logs -f $(docker ps -aq --filter name="mobymask-watcher-server")
@@ -36,7 +38,7 @@ Stack components:
* Check the payment channel status: * Check the payment channel status:
```bash ```bash
docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -s false -h ipld-eth-server-1 -p 4005" docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -h go-nitro -p 4005"
# Expected output: # Expected output:
# { # {
@@ -52,10 +54,10 @@ Stack components:
# } # }
``` ```
* In another terminal, check `ipld-eth-server-1`'s logs to keep track of incoming payments and RPC requests from the MobyMask watcher: * In another terminal, check the reverse payment proxy server's logs to keep track of incoming payments and RPC requests:
```bash ```bash
docker logs -f $(docker ps -aq --filter name="ipld-eth-server-1") docker logs -f $(docker ps -aq --filter name="nitro-reverse-payment-proxy")
``` ```
* MetaMask flask wallet setup for running the MobyMask app: * MetaMask flask wallet setup for running the MobyMask app:
@@ -133,35 +135,31 @@ Stack components:
```bash ```bash
# Expected output: # Expected output:
# ... # ...
# laconic:payments Received a payment voucher of 50 from 0x86804299822212c070178B5135Ba6DdAcFC357D3
# laconic:payments Serving a paid query for 0x86804299822212c070178B5135Ba6DdAcFC357D3 # laconic:payments Serving a paid query for 0x86804299822212c070178B5135Ba6DdAcFC357D3
# vulcanize:resolver isPhisher 0x98ae4f9e9d01cc892adfe6871e1db0287039e0c183d3b5bb31d724228c114744 0x2B6AFbd4F479cE4101Df722cF4E05F941523EaD9 TWT:ash1 # vulcanize:resolver isPhisher 0x98ae4f9e9d01cc892adfe6871e1db0287039e0c183d3b5bb31d724228c114744 0x2B6AFbd4F479cE4101Df722cF4E05F941523EaD9 TWT:ash1
# vulcanize:indexer isPhisher: db miss, fetching from upstream server # vulcanize:indexer isPhisher: db miss, fetching from upstream server
# laconic:payments Making RPC call: eth_chainId # laconic:payments Making RPC call: eth_chainId
# laconic:payments Making RPC call: eth_getBlockByHash # laconic:payments Making RPC call: eth_getBlockByHash
# 2023-10-13T06:33:58.443Z ts-nitro:engine{"msg":"Sent message","_msg":{"to":"0xAAA662","from":"0xBBB676", "payloadSummaries":[],"proposalSummaries":[],"payments":[{"amount":200,"channelId":"0x9a4bdfe03c8e72f368aab07e6bd18f1cd6821170e1a93e59864aad6ee6a853a2"}],"rejectedObjectives":[]}}
# laconic:payments Making RPC call: eth_chainId # laconic:payments Making RPC call: eth_chainId
# laconic:payments Making RPC call: eth_getStorageAt # laconic:payments Making RPC call: eth_getStorageAt
# 2023-10-13T06:34:00.483Z ts-nitro:engine {"msg":"Sent message","_msg":{"to":"0xAAA662","from":"0xBBB676",# "payloadSummaries":[],"proposalSummaries":[],"payments":[{"amount":300,"channelId":"0x9a4bdfe03c8e72f368aab07e6bd18f1cd6821170e1a93e59864aad6ee6a853a2"}],"rejectedObjectives":[]}}
``` ```
* The watcher makes several ETH RPC requests to `ipld-eth-server-1` to fetch data required for satisfying the GQL request(s); check `ipld-eth-server-1` logs for charged RPC requests (`eth_getBlockByHash`, `eth_getBlockByNumber`, `eth_getStorageAt`): * The watcher makes several ETH RPC requests to `ipld-eth-server` to fetch data required for satisfying the GQL request(s); check the payment proxy server logs for charged RPC requests (`eth_getBlockByHash`, `eth_getBlockByNumber`, `eth_getStorageAt`):
```bash ```bash
# Expected output: # Expected output:
# ... # ...
# 2023/10/13 06:34:57 INFO Received a voucher payer=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 amount=100 # {"time":"2023-10-06T06:46:52.769009314Z","level":"DEBUG","msg":"Serving RPC request","method":"eth_chainId"}
# 2023/10/13 06:34:59 INFO Serving a paid RPC request method=eth_getBlockByHash cost=50 sender=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 # {"time":"2023-10-06T06:46:52.773006426Z","level":"DEBUG","msg":"Serving RPC request","method":"eth_getBlockByNumber"}
# time="2023-10-13T06:34:59Z" level=debug msg=START api_method=eth_getBlockByHash api_params="[0x46411a554f30e607bdd79cd157a60a7c8b314c0709557be3357ed2fef53d6c3d false]" api_reqid=52 conn="192.168.64.4:59644" user_id= uuid=a1893211-6992-11ee-a67a-0242c0a8400c # {"time":"2023-10-06T06:46:52.811142054Z","level":"DEBUG","msg":"Request cost","cost-per-byte":1,"response-length":1480,"cost":1480,"method":"eth_getBlockByNumber"}
# WARN [10-13|06:34:59.133] Attempting GerRPCCalls, but default PluginLoader has not been initialized # {"time":"2023-10-06T06:46:52.811418494Z","level":"DEBUG","msg":"sent message","address":"0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE","method":"receive_voucher"}
# time="2023-10-13T06:34:59Z" level=debug msg=END api_method=eth_getBlockByHash api_params="[0x46411a554f30e607bdd79cd157a60a7c8b314c0709557be3357ed2fef53d6c3d false]" api_reqid=52 conn="192.168.64.4:59644" duration=5 user_id= uuid=a1893211-6992-11ee-a67a-0242c0a8400c # {"time":"2023-10-06T06:46:52.812557482Z","level":"DEBUG","msg":"Received voucher","delta":5000}
# 2023/10/13 06:34:59 INFO Serving a free RPC request method=eth_chainId # ...
# time="2023-10-13T06:34:59Z" level=debug msg=START api_method=eth_chainId api_params="[]" api_reqid=53 conn="192.168.64.4:59658" user_id= uuid=a18a96d9-6992-11ee-a67a-0242c0a8400c # {"time":"2023-10-06T06:46:52.87525215Z","level":"DEBUG","msg":"Serving RPC request","method":"eth_getStorageAt"}
# time="2023-10-13T06:34:59Z" level=debug msg=END api_method=eth_chainId api_params="[]" api_reqid=53 conn="192.168.64.4:59658" duration=0 user_id= uuid=a18a96d9-6992-11ee-a67a-0242c0a8400c # {"time":"2023-10-06T06:46:52.882859654Z","level":"DEBUG","msg":"Request cost","cost-per-byte":1,"response-length":104,"cost":104,"method":"eth_getStorageAt"}
# 2023/10/13 06:34:59 INFO Received a voucher payer=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 amount=100 # {"time":"2023-10-06T06:46:52.882946485Z","level":"DEBUG","msg":"sent message","address":"0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE","method":"receive_voucher"}
# 2023/10/13 06:35:01 INFO Serving a paid RPC request method=eth_getStorageAt cost=50 sender=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 # {"time":"2023-10-06T06:46:52.884012641Z","level":"DEBUG","msg":"Received voucher","delta":5000}
# time="2023-10-13T06:35:01Z" level=debug msg=START api_method=eth_getStorageAt api_params="[0x2b6afbd4f479ce4101df722cf4e05f941523ead9 0xf76621c2cc1c1705fabbc22d30ffc5ded7f26e4995feb8d1c9812a2697ba1278 0x46411a554f30e607bdd79cd157a60a7c8b314c0709557be3357ed2fef53d6c3d]" api_reqid=54 conn="192.168.64.4:59660" user_id= uuid=a2bd75d2-6992-11ee-a67a-0242c0a8400c # {"time":"2023-10-06T06:46:52.884032961Z","level":"DEBUG","msg":"Destination request","url":"http://ipld-eth-server:8081/"}
# time="2023-10-13T06:35:01Z" level=debug msg=END api_method=eth_getStorageAt api_params="[0x2b6afbd4f479ce4101df722cf4e05f941523ead9 0xf76621c2cc1c1705fabbc22d30ffc5ded7f26e4995feb8d1c9812a2697ba1278 0x46411a554f30e607bdd79cd157a60a7c8b314c0709557be3357ed2fef53d6c3d]" api_reqid=54 conn="192.168.64.4:59660" duration=7 user_id= uuid=a2bd75d2-6992-11ee-a67a-0242c0a8400c
``` ```
* Change the amount besides `PAY` button in debug panel to `>=100` for phisher reports next * Change the amount besides `PAY` button in debug panel to `>=100` for phisher reports next
@@ -185,10 +183,10 @@ Stack components:
# } # }
``` ```
* Check the watcher - ipld-eth-server-1 payment channel status after a few requests: * Check the watcher - ipld-eth-server payment channel status after a few requests:
```bash ```bash
docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -s false -h ipld-eth-server-1 -p 4005" docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -h go-nitro -p 4005"
# Expected output ('PaidSoFar' should be non zero): # Expected output ('PaidSoFar' should be non zero):
# { # {
@@ -204,6 +202,65 @@ Stack components:
# } # }
``` ```
### ERC20 Ponder App
* Run the ponder app in it's container:
```bash
docker exec -it payments-ponder-app-1 bash -c "pnpm start"
# Expected output:
# 09:58:54.288 INFO payment Creating ledger channel with nitro node 0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE
# ...
# 09:59:14.230 INFO payment Creating payment channel with nitro node 0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE
# ...
# 09:59:14.329 INFO payment Using payment channel 0x10f049519bc3f862e2b26e974be8666886228f30ea54aab06e2f23718afffab0
```
* On starting the Ponder app, it creates a payment channel with the `ipld-eth-server`'s Nitro node and then starts the historical sync service
* The sync service makes several ETH RPC requests to the `ipld-eth-server` to fetch required data; check the payment proxy server logs for charged RPC requests (`eth_getBlockByNumber`, `eth_getLogs`)
```bash
# Expected output:
# ...
# {"time":"2023-10-06T06:51:45.214478402Z","level":"DEBUG","msg":"Serving RPC request","method":"eth_getBlockByNumber"}
# {"time":"2023-10-06T06:51:45.22251171Z","level":"DEBUG","msg":"Request cost","cost-per-byte":1,"response-length":576,"cost":576,"method":"eth_getBlockByNumber"}
# {"time":"2023-10-06T06:51:45.222641963Z","level":"DEBUG","msg":"sent message","address":"0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE","method":"receive_voucher"}
# {"time":"2023-10-06T06:51:45.224042391Z","level":"DEBUG","msg":"Received voucher","delta":5000}
# {"time":"2023-10-06T06:51:45.224061411Z","level":"DEBUG","msg":"Destination request","url":"http://ipld-eth-server:8081/"}
# {"time":"2023-10-06T06:51:45.242064953Z","level":"DEBUG","msg":"Serving RPC request","method":"eth_getLogs"}
# {"time":"2023-10-06T06:51:45.249118517Z","level":"DEBUG","msg":"Request cost","cost-per-byte":1,"response-length":61,"cost":61,"method":"eth_getLogs"}
# {"time":"2023-10-06T06:51:45.249189892Z","level":"DEBUG","msg":"sent message","address":"0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE","method":"receive_voucher"}
# {"time":"2023-10-06T06:51:45.249743149Z","level":"DEBUG","msg":"Received voucher","delta":5000}
# {"time":"2023-10-06T06:51:45.249760631Z","level":"DEBUG","msg":"Destination request","url":"http://ipld-eth-server:8081/"}
# ...
```
* Export the payment channel id to a variable:
```bash
export PONDER_UPSTREAM_PAYMENT_CHANNEL=<PAYMENT_CHANNEL_ID>
```
* Check the ponder - ipld-eth-server payment channel status:
```bash
docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $PONDER_UPSTREAM_PAYMENT_CHANNEL -h go-nitro -p 4005"
# Expected output ('PaidSoFar' is non zero):
# {
# ID: '0x1178ac0f2a43e54a122216fa6afdd30333b590e49e50317a1f9274a591da0f96',
# Status: 'Open',
# Balance: {
# AssetAddress: '0x0000000000000000000000000000000000000000',
# Payee: '0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce',
# Payer: '0x67d5b55604d1af90074fcb69b8c51838fff84f8d',
# PaidSoFar: 215000n,
# RemainingFunds: 999785000n
# }
# }
```
## Clean Up ## Clean Up
@@ -215,9 +272,4 @@ Stack components:
await clearNodeStorage() await clearNodeStorage()
``` ```
* Run the following in the browser console to clear data in local storage:
```bash
localStorage.clear()
```
* On a fresh restart, clear activity tab data in MetaMask for concerned accounts * On a fresh restart, clear activity tab data in MetaMask for concerned accounts
@@ -1,267 +0,0 @@
# Demo
Stack components:
* `ipld-eth-db` database for statediffed data
* Local geth + lighthouse blockchain "fixturenet" running in statediffing mode
* `ipld-eth-server-2` which runs an ETH RPC API and a GQL server; they both serve data from `ipld-eth-db`
* A go-nitro deployment acting as the remote Nitro node for `ipld-eth-server-2`
* Example ERC20 Ponder apps
* `ponder-app-indexer-1` that pays the `ipld-eth-server-2` for ETH RPC requests
* `ponder-app-indexer-2` that pays `ponder-app-indexer-1` for GQL queries
* `ponder-app-watcher` that pays `ponder-app-indexer-2` for GQL queries
## Setup
* In a terminal, check `ipld-eth-server-2`'s logs to keep track of incoming RPC requests from the `ponder-app-indexer-1`:
```bash
docker logs -f $(docker ps -aq --filter name="ipld-eth-server-2")
```
## Run
### ERC20 Ponder App
* Run the first indexer Ponder app:
```bash
docker exec -it payments-ponder-app-indexer-1-1 bash -c "DEBUG=laconic:payments pnpm start"
# Expected output:
# 12:57:03.751 INFO payment Nitro node setup with address 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d
# laconic:payments Starting voucher subscription... +0ms
# ...
# 09:58:54.288 INFO payment Creating ledger channel with nitro node 0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e ...
# 09:59:14.230 INFO payment Creating payment channel with nitro node 0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e ...
# 09:59:14.329 INFO payment Using payment channel 0x1ff59db391b7a55bed723b930ab53c80e7ce857487c1e58771aa5a0737d71625
```
* Export the payment channel id to a variable:
```bash
export PONDER_UPSTREAM_PAYMENT_CHANNEL=<PAYMENT_CHANNEL_ID>
```
* On starting the Ponder app in indexer mode, it creates a payment channel with the `ipld-eth-server-2`'s (external) Nitro node and then starts the historical sync service
* The sync service makes several ETH RPC requests to the `ipld-eth-server-2` to fetch required data; check the `ipld-eth-server-2` logs for charged RPC requests (`eth_getBlockByNumber`, `eth_getLogs`):
```bash
# Expected output:
# ...
# 2023/10/18 05:29:38 INFO Serving a paid RPC request method=eth_getBlockByNumber cost=50 sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d
# time="2023-10-18T05:29:38Z" level=debug msg=START api_method=eth_getBlockByNumber api_params="[latest true]" api_reqid=0 conn="172.26.0.19:42306" user_id= uuid=54992dc3-6d77-11ee-9ede-0242ac1a000f
# WARN [10-18|05:29:38.292] Attempting GerRPCCalls, but default PluginLoader has not been initialized
# time="2023-10-18T05:29:38Z" level=debug msg=END api_method=eth_getBlockByNumber api_params="[latest true]" api_reqid=0 conn="172.26.0.19:42306" duration=22 user_id= uuid=54992dc3-6d77-11ee-9ede-0242ac1a000f
# ...
# 2023/10/18 05:29:40 INFO Serving a paid RPC request method=eth_getLogs cost=50 sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d
# WARN [10-18|05:29:40.340] Attempting GerRPCCalls, but default PluginLoader has not been initialized
# time="2023-10-18T05:29:40Z" level=debug msg="retrieving log cids for receipt ids"
# ...
```
* Check the Ponder - ipld-eth-server-2 payment channel status:
```bash
docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $PONDER_UPSTREAM_PAYMENT_CHANNEL -s false -h go-nitro -p 4006"
# Expected output ('PaidSoFar' is non zero):
# {
# ID: '0x1ff59db391b7a55bed723b930ab53c80e7ce857487c1e58771aa5a0737d71625',
# Status: 'Open',
# Balance: {
# AssetAddress: '0x0000000000000000000000000000000000000000',
# Payee: '0x660a4bef3fbc863fcd8d3cdb39242ae513d7d92e',
# Payer: '0x67d5b55604d1af90074fcb69b8c51838fff84f8d',
# PaidSoFar: 7200n,
# RemainingFunds: 999992800n
# }
# }
```
* In another terminal run the second indexer Ponder app:
```bash
docker exec -it payments-ponder-app-indexer-2-1 bash -c "DEBUG=laconic:payments pnpm start"
# Expected output:
# 08:00:28.701 INFO payment Nitro node setup with address 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01
# laconic:payments Starting voucher subscription... +0ms
# ...
# 09:58:54.288 INFO payment Creating ledger channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ...
# 09:59:14.230 INFO payment Creating payment channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ...
# 09:59:14.329 INFO payment Using payment channel 0xfbf9d7eb7c18446883c7f57f4c94db5607f414a224b3e921c787db07371d2a70
```
* On starting indexer Ponder app, it creates a payment channel with first indexer and then starts the sync services
* Check logs in `ponder-indexer-1` to see payments made from `ponder-indexer-2` from GQL queries to fetch network data
```bash
# ...
# laconic:payments Received a payment voucher of 100 from 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +23ms
# laconic:payments Serving a paid query for 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +0ms
# 13:01:05.671 DEBUG payment Verified payment for GQL queries getEthLogs
# laconic:payments Received a payment voucher of 100 from 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +20ms
# laconic:payments Serving a paid query for 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +0ms
# 13:01:05.691 DEBUG payment Verified payment for GQL queries getEthBlock
# 13:01:07.598 INFO realtime Fetched missing blocks [686, 687] (network=fixturenet)
# 13:01:07.598 DEBUG realtime Started processing new head block 686 (network=fixturenet)
# ...
```
* Following are the example GQL queries (with payment headers) `ponder-indexer-2` makes to `ponder-indexer-1` for fetching data
```graphql
{
getEthLogs(
chainId: 1212,
address: "0x6325439389e0797ab35752b4f43a14c004f22a9c",
fromBlock: 100,
toBlock: 200,
) {
address
blockHash
blockNumber
data
logIndex
removed
topics
transactionHash
transactionIndex
}
getEthBlock(
chainId: 1212,
blockNumber: 150,
fullTransactions: false
) {
baseFeePerGas
difficulty
extraData
gasLimit
gasUsed
hash
logsBloom
miner
mixHash
nonce
number
parentHash
receiptsRoot
sha3Uncles
size
stateRoot
timestamp
totalDifficulty
transactionsRoot
txHashes
}
}
```
* In another terminal run the Ponder app in watcher mode:
```bash
docker exec -it payments-ponder-app-watcher-1 bash -c "DEBUG=laconic:payments pnpm start"
# Expected output:
# 11:23:22.057 DEBUG app Started using config file: ponder.config.ts
# 08:02:12.548 INFO payment Nitro node setup with address 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db
# laconic:payments Starting voucher subscription... +0ms
# 08:02:17.417 INFO payment Creating ledger channel with nitro node 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 ...
# 08:02:37.135 INFO payment Creating payment channel with nitro node 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 ...
# 08:02:37.313 INFO payment Using payment channel 0xc48622577dfa389283beb19ed946274eb034587d72e61445dc997304be671f1a
# ...
# 11:23:22.436 INFO server Started responding as healthy
```
* Check the terminal of the second indexer Ponder app. Logs of payment for `getLogEvents` queries can be seen:
```bash
# ...
# 08:02:37.763 DEBUG realtime Finished processing new head block 89 (network=fixturenet)
# laconic:payments Received a payment voucher of 50 from 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +444ms
# laconic:payments Serving a paid query for 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +1ms
# 08:02:37.804 DEBUG payment Verified payment for GQL queries getLogEvents
# laconic:payments Received a payment voucher of 50 from 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +45ms
# laconic:payments Serving a paid query for 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +0ms
# 08:02:37.849 DEBUG payment Verified payment for GQL queries getLogEvents
```
* Following are the example GQL queries (with payment headers) `ponder-watcher` makes to `ponder-indexer-2` for fetching data
```graphql
getLogEvents(
fromTimestamp: 1695303079,
toTimestamp: 1695304156,
filters: [
{
name: "AdventureGold"
chainId: 1212,
address: ["0x6325439389e0797ab35752b4f43a14c004f22a9c"],
fromBlock: 100,
toBlock: 200,
includeEventSelectors: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
}
]
) {
events {
transaction {
hash
}
log {
id
}
block {
number
}
}
metadata {
pageEndsAtTimestamp
isLastPage
}
}
```
* Open watcher Ponder app endpoint http://localhost:42069
* Try GQL query to see transfer events
```graphql
{
transferEvents (orderBy: "timestamp", orderDirection: "desc") {
id
amount
from {
id
}
to {
id
}
timestamp
}
}
```
* Transfer an ERC20 token on chain
* Get the deployed ERC20 token address
```bash
export TOKEN_ADDRESS=$(docker exec payments-ponder-er20-contracts-1 jq -r '.address' ./deployment/erc20-address.json)
```
* Transfer token
```bash
docker exec -it payments-ponder-er20-contracts-1 bash -c "yarn token:transfer:docker --token ${TOKEN_ADDRESS} --to 0xe22AD83A0dE117bA0d03d5E94Eb4E0d80a69C62a --amount 5000"
```
* Wait for a log in watcher Ponder app
```bash
06:40:47.567 INFO handlers Processed 1 event (up to Oct 19, 2023)
```
* Check the GQL query again in http://localhost:42069 to see a new `TransferEvent` entity
+11 -16
View File
@@ -6,22 +6,19 @@ repos:
- git.vdb.to/cerc-io/go-ethereum@v1.11.6-statediff-v5 - git.vdb.to/cerc-io/go-ethereum@v1.11.6-statediff-v5
- git.vdb.to/cerc-io/lighthouse - git.vdb.to/cerc-io/lighthouse
- git.vdb.to/cerc-io/ipld-eth-db@v5 - git.vdb.to/cerc-io/ipld-eth-db@v5
# ipld-eth-server with payments -- to be used by ipld-eth-server-payments pod - git.vdb.to/cerc-io/ipld-eth-server@v1.11.6-statediff-v5
- git.vdb.to/cerc-io/ipld-eth-server@payments # nitro repos
# nitro repo - github.com/cerc-io/ts-nitro@v0.1.13
- github.com/cerc-io/ts-nitro@v0.1.15 - github.com/cerc-io/go-nitro@v0.1.1-ts-port-0.1.5
- github.com/cerc-io/go-nitro@v0.1.2-ts-port-0.1.9
# mobymask watcher repos # mobymask watcher repos
- github.com/cerc-io/watcher-ts@v0.2.66 - github.com/cerc-io/watcher-ts@v0.2.63
# this is mobymask-v3 - github.com/cerc-io/mobymask-v2-watcher-ts@v0.2.2
- github.com/cerc-io/mobymask-v2-watcher-ts@v0.2.4
- github.com/cerc-io/MobyMask@v0.1.3 - github.com/cerc-io/MobyMask@v0.1.3
# mobymask app repos # mobymask app repos
- github.com/cerc-io/mobymask-snap - github.com/cerc-io/mobymask-snap
- github.com/cerc-io/mobymask-ui@v0.2.2 - github.com/cerc-io/mobymask-ui@v0.2.1
# ponder repo # ponder repo
- github.com/cerc-io/ponder@laconic-esm - github.com/cerc-io/ponder@laconic
- github.com/cerc-io/erc20-watcher-ts
containers: containers:
# fixturenet images # fixturenet images
- cerc/go-ethereum - cerc/go-ethereum
@@ -44,16 +41,14 @@ containers:
- cerc/mobymask-ui - cerc/mobymask-ui
# ponder image # ponder image
- cerc/ponder - cerc/ponder
- cerc/watcher-erc20
pods: pods:
- fixturenet-eth - fixturenet-eth
- ipld-eth-server-payments - ipld-eth-server
- ipld-eth-db - ipld-eth-db
- nitro-contracts - nitro-contracts
- go-nitro - go-nitro
- nitro-rpc-client - nitro-reverse-payment-proxy
- watcher-mobymask-v3 - watcher-mobymask-v3
- mobymask-snap - mobymask-snap
- mobymask-app-v3 - mobymask-app-v3
- ponder-indexer - ponder
- ponder-watcher
@@ -12,7 +12,7 @@ See `stacks/fixturenet-eth/README.md` for more information.
* cerc/tx-spammer * cerc/tx-spammer
## Deploy the stack ## Deploy the stack
Note: if there are any private Go dependencies, `CERC_GO_AUTH_TOKEN` must be set to a valid Gitea access token before running the `build-containers` command. Note: since some Go dependencies are currently private, `CERC_GO_AUTH_TOKEN` must be set to a valid Gitea access token before running the `build-containers` command.
``` ```
$ laconic-so --stack fixturenet-plugeth-tx setup-repositories $ laconic-so --stack fixturenet-plugeth-tx setup-repositories
$ laconic-so --stack fixturenet-plugeth-tx build-containers $ laconic-so --stack fixturenet-plugeth-tx build-containers
@@ -1,9 +0,0 @@
# laconic-dot-com
```
laconic-so --stack laconic-dot-com setup-repositories
laconic-so --stack laconic-dot-com build-containers
laconic-so --stack laconic-dot-com deploy init --output laconic-website-spec.yml --map-ports-to-host localhost-same
laconic-so --stack laconic-dot-com deploy create --spec-file laconic-website-spec.yml --deployment-dir lx-website
laconic-so deployment --dir lx-website start
```
@@ -1,8 +0,0 @@
version: "0.1"
name: laconic-dot-com
repos:
- github.com/LaconicNetwork/laconic.com@v0.0.1
containers:
- cerc/laconic-dot-com
pods:
- laconic-dot-com
@@ -13,11 +13,11 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>. # along with this program. If not, see <http:#www.gnu.org/licenses/>.
from app.util import get_yaml from laconic_stack_orchestrator.util import get_yaml
from app.deploy_types import DeployCommandContext, LaconicStackSetupCommand, DeploymentContext from laconic_stack_orchestrator.deploy_types import DeployCommandContext, LaconicStackSetupCommand, DeploymentContext
from app.stack_state import State from laconic_stack_orchestrator.stack_state import State
from app.deploy_util import VolumeMapping, run_container_command from laconic_stack_orchestrator.deploy_util import VolumeMapping, run_container_command
from app.command_types import CommandOptions from laconic_stack_orchestrator.command_types import CommandOptions
from enum import Enum from enum import Enum
from pathlib import Path from pathlib import Path
from shutil import copyfile, copytree from shutil import copyfile, copytree
+4 -4
View File
@@ -2,11 +2,11 @@ version: "1.0"
description: "MobyMask v3 stack" description: "MobyMask v3 stack"
name: mobymask-v3 name: mobymask-v3
repos: repos:
- github.com/cerc-io/ts-nitro@v0.1.13 - github.com/cerc-io/ts-nitrov0.1.12
- github.com/cerc-io/watcher-ts@v0.2.63 - github.com/cerc-io/watcher-ts@v0.2.57
- github.com/cerc-io/mobymask-v2-watcher-ts@v0.2.2 - github.com/cerc-io/mobymask-v2-watcher-ts@v3 # TODO: Update after fixes
- github.com/cerc-io/MobyMask@v0.1.3 - github.com/cerc-io/MobyMask@v0.1.3
- github.com/cerc-io/mobymask-ui@v0.2.1 - github.com/cerc-io/mobymask-ui@v0.2.0
containers: containers:
- cerc/nitro-contracts - cerc/nitro-contracts
- cerc/watcher-ts - cerc/watcher-ts
+1 -4
View File
@@ -23,7 +23,7 @@ laconic-so --stack mobymask-v3 build-containers --exclude cerc/mobymask-ui
Create and update an env file to be used in the next step ([defaults](../../config/watcher-mobymask-v3/mobymask-params.env)): Create and update an env file to be used in the next step ([defaults](../../config/watcher-mobymask-v3/mobymask-params.env)):
```bash ```bash
# External ETH RPC endpoint for contract(s) deployment # External ETH RPC endpoint (L2 Optimism geth)
CERC_ETH_RPC_ENDPOINT= CERC_ETH_RPC_ENDPOINT=
# External ETH RPC endpoint used for queries in the watcher # External ETH RPC endpoint used for queries in the watcher
@@ -32,9 +32,6 @@ Create and update an env file to be used in the next step ([defaults](../../conf
# External ETH RPC endpoint used for mutations in the watcher # External ETH RPC endpoint used for mutations in the watcher
CERC_ETH_RPC_MUTATION_ENDPOINT= CERC_ETH_RPC_MUTATION_ENDPOINT=
# External ETH endpoint used by watcher's Nitro node
CERC_NITRO_CHAIN_URL=
# Specify the an account PK for contract deployment # Specify the an account PK for contract deployment
CERC_PRIVATE_KEY_DEPLOYER= CERC_PRIVATE_KEY_DEPLOYER=
+1 -1
View File
@@ -2,7 +2,7 @@ version: "1.1"
name: package-registry name: package-registry
description: "Local Package Registry" description: "Local Package Registry"
repos: repos:
- git.vdb.to/cerc-io/hosting - github.com/cerc-io/hosting
- gitea.com/gitea/act_runner - gitea.com/gitea/act_runner
containers: containers:
- cerc/act-runner - cerc/act-runner
+4 -4
View File
@@ -13,10 +13,10 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>. # along with this program. If not, see <http:#www.gnu.org/licenses/>.
from app.util import get_yaml from laconic_stack_orchestrator.util import get_yaml
from app.deploy_types import DeployCommandContext from laconic_stack_orchestrator.deploy_types import DeployCommandContext
from app.stack_state import State from laconic_stack_orchestrator.stack_state import State
from app.deploy_util import VolumeMapping, run_container_command from laconic_stack_orchestrator.deploy_util import VolumeMapping, run_container_command
from pathlib import Path from pathlib import Path
default_spec_file_content = """config: default_spec_file_content = """config:
+1 -1
View File
@@ -2,7 +2,7 @@ version: "1.0"
name: test name: test
description: "A test stack" description: "A test stack"
repos: repos:
- git.vdb.to/cerc-io/laconicd - github.com/cerc-io/laconicd
- git.vdb.to/cerc-io/test-project@test-branch - git.vdb.to/cerc-io/test-project@test-branch
containers: containers:
- cerc/test-container - cerc/test-container
+13 -27
View File
@@ -20,16 +20,17 @@ import copy
import os import os
import sys import sys
from dataclasses import dataclass from dataclasses import dataclass
from decouple import config
from importlib import resources from importlib import resources
import subprocess import subprocess
from python_on_whales import DockerClient, DockerException from python_on_whales import DockerClient, DockerException
import click import click
from pathlib import Path from pathlib import Path
from app.util import include_exclude_check, get_parsed_stack_config, global_options2, get_dev_root_path from .util import include_exclude_check, get_parsed_stack_config, global_options2
from app.deploy_types import ClusterContext, DeployCommandContext from .deploy_types import ClusterContext, DeployCommandContext
from app.deployment_create import create as deployment_create from .deployment_create import create as deployment_create
from app.deployment_create import init as deployment_init from .deployment_create import init as deployment_init
from app.deployment_create import setup as deployment_setup from .deployment_create import setup as deployment_setup
@click.group() @click.group()
@@ -41,16 +42,9 @@ from app.deployment_create import setup as deployment_setup
def command(ctx, include, exclude, env_file, cluster): def command(ctx, include, exclude, env_file, cluster):
'''deploy a stack''' '''deploy a stack'''
# Although in theory for some subcommands (e.g. deploy create) the stack can be inferred,
# Click doesn't allow us to know that here, so we make providing the stack mandatory
stack = global_options2(ctx).stack
if not stack:
print("Error: --stack option is required")
sys.exit(1)
if ctx.parent.obj.debug: if ctx.parent.obj.debug:
print(f"ctx.parent.obj: {ctx.parent.obj}") print(f"ctx.parent.obj: {ctx.parent.obj}")
ctx.obj = create_deploy_context(global_options2(ctx), stack, include, exclude, cluster, env_file) ctx.obj = create_deploy_context(global_options2(ctx), global_options2(ctx).stack, include, exclude, cluster, env_file)
# Subcommand is executed now, by the magic of click # Subcommand is executed now, by the magic of click
@@ -241,15 +235,17 @@ def _make_runtime_env(ctx):
# stack has to be either PathLike pointing to a stack yml file, or a string with the name of a known stack # stack has to be either PathLike pointing to a stack yml file, or a string with the name of a known stack
def _make_cluster_context(ctx, stack, include, exclude, cluster, env_file): def _make_cluster_context(ctx, stack, include, exclude, cluster, env_file):
dev_root_path = get_dev_root_path(ctx) if ctx.local_stack:
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
else:
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
# TODO: huge hack, fix this # TODO: huge hack, fix this
# If the caller passed a path for the stack file, then we know that we can get the compose files # If the caller passed a path for the stack file, then we know that we can get the compose files
# from the same directory # from the same directory
deployment = False
if isinstance(stack, os.PathLike): if isinstance(stack, os.PathLike):
compose_dir = stack.parent.joinpath("compose") compose_dir = stack.parent.joinpath("compose")
deployment = True
else: else:
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
compose_dir = Path(__file__).absolute().parent.joinpath("data", "compose") compose_dir = Path(__file__).absolute().parent.joinpath("data", "compose")
@@ -267,7 +263,7 @@ def _make_cluster_context(ctx, stack, include, exclude, cluster, env_file):
print(f"Using cluster name: {cluster}") print(f"Using cluster name: {cluster}")
# See: https://stackoverflow.com/a/20885799/1701505 # See: https://stackoverflow.com/a/20885799/1701505
from app import data from . import data
with resources.open_text(data, "pod-list.txt") as pod_list_file: with resources.open_text(data, "pod-list.txt") as pod_list_file:
all_pods = pod_list_file.read().splitlines() all_pods = pod_list_file.read().splitlines()
@@ -299,16 +295,6 @@ def _make_cluster_context(ctx, stack, include, exclude, cluster, env_file):
if include_exclude_check(pod_name, include, exclude): if include_exclude_check(pod_name, include, exclude):
if pod_repository is None or pod_repository == "internal": if pod_repository is None or pod_repository == "internal":
compose_file_name = os.path.join(compose_dir, f"docker-compose-{pod_path}.yml") compose_file_name = os.path.join(compose_dir, f"docker-compose-{pod_path}.yml")
else:
if deployment:
compose_file_name = os.path.join(compose_dir, "docker-compose.yml")
pod_pre_start_command = pod["pre_start_command"]
pod_post_start_command = pod["post_start_command"]
script_dir = compose_dir.parent.joinpath("pods", pod_name, "scripts")
if pod_pre_start_command is not None:
pre_start_commands.append(os.path.join(script_dir, pod_pre_start_command))
if pod_post_start_command is not None:
post_start_commands.append(os.path.join(script_dir, pod_post_start_command))
else: else:
pod_root_dir = os.path.join(dev_root_path, pod_repository.split("/")[-1], pod["path"]) pod_root_dir = os.path.join(dev_root_path, pod_repository.split("/")[-1], pod["path"])
compose_file_name = os.path.join(pod_root_dir, "docker-compose.yml") compose_file_name = os.path.join(pod_root_dir, "docker-compose.yml")
+1 -1
View File
@@ -17,7 +17,7 @@ from typing import List
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from python_on_whales import DockerClient from python_on_whales import DockerClient
from app.command_types import CommandOptions from .command_types import CommandOptions
@dataclass @dataclass
+3 -3
View File
@@ -15,15 +15,15 @@
import os import os
from typing import List from typing import List
from app.deploy_types import DeployCommandContext, VolumeMapping from .deploy_types import DeployCommandContext, VolumeMapping
from app.util import get_parsed_stack_config, get_yaml, get_compose_file_dir, get_pod_list from .util import get_parsed_stack_config, get_yaml, get_compose_file_dir
def _container_image_from_service(stack: str, service: str): def _container_image_from_service(stack: str, service: str):
# Parse the compose files looking for the image name of the specified service # Parse the compose files looking for the image name of the specified service
image_name = None image_name = None
parsed_stack = get_parsed_stack_config(stack) parsed_stack = get_parsed_stack_config(stack)
pods = get_pod_list(parsed_stack) pods = parsed_stack["pods"]
yaml = get_yaml() yaml = get_yaml()
for pod in pods: for pod in pods:
pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml") pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml")
+2 -2
View File
@@ -17,8 +17,8 @@ import click
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
import sys import sys
from app.deploy import up_operation, down_operation, ps_operation, port_operation from .deploy import up_operation, down_operation, ps_operation, port_operation
from app.deploy import exec_operation, logs_operation, create_deploy_context from .deploy import exec_operation, logs_operation, create_deploy_context
@dataclass @dataclass
+15 -47
View File
@@ -17,13 +17,12 @@ import click
from importlib import util from importlib import util
import os import os
from pathlib import Path from pathlib import Path
from typing import List
import random import random
from shutil import copy, copyfile, copytree from shutil import copyfile, copytree
import sys import sys
from app.util import (get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config, global_options, get_yaml, from .util import get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config, global_options, get_yaml
get_pod_list, get_pod_file_path, pod_has_scripts, get_pod_script_paths, get_plugin_code_path) from .util import get_compose_file_dir
from app.deploy_types import DeploymentContext, DeployCommandContext, LaconicStackSetupCommand from .deploy_types import DeploymentContext, LaconicStackSetupCommand
def _make_default_deployment_dir(): def _make_default_deployment_dir():
@@ -33,10 +32,10 @@ def _make_default_deployment_dir():
def _get_ports(stack): def _get_ports(stack):
ports = {} ports = {}
parsed_stack = get_parsed_stack_config(stack) parsed_stack = get_parsed_stack_config(stack)
pods = get_pod_list(parsed_stack) pods = parsed_stack["pods"]
yaml = get_yaml() yaml = get_yaml()
for pod in pods: for pod in pods:
pod_file_path = get_pod_file_path(parsed_stack, pod) pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml")
parsed_pod_file = yaml.load(open(pod_file_path, "r")) parsed_pod_file = yaml.load(open(pod_file_path, "r"))
if "services" in parsed_pod_file: if "services" in parsed_pod_file:
for svc_name, svc in parsed_pod_file["services"].items(): for svc_name, svc in parsed_pod_file["services"].items():
@@ -50,10 +49,10 @@ def _get_named_volumes(stack):
# Parse the compose files looking for named volumes # Parse the compose files looking for named volumes
named_volumes = [] named_volumes = []
parsed_stack = get_parsed_stack_config(stack) parsed_stack = get_parsed_stack_config(stack)
pods = get_pod_list(parsed_stack) pods = parsed_stack["pods"]
yaml = get_yaml() yaml = get_yaml()
for pod in pods: for pod in pods:
pod_file_path = get_pod_file_path(parsed_stack, pod) pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml")
parsed_pod_file = yaml.load(open(pod_file_path, "r")) parsed_pod_file = yaml.load(open(pod_file_path, "r"))
if "volumes" in parsed_pod_file: if "volumes" in parsed_pod_file:
volumes = parsed_pod_file["volumes"] volumes = parsed_pod_file["volumes"]
@@ -106,26 +105,15 @@ def _fixup_pod_file(pod, spec, compose_dir):
pod["services"][container_name]["ports"] = container_ports pod["services"][container_name]["ports"] = container_ports
def _commands_plugin_path(ctx: DeployCommandContext):
plugin_path = get_plugin_code_path(ctx.stack)
return plugin_path.joinpath("deploy", "commands.py")
# See: https://stackoverflow.com/a/54625079/1701505
def _has_method(o, name):
return callable(getattr(o, name, None))
def call_stack_deploy_init(deploy_command_context): def call_stack_deploy_init(deploy_command_context):
# Link with the python file in the stack # Link with the python file in the stack
# Call a function in it # Call a function in it
# If no function found, return None # If no function found, return None
python_file_path = _commands_plugin_path(deploy_command_context) python_file_path = get_stack_file_path(deploy_command_context.stack).parent.joinpath("deploy", "commands.py")
if python_file_path.exists(): if python_file_path.exists():
spec = util.spec_from_file_location("commands", python_file_path) spec = util.spec_from_file_location("commands", python_file_path)
imported_stack = util.module_from_spec(spec) imported_stack = util.module_from_spec(spec)
spec.loader.exec_module(imported_stack) spec.loader.exec_module(imported_stack)
if _has_method(imported_stack, "init"):
return imported_stack.init(deploy_command_context) return imported_stack.init(deploy_command_context)
else: else:
return None return None
@@ -136,13 +124,11 @@ def call_stack_deploy_setup(deploy_command_context, parameters: LaconicStackSetu
# Link with the python file in the stack # Link with the python file in the stack
# Call a function in it # Call a function in it
# If no function found, return None # If no function found, return None
python_file_path = _commands_plugin_path(deploy_command_context) python_file_path = get_stack_file_path(deploy_command_context.stack).parent.joinpath("deploy", "commands.py")
print(f"Path: {python_file_path}")
if python_file_path.exists(): if python_file_path.exists():
spec = util.spec_from_file_location("commands", python_file_path) spec = util.spec_from_file_location("commands", python_file_path)
imported_stack = util.module_from_spec(spec) imported_stack = util.module_from_spec(spec)
spec.loader.exec_module(imported_stack) spec.loader.exec_module(imported_stack)
if _has_method(imported_stack, "setup"):
return imported_stack.setup(deploy_command_context, parameters, extra_args) return imported_stack.setup(deploy_command_context, parameters, extra_args)
else: else:
return None return None
@@ -153,12 +139,11 @@ def call_stack_deploy_create(deployment_context, extra_args):
# Link with the python file in the stack # Link with the python file in the stack
# Call a function in it # Call a function in it
# If no function found, return None # If no function found, return None
python_file_path = _commands_plugin_path(deployment_context.command_context) python_file_path = get_stack_file_path(deployment_context.command_context.stack).parent.joinpath("deploy", "commands.py")
if python_file_path.exists(): if python_file_path.exists():
spec = util.spec_from_file_location("commands", python_file_path) spec = util.spec_from_file_location("commands", python_file_path)
imported_stack = util.module_from_spec(spec) imported_stack = util.module_from_spec(spec)
spec.loader.exec_module(imported_stack) spec.loader.exec_module(imported_stack)
if _has_method(imported_stack, "create"):
return imported_stack.create(deployment_context, extra_args) return imported_stack.create(deployment_context, extra_args)
else: else:
return None return None
@@ -278,21 +263,14 @@ def init(ctx, config, output, map_ports_to_host):
def _write_config_file(spec_file: Path, config_env_file: Path): def _write_config_file(spec_file: Path, config_env_file: Path):
spec_content = get_parsed_deployment_spec(spec_file) spec_content = get_parsed_deployment_spec(spec_file)
# Note: we want to write an empty file even if we have no config variables if spec_content["config"]:
with open(config_env_file, "w") as output_file:
if "config" in spec_content and spec_content["config"]:
config_vars = spec_content["config"] config_vars = spec_content["config"]
if config_vars: if config_vars:
with open(config_env_file, "w") as output_file:
for variable_name, variable_value in config_vars.items(): for variable_name, variable_value in config_vars.items():
output_file.write(f"{variable_name}={variable_value}\n") output_file.write(f"{variable_name}={variable_value}\n")
def _copy_files_to_directory(file_paths: List[Path], directory: Path):
for path in file_paths:
# Using copy to preserve the execute bit
copy(path, os.path.join(directory, os.path.basename(path)))
@click.command() @click.command()
@click.option("--spec-file", required=True, help="Spec file to use to create this deployment") @click.option("--spec-file", required=True, help="Spec file to use to create this deployment")
@click.option("--deployment-dir", help="Create deployment files in this directory") @click.option("--deployment-dir", help="Create deployment files in this directory")
@@ -320,19 +298,15 @@ def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
# Copy any config varibles from the spec file into an env file suitable for compose # Copy any config varibles from the spec file into an env file suitable for compose
_write_config_file(spec_file, os.path.join(deployment_dir, "config.env")) _write_config_file(spec_file, os.path.join(deployment_dir, "config.env"))
# Copy the pod files into the deployment dir, fixing up content # Copy the pod files into the deployment dir, fixing up content
pods = get_pod_list(parsed_stack) pods = parsed_stack['pods']
destination_compose_dir = os.path.join(deployment_dir, "compose") destination_compose_dir = os.path.join(deployment_dir, "compose")
os.mkdir(destination_compose_dir) os.mkdir(destination_compose_dir)
destination_pods_dir = os.path.join(deployment_dir, "pods")
os.mkdir(destination_pods_dir)
data_dir = Path(__file__).absolute().parent.joinpath("data") data_dir = Path(__file__).absolute().parent.joinpath("data")
yaml = get_yaml() yaml = get_yaml()
for pod in pods: for pod in pods:
pod_file_path = get_pod_file_path(parsed_stack, pod) pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml")
parsed_pod_file = yaml.load(open(pod_file_path, "r")) parsed_pod_file = yaml.load(open(pod_file_path, "r"))
extra_config_dirs = _find_extra_config_dirs(parsed_pod_file, pod) extra_config_dirs = _find_extra_config_dirs(parsed_pod_file, pod)
destination_pod_dir = os.path.join(destination_pods_dir, pod)
os.mkdir(destination_pod_dir)
if global_options(ctx).debug: if global_options(ctx).debug:
print(f"extra config dirs: {extra_config_dirs}") print(f"extra config dirs: {extra_config_dirs}")
_fixup_pod_file(parsed_pod_file, parsed_spec, destination_compose_dir) _fixup_pod_file(parsed_pod_file, parsed_spec, destination_compose_dir)
@@ -348,12 +322,6 @@ def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
# If the same config dir appears in multiple pods, it may already have been copied # If the same config dir appears in multiple pods, it may already have been copied
if not os.path.exists(destination_config_dir): if not os.path.exists(destination_config_dir):
copytree(source_config_dir, destination_config_dir) copytree(source_config_dir, destination_config_dir)
# Copy the script files for the pod, if any
if pod_has_scripts(parsed_stack, pod):
destination_script_dir = os.path.join(destination_pod_dir, "scripts")
os.mkdir(destination_script_dir)
script_paths = get_pod_script_paths(parsed_stack, pod)
_copy_files_to_directory(script_paths, destination_script_dir)
# Delegate to the stack's Python code # Delegate to the stack's Python code
# The deploy create command doesn't require a --stack argument so we need to insert the # The deploy create command doesn't require a --stack argument so we need to insert the
# stack member here. # stack member here.
+2 -2
View File
@@ -25,7 +25,7 @@ import click
import importlib.resources import importlib.resources
from pathlib import Path from pathlib import Path
import yaml import yaml
from app.util import include_exclude_check from .util import include_exclude_check
class GitProgress(git.RemoteProgress): class GitProgress(git.RemoteProgress):
@@ -232,7 +232,7 @@ def command(ctx, include, exclude, git_ssh, check_only, pull, branches, branches
os.makedirs(dev_root_path) os.makedirs(dev_root_path)
# See: https://stackoverflow.com/a/20885799/1701505 # See: https://stackoverflow.com/a/20885799/1701505
from app import data from . import data
with importlib.resources.open_text(data, "repository-list.txt") as repository_list_file: with importlib.resources.open_text(data, "repository-list.txt") as repository_list_file:
all_repos = repository_list_file.read().splitlines() all_repos = repository_list_file.read().splitlines()
+1 -1
View File
@@ -23,7 +23,7 @@ import sys
import stat import stat
import shutil import shutil
import validators import validators
from app.util import get_yaml from .util import get_yaml
def _download_url(url: str, file_path: Path): def _download_url(url: str, file_path: Path):
-73
View File
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>. # along with this program. If not, see <http:#www.gnu.org/licenses/>.
from decouple import config
import os.path import os.path
import sys import sys
import ruamel.yaml import ruamel.yaml
@@ -38,16 +37,6 @@ def get_stack_file_path(stack):
return stack_file_path return stack_file_path
def get_dev_root_path(ctx):
if ctx and ctx.local_stack:
# TODO: This code probably doesn't work
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
else:
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
return dev_root_path
# Caller can pass either the name of a stack, or a path to a stack file # Caller can pass either the name of a stack, or a path to a stack file
def get_parsed_stack_config(stack): def get_parsed_stack_config(stack):
stack_file_path = stack if isinstance(stack, os.PathLike) else get_stack_file_path(stack) stack_file_path = stack if isinstance(stack, os.PathLike) else get_stack_file_path(stack)
@@ -67,68 +56,6 @@ def get_parsed_stack_config(stack):
sys.exit(1) sys.exit(1)
def get_pod_list(parsed_stack):
# Handle both old and new format
pods = parsed_stack["pods"]
if type(pods[0]) is str:
result = pods
else:
result = []
for pod in pods:
result.append(pod["name"])
return result
def get_plugin_code_path(stack):
parsed_stack = get_parsed_stack_config(stack)
pods = parsed_stack["pods"]
# TODO: Hack
pod = pods[0]
if type(pod) is str:
result = get_stack_file_path(stack).parent
else:
pod_root_dir = os.path.join(get_dev_root_path(None), pod["repository"].split("/")[-1], pod["path"])
result = Path(os.path.join(pod_root_dir, "stack"))
return result
def get_pod_file_path(parsed_stack, pod_name: str):
pods = parsed_stack["pods"]
if type(pods[0]) is str:
result = os.path.join(get_compose_file_dir(), f"docker-compose-{pod_name}.yml")
else:
for pod in pods:
if pod["name"] == pod_name:
pod_root_dir = os.path.join(get_dev_root_path(None), pod["repository"].split("/")[-1], pod["path"])
result = os.path.join(pod_root_dir, "docker-compose.yml")
return result
def get_pod_script_paths(parsed_stack, pod_name: str):
pods = parsed_stack["pods"]
result = []
if not type(pods[0]) is str:
for pod in pods:
if pod["name"] == pod_name:
pod_root_dir = os.path.join(get_dev_root_path(None), pod["repository"].split("/")[-1], pod["path"])
if "pre_start_command" in pod:
result.append(os.path.join(pod_root_dir, pod["pre_start_command"]))
if "post_start_command" in pod:
result.append(os.path.join(pod_root_dir, pod["post_start_command"]))
return result
def pod_has_scripts(parsed_stack, pod_name: str):
pods = parsed_stack["pods"]
if type(pods[0]) is str:
result = False
else:
for pod in pods:
if pod["name"] == pod_name:
result = "pre_start_command" in pod or "post_start_command" in pod
return result
def get_compose_file_dir(): def get_compose_file_dir():
# TODO: refactor to use common code with deploy command # TODO: refactor to use common code with deploy command
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
+1 -1
View File
@@ -23,7 +23,7 @@ def command(ctx):
'''print tool version''' '''print tool version'''
# See: https://stackoverflow.com/a/20885799/1701505 # See: https://stackoverflow.com/a/20885799/1701505
from app import data from . import data
with importlib.resources.open_text(data, "build_tag.txt") as version_file: with importlib.resources.open_text(data, "build_tag.txt") as version_file:
# TODO: code better version that skips comment lines # TODO: code better version that skips comment lines
version_string = version_file.read().splitlines()[1] version_string = version_file.read().splitlines()[1]
+5 -4
View File
@@ -1,5 +1,5 @@
# See https://medium.com/nerd-for-tech/how-to-build-and-distribute-a-cli-tool-with-python-537ae41d9d78 # See https://medium.com/nerd-for-tech/how-to-build-and-distribute-a-cli-tool-with-python-537ae41d9d78
from setuptools import setup, find_packages from setuptools import setup
with open("README.md", "r", encoding="utf-8") as fh: with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read() long_description = fh.read()
with open("requirements.txt", "r", encoding="utf-8") as fh: with open("requirements.txt", "r", encoding="utf-8") as fh:
@@ -14,8 +14,9 @@ setup(
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
url='https://github.com/cerc-io/stack-orchestrator', url='https://github.com/cerc-io/stack-orchestrator',
py_modules=['cli', 'app'], packages=['laconic_stack_orchestrator'],
packages=find_packages(), package_dir={'laconic_stack_orchestrator': 'app'},
py_modules=['laconic_stack_orchestrator', 'laconic_stack_orchestrator.cli'],
install_requires=[requirements], install_requires=[requirements],
python_requires='>=3.7', python_requires='>=3.7',
include_package_data=True, include_package_data=True,
@@ -25,6 +26,6 @@ setup(
"Operating System :: OS Independent", "Operating System :: OS Independent",
], ],
entry_points={ entry_points={
'console_scripts': ['laconic-so=cli:cli'], 'console_scripts': ['laconic-so=laconic_stack_orchestrator.cli:cli'],
} }
) )
+1 -1
View File
@@ -85,7 +85,7 @@ if [ ! -f "$test_deployment_spec" ]; then
exit 1 exit 1
fi fi
echo "deploy init test: passed" echo "deploy init test: passed"
$TEST_TARGET_SO --stack test deploy create --spec-file $test_deployment_spec --deployment-dir $test_deployment_dir $TEST_TARGET_SO deploy create --spec-file $test_deployment_spec --deployment-dir $test_deployment_dir
# Check the deployment dir exists # Check the deployment dir exists
if [ ! -d "$test_deployment_dir" ]; then if [ ! -d "$test_deployment_dir" ]; then
echo "deploy create test: deployment directory not present" echo "deploy create test: deployment directory not present"
-105
View File
@@ -1,105 +0,0 @@
#!/usr/bin/env bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
echo "$(date +"%Y-%m-%d %T"): Running stack-orchestrator Payments stack fixturenet test"
# Bit of a hack, test the most recent package
TEST_TARGET_SO=$( ls -t1 ./package/laconic-so* | head -1 )
# Set a new unique repo dir
export CERC_REPO_BASE_DIR=$(mktemp -d stack-orchestrator-fixturenet-payments-test.XXXXXXXXXX)
echo "$(date +"%Y-%m-%d %T"): Testing this package: $TEST_TARGET_SO"
echo "$(date +"%Y-%m-%d %T"): Test version command"
reported_version_string=$( $TEST_TARGET_SO version )
echo "$(date +"%Y-%m-%d %T"): Version reported is: ${reported_version_string}"
echo "$(date +"%Y-%m-%d %T"): Cloning repositories into: $CERC_REPO_BASE_DIR"
$TEST_TARGET_SO --stack fixturenet-payments setup-repositories --pull
echo "$(date +"%Y-%m-%d %T"): Building containers"
$TEST_TARGET_SO --stack fixturenet-payments build-containers
echo "$(date +"%Y-%m-%d %T"): Starting stack"
$TEST_TARGET_SO --stack fixturenet-payments deploy --cluster payments up
echo "$(date +"%Y-%m-%d %T"): Stack started"
# Verify that the fixturenet is up and running
$TEST_TARGET_SO --stack fixturenet-payments deploy --cluster payments ps
# get watcher payments channel id
timeout=600 # 10 minutes
echo "$(date +"%Y-%m-%d %T"): Waiting for watcher payment channel id. Timeout set to $timeout seconds"
start_time=$(date +%s)
elapsed_time=0
while [ -z "$WATCHER_UPSTREAM_PAYMENT_CHANNEL" ] && [ $elapsed_time -lt $timeout ]; do
sleep 10
echo "$(date +"%Y-%m-%d %T"): Waiting for channel..."
WATCHER_UPSTREAM_PAYMENT_CHANNEL=$(docker logs $(docker ps -aq --filter name="mobymask-watcher-server") 2>&1 | \
grep "payment channel created with id" | \
grep -o '0x[0-9a-fA-F]\+') \
|| true
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))
done
echo "Watcher payment channel id: $WATCHER_UPSTREAM_PAYMENT_CHANNEL"
sleep 120
# check watcher payment channel status. Expected result: 'Open'
timeout=600 # 10 minutes
echo "$(date +"%Y-%m-%d %T"): Querying watcher payment channel status. Timeout set to $timeout seconds"
start_time=$(date +%s)
elapsed_time=0
query="Status:"
while [ -z "$watcher_query_result" ] && [ $elapsed_time -lt $timeout ]; do
sleep 10
echo "$(date +"%Y-%m-%d %T"): Waiting for channel..."
watcher_query_result=$(docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -s false -h ipld-eth-server-1 -p 4005" | \
grep "$query" | \
grep -o "'.*'") \
|| true
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))
done
# run ponder indexer to get ponder payment channel id
timeout=600 # 10 minutes
echo "$(date +"%Y-%m-%d %T"): Starting Ponder indexer and waiting for payment channel id. Timeout set to $timeout seconds"
start_time=$(date +%s)
elapsed_time=0
docker exec -itd payments-ponder-app-indexer-1-1 bash -c "DEBUG=laconic:payments pnpm start > /output.log 2>&1"
while [ -z "$PONDER_UPSTREAM_PAYMENT_CHANNEL" ] && [ $elapsed_time -lt $timeout ]; do
sleep 10
echo "$(date +"%Y-%m-%d %T"): Waiting for channel id..."
PONDER_UPSTREAM_PAYMENT_CHANNEL=$(docker exec payments-ponder-app-indexer-1-1 bash -c "grep 'Using payment channel' /output.log" | grep -o '0x[0-9a-fA-F]\+' || true)
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))
done
echo "Ponder payment channel id: $PONDER_UPSTREAM_PAYMENT_CHANNEL"
if [[ -z "$PONDER_UPSTREAM_PAYMENT_CHANNEL" ]]; then
echo "Ponder payment channel id not found."
ponder_query_result=0
else
echo "Ponder payment channel id: $PONDER_UPSTREAM_PAYMENT_CHANNEL"
# query ponder payment channel, Expected result: PaidSoFar is nonzero
query="PaidSoFar"
ponder_query_result=$(docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $PONDER_UPSTREAM_PAYMENT_CHANNEL -s false -h go-nitro -p 4006" | \
grep "$query" | \
grep -o '[0-9]\+') \
|| true
fi
if [[ "$watcher_query_result" == "'Open'" && "$ponder_query_result" -gt 0 ]]; then
echo "Test passed"
test_result=0
else
echo "Test failed: watcher_query_result was $watcher_query_result and ponder_query_result was $ponder_query_result"
echo "Logs from stack:"
$TEST_TARGET_SO --stack fixturenet-payments deploy logs
test_result=1
fi
$TEST_TARGET_SO --stack fixturenet-payments deploy --cluster payments down 30 --delete-volumes
echo "$(date +"%Y-%m-%d %T"): Removing cloned repositories"
rm -rf $CERC_REPO_BASE_DIR
echo "$(date +"%Y-%m-%d %T"): Test finished"
exit $test_result
+4
View File
@@ -37,4 +37,8 @@ $TEST_TARGET_SO --stack test deploy-system down
# Run same test but not using the stack definition # Run same test but not using the stack definition
# Test building the a stack container # Test building the a stack container
$TEST_TARGET_SO build-containers --include cerc/test-container $TEST_TARGET_SO build-containers --include cerc/test-container
# Deploy the test container
$TEST_TARGET_SO deploy-system --include test up
# Clean up
$TEST_TARGET_SO deploy-system --include test down
echo "Test passed" echo "Test passed"