Skip to content

feat(builders): curated builder icons backed by a builder profile table (ROO-94) - #2185

Open
sleyter93 wants to merge 1 commit into
mainfrom
feat/roo-94-builder-icons
Open

feat(builders): curated builder icons backed by a builder profile table (ROO-94)#2185
sleyter93 wants to merge 1 commit into
mainfrom
feat/roo-94-builder-icons

Conversation

@sleyter93

Copy link
Copy Markdown
Collaborator

Closes ROO-94.

Builders render a generated identicon everywhere, so the Builders table and the
"builders you may want to back" cards show geometric noise instead of the projects'
own marks — the exact screenshot attached to the ticket.

Why it happened

The plumbing for a real image already existed, but nothing fed it:

  • BuilderCard called BuilderHeader without ever passing imageIpfs, so IpfsAvatar always fell through to the identicon.
  • The Builder type had no image field at all — the imageIpfs that circulates in the app comes from the delegates/RNS path, not from builders.
  • Four call sites bypassed IpfsAvatar entirely and used Jdenticon directly.

Approach

Adds dao_data.BuilderProfiles, an app-owned table keyed by builder address — which
is already the builder's id in the indexer (Builder.id). It is deliberately a table
rather than a static map because ROO-94 itself anticipates growth: "this will help
with visibility later on for builder profiles"
, and ROO-96/ROO-97 build on it.

The indexer database and dao_data sit behind two different connections, so they
cannot be joined in SQL. They are merged in BuilderContext, which already
centralises the builders map and feeds the table, spotlight and cards from one place.

The merge costs nothing: the builder list is assembled client-side from five
dependent waves of on-chain reads, and the profiles request runs in parallel with
them. It is not on the critical path.

The image column holds a reference, not a blob

Either a root-relative path to an asset in public/, or an IPFS CID. Assets ship in
the repo so they need no images.remotePatterns entry and render in local
development, which the Pinata gateway does not permit without
NEXT_PUBLIC_PINATA_GATEWAY_KEY. Moving a builder to IPFS later is an UPDATE on
that row — no schema change, no component change, since IpfsAvatar already routes
anything not starting with / through the gateway.

Coverage

Ships icons for 7 builders: MoneyOnChain, Boltz, Steer Protocol, Vottun, Symbiosis,
Beexo Wallet and OpenOcean (which occupies two rows — 0x7A1a… is a reward-receiver
migration of the same builder, self-proposed from 0x1D11…, not a second project).

A builder with no row keeps the identicon, so a missing icon is never a broken
image.
The remaining 12 are pending better source assets; the fastest path for most
of them is asking the builders directly. Stelios & Mick (Geyser Team) is
intentionally left on the identicon — they are individuals, and their application
explicitly states that Geyser is not the applicant, so the Geyser logo would
misattribute the entry.

Worth a reviewer's attention

  • IpfsAvatar gains fallbackClassName. The light backing belongs to the identicon only. The table cells previously painted bg-white on the container, which is right for a dark-on-transparent identicon but made white-on-transparent logos vanish. Verified by rendering every asset at 88px and 40px.
  • Asset selection is constrained by the circular avatar. Wordmarks get cropped to their middle, and marks that are black on transparent disappear against the dark background. Documented in public/images/builders/README.md.
  • The seed prunes. Rows dropped from the manifest are deleted, so the manifest stays the source of truth instead of leaving rows pointing at deleted assets.

Migration

prisma/migrations/2_builder_profiles is committed but has not been applied to any
remote environment
— that is a deploy decision. Applied and verified against the
local dao-data postgres only.

Verification

  • tsc --noEmit clean, eslint . clean, 1390 tests pass across 145 files.
  • Migration applied to local docker postgres; table and unique index created as expected.
  • Full chain verified: manifest → npm run db:seed:builders → database → GET /api/builder-profiles returning the 8 expected rows.
  • Merge and fallback verified in the running app against testnet builders: exactly one real <img> for the seeded builder and identicons for the rest.
  • Every shipped asset checked at 88px and 40px in a circle.

One gap: the icons could not be seen on the real builders page locally, because local
dev runs testnet while these are mainnet addresses. The pipeline is proven end to end
with a testnet address; this specific set of logos will first be visible on deploy.

…le (ROO-94)

Builders rendered a generated identicon everywhere, so the Builders table and
the "builders you may want to back" cards showed geometric noise instead of the
projects' own marks.

The plumbing for a real image already existed but nothing fed it: `BuilderCard`
never passed `imageIpfs` to `BuilderHeader`, and the `Builder` type had no image
field at all. Four call sites bypassed `IpfsAvatar` and used `Jdenticon` directly.

Adds `dao_data.BuilderProfiles`, an app-owned table keyed by builder address —
which is already the builder's id in the indexer. The indexer database and
`dao_data` sit behind two different connections, so the two are merged in
`BuilderContext` rather than joined in SQL; the profiles request runs in parallel
with the on-chain reads that already gate the page, so it adds no latency to the
critical path.

The `image` column holds a reference, not a blob: a root-relative path to an
asset in `public/`, or an IPFS CID. Assets ship in the repo so they need no
`remotePatterns` entry and render in local development, which the Pinata gateway
does not allow without a key. Moving a builder to IPFS later is an UPDATE on that
row, with no schema or component change.

Ships icons for 7 builders. Any builder without a row keeps the identicon, so a
missing icon is never a broken image.

Notes:
- `IpfsAvatar` gains `fallbackClassName`: the light backing belongs to the
  identicon only. Painting it behind a real logo made white-on-transparent marks
  disappear.
- The seed prunes rows dropped from the manifest, so the manifest stays the
  source of truth instead of leaving rows pointing at deleted assets.
- The migration is committed but not applied to any remote environment.
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant