Read the auction duration per launch path; release 2.1.0 - #13
Conversation
The Standard/advanced auction window changed from 7 days to 2 days when its timelock executed. `ChainLaunchConfig.advancedDuration` was a hardcoded "7 Days" string, and the CLI's `--path` help text repeated "advanced (7d)". Add `getAuctionDurationMs(path)` as the fallback and `fetchAuctionDuration( client, chainId, path)` reading `expressDuration` / `advancedDuration`, matching what `fetchGraduationThreshold` already does for the threshold. The full ABIs already carry both getters. `expressDuration` / `advancedDuration` stay on `ChainLaunchConfig` but are now derived from the fallback and marked `@deprecated`. Removing them would be a second breaking change days after 2.0.0 for fields with no consumers; they go in the next major. `formatAuctionDuration` and `getAuctionDurationMs` are declared above `makeLaunchConfig`, which calls them at module load — the test suite caught a temporal dead zone when they were appended at the end of the file. Bump 2.0.0 -> 2.1.0 across package.json, the lockfile, the CLI `--version`, the README pin and both skill files. Additive, so a minor.
PR SummaryLow Risk Overview New exports: CLI Reviewed by Cursor Bugbot for commit ef26cb9. Configure here. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe SDK version changes to 2.1.0. Launch parameters now support path-specific fallbacks and live factory reads. The CLI and documentation report live durations and the 24-hour advanced start delay. ChangesAuction duration configuration
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant fetchLaunchParams
participant LaunchFactory
participant launch-config
CLI->>fetchLaunchParams: Request path-specific launch parameters
fetchLaunchParams->>LaunchFactory: Multicall graduation threshold and auction duration
LaunchFactory-->>fetchLaunchParams: Return factory values
fetchLaunchParams->>launch-config: Apply validation and configured fallbacks
launch-config-->>CLI: Return threshold and duration
CLI-->>CLI: Display live duration and advanced start delay
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef26cb9f57
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const AUCTION_DURATION_FALLBACK_MS: Record<"express" | "advanced", number> = { | ||
| express: 24 * 60 * 60 * 1000, | ||
| advanced: 2 * 24 * 60 * 60 * 1000, | ||
| }; |
There was a problem hiding this comment.
Move the duration fallback into constants.ts
The new fallback is a package constant, but this repository requires all constants in src/constants.ts. Move it there to keep fallback values discoverable and avoid scattered sources of truth.
AGENTS.md reference: AGENTS.md:L50-L52
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Declined — moving only this one would make things less discoverable, not more.
GRADUATION_FALLBACK_WEI already lives in src/registry/launch-config.ts and shipped that way in 2.0.0. The duration fallback is its exact sibling: same shape, same per-path keying, same "fallback for the live factory read" role, consumed by the same module. Splitting them across constants.ts and registry/launch-config.ts is the scattering the rule is trying to prevent.
src/registry/ is also where per-chain/per-deployment config deliberately lives (contracts.ts, chains.ts, launch-config.ts), which is why the threshold landed here in the first place.
Happy to move both in a follow-up if the team reads the rule as covering registry values too — but that is a consistency pass on existing code, not something this PR should do to one half of a pair.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/read/launches.ts`:
- Around line 140-145: Update fetchAuctionDuration so getContracts(chainId)
executes before the try block, keeping unsupported-chain errors propagating
instead of being converted to the path fallback. Keep only the
client.readContract RPC failure handling inside the fallback path.
- Around line 135-151: Update fetchAuctionDuration so getContracts(chainId) runs
before the try block, allowing unsupported-chain errors to propagate; validate
the returned duration as a positive, in-range bigint before converting it to
milliseconds, otherwise use getAuctionDurationMs(path). Add Vitest coverage for
valid, zero, non-bigint, thrown, out-of-range, and unsupported-chain outcomes,
plus formatting cases for “24 Hours” and “2 Days”.
- Around line 146-147: Update the duration conversion branch around the seconds
handling to accept bigint values only when they are positive and at most
BigInt(Number.MAX_SAFE_INTEGER) / 1000n; otherwise preserve the existing
fallback behavior. Add coverage for valid, zero, and oversized uint256
durations.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 58b6e4ff-8864-49c2-b727-a43e8c177b96
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
README.mdpackage.jsonskills/boardwalk/SKILL.mdskills/boardwalk/plugins/boardwalk.mdsrc/cli.tssrc/index.tssrc/read/launches.tssrc/registry/launch-config.ts
`getContracts(chainId)` throws for an unsupported chain, but both `fetchGraduationThreshold` and `fetchAuctionDuration` called it inside the try, so an unsupported chain was masked as an RPC failure and silently returned a fallback — making the chain look configured. Resolve the address before the try so only `readContract` failures fall through. The threshold half of this was already shipped in 2.0.0; this fixes both. Cap the duration before converting: `SET_EXPRESS_DURATION` only requires > 0, so an oversized `uint256` would lose precision through `Number()`. Adds test/launch-config.test.ts covering valid, zero, non-bigint, thrown, out-of-range and unsupported-chain results, plus the duration formatting across the 2-14 day admin range.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5d1bf5972
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
`fetchAuctionDuration` had no internal caller — the live read existed but the
CLI never used it, so `launch` reported a threshold read from the factory and
nothing for the duration, and the `--path` help restated a tunable "2d". That is
the same staleness this branch set out to fix.
`launch` now emits `auctionDuration { seconds, display, startDelaySeconds }`
alongside `graduationThreshold`, both fetched in parallel. The help text points
at that field instead of naming a number. `ADVANCED_START_DELAY_SECONDS` goes in
constants.ts — it mirrors an immutable contract constant, unlike the per-chain
registry values.
`formatAuctionDuration` no longer rounds: a 90-minute window read as "2 Hours"
and a one-hour window as "1 Hours". It now composes exact day/hour/minute parts
with correct pluralisation, leaving "24 Hours" and "2 Days" unchanged.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e48e84dbed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ( | ||
| typeof seconds === "bigint" && | ||
| seconds > BigInt(0) && | ||
| seconds <= BigInt(MAX_PLAUSIBLE_DURATION_SECONDS) |
There was a problem hiding this comment.
Accept every valid express duration
When the timelock sets expressDuration above 365 days, this check rejects the onchain value and reports the 24-hour fallback. The contract only requires a positive express duration, so 366 days remains valid and converts safely to a JavaScript number. Bound the conversion by numeric safety instead of adding a stricter protocol limit.
AGENTS.md reference: AGENTS.md:L3-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Declined — repo owner reviewed this and called it overkill, and I agree.
The scenario requires an admin to set expressDuration above 365 days. Express exists to be the short path (currently 24h); a 400-day express auction is not a configuration anyone reaches by accident, and it would need a 7-day timelock to land.
Weighing the two failure modes: too tight silently shows 24h instead of 400 days, in a scenario that will not occur. Too loose accepts a garbage uint256 and feeds it into date math, which is the case CodeRabbit asked to be guarded on this same PR — and it reviewed the one-year cap and confirmed it as "safely below the JavaScript Date range". Swapping it for a numeric-safety bound trades a guard that fires on real garbage for coverage of a scenario that does not exist.
The principle that a fallback should mean "could not read it" rather than "read a value I disagree with" is a fair point, and worth revisiting if the express window is ever tuned beyond a day. Not worth another round now.
AGENTS.md's "Reads" convention is explicit: batch independent reads with `client.multicall` rather than `Promise.all` of single `readContract` calls, because public RPCs rate-limit adjacent round-trips. The `Promise.all` added for the threshold and duration was the only one of its kind left in the repo. `fetchLaunchParams` reads both in one multicall via MULTICALL3_ADDRESS, matching the existing batches in the contribute and LP paths. Each field still falls back independently when the factory returns something unusable; an unreachable RPC or a chain without Multicall3 falls back on both, and an unsupported chain still throws. `fetchGraduationThreshold` and `fetchAuctionDuration` stay exported for consumers reading one value; the shared validity guards are now factored out so all three agree.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4233055d20
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (totalHours > 0) parts.push(plural(totalHours, "Hour")); | ||
| if (minutes > 0) parts.push(plural(minutes, "Minute")); | ||
| if (parts.length === 0) parts.push(plural(seconds, "Second")); |
There was a problem hiding this comment.
Preserve seconds in duration displays
When the tunable duration includes leftover seconds, this formatter drops them whenever an hour or minute exists. For example, 3,630 seconds becomes 1 Hour, although the CLI's numeric field reports 3,630. Include the seconds remainder so the public display does not shorten the configured auction window.
AGENTS.md reference: AGENTS.md:L66-L66
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Declined — real but not worth the precision.
Confirmed: 3,630 seconds renders as 1 Hour while auctionDuration.seconds reports 3630, so the display drops the 30-second remainder. For every value the protocol actually uses — 24h, 2d, the 2-14 day admin range — the seconds remainder is zero and the display is exact.
Machine consumers should read auctionDuration.seconds, which is exact by construction; display is human copy where second-level precision on a multi-day auction window is noise. The repo owner reviewed this class of edge case and asked to stop chasing it.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@skills/boardwalk/SKILL.md`:
- Line 165: Update the Naming guidance near the standard/advanced launch
terminology to replace “onchain contracts” with “on-chain contracts,” preserving
the surrounding wording and meaning.
In `@src/read/launches.ts`:
- Around line 192-217: Update the multicall in getLaunchConfig to use
allowFailure: true and process each viem result independently via its status and
result, preserving valid threshold or duration values while applying the
corresponding fallback only to reverted or invalid subcalls. In
test/launch-config.test.ts:22-31 and test/launch-config.test.ts:148-156, update
mocks to viem-shaped results and cover both threshold-reverts/duration-succeeds
and duration-reverts/threshold-succeeds permutations.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f8cebcf8-5c64-4ee9-ab0f-9b70b719f21e
📒 Files selected for processing (8)
README.mdskills/boardwalk/SKILL.mdsrc/cli.tssrc/constants.tssrc/index.tssrc/read/launches.tssrc/registry/launch-config.tstest/launch-config.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- src/index.ts
- README.md
- src/registry/launch-config.ts
SKILL.md was updated to drop the hardcoded window and point agents at the `launch` output's `auctionDuration`, but its sibling plugin doc still said "standard (2d after a 24h start delay)". Both durations are timelock-tunable, so that line goes stale on the next change — the exact failure this branch removes. The 24h start delay stays stated: `PresaleManager.ADVANCED_START_DELAY` is an immutable contract constant.
The Standard/advanced auction window changed from 7 days to 2 days when its timelock executed (
advancedDuration()= 172800s on all four chains).ChainLaunchConfig.advancedDurationwas a hardcoded"7 Days", and the CLI's--pathhelp repeatedadvanced (7d)in two places.Changes
getAuctionDurationMs(path)fallback +fetchAuctionDuration(client, chainId, path)readingexpressDuration/advancedDuration— mirrorsfetchGraduationThreshold. The registry ships full ABIs, so no ABI change.formatAuctionDurationderives"24 Hours"/"2 Days"from ms. Verified across the 2-14 day admin range.--pathhelp now readsadvanced (2d after a 24h start delay).README.md,skills/boardwalk/SKILL.mdand the Base-MCP plugin doc.Why the deprecated fields stay
expressDuration/advancedDurationare per-path values sitting on a per-chain type — the same modelling error the threshold had, and the FE removed them outright. Here they are now derived fromgetAuctionDurationMs(so correct) and marked@deprecated.Removing them would be a second breaking major days after 2.0.0, for fields with zero consumers inside the SDK. Not worth the churn on published consumers; they go in the next major.
A bug the test suite caught
formatAuctionDuration/getAuctionDurationMswere initially appended at the end of the file, butmakeLaunchConfigcalls them at module load to buildchainLaunchConfig. That is a temporal dead zone —ReferenceError: Cannot access 'AUCTION_DURATION_FALLBACK_MS' before initializationon import, which would have broken every consumer. They are now declared above their call site.Version
2.0.0 → 2.1.0, additive. Bumped across
package.json,package-lock.json, CLI.version(), README pin and both skill files per AGENTS.md.Note the lockfile edit is exactly the two entries naming this package — an earlier blunt string replace clobbered
@types/node,pathval,siginfoand node engine ranges, and was reverted.tsc --noEmitclean.vitest run— 83/83 pass.Summary by CodeRabbit
New Features
Documentation
Chores