Move platform-neutral hooks and utils out of frontend - #74
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🧪 Coverage
|
aichannode
approved these changes
Aug 10, 2026
aichannode
left a comment
Collaborator
There was a problem hiding this comment.
It looks clean, thanks @heyradcode 👍
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Moves code that has no web coupling out of
frontendand into@shared/core, somobile can consume it instead of reimplementing it. From a review that flagged four
items; a sweep for completeness found two more.
Moved
frontend/src/hooks/usePetCooldowns.tsshared/src/hooks/pets/usePetCooldowns.tsfrontend/src/hooks/battle/useLiveBattleAnimation.tsshared/src/hooks/battle/useLiveBattleAnimation.tsfrontend/src/hooks/battle/useBattleOutcome.tsshared/src/hooks/battle/useBattleOutcome.tsfrontend/src/utils/address.tsshared/src/utils/common/address.ts.../battle/battle-matchmaking.tsshared/src/utils/battleMatchmaking.tstoDialoguePet,BattlePersonasfrom.../battle/battle-utils.tsshared/src/utils/battleDialoguePet.tsBodies are unchanged. Only the imports moved to relative paths, and
StrikeLogEntrynow comes from
@cryptopets/protocoldirectly, matching the sibling hooks in thatfolder. Every test moved with its code: frontend 394 to 370, shared 543 to 567.
Three decisions worth reviewing:
sameAccountmoved withshortAddress. Same file, same test file, sameplatform-neutrality test. It is a two-line wrapper over the protocol's
normalizeAccount, and mobile needs it for the same "is this me" checks the chatand leaderboard do. Leaving it would split one module across two packages.
BattleOutcomemoved toshared/src/types/battle.ts, since it is the hook'sreturn type.
MechanicalLogLinestayed in the frontend:isFighteris a renderingconcern.
battle-utils.tskept its three message strings. Those are frontend copy;mobile will want its own wording. What moved is the two functions that are
contracts with the backend:
toDialoguePetbuilds the dialogue endpoint's payload,and
opponentKeyencodes theowner::idshape that exists because Solana pet idsare not globally unique.
battle-matchmaking.tsis the one worth a second look.pickRandomOpponentandsortOpponentsByMatchdecide which opponents a player sees and in what order, so areimplementation on mobile would rank the same roster differently, and nobody would
notice until two screens were compared side by side.
Also in here
mobile/src/components/ConnectButton.tsxhad its own inline copy of the addresstruncation, with an ASCII
...and no length guard. It now callsshortAddress,so both clients render addresses the same way. That is the first place the move
pays for itself.
no-restricted-importsboundary onshared: nothing in@shared/coremayimport through a frontend path alias (
@components/*,@hooks/*, and the rest) ora platform-only module (
react-router-dom,react-native,next/*). Verified itfires by probing each group, not just that the package still passes. This is how
the six modules ended up misplaced to begin with.
bash.exe.stackdump, committed at the repo root, is untracked now.CLAUDE.mdpointed atuseBattleOutcomebesideuseBattlePanel. That line existsto stop someone splitting the panel, so a wrong pointer in it does real damage.
AGENTS.mdclaimed no module-boundary lint existed; it now says one does, and whatit does not cover.
Test factories
Three frontend suites replace
@shared/corewith a mock factory and were relying onthe real implementations reaching them by a separate module path. They now import
those modules directly and spread them, so the assertions still run against real
code rather than stubs:
useBattlePanel.test.tsasserts on the animation's 700ms timing (the result cardmust stay hidden until the last strike plays).
useResultDialogue.test.tsasserts on the personatoDialoguePetbuilds.chat.test.tsxandleaderboard.test.tsxassert on the EVM-folds/base58-does-notrule, and their hand-written
normalizeAccountstubs are now dead, since nothingin the frontend imports it any more.
Verification
frontend 370 tests / 48 files, shared 567 / 80, mobile jest 1/1. Lint clean on
frontend (including
lint:css), shared, and mobile.tsc -b --forceandvite buildon frontend,pnpm --filter backend buildfor the third@shared/coreconsumer (it only imports
@shared/core/node, which is untouched).