Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/taskengine/summarizer_format_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func buildFeesSectionHTML(s Summary) string {
if s.Workflow != nil && s.Workflow.IsSimulation {
// Heading omitted — the placeholder line carries enough context on its own.
return `<div style="margin-bottom: 20px;">` +
`<p style="margin: 0; color: #666; font-style: italic;">⛽ (cost estimated at deploy)</p>` +
`<p style="margin: 0; color: #666; font-style: italic;">⛽ (see cost estimate before deploy)</p>` +
`</div>`
}

Expand Down
4 changes: 2 additions & 2 deletions core/taskengine/summarizer_format_telegram.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ func formatSubjectWithBoldName(subject string) string {
// Format: "⛽ <b>Cost:</b> 0.000003 ETH ($0.01), 1.2 USDC ($1.20)" — native
// token first, comma-separated, USD parenthetical per token. Unpriceable
// tokens render as "$?". For simulations the line collapses to the static
// "⛽ (cost estimated at deploy)" placeholder. Returns "" when there's
// "⛽ (see cost estimate before deploy)" placeholder. Returns "" when there's
// nothing to render.
func formatTelegramCostLine(s Summary) string {
if s.Workflow != nil && s.Workflow.IsSimulation {
return "⛽ <i>(cost estimated at deploy)</i>\n"
return "⛽ <i>(see cost estimate before deploy)</i>\n"
}
if s.Fees == nil || len(s.Fees.Total) == 0 {
return ""
Expand Down
8 changes: 4 additions & 4 deletions core/taskengine/summarizer_format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,7 @@ func TestFormatTelegramFromStructured_RunnerAndFees(t *testing.T) {
if strings.Contains(out, "(~") || strings.Contains(out, "<b>Value fee:</b>") {
t.Errorf("Telegram should not render gas-units detail or Value fee line, got:\n%s", out)
}
if strings.Contains(out, "(cost estimated at deploy)") {
if strings.Contains(out, "(see cost estimate before deploy)") {
t.Errorf("deployed run should not show simulation placeholder, got:\n%s", out)
}

Expand Down Expand Up @@ -1290,7 +1290,7 @@ func mustBigInt(s string) *big.Int {
}

// TestFormatTelegramFromStructured_Simulation_PlaceholderCost confirms simulation
// runs render the "(cost estimated at deploy)" placeholder instead of fake-precision
// runs render the "(see cost estimate before deploy)" placeholder instead of fake-precision
// numbers. Sim gas prices are conservative chain defaults, so any specific ETH/gas
// figure would mislead the user.
func TestFormatTelegramFromStructured_Simulation_PlaceholderCost(t *testing.T) {
Expand Down Expand Up @@ -1318,7 +1318,7 @@ func TestFormatTelegramFromStructured_Simulation_PlaceholderCost(t *testing.T) {

out := FormatForMessageChannels(summary, "telegram", nil)

if !strings.Contains(out, "⛽ <i>(cost estimated at deploy)</i>") {
if !strings.Contains(out, "⛽ <i>(see cost estimate before deploy)</i>") {
t.Errorf("simulation should render the deploy-time placeholder, got:\n%s", out)
}
for _, banned := range []string{"<b>Cost:</b>", "0.0000105 ETH", "21 K gas", "platform fee"} {
Expand Down Expand Up @@ -1729,7 +1729,7 @@ func TestComposeSummary_SimulateTaskFromClientPayload(t *testing.T) {
}

// The simulation Cost placeholder uses italic text; allow that but no other italics.
if strings.Contains(telegram, "<i>") && !strings.Contains(telegram, "<i>(cost estimated at deploy)</i>") {
if strings.Contains(telegram, "<i>") && !strings.Contains(telegram, "<i>(see cost estimate before deploy)</i>") {
t.Errorf("Telegram should not contain italic annotation other than the cost placeholder, got:\n%s", telegram)
}

Expand Down
4 changes: 2 additions & 2 deletions docs/changes/20260502-notification-cost-line-and-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Single-line, multi-token, native unit first with USD parenthetical per token:
| ETH gas + USDC value-fee | `⛽ Cost: 0.000003 ETH ($0.01), 1.2 USDC ($1.20)` |
| Unpriceable ERC20 | `⛽ Cost: 0.000003 ETH ($0.01), 0.005 PEPE ($?)` |
| Read-only deployed (no on-chain steps) | (line omitted) |
| Simulation | `⛽ (cost estimated at deploy)` — static, no numbers |
| Simulation | `⛽ (see cost estimate before deploy)` — static, no numbers |

Telegram drops bullets, gas-units, and value-fee detail; email matches. Breakdowns live on the dashboard. Simulation collapses to the placeholder because sim gas prices are conservative chain defaults rather than real network conditions — any specific number would mislead.

Expand Down Expand Up @@ -83,7 +83,7 @@ To make simulation cogs[] non-empty in the first place, the Tenderly client now
- `TestPercentOfRaw` — value-fee percentage math against raw amounts.
- `TestTokenBucketToTokenTotal` — stablecoin shortcut, zero-rounding omission, missing price service path.
- `TestFormatTelegramFromStructured_RunnerAndFees` and `TestFormatTelegramFromStructured_MultiToken_USDPlaceholder` — end-to-end render assertions.
- Production verification: the next deployed run on Sepolia after `cba1ac8` showed the Telegram block ordering with Runner-and-Network folded onto one line; the simulation summary correctly rendered `⛽ (cost estimated at deploy)` after `4f784c9` (`vm.IsSimulation` flowing through to the formatter).
- Production verification: the next deployed run on Sepolia after `cba1ac8` showed the Telegram block ordering with Runner-and-Network folded onto one line; the simulation summary correctly rendered `⛽ (see cost estimate before deploy)` after `4f784c9` (`vm.IsSimulation` flowing through to the formatter).
- The aggregator's existing tests pass with the price service possibly nil: executor (`executor.go:321,478`), fee estimator (`fee_estimator.go:195`), and the new `buildTotalsFromVM` all guard against `nil` rather than panicking.

## Cross-repo coordination
Expand Down
Loading