Show transaction status, action, and timestamp in social link previews - #3596
Show transaction status, action, and timestamp in social link previews#3596tom2drum wants to merge 14 commits into
Conversation
Medium task, five subtasks: make the `og` block a default/enhanced template layer, share the interpretation currency rounding and render summaries as plain text, derive the status/action/timestamp params, wire the bot-gated server-side fetch plus the /tx/[hash] templates, and verify on a demo (agent deploys, human confirms the real card). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. To trigger a review, include ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The `og` entry in the route template map was static data: `og.description` was passed through to the meta tag without ever reaching `compileValue`, so it could hold no placeholders, and the record required a description and an image together. That ruled out a per-route dynamic OG description. OG title and OG description now each accept the same `default`/`enhanced` shape as the metadata templates and are compiled against the same params; the image is independent of both. A route that declares no OG template falls back to the page title and description — written out explicitly so the resolution rule is uniform, which is why routes without an OG description now emit an `og:description` carrying the text crawlers previously inferred from `<meta name="description">`. The new `hash_short` param shortens a route's hash the way `truncation="constant"` does on the page. No route declares OG templates yet — `/tx/[hash]`'s land in the next steps. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The OG description needs the transaction action to read exactly as the subheading on the page does, but the summary is a template of typed variables that only `TxInterpretation` knows how to turn into React elements. A plain-text renderer walks the same parsing pipeline and maps each variable type to the text its UI counterpart displays. Two pieces of that mapping were inline in components and are now shared, so the preview cannot drift from the page: the currency rounding ladder, which the interpretation component calls instead of holding its own copy, and the address name chain, extracted into the address slice and called by `AddressEntity` itself. Neither component's output changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Turns the transaction and its interpretation summary into the three strings the OG description template compiles — status word, action, UTC timestamp — or nothing at all when any of them is missing, which is what keeps the template's all-or-nothing rule true at the source. The unit lives in the tx slice rather than beside `generate()`: metadata is regenerated on every client-side route change, so anything reachable from there ships to all users, and the responses would otherwise be serialized into `__NEXT_DATA__` whole. Three short strings instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A worktree under `.claude/worktrees/` is a full checkout of the repo, so every tool that walks the tree from the root sees each file twice: cspell and the two test runners duplicate their work, tsc type-checks a copy with no dependencies installed, and eslint exhausted the Node heap outright. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A shared transaction link produced a card titled with the full 66-character hash and described by the generic page copy, since the route declared no OG templates and crawlers never run the client-side metadata update. `/tx/[hash]` now carries a short-hash OG title for every crawler, and its `getServerSideProps` fetches the transaction and its interpretation summary for social-preview bots specifically, turning them into a status · action · timestamp description. Anything less than all three parts falls back to the generic description, so a pending transaction or a failed request degrades to exactly today's card. Both requests run in parallel with a 2 s timeout. That is longer than the other routes allow because both endpoints compute their response on the first request for a transaction and cache it afterwards, and a crawler is always that first request: on eth mainnet a cold summary averages 0.95 s against 0.30 s warm. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TEAM.md mixed the roster with the rules for using it: who picks a task's contacts, that product questions go to a channel rather than a DM, which channel, and how to mention the addressee. Those already lived in `grill-the-task` and `to-spec`, so the file was a second, drifting copy — the skills are what an agent actually reads when routing a question. What stays in TEAM.md is the data plus what makes it readable: the meaning of the `default` marker, where IDs come from, and each team's ownership. One rule was only implied in the skill and is now explicit there: the roster default is what to record when the developer has no task-specific pick. The backend section also gains Slack group IDs beside its members, so a question can be addressed to a whole team once a skill has a rule for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The demo proved the wiring: every branch of the description was observed on a public URL, including the interpretation summary and the called-method fallback with a named address. It also showed the feature barely enhances on that instance, so the subtask now carries the sampling behind that — both transaction endpoints measured against a network control, and the ruling not to raise the timeout, since no crawler waits as long as the API takes. The latency goes to the backend team as Q2; it gates the release decision rather than any remaining work, because the code degrades to today's card wherever the API is slow. Also corrects a claim the spec made from the start: `logRequestFromBot` and `fetchApi` do record their metrics, but the SSR bundle keeps a registry of its own, so `/api/metrics` never exports them and the timeout evidence had to come from sampling the API directly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The `review` variant exports them, `review-2` did not, so `/api/metrics` answered 404 there — and the metrics are how a demo shows what the app did server-side, which is the point of deploying one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All three open questions came back. The demo verification is done: the card was confirmed in Telegram and X on an eth-mainnet demo, and the timeout question was settled by the metrics once they worked — on the loaded instance the mandatory call aborted on every crawler request, so the answer is to keep 2 s and change where the data comes from. That leaves two pieces of work rather than one. The backend is building an endpoint shaped for this preview, with switchable ens/metadata/summary preloads, going to staging to be measured — subtask 6, a brief until its shape is agreed. And the Noves decision needs code: the product call is to emit no enhanced description there, but an instance running Noves currently still requests the Blockscout summary and lands on the called-method fallback, which is the option that was rejected — subtask 7, scoped and ready. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An instance runs a single interpretation provider. On a Noves one the transaction page renders Noves' prose and the Blockscout summary endpoint has nothing to serve, so the preview fell through to the `called … on …` line — the option the PM ruled against, since pointing crawler traffic at a third party's slow API is not ours to decide. Both gates now require the provider to be `blockscout`: the util has no action without it, and the page makes no request at all. That also drops the `core:tx` request on instances with the feature off entirely, where it could never produce a description — and `none` is the provider's default.
All three read OG tags, none of them was in `detectBotRequest`, so their crawlers were treated as ordinary visitors and every route that enhances its preview for social bots — transaction, address, token, NFT instance, stats — served them the generic description instead. Reported for WhatsApp from a real card. Discord and LinkedIn match the `…bot` suffix rather than the bare product name, because both also ship an in-app browser whose user agent carries that name and whose requests are real visitors.
Resolves #3593
A shared link to a transaction page currently produces a near-useless social preview: the OG title carries the full 66-character hash and there is no
og:descriptionat all, so Telegram and X fall back to the generic page description. This task makes the preview describe the actual transaction — a short hash in the title, and{status} · {action} · {timestamp}as the description, with the action reading the same as the transaction details page subheading, including its fallback chain and amount rounding.Plan:
.agents/tasks/3593-tx-og-title-description/spec.md—medium, five subtasks.This is a spec-first draft: only the spec is committed so far. The branch will receive the task's work subtask by subtask, and the final description will be written when the PR is marked ready for review.