#!/usr/bin/env bash # Load project environment: .env, config, and secrets # No hardcoded IPs or secrets - all from config and .env # # Usage: source "${SCRIPT_DIR}/lib/load-project-env.sh" # # Env precedence (first wins): 1) .env 2) config/ip-addresses.conf 3) smom-dbis-138/.env 4) dbis_core config # Version: 2026-01-31 [[ -n "${PROJECT_ROOT:-}" ]] || PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" export PROJECT_ROOT # err_exit: print message and exit (use when load-project-env is sourced) err_exit() { echo "ERROR: $1" >&2; exit 1; } # Path validation [[ -d "$PROJECT_ROOT" ]] || err_exit "PROJECT_ROOT not a directory: $PROJECT_ROOT" [[ -f "${PROJECT_ROOT}/config/ip-addresses.conf" ]] || echo "WARN: config/ip-addresses.conf not found; using defaults" >&2 # 1. Root .env (Cloudflare, Proxmox, etc.) [[ -f "${PROJECT_ROOT}/.env" ]] && set -a && source "${PROJECT_ROOT}/.env" 2>/dev/null && set +a # 2. IP/config from centralized config [[ -f "${PROJECT_ROOT}/config/ip-addresses.conf" ]] && source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true # 3. smom-dbis-138 .env (PRIVATE_KEY, bridge addrs, RPC) — PRIVATE_KEY is read from this dotenv when not set [[ -f "${PROJECT_ROOT}/smom-dbis-138/.env" ]] && set -a && source "${PROJECT_ROOT}/smom-dbis-138/.env" 2>/dev/null && set +a # 3b. Secure secrets (PRIVATE_KEY) — when not set, try ~/.secure-secrets/private-keys.env [[ -z "${PRIVATE_KEY:-}" ]] && [[ -f "${HOME}/.secure-secrets/private-keys.env" ]] && set -a && source "${HOME}/.secure-secrets/private-keys.env" 2>/dev/null && set +a # 4. dbis_core config if present [[ -f "${PROJECT_ROOT}/dbis_core/config/dbis-core-proxmox.conf" ]] && source "${PROJECT_ROOT}/dbis_core/config/dbis-core-proxmox.conf" 2>/dev/null || true # 5. Contract addresses from master JSON (config/smart-contracts-master.json) when not set by .env [[ -f "${PROJECT_ROOT}/scripts/lib/load-contract-addresses.sh" ]] && source "${PROJECT_ROOT}/scripts/lib/load-contract-addresses.sh" 2>/dev/null || true # Ensure hosts have fallbacks (from config or defaults) PROXMOX_HOST_R630_01="${PROXMOX_HOST_R630_01:-${PROXMOX_R630_01:-192.168.11.11}}" PROXMOX_HOST_R630_02="${PROXMOX_HOST_R630_02:-${PROXMOX_R630_02:-192.168.11.12}}" PROXMOX_HOST_ML110="${PROXMOX_HOST_ML110:-${PROXMOX_ML110:-192.168.11.10}}" # Derived vars (from config; fallbacks for missing config) export RPC_CORE_1="${RPC_CORE_1:-192.168.11.211}" export RPC_PUBLIC_1="${RPC_PUBLIC_1:-192.168.11.221}" # Chain 138 two standards: (1) Core RPC_URL_138 admin/deploy VMID 2101; (2) Public RPC_URL_138_PUBLIC bridge/frontend VMID 2201. Alias: RPC_URL -> RPC_URL_138. export RPC_URL_138="${RPC_URL_138:-${CHAIN138_RPC_URL:-${RPC_URL:-http://${RPC_CORE_1}:8545}}}" export CHAIN138_RPC_URL="$RPC_URL_138" export CHAIN138_RPC="$RPC_URL_138" # Foundry uses ETH_RPC_URL; set so forge create/script use Chain 138 when --rpc-url not passed export ETH_RPC_URL="${ETH_RPC_URL:-$RPC_URL_138}" export RPC_URL_138_PUBLIC="${RPC_URL_138_PUBLIC:-http://${RPC_PUBLIC_1}:8545}" export WS_URL_138_PUBLIC="${WS_URL_138_PUBLIC:-ws://${RPC_PUBLIC_1}:8546}" export SMOM_DIR="${SMOM_DBIS_138_DIR:-${PROJECT_ROOT}/smom-dbis-138}" export DBIS_CORE_DIR="${DBIS_CORE_DIR:-${PROJECT_ROOT}/dbis_core}" # VMID -> Proxmox host (for pct/qm operations) # Covers: DBIS (101xx), RPC (2101, 2201, 2301, etc.), Blockscout (5000), CCIP (5400-5476), NPMplus (10233, 10234) get_host_for_vmid() { local vmid="$1" case "$vmid" in 10130|10150|10151|106|107|108|10000|10001|10020|10100|10101|10120|10233|10235) echo "${PROXMOX_HOST_R630_01}";; 2101) echo "${PROXMOX_HOST_R630_01}";; 5000|7810|2201|2303|2401|6200|6201|10234|10237|5800|5801) echo "${PROXMOX_HOST_R630_02}";; 2301|2400|1504|2503|2504|2505) echo "${PROXMOX_HOST_ML110}";; 5400|5401|5402|5403|5410|5411|5412|5413|5414|5415|5416|5417|5418|5419|5420|5421|5422|5423|5424|5425|5440|5441|5442|5443|5444|5445|5446|5447|5448|5449|5450|5451|5452|5453|5454|5455|5470|5471|5472|5473|5474|5475|5476) echo "${PROXMOX_HOST_R630_02}";; *) echo "${PROXMOX_HOST_R630_01:-${PROXMOX_R630_02}}";; esac }