diff --git a/README.md b/README.md index 1081f402..5aa63cd3 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,12 @@ pnpm --filter @ickb/supervisor build pnpm live:supervisor ``` +To rebuild the standard ignored testnet configs from environment variables without printing private keys, set `ICKB_TESTNET_BOT_PRIVATE_KEY` and `ICKB_TESTNET_TESTER_PRIVATE_KEY`, optionally set `ICKB_TESTNET_RPC_URL`, `ICKB_TESTNET_SLEEP_INTERVAL_SECONDS`, `ICKB_TESTNET_MAX_ITERATIONS`, and `ICKB_TESTNET_MAX_RETRYABLE_ATTEMPTS`, then run: + +```bash +pnpm live:config-from-env +``` + By default the supervisor uses ignored `config/bot-testnet.json` and `config/tester-testnet.json`, writes artifacts under ignored `logs/live-supervisor//` paths, and runs deterministic bounded bot/tester commands only. It does not patch, verify, rebuild, relaunch, or invoke an LLM; external loops and operators consume `summary.json` between runs. For repeated bounded invocations, keep loop-owned options before `--` and supervisor options after it: diff --git a/apps/bot/README.md b/apps/bot/README.md index 7e0bae18..a1481cb4 100644 --- a/apps/bot/README.md +++ b/apps/bot/README.md @@ -13,10 +13,10 @@ The bot minimizes excess iCKB holdings so more liquidity stays available in CKB The bot reads one strict JSON config file named by `BOT_CONFIG_FILE`: ```json -{"chain":"testnet","privateKey":"0x...","rpcUrl":"http://127.0.0.1:8114/","sleepIntervalSeconds":60} +{"chain":"testnet","privateKey":"0x...","sleepIntervalSeconds":60,"maxRetryableAttempts":10} ``` -The JSON config accepts exactly `chain`, `privateKey`, `rpcUrl`, `sleepIntervalSeconds`, and optional `maxIterations`. Unknown keys, wrong types, non-HTTP(S) RPC URLs, whitespace/control characters in `rpcUrl`, and non-canonical private keys are rejected. The private key must be exactly lowercase `0x` plus 64 lowercase hex characters, with no newline, spaces, tabs, or comments. Local config files under `config/` are ignored by git. +The JSON config accepts exactly `chain`, `privateKey`, optional `rpcUrl`, `sleepIntervalSeconds`, optional `maxIterations`, and optional `maxRetryableAttempts`. Unknown keys, wrong types, non-HTTP(S) RPC URLs, whitespace/control characters in `rpcUrl`, and non-canonical private keys are rejected. Omitting `rpcUrl` lets CCC use its default endpoint. The private key must be exactly lowercase `0x` plus 64 lowercase hex characters, with no newline, spaces, tabs, or comments. Local config files under `config/` are ignored by git. Current network support: diff --git a/apps/tester/README.md b/apps/tester/README.md index 5aedc322..7f3e5337 100644 --- a/apps/tester/README.md +++ b/apps/tester/README.md @@ -7,10 +7,10 @@ The tester is now CCC-native. It waits while its own fresh matchable orders are The tester reads one strict JSON config file named by `TESTER_CONFIG_FILE`: ```json -{"chain":"testnet","privateKey":"0x...","rpcUrl":"http://127.0.0.1:8114/","sleepIntervalSeconds":10,"maxIterations":1} +{"chain":"testnet","privateKey":"0x...","sleepIntervalSeconds":10,"maxIterations":1,"maxRetryableAttempts":10} ``` -The JSON config accepts exactly `chain`, `privateKey`, `rpcUrl`, `sleepIntervalSeconds`, and optional `maxIterations`. Unknown keys, wrong types, non-HTTP(S) RPC URLs, whitespace/control characters in `rpcUrl`, and non-canonical private keys are rejected. The private key must be exactly lowercase `0x` plus 64 lowercase hex characters, with no newline, spaces, tabs, or comments. Local config files under `config/` are ignored by git. +The JSON config accepts exactly `chain`, `privateKey`, optional `rpcUrl`, `sleepIntervalSeconds`, optional `maxIterations`, and optional `maxRetryableAttempts`. Unknown keys, wrong types, non-HTTP(S) RPC URLs, whitespace/control characters in `rpcUrl`, and non-canonical private keys are rejected. Omitting `rpcUrl` lets CCC use its default endpoint. The private key must be exactly lowercase `0x` plus 64 lowercase hex characters, with no newline, spaces, tabs, or comments. Local config files under `config/` are ignored by git. Current network support: diff --git a/package.json b/package.json index 66983336..a1a93ed1 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "forks:ccc:smoke": "node scripts/forks-ccc-smoke.mjs", "forks:ccc:watch": "node scripts/forks-ccc.mjs --watch", "live:generate-config": "node scripts/ickb-generate-config.mjs", + "live:config-from-env": "node scripts/ickb-live-config-from-env.mjs", "live:preflight": "node scripts/ickb-live-preflight.mjs", "live:supervisor": "node apps/supervisor/dist/index.js", "live:supervisor:loop": "node scripts/ickb-supervisor-loop.mjs", diff --git a/scripts/ickb-generate-config.mjs b/scripts/ickb-generate-config.mjs index 33fdcbfd..630615f3 100644 --- a/scripts/ickb-generate-config.mjs +++ b/scripts/ickb-generate-config.mjs @@ -1,10 +1,10 @@ #!/usr/bin/env node -import { spawnSync } from "node:child_process"; import { randomBytes } from "node:crypto"; import { constants } from "node:fs"; -import { lstat, mkdir, open, realpath, writeFile } from "node:fs/promises"; +import { link, lstat, mkdir, open, realpath, rename, unlink } from "node:fs/promises"; import { dirname, isAbsolute, relative, resolve } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; +import { defaultCheckIgnored } from "./ickb-live-config-git.mjs"; const rootDir = fileURLToPath(new URL("..", import.meta.url)); const SECP256K1_ORDER = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); @@ -21,6 +21,7 @@ export function parseArgs(argv) { role: "bot", sleepIntervalSeconds: 1, maxIterations: 1, + maxRetryableAttempts: 10, force: false, }; for (let index = 0; index < argv.length; index += 1) { @@ -56,6 +57,14 @@ export function parseArgs(argv) { args.maxIterations = parsePositiveInteger(valueAfter(argv, ++index, arg), arg); continue; } + if (arg === "--max-retryable-attempts") { + args.maxRetryableAttempts = parsePositiveInteger(valueAfter(argv, ++index, arg), arg); + continue; + } + if (arg === "--no-max-retryable-attempts") { + args.maxRetryableAttempts = undefined; + continue; + } if (arg === "--no-max-iterations") { args.maxIterations = undefined; continue; @@ -74,8 +83,8 @@ export function parseArgs(argv) { export function usage() { return [ - "Usage: node scripts/ickb-generate-config.mjs [--chain testnet|mainnet] [--role