forked from cerc-io/stack-orchestrator
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e36e3e2ae | ||
|
|
f7eb8b9a38 | ||
|
|
5b9b12a223 | ||
|
|
567dadef7d | ||
|
|
052f0df4b0 | ||
|
|
c51671f786 | ||
|
|
573a19a3b7 | ||
|
|
fc051265d8 | ||
|
|
ddebb9c690 | ||
|
|
fe6c3f92ed | ||
|
|
c06be6da81 | ||
|
|
3291c16466 | ||
|
|
69b071ee7a | ||
|
|
4a90cedeb2 | ||
|
|
2402220273 | ||
|
|
771943864e | ||
|
|
dd4dd519dd | ||
|
|
3262ebe4ac | ||
|
|
8246e3551f | ||
|
|
e26a05f2c7 | ||
|
|
f9b102f5fa | ||
|
|
7ce40331d8 | ||
|
|
479a7772f3 |
@@ -48,3 +48,4 @@ jobs:
|
||||
- name: "Run smoke tests"
|
||||
run: ./tests/smoke-test/run-smoke-test.sh
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
Change this file to trigger running the fixturenet-eth-plugeth-test CI job
|
||||
trigger
|
||||
trigger
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Change this file to trigger running the fixturenet-eth-test CI job
|
||||
trigger
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Fixturenet-Eth Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '*'
|
||||
paths:
|
||||
- '!**'
|
||||
- '.github/workflows/triggers/fixturenet-eth-test'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: "Run fixturenet-eth 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-eth tests"
|
||||
run: ./tests/fixturenet-eth/run-test.sh
|
||||
@@ -0,0 +1,2 @@
|
||||
Change this file to trigger running the fixturenet-eth-test CI job
|
||||
|
||||
+1
-1
@@ -7,4 +7,4 @@ __pycache__
|
||||
*~
|
||||
package
|
||||
app/data/build_tag.txt
|
||||
build
|
||||
/build
|
||||
|
||||
@@ -52,7 +52,7 @@ Version: 1.1.0-7a607c2-202304260513
|
||||
Save the distribution url to `~/.laconic-so/config.yml`:
|
||||
```bash
|
||||
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
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
|
||||
import os
|
||||
from abc import ABC, abstractmethod
|
||||
from app.deploy import get_stack_status
|
||||
from app.deploy.deploy import get_stack_status
|
||||
from decouple import config
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ def command(ctx, include, exclude, force_rebuild, extra_build_args):
|
||||
continue_on_error = ctx.obj.continue_on_error
|
||||
|
||||
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
||||
container_build_dir = Path(__file__).absolute().parent.joinpath("data", "container-build")
|
||||
container_build_dir = Path(__file__).absolute().parent.parent.joinpath("data", "container-build")
|
||||
|
||||
if local_stack:
|
||||
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
||||
@@ -11,10 +11,13 @@ services:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546}
|
||||
CERC_NITRO_PK: ${CERC_NITRO_PK:-2d999770f7b5d49b694080f987b82bbc9fc9ac2b4dcc10b0f8aba7d700f69c6d}
|
||||
CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK:-570b909da9669b2f35a0b1ac70b8358516d55ae1b5b3710e95e9a94395090597}
|
||||
CERC_NITRO_PK: ${CERC_NITRO_PK:-f36f6dd450892224ee113899195ef922a4795d41c32cafb386d9aab6e0b7b0c6}
|
||||
CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK:-888814df89c4358d7ddb3fa4b0213e7331239a80e1f013eaa7b2deca2a41a218}
|
||||
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_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_VPA_ADDRESS: ${CERC_VPA_ADDRESS}
|
||||
CERC_CA_ADDRESS: ${CERC_CA_ADDRESS}
|
||||
@@ -24,25 +27,15 @@ services:
|
||||
- nitro_deployment:/app/deployment
|
||||
- ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh
|
||||
healthcheck:
|
||||
test: ["CMD", "nc", "-vz", "localhost", "4005"]
|
||||
interval: 10s
|
||||
test: ["CMD", "nc", "-vz", "localhost", "4006"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 10s
|
||||
ports:
|
||||
- "3005"
|
||||
- "4005:4005"
|
||||
- "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"]
|
||||
- "3006:3006"
|
||||
- "4006:4006"
|
||||
- "5006:5006"
|
||||
|
||||
volumes:
|
||||
go_nitro_data:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
version: "3.2"
|
||||
services:
|
||||
ipld-eth-server:
|
||||
ipld-eth-server-1:
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
ipld-eth-db:
|
||||
@@ -27,11 +27,12 @@ services:
|
||||
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:-false}
|
||||
NITRO_DURABLE_STORE_FOLDER: ${CERC_NITRO_DURABLE_STORE_FOLDER:-/app/data/nitro-store}
|
||||
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}
|
||||
@@ -40,7 +41,7 @@ services:
|
||||
- type: bind
|
||||
source: ../config/ipld-eth-server/chain.json
|
||||
target: /tmp/chain.json
|
||||
- eth_server_nitro_data:/app/data
|
||||
- eth_server_nitro_data:/app/nitro-data
|
||||
- nitro_deployment:/app/deployment
|
||||
- ../config/ipld-eth-server/entrypoint.sh:/app/entrypoint.sh
|
||||
ports:
|
||||
@@ -48,7 +49,7 @@ services:
|
||||
- "8082"
|
||||
- "8090"
|
||||
- "40000"
|
||||
- "3005"
|
||||
- "3005:3005"
|
||||
- "4005:4005"
|
||||
- "5005:5005"
|
||||
healthcheck:
|
||||
@@ -58,6 +59,53 @@ services:
|
||||
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:
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
version: "3.2"
|
||||
|
||||
services:
|
||||
laconic-dot-com:
|
||||
image: cerc/laconic-dot-com:local
|
||||
restart: always
|
||||
ports:
|
||||
- "3000"
|
||||
@@ -1,27 +0,0 @@
|
||||
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"
|
||||
@@ -0,0 +1,80 @@
|
||||
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:
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
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:
|
||||
@@ -1,63 +0,0 @@
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
ponder-app-indexer:
|
||||
hostname: ponder-app-indexer
|
||||
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:8081}
|
||||
CERC_PONDER_NITRO_PK: ${CERC_PONDER_INDEXER_NITRO_PK:-58368d20ff12f17669c06158c21d885897aa56f9be430edc789614bf9851d53f}
|
||||
CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_INDEXER_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/ipld-eth-server/tcp/5005/ws/p2p/16Uiu2HAmSjXJqsyBJgcBUU2HQmykxGseafSatbpq5471XmuaUqyv}
|
||||
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.config.ts:/app/examples/token-erc20/ponder.config.ts
|
||||
- peers_ids:/peers
|
||||
- nitro_deployment:/nitro
|
||||
- ponder_indexer_nitro_data:/app/examples/token-erc20/.ponder/nitro-db
|
||||
ports:
|
||||
- "42070"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
ponder-app-watcher:
|
||||
hostname: ponder-app-watcher
|
||||
depends_on:
|
||||
- ponder-app-indexer
|
||||
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:42070/graphql}
|
||||
CERC_INDEXER_NITRO_ADDRESS: ${CERC_INDEXER_NITRO_ADDRESS:-0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d}
|
||||
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
|
||||
- peers_ids:/peers
|
||||
- nitro_deployment:/nitro
|
||||
- ponder_watcher_nitro_data:/app/examples/token-erc20/.ponder/nitro-db
|
||||
ports:
|
||||
- "42069"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
volumes:
|
||||
peers_ids:
|
||||
nitro_deployment:
|
||||
ponder_indexer_nitro_data:
|
||||
ponder_watcher_nitro_data:
|
||||
@@ -34,7 +34,7 @@ services:
|
||||
- ETH_RPC_URL=http://go-ethereum:8545
|
||||
command: ["sh", "-c", "yarn server"]
|
||||
volumes:
|
||||
- ../config/watcher-erc20/erc20-watcher.toml:/app/packages/erc20-watcher/environments/local.toml
|
||||
- ../config/watcher-erc20/erc20-watcher.toml:/app/environments/local.toml
|
||||
ports:
|
||||
- "0.0.0.0:3002:3001"
|
||||
- "0.0.0.0:9002:9001"
|
||||
|
||||
@@ -89,7 +89,7 @@ services:
|
||||
CERC_PEER_ID: ${CERC_PEER_ID}
|
||||
CERC_ENABLE_UPSTREAM_PAYMENTS: ${CERC_ENABLE_UPSTREAM_PAYMENTS}
|
||||
CERC_UPSTREAM_NITRO_ADDRESS: ${CERC_UPSTREAM_NITRO_ADDRESS:-0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE}
|
||||
CERC_UPSTREAM_NITRO_MULTIADDR: ${CERC_UPSTREAM_NITRO_MULTIADDR:-/dns4/ipld-eth-server/tcp/5005/ws/p2p/16Uiu2HAmSjXJqsyBJgcBUU2HQmykxGseafSatbpq5471XmuaUqyv}
|
||||
CERC_UPSTREAM_NITRO_MULTIADDR: ${CERC_UPSTREAM_NITRO_MULTIADDR:-/dns4/ipld-eth-server-1/tcp/5005/ws/p2p/16Uiu2HAmSjXJqsyBJgcBUU2HQmykxGseafSatbpq5471XmuaUqyv}
|
||||
CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-100}
|
||||
command: ["bash", "./start-server.sh"]
|
||||
volumes:
|
||||
|
||||
@@ -5,5 +5,5 @@ services:
|
||||
userKey: REPLACE_WITH_MYKEY
|
||||
bondId:
|
||||
chainId: laconic_9000-1
|
||||
gas: 250000
|
||||
gas: 350000
|
||||
fees: 200000aphoton
|
||||
|
||||
@@ -47,4 +47,4 @@ while true; do
|
||||
sleep $retry_interval
|
||||
done
|
||||
|
||||
./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}
|
||||
./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 ""
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/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,34 +1,57 @@
|
||||
#!/bin/sh
|
||||
|
||||
nitro_addresses_file="/app/deployment/nitro-addresses.json"
|
||||
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"
|
||||
# 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}"
|
||||
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
|
||||
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})
|
||||
curl -I -s -o /dev/null $NITRO_ENDPOINT/health
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Nitro endpoint is up"
|
||||
break
|
||||
else
|
||||
echo "File not yet available, retrying in $retry_interval seconds..."
|
||||
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"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"freeQueriesLimit": 10,
|
||||
"freeQueriesList": [],
|
||||
"queries": {
|
||||
"getLogEvents": "50",
|
||||
"getEthLogs": "50",
|
||||
"getEthBlock": "50"
|
||||
},
|
||||
"mutations": {}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
#!/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
|
||||
@@ -31,6 +31,21 @@ else
|
||||
exit 1
|
||||
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_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"
|
||||
@@ -56,6 +71,7 @@ echo "UPSTREAM_NITRO_PAY_AMOUNT=\"$CERC_UPSTREAM_NITRO_PAY_AMOUNT\"" >> "$env_fi
|
||||
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"
|
||||
|
||||
|
||||
+14
-2
@@ -34,8 +34,8 @@ export const config: Config = {
|
||||
name: "AdventureGold",
|
||||
network: "fixturenet",
|
||||
abi: "./abis/AdventureGold.json",
|
||||
address: "0x32353A6C91143bfd6C7d363B546e62a9A2489A20",
|
||||
startBlock: 5,
|
||||
address: process.env.ERC20_CONTRACT,
|
||||
startBlock: 1,
|
||||
maxBlockRange: 100,
|
||||
},
|
||||
],
|
||||
@@ -49,5 +49,17 @@ export const config: Config = {
|
||||
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,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
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,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -14,8 +14,8 @@ export const config: Config = {
|
||||
name: "AdventureGold",
|
||||
network: "fixturenet",
|
||||
abi: "./abis/AdventureGold.json",
|
||||
address: "0x32353A6C91143bfd6C7d363B546e62a9A2489A20",
|
||||
startBlock: 5,
|
||||
address: process.env.ERC20_CONTRACT,
|
||||
startBlock: 1,
|
||||
maxBlockRange: 100,
|
||||
},
|
||||
],
|
||||
@@ -42,5 +42,17 @@ export const config: Config = {
|
||||
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"
|
||||
|
||||
# ETH RPC endpoint used for queries in the watcher
|
||||
DEFAULT_CERC_ETH_RPC_QUERY_ENDPOINT="http://ipld-eth-server:8081"
|
||||
DEFAULT_CERC_ETH_RPC_QUERY_ENDPOINT="http://ipld-eth-server-1:8081"
|
||||
|
||||
# ETH RPC endpoint used for mutations in the watcher
|
||||
DEFAULT_CERC_ETH_RPC_MUTATION_ENDPOINT="http://fixturenet-eth-geth-1:8545"
|
||||
|
||||
@@ -20,21 +20,24 @@ if [[ $? -ne 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stop geth.
|
||||
echo -n "Exporting ethdb.... "
|
||||
GETH_CONTAINER=`docker ps -q -f "name=${CERC_SO_COMPOSE_PROJECT}-fixturenet-eth-geth-2-1"`
|
||||
if [[ -z "$GETH_CONTAINER" ]]; then
|
||||
echo "not found"
|
||||
exit 1
|
||||
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 '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'
|
||||
|
||||
# Stop geth and zip up 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'
|
||||
|
||||
# Stop geth and zip up ethdb.
|
||||
echo -n "Exporting ethdb.... "
|
||||
docker exec $GETH_CONTAINER sh -c "killall geth && sleep 2 && tar chzf /root/tmp/ethdb.tgz -C /root/tmp/export ."
|
||||
|
||||
# Copy ethdb to host.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
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,4 +3,6 @@
|
||||
|
||||
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
|
||||
|
||||
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
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
docker build -t cerc/go-nitro:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/go-nitro
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/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
|
||||
@@ -54,8 +54,10 @@ RUN yarn global add @cerc-io/laconic-registry-cli
|
||||
|
||||
# Add scripts
|
||||
RUN mkdir /scripts
|
||||
RUN mkdir /scripts/demo-records
|
||||
ENV PATH="${PATH}:/scripts"
|
||||
COPY ./create-demo-records.sh /scripts
|
||||
COPY ./demo-records /scripts/demo-records
|
||||
COPY ./import-key.sh /scripts
|
||||
COPY ./import-address.sh /scripts
|
||||
|
||||
|
||||
@@ -4,26 +4,26 @@ set -e
|
||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
registry_command="laconic cns"
|
||||
record_1_filename=demo-record-1.yml
|
||||
cat <<EOF > ${record_1_filename}
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://cerc.io'
|
||||
repo_registration_record_cid: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
|
||||
build_artifact_cid: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9
|
||||
tls_cert_cid: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
|
||||
version: 1.0.23
|
||||
EOF
|
||||
demo_records_dir="scripts/demo-records"
|
||||
|
||||
# Check we have funds
|
||||
funds_response=$(${registry_command} account get --address $(cat my-address.txt))
|
||||
funds_balance=$(echo ${funds_response} | jq -r .[0].balance[0].quantity)
|
||||
echo "Balance is: ${funds_balance}"
|
||||
|
||||
# Create a bond
|
||||
bond_create_result=$(${registry_command} bond create --type aphoton --quantity 1000000000)
|
||||
bond_id=$(echo ${bond_create_result} | jq -r .bondId)
|
||||
echo "Created bond with id: ${bond_id}"
|
||||
# Publish a demo record
|
||||
publish_response=$(${registry_command} record publish --filename ${record_1_filename} --bond-id ${bond_id})
|
||||
published_record_id=$(echo ${publish_response} | jq -r .id)
|
||||
echo "Published ${record_1_filename} with id: ${published_record_id}"
|
||||
|
||||
## Publish the demo records
|
||||
if [ -d $demo_records_dir ]; then
|
||||
for demo_record in "${demo_records_dir}"/*; do
|
||||
publish_response=$(${registry_command} record publish --filename ${demo_record} --bond-id ${bond_id})
|
||||
published_record_id=$(echo ${publish_response} | jq -r .id)
|
||||
echo "Published ${demo_record} with id: ${published_record_id}"
|
||||
cat ${demo_record}
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://hello-urbit.laconic.com'
|
||||
repo_registration_record_cid: QmTZQ8ZJS6mALjEM2wY71msFno6zzxFftVCiZELj9xREPx
|
||||
build_artifact_cid: '~lostex-rabdur-labtul-moltev/hello-urbit'
|
||||
tls_cert_cid: QmR1acEmQt7Tjmhp9cFtymie2eFcrHURQKt9kGto1TQTW1
|
||||
version: 0.2.4
|
||||
@@ -0,0 +1,7 @@
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://dev-hello-urbit.laconic.com'
|
||||
repo_registration_record_cid: QmPbKkK7gKojnGAgKAE6bK5qBY8BcYp2YDB1e4b28NxvVv
|
||||
build_artifact_cid: '~lostex-rabdur-labtul-moltev/hello-urbit-dev'
|
||||
tls_cert_cid: QmWbCv4k9Q9P6XptHNJN6EupDyKVLSLRV6W6T2sAYkfBxr
|
||||
version: 0.2.5
|
||||
@@ -0,0 +1,7 @@
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://app.osmosis.zone'
|
||||
repo_registration_record_cid: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
|
||||
build_artifact_cid: '~larryx-woldyr/osmosis:latest'
|
||||
tls_cert_cid: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
|
||||
version: 1.3.5
|
||||
@@ -0,0 +1,7 @@
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://dev.osmosis.zone'
|
||||
repo_registration_record_cid: QmPbKkK7gKojnGAgKAE6bK5qBY8BcYp2YDB1e4b28NxvVv
|
||||
build_artifact_cid: '~larryx-woldyr/osmosis:dev'
|
||||
tls_cert_cid: QmWbCv4k9Q9P6XptHNJN6EupDyKVLSLRV6W6T2sAYkfBxr
|
||||
version: 1.3.6
|
||||
@@ -0,0 +1,7 @@
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://pwa-1-1-3.iglootools.xyz'
|
||||
repo_registration_record_cid: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
|
||||
build_artifact_cid: https://ipfs.io/ipfs/QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9
|
||||
tls_cert_cid: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
|
||||
version: 1.1.3
|
||||
@@ -0,0 +1,7 @@
|
||||
record:
|
||||
type: WebsiteRegistrationRecord
|
||||
url: 'https://pwa-1-2-3.iglootools.xyz'
|
||||
repo_registration_record_cid: QmVjYQ59z3fuKfYUV1aXhDR82JAKxdqB5JMPfUsHkJUkJq
|
||||
build_artifact_cid: https://ipfs.io/ipfs/QmN2yevgjC92gzGi2BY6Q2yBWmR6JNWQ9yscoPPyy1V2Hv
|
||||
tls_cert_cid: QmTAnmDMSnzqAN3yyXtFD4KpyATkeze62ZkbmXHjJ8xQW8
|
||||
version: 1.2.3
|
||||
@@ -1,13 +1,10 @@
|
||||
FROM node:16.17.1-alpine3.16
|
||||
|
||||
RUN apk --update --no-cache add git python3 alpine-sdk
|
||||
RUN apk --update --no-cache add git python3 alpine-sdk bash curl jq
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN echo "Building watcher-ts" && \
|
||||
git checkout v0.2.19 && \
|
||||
RUN echo "Building erc20-watcher-ts" && \
|
||||
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
|
||||
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}/watcher-ts
|
||||
docker build -t cerc/watcher-erc20:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/erc20-watcher-ts
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:18.17.1-alpine3.18
|
||||
FROM node:18.17.1-alpine3.17
|
||||
|
||||
RUN apk --update --no-cache add git python3 alpine-sdk jq
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ mobymask-app-v3
|
||||
go-nitro
|
||||
nitro-rpc-client
|
||||
nitro-contracts
|
||||
nitro-reverse-payment-proxy
|
||||
mobymask-snap
|
||||
ponder
|
||||
ipld-eth-server-payments
|
||||
|
||||
@@ -4,8 +4,8 @@ repos:
|
||||
- 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-server@v1.11.6-statediff-v5
|
||||
- github.com/cerc-io/watcher-ts
|
||||
- github.com/dboreham/foundry
|
||||
- github.com/cerc-io/erc20-watcher-ts
|
||||
containers:
|
||||
- cerc/foundry
|
||||
- cerc/go-ethereum
|
||||
|
||||
@@ -2,14 +2,14 @@ version: "1.1"
|
||||
name: fixturenet-laconic-loaded
|
||||
description: "A full featured laconic fixturenet"
|
||||
repos:
|
||||
- github.com/cerc-io/laconicd
|
||||
- git.vdb.to/cerc-io/laconicd
|
||||
- github.com/lirewine/debug
|
||||
- github.com/lirewine/crypto
|
||||
- github.com/lirewine/gem
|
||||
- github.com/lirewine/sdk
|
||||
- github.com/cerc-io/laconic-sdk
|
||||
- github.com/cerc-io/laconic-registry-cli
|
||||
- github.com/cerc-io/laconic-console
|
||||
- git.vdb.to/cerc-io/laconic-sdk
|
||||
- git.vdb.to/cerc-io/laconic-registry-cli
|
||||
- git.vdb.to/cerc-io/laconic-console
|
||||
npms:
|
||||
- laconic-sdk
|
||||
- laconic-registry-cli
|
||||
|
||||
@@ -2,9 +2,9 @@ version: "1.0"
|
||||
name: fixturenet-laconicd
|
||||
description: "A laconicd fixturenet"
|
||||
repos:
|
||||
- github.com/cerc-io/laconicd
|
||||
- github.com/cerc-io/laconic-sdk
|
||||
- github.com/cerc-io/laconic-registry-cli
|
||||
- git.vdb.to/cerc-io/laconicd
|
||||
- git.vdb.to/cerc-io/laconic-sdk
|
||||
- git.vdb.to/cerc-io/laconic-registry-cli
|
||||
npms:
|
||||
- laconic-sdk
|
||||
- laconic-registry-cli
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# fixturenet-payments
|
||||
|
||||
Instructions to setup and deploy an end-to-end fixturenet-payments stack
|
||||
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.
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -22,22 +22,48 @@ Deploy the stack:
|
||||
|
||||
```bash
|
||||
laconic-so --stack fixturenet-payments deploy --cluster payments up
|
||||
```
|
||||
|
||||
```bash
|
||||
# Exposed on host ports:
|
||||
# 4005: go-nitro node's RPC endpoint
|
||||
# 5005: go-nitro node's p2p endpoint
|
||||
# 8081: reverse payment proxy's RPC endpoint
|
||||
# 32***: geth in statediffing mode and ipld-eth-server(s)
|
||||
# 4005: in-process go-nitro node's RPC endpoint
|
||||
# 3005: in-process go-nitro node's p2p TCP 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
|
||||
# 3001: MobyMask v3 watcher endpoint
|
||||
# 9090: MobyMask v3 watcher relay node endpoint
|
||||
# 8080: MobyMask snap
|
||||
# 3004: MobyMask v3 app
|
||||
# 32***: geth in statediffing mode
|
||||
# 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
|
||||
|
||||
Follow the [demo](./demo.md) to try out end-to-end payments
|
||||
- Follow the [mobymask-demo](./mobymask-demo.md) to try out MobyMask end-to-end payments.
|
||||
- Follow the [ponder-demo](./ponder-demo.md) to try out Ponder end-to-end payments.
|
||||
|
||||
## Clean up
|
||||
|
||||
|
||||
+13
-105
@@ -3,15 +3,14 @@
|
||||
Stack components:
|
||||
* `ipld-eth-db` database for statediffed data
|
||||
* Local geth + lighthouse blockchain "fixturenet" running in statediffing mode
|
||||
* `ipld-eth-server` which runs an ETH RPC API and a GQL server; serves data from `ipld-eth-db`; also runs an in-process go-nitro node for payments required for configured RPC requests
|
||||
* A MobyMask v3 watcher that pays the `ipld-eth-server` for ETH RPC requests
|
||||
* `ipld-eth-server-1` which runs an ETH RPC API and a GQL server; they both serve data from `ipld-eth-db`
|
||||
* It runs an in-process go-nitro node for payments required for configured RPC requests
|
||||
* A MobyMask v3 watcher that pays the `ipld-eth-server-1` for ETH RPC requests
|
||||
* A MobyMask v3 app that pays the watcher for reads (GQL queries) and writes
|
||||
* An example ERC20 Ponder indexer app that pays the `ipld-eth-server` for ETH RPC requests
|
||||
* An example ERC20 Ponder watcher app that pays the Ponder indexer app for GQL queries
|
||||
|
||||
## Setup
|
||||
|
||||
* 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:
|
||||
* 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:
|
||||
|
||||
```bash
|
||||
docker logs -f $(docker ps -aq --filter name="mobymask-watcher-server")
|
||||
@@ -37,7 +36,7 @@ Stack components:
|
||||
* Check the payment channel status:
|
||||
|
||||
```bash
|
||||
docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -h ipld-eth-server -p 4005"
|
||||
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"
|
||||
|
||||
# Expected output:
|
||||
# {
|
||||
@@ -53,10 +52,10 @@ Stack components:
|
||||
# }
|
||||
```
|
||||
|
||||
* In another terminal, check `ipld-eth-server`'s logs to keep track of incoming payments and RPC requests:
|
||||
* In another terminal, check `ipld-eth-server-1`'s logs to keep track of incoming payments and RPC requests from the MobyMask watcher:
|
||||
|
||||
```bash
|
||||
docker logs -f $(docker ps -aq --filter name="ipld-eth-server")
|
||||
docker logs -f $(docker ps -aq --filter name="ipld-eth-server-1")
|
||||
```
|
||||
|
||||
* MetaMask flask wallet setup for running the MobyMask app:
|
||||
@@ -134,6 +133,7 @@ Stack components:
|
||||
```bash
|
||||
# Expected output:
|
||||
# ...
|
||||
# laconic:payments Received a payment voucher of 50 from 0x86804299822212c070178B5135Ba6DdAcFC357D3
|
||||
# laconic:payments Serving a paid query for 0x86804299822212c070178B5135Ba6DdAcFC357D3
|
||||
# vulcanize:resolver isPhisher 0x98ae4f9e9d01cc892adfe6871e1db0287039e0c183d3b5bb31d724228c114744 0x2B6AFbd4F479cE4101Df722cF4E05F941523EaD9 TWT:ash1
|
||||
# vulcanize:indexer isPhisher: db miss, fetching from upstream server
|
||||
@@ -143,16 +143,15 @@ Stack components:
|
||||
# laconic:payments Making RPC call: eth_chainId
|
||||
# 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` to fetch data required for satisfying the GQL request(s); check `ipld-eth-server` logs for charged RPC requests (`eth_getBlockByHash`, `eth_getBlockByNumber`, `eth_getStorageAt`):
|
||||
* 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`):
|
||||
|
||||
```bash
|
||||
# Expected output:
|
||||
# ...
|
||||
# 2023/10/13 06:34:57 INFO Received a voucher payer=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 amount=100
|
||||
# 2023/10/13 06:34:59 INFO Serving a paid RPC request method=eth_getBlockByHash sender=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94
|
||||
# 2023/10/13 06:34:59 INFO Serving a paid RPC request method=eth_getBlockByHash cost=50 sender=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94
|
||||
# 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
|
||||
# WARN [10-13|06:34:59.133] Attempting GerRPCCalls, but default PluginLoader has not been initialized
|
||||
# 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
|
||||
@@ -160,7 +159,7 @@ Stack components:
|
||||
# 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-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
|
||||
# 2023/10/13 06:34:59 INFO Received a voucher payer=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 amount=100
|
||||
# 2023/10/13 06:35:01 INFO Serving a paid RPC request method=eth_getStorageAt sender=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94
|
||||
# 2023/10/13 06:35:01 INFO Serving a paid RPC request method=eth_getStorageAt cost=50 sender=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94
|
||||
# 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-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
|
||||
```
|
||||
@@ -186,10 +185,10 @@ Stack components:
|
||||
# }
|
||||
```
|
||||
|
||||
* Check the watcher - ipld-eth-server payment channel status after a few requests:
|
||||
* Check the watcher - ipld-eth-server-1 payment channel status after a few requests:
|
||||
|
||||
```bash
|
||||
docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $WATCHER_UPSTREAM_PAYMENT_CHANNEL -h ipld-eth-server -p 4005"
|
||||
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"
|
||||
|
||||
# Expected output ('PaidSoFar' should be non zero):
|
||||
# {
|
||||
@@ -205,97 +204,6 @@ Stack components:
|
||||
# }
|
||||
```
|
||||
|
||||
### ERC20 Ponder App
|
||||
|
||||
* Run the ponder app in indexer mode:
|
||||
|
||||
```bash
|
||||
docker exec -it payments-ponder-app-indexer-1 bash -c "DEBUG=laconic:payments pnpm start"
|
||||
|
||||
# Expected output:
|
||||
# 08:00:28.701 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 0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE
|
||||
# ...
|
||||
# 09:59:14.230 INFO payment Creating payment channel with nitro node 0xAAA6628Ec44A8a742987EF3A114dDFE2D4F7aDCE
|
||||
# ...
|
||||
# 09:59:14.329 INFO payment Using payment channel 0x10f049519bc3f862e2b26e974be8666886228f30ea54aab06e2f23718afffab0
|
||||
```
|
||||
|
||||
* 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`'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 `ipld-eth-server` logs for charged RPC requests (`eth_getBlockByNumber`, `eth_getLogs`):
|
||||
|
||||
```bash
|
||||
# Expected output:
|
||||
# ...
|
||||
# 2023/10/13 06:59:49 INFO Received a voucher payer=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d amount=100
|
||||
# time="2023-10-13T06:59:51Z" level=debug msg=START api_method=eth_getLogs api_params="[map[address:0x32353a6c91143bfd6c7d363b546e62a9a2489a20 fromBlock:0x5 toBlock:0x68]]" api_reqid=1 conn="192.168.64.2:55578" user_id= uuid=1aedde38-6996-11ee-a67a-0242c0a8400c
|
||||
# 2023/10/13 06:59:51 INFO Serving a paid RPC request method=eth_getLogs sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d
|
||||
# WARN [10-13|06:59:51.287] Attempting GerRPCCalls, but default PluginLoader has not been initialized
|
||||
# time="2023-10-13T06:59:51Z" level=debug msg="retrieving log cids for receipt ids"
|
||||
# time="2023-10-13T06:59:51Z" level=debug msg=END api_method=eth_getLogs api_params="[map[address:0x32353a6c91143bfd6c7d363b546e62a9a2489a20 fromBlock:0x5 toBlock:0x68]]" api_reqid=1 conn="192.168.64.2:55578" duration=17 user_id= uuid=1aedde38-6996-11ee-a67a-0242c0a8400c
|
||||
# 2023/10/13 06:59:51 INFO Received a voucher payer=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d amount=100
|
||||
# 2023/10/13 06:59:53 INFO Serving a paid RPC request method=eth_getBlockByNumber sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d
|
||||
# 2023/10/13 06:59:53 INFO Received a voucher payer=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d amount=100
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
* 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 ipld-eth-server -p 4005"
|
||||
|
||||
# Expected output ('PaidSoFar' is non zero):
|
||||
# {
|
||||
# ID: '0x1178ac0f2a43e54a122216fa6afdd30333b590e49e50317a1f9274a591da0f96',
|
||||
# Status: 'Open',
|
||||
# Balance: {
|
||||
# AssetAddress: '0x0000000000000000000000000000000000000000',
|
||||
# Payee: '0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce',
|
||||
# Payer: '0x67d5b55604d1af90074fcb69b8c51838fff84f8d',
|
||||
# PaidSoFar: 215000n,
|
||||
# RemainingFunds: 999785000n
|
||||
# }
|
||||
# }
|
||||
```
|
||||
|
||||
* 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 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ...
|
||||
# 08:02:37.135 INFO payment Creating payment channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ...
|
||||
# 08:02:37.313 INFO payment Using payment channel 0x4b8e67f6a6fcfe114fdd60b85f963344ece4c77d4eea3825688c74b45ff5509b
|
||||
# ...
|
||||
# 11:23:22.436 INFO server Started responding as healthy
|
||||
```
|
||||
|
||||
* Check the terminal in which ponder is running in indexer mode. Logs of payment for `eth_getLogs` 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
|
||||
```
|
||||
|
||||
## Clean Up
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
# 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
|
||||
@@ -9,17 +9,19 @@ repos:
|
||||
# ipld-eth-server with payments -- to be used by ipld-eth-server-payments pod
|
||||
- git.vdb.to/cerc-io/ipld-eth-server@payments
|
||||
# nitro repo
|
||||
- github.com/cerc-io/ts-nitro@v0.1.13
|
||||
- github.com/cerc-io/go-nitro@v0.1.1-ts-port-0.1.7
|
||||
- github.com/cerc-io/ts-nitro@v0.1.15
|
||||
- github.com/cerc-io/go-nitro@v0.1.2-ts-port-0.1.9
|
||||
# mobymask watcher repos
|
||||
- github.com/cerc-io/watcher-ts@v0.2.65
|
||||
- github.com/cerc-io/mobymask-v2-watcher-ts@v0.2.3
|
||||
- github.com/cerc-io/watcher-ts@v0.2.66
|
||||
# this is mobymask-v3
|
||||
- github.com/cerc-io/mobymask-v2-watcher-ts@v0.2.4
|
||||
- github.com/cerc-io/MobyMask@v0.1.3
|
||||
# mobymask app repos
|
||||
- github.com/cerc-io/mobymask-snap
|
||||
- github.com/cerc-io/mobymask-ui@v0.2.1
|
||||
- github.com/cerc-io/mobymask-ui@v0.2.2
|
||||
# ponder repo
|
||||
- github.com/cerc-io/ponder@laconic-esm
|
||||
- github.com/cerc-io/erc20-watcher-ts
|
||||
containers:
|
||||
# fixturenet images
|
||||
- cerc/go-ethereum
|
||||
@@ -31,7 +33,7 @@ containers:
|
||||
- cerc/ipld-eth-db
|
||||
- cerc/ipld-eth-server
|
||||
- cerc/nitro-contracts
|
||||
# - cerc/go-nitro
|
||||
- cerc/go-nitro
|
||||
- cerc/nitro-rpc-client
|
||||
# mobymask watcher images
|
||||
- cerc/watcher-ts
|
||||
@@ -42,14 +44,16 @@ containers:
|
||||
- cerc/mobymask-ui
|
||||
# ponder image
|
||||
- cerc/ponder
|
||||
- cerc/watcher-erc20
|
||||
pods:
|
||||
- fixturenet-eth
|
||||
- ipld-eth-server-payments
|
||||
- ipld-eth-db
|
||||
- nitro-contracts
|
||||
# - go-nitro
|
||||
- go-nitro
|
||||
- nitro-rpc-client
|
||||
- watcher-mobymask-v3
|
||||
- mobymask-snap
|
||||
- mobymask-app-v3
|
||||
- ponder
|
||||
- ponder-indexer
|
||||
- ponder-watcher
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# 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
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
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
|
||||
@@ -14,9 +14,9 @@
|
||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||
|
||||
from app.util import get_yaml
|
||||
from app.deploy_types import DeployCommandContext, LaconicStackSetupCommand, DeploymentContext
|
||||
from app.stack_state import State
|
||||
from app.deploy_util import VolumeMapping, run_container_command
|
||||
from app.deploy.deploy_types import DeployCommandContext, LaconicStackSetupCommand, DeploymentContext
|
||||
from app.deploy.stack_state import State
|
||||
from app.deploy.deploy_util import VolumeMapping, run_container_command
|
||||
from app.command_types import CommandOptions
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||
|
||||
from app.util import get_yaml
|
||||
from app.deploy_types import DeployCommandContext
|
||||
from app.stack_state import State
|
||||
from app.deploy_util import VolumeMapping, run_container_command
|
||||
from app.deploy.deploy_types import DeployCommandContext
|
||||
from app.deploy.stack_state import State
|
||||
from app.deploy.deploy_util import VolumeMapping, run_container_command
|
||||
from pathlib import Path
|
||||
|
||||
default_spec_file_content = """config:
|
||||
|
||||
@@ -2,7 +2,7 @@ version: "1.0"
|
||||
name: test
|
||||
description: "A test stack"
|
||||
repos:
|
||||
- github.com/cerc-io/laconicd
|
||||
- git.vdb.to/cerc-io/laconicd
|
||||
- git.vdb.to/cerc-io/test-project@test-branch
|
||||
containers:
|
||||
- cerc/test-container
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# Copyright © 2022, 2023 Vulcanize
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# 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/>.
|
||||
|
||||
from python_on_whales import DockerClient, DockerException
|
||||
from app.deploy.deployer import Deployer, DeployerException
|
||||
|
||||
|
||||
class DockerDeployer(Deployer):
|
||||
name: str = "compose"
|
||||
|
||||
def __init__(self, compose_files, compose_project_name, compose_env_file) -> None:
|
||||
self.docker = DockerClient(compose_files=compose_files, compose_project_name=compose_project_name,
|
||||
compose_env_file=compose_env_file)
|
||||
|
||||
def up(self, detach, services):
|
||||
try:
|
||||
return self.docker.compose.up(detach=detach, services=services)
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def down(self, timeout, volumes):
|
||||
try:
|
||||
return self.docker.compose.down(timeout=timeout, volumes=volumes)
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def ps(self):
|
||||
try:
|
||||
return self.docker.compose.ps()
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def port(self, service, private_port):
|
||||
try:
|
||||
return self.docker.compose.port(service=service, private_port=private_port)
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def execute(self, service, command, envs):
|
||||
try:
|
||||
return self.docker.compose.execute(service=service, command=command, envs=envs)
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def logs(self, services, tail, follow, stream):
|
||||
try:
|
||||
return self.docker.compose.logs(services=services, tail=tail, follow=follow, stream=stream)
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
|
||||
def run(self, image, command, user, volumes, entrypoint=None):
|
||||
try:
|
||||
return self.docker.run(image=image, command=command, user=user, volumes=volumes, entrypoint=entrypoint)
|
||||
except DockerException as e:
|
||||
raise DeployerException(e)
|
||||
@@ -13,7 +13,7 @@
|
||||
# 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/>.
|
||||
|
||||
# Deploys the system components using docker-compose
|
||||
# Deploys the system components using a deployer (either docker-compose or k8s)
|
||||
|
||||
import hashlib
|
||||
import copy
|
||||
@@ -22,14 +22,15 @@ import sys
|
||||
from dataclasses import dataclass
|
||||
from importlib import resources
|
||||
import subprocess
|
||||
from python_on_whales import DockerClient, DockerException
|
||||
import click
|
||||
from pathlib import Path
|
||||
from app.util import include_exclude_check, get_parsed_stack_config, global_options2, get_dev_root_path
|
||||
from app.deploy_types import ClusterContext, DeployCommandContext
|
||||
from app.deployment_create import create as deployment_create
|
||||
from app.deployment_create import init as deployment_init
|
||||
from app.deployment_create import setup as deployment_setup
|
||||
from app.deploy.deployer import Deployer, DeployerException
|
||||
from app.deploy.deployer_factory import getDeployer
|
||||
from app.deploy.deploy_types import ClusterContext, DeployCommandContext
|
||||
from app.deploy.deployment_create import create as deployment_create
|
||||
from app.deploy.deployment_create import init as deployment_init
|
||||
from app.deploy.deployment_create import setup as deployment_setup
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -37,8 +38,9 @@ from app.deployment_create import setup as deployment_setup
|
||||
@click.option("--exclude", help="don\'t start these components")
|
||||
@click.option("--env-file", help="env file to be used")
|
||||
@click.option("--cluster", help="specify a non-default cluster name")
|
||||
@click.option("--deploy-to", help="cluster system to deploy to (compose or k8s)")
|
||||
@click.pass_context
|
||||
def command(ctx, include, exclude, env_file, cluster):
|
||||
def command(ctx, include, exclude, env_file, cluster, deploy_to):
|
||||
'''deploy a stack'''
|
||||
|
||||
# Although in theory for some subcommands (e.g. deploy create) the stack can be inferred,
|
||||
@@ -50,16 +52,20 @@ def command(ctx, include, exclude, env_file, cluster):
|
||||
|
||||
if ctx.parent.obj.debug:
|
||||
print(f"ctx.parent.obj: {ctx.parent.obj}")
|
||||
ctx.obj = create_deploy_context(global_options2(ctx), stack, include, exclude, cluster, env_file)
|
||||
|
||||
if deploy_to is None:
|
||||
deploy_to = "compose"
|
||||
|
||||
ctx.obj = create_deploy_context(global_options2(ctx), stack, include, exclude, cluster, env_file, deploy_to)
|
||||
# Subcommand is executed now, by the magic of click
|
||||
|
||||
|
||||
def create_deploy_context(global_context, stack, include, exclude, cluster, env_file):
|
||||
def create_deploy_context(global_context, stack, include, exclude, cluster, env_file, deployer):
|
||||
cluster_context = _make_cluster_context(global_context, stack, include, exclude, cluster, env_file)
|
||||
# See: https://gabrieldemarmiesse.github.io/python-on-whales/sub-commands/compose/
|
||||
docker = DockerClient(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster,
|
||||
compose_env_file=cluster_context.env_file)
|
||||
return DeployCommandContext(stack, cluster_context, docker)
|
||||
deployer = getDeployer(deployer, compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster,
|
||||
compose_env_file=cluster_context.env_file)
|
||||
return DeployCommandContext(stack, cluster_context, deployer)
|
||||
|
||||
|
||||
def up_operation(ctx, services_list, stay_attached=False):
|
||||
@@ -74,10 +80,10 @@ def up_operation(ctx, services_list, stay_attached=False):
|
||||
print(f"Running compose up with container_exec_env: {container_exec_env}, extra_args: {services_list}")
|
||||
for pre_start_command in cluster_context.pre_start_commands:
|
||||
_run_command(global_context, cluster_context.cluster, pre_start_command)
|
||||
deploy_context.docker.compose.up(detach=not stay_attached, services=services_list)
|
||||
deploy_context.deployer.up(detach=not stay_attached, services=services_list)
|
||||
for post_start_command in cluster_context.post_start_commands:
|
||||
_run_command(global_context, cluster_context.cluster, post_start_command)
|
||||
_orchestrate_cluster_config(global_context, cluster_context.config, deploy_context.docker, container_exec_env)
|
||||
_orchestrate_cluster_config(global_context, cluster_context.config, deploy_context.deployer, container_exec_env)
|
||||
|
||||
|
||||
def down_operation(ctx, delete_volumes, extra_args_list):
|
||||
@@ -89,7 +95,7 @@ def down_operation(ctx, delete_volumes, extra_args_list):
|
||||
if extra_args_list:
|
||||
timeout_arg = extra_args_list[0]
|
||||
# Specify shutdown timeout (default 10s) to give services enough time to shutdown gracefully
|
||||
ctx.obj.docker.compose.down(timeout=timeout_arg, volumes=delete_volumes)
|
||||
ctx.obj.deployer.down(timeout=timeout_arg, volumes=delete_volumes)
|
||||
|
||||
|
||||
def ps_operation(ctx):
|
||||
@@ -97,7 +103,7 @@ def ps_operation(ctx):
|
||||
if not global_context.dry_run:
|
||||
if global_context.verbose:
|
||||
print("Running compose ps")
|
||||
container_list = ctx.obj.docker.compose.ps()
|
||||
container_list = ctx.obj.deployer.ps()
|
||||
if len(container_list) > 0:
|
||||
print("Running containers:")
|
||||
for container in container_list:
|
||||
@@ -128,7 +134,7 @@ def port_operation(ctx, extra_args):
|
||||
exposed_port = extra_args_list[1]
|
||||
if global_context.verbose:
|
||||
print(f"Running compose port {service_name} {exposed_port}")
|
||||
mapped_port_data = ctx.obj.docker.compose.port(service_name, exposed_port)
|
||||
mapped_port_data = ctx.obj.deployer.port(service_name, exposed_port)
|
||||
print(f"{mapped_port_data[0]}:{mapped_port_data[1]}")
|
||||
|
||||
|
||||
@@ -145,8 +151,8 @@ def exec_operation(ctx, extra_args):
|
||||
if global_context.verbose:
|
||||
print(f"Running compose exec {service_name} {command_to_exec}")
|
||||
try:
|
||||
ctx.obj.docker.compose.execute(service_name, command_to_exec, envs=container_exec_env)
|
||||
except DockerException:
|
||||
ctx.obj.deployer.execute(service_name, command_to_exec, envs=container_exec_env)
|
||||
except DeployerException:
|
||||
print("container command returned error exit status")
|
||||
|
||||
|
||||
@@ -157,7 +163,7 @@ def logs_operation(ctx, tail: int, follow: bool, extra_args: str):
|
||||
if global_context.verbose:
|
||||
print("Running compose logs")
|
||||
services_list = extra_args_list if extra_args_list is not None else []
|
||||
logs_stream = ctx.obj.docker.compose.logs(services=services_list, tail=tail, follow=follow, stream=True)
|
||||
logs_stream = ctx.obj.deployer.logs(services=services_list, tail=tail, follow=follow, stream=True)
|
||||
for stream_type, stream_content in logs_stream:
|
||||
print(stream_content.decode("utf-8"), end="")
|
||||
|
||||
@@ -214,11 +220,11 @@ def get_stack_status(ctx, stack):
|
||||
ctx_copy.stack = stack
|
||||
|
||||
cluster_context = _make_cluster_context(ctx_copy, stack, None, None, None, None)
|
||||
docker = DockerClient(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster)
|
||||
deployer = Deployer(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster)
|
||||
# TODO: refactor to avoid duplicating this code above
|
||||
if ctx.verbose:
|
||||
print("Running compose ps")
|
||||
container_list = docker.compose.ps()
|
||||
container_list = deployer.ps()
|
||||
if len(container_list) > 0:
|
||||
if ctx.debug:
|
||||
print(f"Container list from compose ps: {container_list}")
|
||||
@@ -252,7 +258,7 @@ def _make_cluster_context(ctx, stack, include, exclude, cluster, env_file):
|
||||
deployment = True
|
||||
else:
|
||||
# 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.parent.joinpath("data", "compose")
|
||||
|
||||
if cluster is None:
|
||||
# Create default unique, stable cluster name from confile file path and stack name if provided
|
||||
@@ -359,7 +365,7 @@ def _run_command(ctx, cluster_name, command):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _orchestrate_cluster_config(ctx, cluster_config, docker, container_exec_env):
|
||||
def _orchestrate_cluster_config(ctx, cluster_config, deployer, container_exec_env):
|
||||
|
||||
@dataclass
|
||||
class ConfigDirective:
|
||||
@@ -390,13 +396,13 @@ def _orchestrate_cluster_config(ctx, cluster_config, docker, container_exec_env)
|
||||
# TODO: fix the script paths so they're consistent between containers
|
||||
source_value = None
|
||||
try:
|
||||
source_value = docker.compose.execute(pd.source_container,
|
||||
["sh", "-c",
|
||||
"sh /docker-entrypoint-scripts.d/export-"
|
||||
f"{pd.source_variable}.sh"],
|
||||
tty=False,
|
||||
envs=container_exec_env)
|
||||
except DockerException as error:
|
||||
source_value = deployer.execute(pd.source_container,
|
||||
["sh", "-c",
|
||||
"sh /docker-entrypoint-scripts.d/export-"
|
||||
f"{pd.source_variable}.sh"],
|
||||
tty=False,
|
||||
envs=container_exec_env)
|
||||
except DeployerException as error:
|
||||
if ctx.debug:
|
||||
print(f"Docker exception reading config source: {error}")
|
||||
# If the script executed failed for some reason, we get:
|
||||
@@ -411,12 +417,12 @@ def _orchestrate_cluster_config(ctx, cluster_config, docker, container_exec_env)
|
||||
if source_value:
|
||||
if ctx.debug:
|
||||
print(f"fetched source value: {source_value}")
|
||||
destination_output = docker.compose.execute(pd.destination_container,
|
||||
["sh", "-c",
|
||||
f"sh /scripts/import-{pd.destination_variable}.sh"
|
||||
f" {source_value}"],
|
||||
tty=False,
|
||||
envs=container_exec_env)
|
||||
destination_output = deployer.execute(pd.destination_container,
|
||||
["sh", "-c",
|
||||
f"sh /scripts/import-{pd.destination_variable}.sh"
|
||||
f" {source_value}"],
|
||||
tty=False,
|
||||
envs=container_exec_env)
|
||||
waiting_for_data = False
|
||||
if ctx.debug:
|
||||
print(f"destination output: {destination_output}")
|
||||
@@ -16,8 +16,8 @@
|
||||
from typing import List
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from python_on_whales import DockerClient
|
||||
from app.command_types import CommandOptions
|
||||
from app.deploy.deployer import Deployer
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -35,7 +35,7 @@ class ClusterContext:
|
||||
class DeployCommandContext:
|
||||
stack: str
|
||||
cluster_context: ClusterContext
|
||||
docker: DockerClient
|
||||
deployer: Deployer
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
import os
|
||||
from typing import List
|
||||
from app.deploy_types import DeployCommandContext, VolumeMapping
|
||||
from app.deploy.deploy_types import DeployCommandContext, VolumeMapping
|
||||
from app.util import get_parsed_stack_config, get_yaml, get_compose_file_dir, get_pod_list
|
||||
|
||||
|
||||
@@ -47,12 +47,12 @@ def _volumes_to_docker(mounts: List[VolumeMapping]):
|
||||
|
||||
|
||||
def run_container_command(ctx: DeployCommandContext, service: str, command: str, mounts: List[VolumeMapping]):
|
||||
docker = ctx.docker
|
||||
deployer = ctx.deployer
|
||||
container_image = _container_image_from_service(ctx.stack, service)
|
||||
docker_volumes = _volumes_to_docker(mounts)
|
||||
if ctx.cluster_context.options.debug:
|
||||
print(f"Running this command in {service} container: {command}")
|
||||
docker_output = docker.run(
|
||||
docker_output = deployer.run(
|
||||
container_image,
|
||||
["-c", command], entrypoint="sh",
|
||||
user=f"{os.getuid()}:{os.getgid()}",
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright © 2023 Vulcanize
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# 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/>.
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class Deployer(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def up(self, detach, services):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def down(self, timeout, volumes):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def ps(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def port(self, service, private_port):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def execute(self, service_name, command, envs):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def logs(self, services, tail, follow, stream):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def run(self, image, command, user, volumes, entrypoint):
|
||||
pass
|
||||
|
||||
|
||||
class DeployerException(Exception):
|
||||
def __init__(self, *args: object) -> None:
|
||||
super().__init__(*args)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright © 2023 Vulcanize
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# 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/>.
|
||||
|
||||
from app.deploy.k8s.deploy_k8s import K8sDeployer
|
||||
from app.deploy.compose.deploy_docker import DockerDeployer
|
||||
|
||||
|
||||
def getDeployer(type, compose_files, compose_project_name, compose_env_file):
|
||||
if type == "compose" or type is None:
|
||||
return DockerDeployer(compose_files, compose_project_name, compose_env_file)
|
||||
elif type == "k8s":
|
||||
return K8sDeployer(compose_files, compose_project_name, compose_env_file)
|
||||
else:
|
||||
print(f"ERROR: deploy-to {type} is not valid")
|
||||
@@ -14,20 +14,25 @@
|
||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||
|
||||
import click
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from app.deploy import up_operation, down_operation, ps_operation, port_operation
|
||||
from app.deploy import exec_operation, logs_operation, create_deploy_context
|
||||
from app.deploy.deploy import up_operation, down_operation, ps_operation, port_operation
|
||||
from app.deploy.deploy import exec_operation, logs_operation, create_deploy_context
|
||||
from app.deploy.stack import Stack
|
||||
from app.deploy.spec import Spec
|
||||
|
||||
|
||||
@dataclass
|
||||
class DeploymentContext:
|
||||
dir: Path
|
||||
spec: Spec
|
||||
stack: Stack
|
||||
|
||||
def get_stack_file(self):
|
||||
return self.dir.joinpath("stack.yml")
|
||||
|
||||
def get_spec_file(self):
|
||||
return self.dir.joinpath("spec.yml")
|
||||
|
||||
def get_env_file(self):
|
||||
return self.dir.joinpath("config.env")
|
||||
|
||||
@@ -35,12 +40,19 @@ class DeploymentContext:
|
||||
def get_cluster_name(self):
|
||||
return None
|
||||
|
||||
def init(self, dir):
|
||||
self.dir = dir
|
||||
self.stack = Stack()
|
||||
self.stack.init_from_file(self.get_stack_file())
|
||||
self.spec = Spec()
|
||||
self.spec.init_from_file(self.get_spec_file())
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.option("--dir", required=True, help="path to deployment directory")
|
||||
@click.pass_context
|
||||
def command(ctx, dir):
|
||||
'''create a deployment'''
|
||||
'''manage a deployment'''
|
||||
|
||||
# Check that --stack wasn't supplied
|
||||
if ctx.parent.obj.stack:
|
||||
@@ -55,14 +67,18 @@ def command(ctx, dir):
|
||||
print(f"Error: supplied deployment directory path {dir} exists but is a file not a directory")
|
||||
sys.exit(1)
|
||||
# Store the deployment context for subcommands
|
||||
ctx.obj = DeploymentContext(dir_path)
|
||||
deployment_context = DeploymentContext()
|
||||
deployment_context.init(dir_path)
|
||||
ctx.obj = deployment_context
|
||||
|
||||
|
||||
def make_deploy_context(ctx):
|
||||
stack_file_path = ctx.obj.get_stack_file()
|
||||
env_file = ctx.obj.get_env_file()
|
||||
cluster_name = ctx.obj.get_cluster_name()
|
||||
return create_deploy_context(ctx.parent.parent.obj, stack_file_path, None, None, cluster_name, env_file)
|
||||
context: DeploymentContext = ctx.obj
|
||||
stack_file_path = context.get_stack_file()
|
||||
env_file = context.get_env_file()
|
||||
cluster_name = context.get_cluster_name()
|
||||
return create_deploy_context(ctx.parent.parent.obj, stack_file_path, None, None, cluster_name, env_file,
|
||||
context.spec.obj["deploy-to"])
|
||||
|
||||
|
||||
@command.command()
|
||||
@@ -23,7 +23,7 @@ from shutil import copy, copyfile, copytree
|
||||
import sys
|
||||
from app.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 app.deploy_types import DeploymentContext, DeployCommandContext, LaconicStackSetupCommand
|
||||
from app.deploy.deploy_types import DeploymentContext, DeployCommandContext, LaconicStackSetupCommand
|
||||
|
||||
|
||||
def _make_default_deployment_dir():
|
||||
@@ -249,7 +249,7 @@ def init(ctx, config, output, map_ports_to_host):
|
||||
stack = global_options(ctx).stack
|
||||
debug = global_options(ctx).debug
|
||||
default_spec_file_content = call_stack_deploy_init(ctx.obj)
|
||||
spec_file_content = {"stack": stack}
|
||||
spec_file_content = {"stack": stack, "deploy-to": ctx.obj.deployer.name}
|
||||
if default_spec_file_content:
|
||||
spec_file_content.update(default_spec_file_content)
|
||||
config_variables = _parse_config_variables(config)
|
||||
@@ -315,7 +315,7 @@ def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
|
||||
sys.exit(1)
|
||||
os.mkdir(deployment_dir)
|
||||
# Copy spec file and the stack file into the deployment dir
|
||||
copyfile(spec_file, os.path.join(deployment_dir, os.path.basename(spec_file)))
|
||||
copyfile(spec_file, os.path.join(deployment_dir, "spec.yml"))
|
||||
copyfile(stack_file, os.path.join(deployment_dir, os.path.basename(stack_file)))
|
||||
# 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"))
|
||||
@@ -325,7 +325,7 @@ def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
|
||||
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.parent.joinpath("data")
|
||||
yaml = get_yaml()
|
||||
for pod in pods:
|
||||
pod_file_path = get_pod_file_path(parsed_stack, pod)
|
||||
@@ -0,0 +1,46 @@
|
||||
# Copyright © 2023 Vulcanize
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# 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/>.
|
||||
|
||||
from kubernetes import client, config
|
||||
from app.deploy.deployer import Deployer
|
||||
|
||||
|
||||
class K8sDeployer(Deployer):
|
||||
name: str = "k8s"
|
||||
|
||||
def __init__(self, compose_files, compose_project_name, compose_env_file) -> None:
|
||||
config.load_kube_config()
|
||||
self.client = client.CoreV1Api()
|
||||
|
||||
def up(self, detach, services):
|
||||
pass
|
||||
|
||||
def down(self, timeout, volumes):
|
||||
pass
|
||||
|
||||
def ps(self):
|
||||
pass
|
||||
|
||||
def port(self, service, private_port):
|
||||
pass
|
||||
|
||||
def execute(self, service_name, command, envs):
|
||||
pass
|
||||
|
||||
def logs(self, services, tail, follow, stream):
|
||||
pass
|
||||
|
||||
def run(self, image, command, user, volumes, entrypoint=None):
|
||||
pass
|
||||
@@ -0,0 +1,30 @@
|
||||
# Copyright © 2022, 2023 Vulcanize
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# 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/>.
|
||||
|
||||
from pathlib import Path
|
||||
import typing
|
||||
from app.util import get_yaml
|
||||
|
||||
|
||||
class Spec:
|
||||
|
||||
obj: typing.Any
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def init_from_file(self, file_path: Path):
|
||||
with file_path:
|
||||
self.obj = get_yaml().load(open(file_path, "r"))
|
||||
@@ -0,0 +1,30 @@
|
||||
# Copyright © 2023 Vulcanize
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
# 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/>.
|
||||
|
||||
from pathlib import Path
|
||||
import typing
|
||||
from app.util import get_yaml
|
||||
|
||||
|
||||
class Stack:
|
||||
|
||||
obj: typing.Any
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def init_from_file(self, file_path: Path):
|
||||
with file_path:
|
||||
self.obj = get_yaml().load(open(file_path, "r"))
|
||||
@@ -240,7 +240,7 @@ def command(ctx, include, exclude, git_ssh, check_only, pull, branches, branches
|
||||
if stack:
|
||||
# In order to be compatible with Python 3.8 we need to use this hack to get the path:
|
||||
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
||||
stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml")
|
||||
stack_file_path = Path(__file__).absolute().parent.parent.joinpath("data", "stacks", stack, "stack.yml")
|
||||
with stack_file_path:
|
||||
stack_config = yaml.safe_load(open(stack_file_path, "r"))
|
||||
# TODO: syntax check the input here
|
||||
@@ -16,12 +16,12 @@
|
||||
import click
|
||||
|
||||
from app.command_types import CommandOptions
|
||||
from app import setup_repositories
|
||||
from app import build_containers
|
||||
from app import build_npms
|
||||
from app import deploy
|
||||
from app.repos import setup_repositories
|
||||
from app.build import build_containers
|
||||
from app.build import build_npms
|
||||
from app.deploy import deploy
|
||||
from app import version
|
||||
from app import deployment
|
||||
from app.deploy import deployment
|
||||
from app import update
|
||||
|
||||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
The following tutorial explains the steps to run a laconicd fixturenet with CLI and web console that displays records in the registry. It is designed as an introduction to Stack Orchestrator and to showcase one component of the Laconic Stack. Prior to Stack Orchestrator, the following 4 repositories had to be cloned and setup manually:
|
||||
|
||||
- https://github.com/cerc-io/laconicd
|
||||
- https://github.com/cerc-io/laconic-sdk
|
||||
- https://github.com/cerc-io/laconic-registry-cli
|
||||
- https://github.com/cerc-io/laconic-console
|
||||
- https://git.vdb.to/cerc-io/laconicd
|
||||
- https://git.vdb.to/cerc-io/laconic-sdk
|
||||
- https://git.vdb.to/cerc-io/laconic-registry-cli
|
||||
- https://git.vdb.to/cerc-io/laconic-console
|
||||
|
||||
Now, with Stack Orchestrator, it is a few quick commands. Additionally, the `docker` and `docker compose` integration on the back-end allows the stack to easily persist, facilitating workflows.
|
||||
|
||||
@@ -52,7 +52,7 @@ laconic-so version
|
||||
1. Get the repositories
|
||||
|
||||
```
|
||||
laconic-so --stack fixturenet-laconic-loaded setup-repositories --include github.com/cerc-io/laconicd,github.com/cerc-io/laconic-sdk,github.com/cerc-io/laconic-registry-cli,github.com/cerc-io/laconic-console
|
||||
laconic-so --stack fixturenet-laconic-loaded setup-repositories --include git.vdb.to/cerc-io/laconicd,git.vdb.to/cerc-io/laconic-sdk,git.vdb.to/cerc-io/laconic-registry-cli,git.vdb.to/cerc-io/laconic-console
|
||||
```
|
||||
|
||||
2. Set this environment variable to the Laconic self-hosted Gitea instance:
|
||||
@@ -212,7 +212,7 @@ record:
|
||||
|
||||
3. Try out additional CLI commands
|
||||
|
||||
- these are documented [here](https://github.com/cerc-io/laconic-registry-cli#readme) and updates are forthcoming
|
||||
- these are documented [here](https://git.vdb.to/cerc-io/laconic-registry-cli#readme) and updates are forthcoming
|
||||
- e.g,:
|
||||
|
||||
```
|
||||
|
||||
@@ -8,3 +8,4 @@ ruamel.yaml>=0.17.32
|
||||
pydantic==1.10.9
|
||||
tomli==2.0.1
|
||||
validators==0.22.0
|
||||
kubernetes>=28.1.0
|
||||
|
||||
@@ -24,13 +24,45 @@ echo "$(date +"%Y-%m-%d %T"): Stack started"
|
||||
$TEST_TARGET_SO --stack fixturenet-eth deploy ps
|
||||
# echo "$(date +"%Y-%m-%d %T"): Getting stack status"
|
||||
# $TEST_TARGET_SO --stack fixturenet-eth deploy exec fixturenet-eth-bootnode-lighthouse /scripts/status-internal.sh
|
||||
echo "$(date +"%Y-%m-%d %T"): Getting initial block number"
|
||||
initial_block_number=$($TEST_TARGET_SO --stack fixturenet-eth deploy exec foundry "cast block-number")
|
||||
# Check that the block number increases some time later
|
||||
sleep 120
|
||||
echo "$(date +"%Y-%m-%d %T"): Getting subsequent block number"
|
||||
subsequent_block_number=$($TEST_TARGET_SO --stack fixturenet-eth deploy exec foundry "cast block-number")
|
||||
|
||||
timeout=900 # 15 minutes
|
||||
echo "$(date +"%Y-%m-%d %T"): Getting initial block number. Timeout set to $timeout seconds"
|
||||
start_time=$(date +%s)
|
||||
elapsed_time=0
|
||||
initial_block_number=0
|
||||
while [ "$initial_block_number" -eq 0 ] && [ $elapsed_time -lt $timeout ]; do
|
||||
sleep 10
|
||||
echo "$(date +"%Y-%m-%d %T"): Waiting for initial block..."
|
||||
initial_block_number=$($TEST_TARGET_SO --stack fixturenet-eth deploy exec foundry "cast block-number")
|
||||
current_time=$(date +%s)
|
||||
elapsed_time=$((current_time - start_time))
|
||||
done
|
||||
|
||||
subsequent_block_number=$initial_block_number
|
||||
|
||||
# if initial block was 0 after timeout, assume chain did not start successfully and skip finding subsequent block
|
||||
if [[ $initial_block_number -gt 0 ]]; then
|
||||
timeout=300
|
||||
echo "$(date +"%Y-%m-%d %T"): Getting subsequent block number. Timeout set to $timeout seconds"
|
||||
start_time=$(date +%s)
|
||||
elapsed_time=0
|
||||
# wait for 5 blocks or timeout
|
||||
while [ "$subsequent_block_number" -le $((initial_block_number + 5)) ] && [ $elapsed_time -lt $timeout ]; do
|
||||
sleep 10
|
||||
echo "$(date +"%Y-%m-%d %T"): Waiting for five blocks or $timeout seconds..."
|
||||
subsequent_block_number=$($TEST_TARGET_SO --stack fixturenet-eth deploy exec foundry "cast block-number")
|
||||
current_time=$(date +%s)
|
||||
elapsed_time=$((current_time - start_time))
|
||||
done
|
||||
fi
|
||||
|
||||
# will return 0 if either of the above loops timed out
|
||||
block_number_difference=$((subsequent_block_number - initial_block_number))
|
||||
|
||||
echo "$(date +"%Y-%m-%d %T"): Results of block height queries:"
|
||||
echo "Initial block height: $initial_block_number"
|
||||
echo "Subsequent block height: $subsequent_block_number"
|
||||
|
||||
# Block height difference should be between 1 and some small number
|
||||
if [[ $block_number_difference -gt 1 && $block_number_difference -lt 100 ]]; then
|
||||
echo "Test passed"
|
||||
@@ -41,7 +73,7 @@ else
|
||||
$TEST_TARGET_SO --stack fixturenet-eth deploy logs
|
||||
test_result=1
|
||||
fi
|
||||
$TEST_TARGET_SO --stack fixturenet-eth deploy down
|
||||
$TEST_TARGET_SO --stack fixturenet-eth deploy down --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"
|
||||
|
||||
Reference in New Issue
Block a user