shared+buyer/cli: lazy-read VECTOR_ZERO_TIME_MS; CLI populates process.env

lucidContext.ts captured VECTOR_ZERO_TIME at module-load time, so CLIs
that read a .env file at runtime (rather than letting Docker env_file
populate process.env before the runtime starts) got the testnet default
and built txs with a wrong slot origin -- Ogmios rejected with code
3118 "outside validity interval" on mainnet.

Two fixes:
- lucidContext.ts: read process.env.VECTOR_ZERO_TIME_MS inside
  applyVectorSlotConfig() so the defensive re-apply in createLucidContext
  picks up env vars set after module-load.
- run-cycle.ts / reclaim-orphans.ts: inject VECTOR_ZERO_TIME_MS,
  OGMIOS_URL, INDEXER_URL, NETWORK_ID into process.env right after
  reading the --env file, before any tx work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
david
2026-05-19 13:37:58 +02:00
parent 7910888234
commit f344d1475d
3 changed files with 16 additions and 1 deletions

View File

@@ -109,6 +109,11 @@ async function main(argv: string[]): Promise<number> {
return 1;
}
const networkId: 0 | 1 = env.NETWORK_ID === "1" ? 1 : 0;
// Inject loaded vars into process.env so shared tx builders see them
// (e.g. lucidContext.ts's VECTOR_ZERO_TIME_MS). See run-cycle.ts for context.
for (const key of ["VECTOR_ZERO_TIME_MS", "OGMIOS_URL", "INDEXER_URL", "NETWORK_ID"]) {
if (env[key] && !process.env[key]) process.env[key] = env[key];
}
const wk = deriveWalletKey(env.BUYER_PRIV_KEY_HEX, networkId);
const chain: ChainProvider = new LiveOgmiosProvider({ ogmiosUrl: env.OGMIOS_URL });

View File

@@ -179,6 +179,12 @@ async function main(argv: string[]): Promise<number> {
return 1;
}
const networkId: 0 | 1 = env.NETWORK_ID === "1" ? 1 : 0;
// Inject loaded vars into process.env so downstream tx-building modules
// (e.g. lucidContext.ts's VECTOR_ZERO_TIME_MS) see them. The shared tx
// builders read these from process.env, not the CLI-local env map.
for (const key of ["VECTOR_ZERO_TIME_MS", "OGMIOS_URL", "INDEXER_URL", "NETWORK_ID"]) {
if (env[key] && !process.env[key]) process.env[key] = env[key];
}
const advertRef = parseEscrowRef(env.ADVERT_REF);
const wk = deriveWalletKey(env.BUYER_PRIV_KEY_HEX, networkId);
const chain: ChainProvider = new LiveOgmiosProvider({ ogmiosUrl: env.OGMIOS_URL });

View File

@@ -41,11 +41,15 @@ const HEX64_RE = /^[0-9a-fA-F]{64}$/;
// idempotent — repeated calls leave the values identical. createLucidContext
// invokes it before constructing the Lucid instance.
const VECTOR_ZERO_TIME = Number(process.env.VECTOR_ZERO_TIME_MS) || 1_752_057_484_000;
const VECTOR_ZERO_SLOT = 0;
const VECTOR_SLOT_LENGTH = 1000;
export function applyVectorSlotConfig(): void {
// Read VECTOR_ZERO_TIME_MS lazily so callers that populate process.env after
// module load (e.g. CLIs that read a .env file at runtime) still get the
// right value. Capturing this as a module-level const broke run-cycle.ts
// with the testnet default while pointing at mainnet.
const VECTOR_ZERO_TIME = Number(process.env.VECTOR_ZERO_TIME_MS) || 1_752_057_484_000;
const cfg = SLOT_CONFIG_NETWORK["Mainnet"];
if (
cfg.zeroTime !== VECTOR_ZERO_TIME ||