Skip to content

Conversation

@EehMauro
Copy link
Contributor

@EehMauro EehMauro commented Oct 13, 2025

Summary by CodeRabbit

  • New Features

    • Cardano Summit 2025 token and animated icon added to the visualizer and token lists.
    • New "How to play" sections: Gather Fuel, Gather Token, Mine Asteria, Quit Game — each with docs, interactive forms, example TX files and copyable code.
    • "How to play" menu item re-enabled and visible in the navigation.
    • Ship selection now syncs with the UI for interactive previews.
  • UX

    • Form inputs gained inline buttons/comments and fetch-last-slot helpers for convenience.

@coderabbitai
Copy link

coderabbitai bot commented Oct 13, 2025

Walkthrough

Adds Cardano token assets and Godot texture/animation, extends Godot project to 4.5, and introduces multiple new frontend “how-to-play” sections, UI inputs, API routes, tx3 template and protocol binding changes to support gather-fuel/gather-token/mine-asteria/quit-game flows and updated move/create ship timing fields.

Changes

Cohort / File(s) Summary
Frontend challenge tokens
frontend/src/stores/challenge.ts
Appends a Cardano Summit 2025 token entry (name, displayName, assetName, policyId) to mainnet challenge tokens (data-only change).
Godot assets & scene
godot-visualizer/resources/token_cardano.png.import, godot-visualizer/scenes/token.tscn, godot-visualizer/project.godot
Adds import config for token_cardano.png, a new SpriteFrames animation cardano and sets it active; bumps Godot feature set to 4.5.
Godot JS bridge
godot-visualizer/scripts/map.gd
Posts ship_selected message via parent.window.postMessage with ship position and JSON payload when a ship is selected.
Docker / Godot version
docker/Dockerfile.frontend
Updates ARG GODOT_VERSION from "4.4" to "4.5.1".
UI — navigation & menu
frontend/src/components/how-to-play/Menu.tsx, frontend/src/components/ui/NavBar.tsx
Re-enables "How to play" nav item and activates previously commented menu items including a new “GATHER TOKEN” entry and "QUIT GAME".
UI — Input component
frontend/src/components/ui/Input.tsx
Adds button, onClickButton, and comment props; renders optional inline button and comment beside labels.
How-to-play page wiring
frontend/src/pages/how-to-play/index.tsx
Imports and renders new sections: GatherFuel, GatherToken, MineAsteria, QuitGame (wired into tabs).
New documentation MDX
frontend/src/components/how-to-play/*/Description.mdx
Adds MDX description pages for: create-ship (expanded), gather-fuel, gather-token, mine-asteria, quit-game, and quit-game; content and layout components exported.
New/updated how-to-play components
frontend/src/components/how-to-play/*/Section.tsx (gather-fuel, gather-token, mine-asteria, quit-game, create-ship, move-ship, mine-asteria, etc.)
Adds new components GatherFuel/GatherToken/MineAsteria/QuitGame with multi-tab UI (Description, Tx Form, Tx3, JS Code), wallet/connect handlers, tip-slot fetch, form validation/submission to corresponding API endpoints; updates CreateShip and MoveShip sections with new fields (last_move_timestamp, since_slot, until_slot) and UI changes (delta inputs).
Pages API — new endpoints
frontend/src/pages/api/asteria/gather-fuel.ts, .../gather-token.ts, .../mine-asteria.ts, .../quit-game.ts
Adds POST handlers that validate form data, compute since/until slot logic, encode pilot/ship/token names, call getProtocol(...).<tx>() methods (gatherFuelTx/gatherTokenTx/mineAsteriaTx/quitGameTx) and return structured JSON responses with tx or errors.
Pages API — updated endpoints
frontend/src/pages/api/asteria/create-ship.ts, frontend/src/pages/api/asteria/move-ship.ts
create-ship: adds lastMoveTimestamp to payload; move-ship: replaces absolute position with deltaX/deltaY, updates distance/fuel math, introduces since_slot/until_slot/lastMoveTimestamp and revised timing/fuel calculations.
Top-level frontend changes
frontend/src/pages/index.tsx
Removes unused store import and minor formatting tweak.
Protocol bindings & tx3
frontend/tx3/bindings/protocol.ts, frontend/tx3/main.tx3
Large API and schema changes: add lastMoveTimestamp to CreateShip/MoveShip types, replace tipSlot with sinceSlot/untilSlot, rename pGatherAmount→pAmount, add pelletRef/pilotName and many new types (GatherTokenParams, MineAsteriaParams, QuitGameParams), new IR constants (GATHER_TOKEN_IR, MINE_ASTERIA_IR, QUIT_GAME_IR), new Client methods (gatherTokenTx, mineAsteriaTx, quitGameTx), and major tx3 rewrite: new redeemer enums, changed ShipDatum, added collateral/gas_change/pilot_change flows, expanded create/move/gather/mine/quit tx logic.

Sequence Diagram(s)

sequenceDiagram
  participant FE as Frontend (UI)
  participant API as Next.js API
  participant Proto as Protocol Client
  participant Chain as Remote service/Plutus IR

  FE->>API: POST /api/asteria/gather-fuel {player, ship, pelletRef, fuel, blockSlot, network}
  API->>API: validate inputs, compute sinceSlot
  API->>Proto: gatherFuelTx(payload with pilotName/shipName/pelletRef/sinceSlot/...)
  Proto->>Chain: resolve IR -> build tx3 -> sign/resolve
  Chain-->>Proto: tx (hex)
  Proto-->>API: ResolveResponse { tx }
  API-->>FE: 200 { data: { tx } }
Loading

Note: the same flow applies for gather-token, mine-asteria, quit-game and move-ship/create-ship with different payload fields (since/until/lastMoveTimestamp or deltaX/deltaY).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Focus areas for reviewers:

  • frontend/tx3/bindings/protocol.ts and frontend/tx3/main.tx3 (type/signature and IR correctness)
  • API handlers in frontend/src/pages/api/asteria/* (validation, encoding, error handling)
  • Move/create ship timing logic and fuel/distance calculations (move-ship API + UI changes)
  • UI components that manage wallet integration and state (Gather*/Mine*/Quit* Section.tsx files)
  • Godot integration points (map.gd postMessage payloads) and Godot project version bump compatibility

Poem

I hop on maps and post a ping,
New tokens sparkle—what a thing!
I nibble code, I nudge a frame,
Ship slots tick and sprites proclaim.
With floppy ears and nimble art,
I stitch these changes—cheerful heart! 🐰✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: add cardano summit token" refers to a real and present change in the changeset—specifically, the addition of a new Cardano Summit 2025 token entry to the challenge tokens array in frontend/src/stores/challenge.ts. However, this token addition is not the primary focus of the PR. The changeset includes substantial new functionality: multiple new transaction types (gather-fuel, gather-token, mine-asteria, quit-game), extensive UI component implementations, new API routes, protocol binding expansions, transaction logic overhauls with new redeemer structures, and a Godot version upgrade. The title describes a real aspect of the change but captures only a minor part rather than the main objectives, making it a partially related title per the evaluation criteria.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/add-cardano-summit-token

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@EehMauro EehMauro merged commit a528558 into main Oct 31, 2025
1 of 3 checks passed
@EehMauro EehMauro deleted the feat/add-cardano-summit-token branch October 31, 2025 18:05
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/how-to-play/move-ship/Section.tsx (1)

266-278: Display the correct validation error for “Latest block slot”.

This input is bound to errors.shipNumber, so block-slot validation feedback never appears and ship-number errors show up twice. Wire it to errors.blockSlot instead.

-                error={errors.shipNumber}
+                error={errors.blockSlot}
🧹 Nitpick comments (5)
frontend/src/components/how-to-play/move-ship/Description.mdx (1)

8-12: Consider minor style improvements for readability.

The content is clear, but you may want to address these minor style points:

  1. "Rules to take into account" could be shortened to "Rules to consider"
  2. Lines 10-12 begin with "the", which could be varied for better flow

Apply this diff for improved readability:

-#### Rules to take into account:
+#### Rules to consider:
 
-- the ship number has to be the one controlled by the pilot token in your wallet.
-- the total distance you travel is constrained by the number of slots between your tx validity range (ttl end - ttl start).
-- the amount of fuel you pass is proportional to the total distance you travel (deltaX + deltaY).
+- The ship number must be controlled by the pilot token in your wallet.
+- Total travel distance is constrained by the slot count in your tx validity range (ttl end - ttl start).
+- Fuel consumption is proportional to the total distance traveled (deltaX + deltaY).
frontend/src/components/how-to-play/quit-game/Description.mdx (1)

8-10: Consider minor style improvement for conciseness.

The heading "Rules to take into account" could be shortened to "Rules to consider" for brevity.

Apply this diff:

-#### Rules to take into account:
+#### Rules to consider:
frontend/src/components/how-to-play/gather-token/Description.mdx (1)

8-12: Consider minor style improvement for conciseness.

The heading "Rules to take into account" could be shortened to "Rules to consider" for brevity.

Apply this diff:

-#### Rules to take into account:
+#### Rules to consider:
frontend/src/components/how-to-play/gather-fuel/Description.mdx (1)

8-12: Consider minor style improvement for conciseness.

The heading "Rules to take into account" could be shortened to "Rules to consider" for brevity.

Apply this diff:

-#### Rules to take into account:
+#### Rules to consider:
frontend/src/components/how-to-play/move-ship/Section.tsx (1)

151-159: Add cleanup for the window message listener.

We attach a new message handler but never remove it. Every mount stacks another listener, keeping old closures alive and dispatching duplicate move_ship commands. Capture the handler and unregister it in the effect cleanup.

-  useEffect(() => {
-    window.addEventListener('message', (event) => {
-      if (pathname.includes('how-to-play') && window.location.hash === '#move-ship') {
-        if (event.data.action == 'ship_selected') {
-          updatePosition(event.data.position.x, event.data.position.y);
-        }
-      }
-    });
-  }, []);
+  useEffect(() => {
+    const handleMessage = (event: MessageEvent<{ action?: string; position?: { x: number; y: number } }>) => {
+      if (pathname.includes('how-to-play') && window.location.hash === '#move-ship' && event.data?.action === 'ship_selected' && event.data.position) {
+        updatePosition(event.data.position.x, event.data.position.y);
+      }
+    };
+
+    window.addEventListener('message', handleMessage);
+    return () => {
+      window.removeEventListener('message', handleMessage);
+    };
+  }, []);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a589ff and 4e15c86.

📒 Files selected for processing (28)
  • docker/Dockerfile.frontend (1 hunks)
  • frontend/src/components/how-to-play/Menu.tsx (1 hunks)
  • frontend/src/components/how-to-play/create-ship/Description.mdx (1 hunks)
  • frontend/src/components/how-to-play/create-ship/Section.tsx (6 hunks)
  • frontend/src/components/how-to-play/gather-fuel/Description.mdx (1 hunks)
  • frontend/src/components/how-to-play/gather-fuel/Section.tsx (1 hunks)
  • frontend/src/components/how-to-play/gather-token/Description.mdx (1 hunks)
  • frontend/src/components/how-to-play/gather-token/Section.tsx (1 hunks)
  • frontend/src/components/how-to-play/mine-asteria/Description.mdx (1 hunks)
  • frontend/src/components/how-to-play/mine-asteria/Section.tsx (1 hunks)
  • frontend/src/components/how-to-play/move-ship/Description.mdx (1 hunks)
  • frontend/src/components/how-to-play/move-ship/Section.tsx (6 hunks)
  • frontend/src/components/how-to-play/quit-game/Description.mdx (1 hunks)
  • frontend/src/components/how-to-play/quit-game/Section.tsx (1 hunks)
  • frontend/src/components/ui/Input.tsx (1 hunks)
  • frontend/src/components/ui/NavBar.tsx (1 hunks)
  • frontend/src/pages/api/asteria/create-ship.ts (1 hunks)
  • frontend/src/pages/api/asteria/gather-fuel.ts (1 hunks)
  • frontend/src/pages/api/asteria/gather-token.ts (1 hunks)
  • frontend/src/pages/api/asteria/mine-asteria.ts (1 hunks)
  • frontend/src/pages/api/asteria/move-ship.ts (1 hunks)
  • frontend/src/pages/api/asteria/quit-game.ts (1 hunks)
  • frontend/src/pages/how-to-play/index.tsx (2 hunks)
  • frontend/src/pages/index.tsx (1 hunks)
  • frontend/tx3/bindings/protocol.ts (3 hunks)
  • frontend/tx3/main.tx3 (10 hunks)
  • godot-visualizer/project.godot (1 hunks)
  • godot-visualizer/scripts/map.gd (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
frontend/src/pages/api/asteria/quit-game.ts (2)
frontend/src/pages/api/asteria/gather-fuel.ts (2)
  • ResponseData (6-9)
  • handler (11-75)
frontend/src/utils/cli-protocol.ts (1)
  • getProtocol (3-11)
frontend/src/pages/api/asteria/gather-token.ts (2)
frontend/src/pages/api/asteria/gather-fuel.ts (2)
  • ResponseData (6-9)
  • handler (11-75)
frontend/src/utils/cli-protocol.ts (1)
  • getProtocol (3-11)
frontend/src/components/how-to-play/gather-fuel/Section.tsx (8)
frontend/src/stores/challenge.ts (1)
  • useChallengeStore (203-208)
frontend/src/pages/api/asteria/gather-fuel.ts (1)
  • ResponseData (6-9)
frontend/src/hooks/useCardano.ts (1)
  • ConnectedWallet (11-15)
frontend/src/components/how-to-play/Tabs.tsx (2)
  • Tabs (25-114)
  • Tab (21-23)
frontend/src/components/ui/ConnectWallet.tsx (1)
  • ConnectWallet (10-50)
frontend/src/components/ui/Alert.tsx (1)
  • Alert (11-82)
frontend/src/components/ui/CopyButton.tsx (1)
  • CopyButton (3-23)
frontend/src/components/ui/CodeBlock.tsx (1)
  • CodeBlock (11-23)
frontend/src/pages/index.tsx (1)
frontend/src/components/home/HeroSection.tsx (1)
  • HeroSection (8-53)
frontend/src/pages/api/asteria/mine-asteria.ts (1)
frontend/src/utils/cli-protocol.ts (1)
  • getProtocol (3-11)
frontend/src/components/how-to-play/gather-token/Section.tsx (8)
frontend/src/stores/challenge.ts (1)
  • useChallengeStore (203-208)
frontend/src/pages/api/asteria/gather-token.ts (1)
  • ResponseData (6-9)
frontend/src/hooks/useCardano.ts (1)
  • ConnectedWallet (11-15)
frontend/src/components/how-to-play/Tabs.tsx (2)
  • Tabs (25-114)
  • Tab (21-23)
frontend/src/components/ui/ConnectWallet.tsx (1)
  • ConnectWallet (10-50)
frontend/src/components/ui/Alert.tsx (1)
  • Alert (11-82)
frontend/src/components/ui/CopyButton.tsx (1)
  • CopyButton (3-23)
frontend/src/components/ui/CodeBlock.tsx (1)
  • CodeBlock (11-23)
frontend/src/pages/how-to-play/index.tsx (1)
frontend/src/components/how-to-play/Section.tsx (1)
  • Section (10-22)
frontend/src/components/how-to-play/create-ship/Section.tsx (1)
frontend/src/components/how-to-play/Tabs.tsx (1)
  • Tab (21-23)
frontend/src/components/how-to-play/mine-asteria/Section.tsx (8)
frontend/src/stores/challenge.ts (1)
  • useChallengeStore (203-208)
frontend/src/pages/api/asteria/mine-asteria.ts (1)
  • ResponseData (6-9)
frontend/src/hooks/useCardano.ts (1)
  • ConnectedWallet (11-15)
frontend/src/components/how-to-play/Tabs.tsx (2)
  • Tabs (25-114)
  • Tab (21-23)
frontend/src/components/ui/ConnectWallet.tsx (1)
  • ConnectWallet (10-50)
frontend/src/components/ui/Alert.tsx (1)
  • Alert (11-82)
frontend/src/components/ui/CopyButton.tsx (1)
  • CopyButton (3-23)
frontend/src/components/ui/CodeBlock.tsx (1)
  • CodeBlock (11-23)
frontend/src/components/how-to-play/move-ship/Section.tsx (2)
frontend/src/hooks/useCardano.ts (1)
  • ConnectedWallet (11-15)
frontend/src/components/how-to-play/Tabs.tsx (1)
  • Tab (21-23)
frontend/src/pages/api/asteria/gather-fuel.ts (1)
frontend/src/utils/cli-protocol.ts (1)
  • getProtocol (3-11)
frontend/src/components/how-to-play/quit-game/Section.tsx (8)
frontend/src/stores/challenge.ts (1)
  • useChallengeStore (203-208)
frontend/src/pages/api/asteria/quit-game.ts (1)
  • ResponseData (6-9)
frontend/src/hooks/useCardano.ts (1)
  • ConnectedWallet (11-15)
frontend/src/components/how-to-play/Tabs.tsx (2)
  • Tabs (25-114)
  • Tab (21-23)
frontend/src/components/ui/ConnectWallet.tsx (1)
  • ConnectWallet (10-50)
frontend/src/components/ui/Alert.tsx (1)
  • Alert (11-82)
frontend/src/components/ui/CopyButton.tsx (1)
  • CopyButton (3-23)
frontend/src/components/ui/CodeBlock.tsx (1)
  • CodeBlock (11-23)
frontend/src/pages/api/asteria/move-ship.ts (1)
frontend/src/utils/cli-protocol.ts (1)
  • getProtocol (3-11)
🪛 LanguageTool
frontend/src/components/how-to-play/create-ship/Description.mdx

[style] ~4-~4: Consider a more concise word here.
Context: ...; #### This is the first step in order to play the game. This transaction create...

(IN_ORDER_TO_PREMIUM)


[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...E_FEE` paid by the user. #### Rules to take into account: - the ship number has to be exactly +...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)

frontend/src/components/how-to-play/gather-fuel/Description.mdx

[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...kens held in the pellet. #### Rules to take into account: - the ship number has to be the one c...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)

frontend/src/components/how-to-play/quit-game/Description.mdx

[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...e remaining fuel tokens. #### Rules to take into account: - the ship number has to be the one c...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)

frontend/src/components/how-to-play/mine-asteria/Description.mdx

[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...g fuel tokens are burnt. #### Rules to take into account: - the ship number has to be the one c...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)

frontend/src/components/how-to-play/gather-token/Description.mdx

[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...kens held in the pellet. #### Rules to take into account: - the ship number has to be the one c...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)

frontend/src/components/how-to-play/move-ship/Description.mdx

[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...range latest posix time. #### Rules to take into account: - the ship number has to be the one c...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)


[style] ~12-~12: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...validity range (ttl end - ttl start). - the amount of fuel you pass is proportional...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (7)
godot-visualizer/scripts/map.gd (1)

206-209: Verify platform compatibility assumption and refine JSON escaping approach.

The review raises two concerns, but the proposed fix requires refinement:

  1. Platform check validity: The codebase has no OS.has_feature checks anywhere—JavaScriptBridge is called directly throughout main.gd (lines 96-97, 118-125, 145-151, 154) without guards. This appears to be an architectural assumption rather than a per-call issue. Verify whether this code is only intended for web exports.

  2. JSON escaping limitation: The suggested .replace("\\", "\\\\").replace("'", "\\'") is incomplete. Proper escaping would need to handle all JavaScript escape sequences (newlines, carriage returns, unicode, etc.). A better approach would be using JSON.stringify() in JavaScript or restructuring the message format to avoid string interpolation altogether.

Note: The same pattern exists at lines 98-101 (map_click). Both should be addressed consistently.

godot-visualizer/project.godot (1)

15-15: Version upgrade is consistent with no conflicting references found, but runtime verification required.

The change updates config/features from 4.4 to 4.5 and is the only Godot version reference in the codebase—no conflicting version strings detected. However, upgrading between minor versions can introduce subtle compatibility issues that require testing.

Follow the 4.5 migration checklist before merging:

  1. Open the project with Godot 4.5
  2. Review the editor's conversion log for errors/warnings
  3. Validate Resource files and packed scenes (common source of issues)
  4. Test all scenes, especially physics and input handling
  5. Verify rendering (new settings like specular-occlusion may affect appearance)

See the official Godot 4.5 release notes for the complete breaking changes list.

frontend/src/pages/api/asteria/create-ship.ts (1)

56-57: LGTM! New timing field added.

The addition of lastMoveTimestamp alongside the existing tipSlot extends the transaction with dual timing mechanisms (slot-based and timestamp-based). This aligns with the protocol binding upgrades described in the PR summary.

frontend/src/components/ui/NavBar.tsx (1)

33-36: LGTM! Navigation item activated.

The "How to play" link is now properly activated with correct styling and separator, consistent with other navigation items.

frontend/src/pages/how-to-play/index.tsx (2)

10-13: LGTM! New section imports added.

The imports for GatherFuel, GatherToken, MineAsteria, and QuitGame sections are properly structured.


70-84: LGTM! New sections integrated correctly.

The four new sections (GATHER FUEL, GATHER TOKEN, MINE ASTERIA, QUIT GAME) are properly integrated into the render tree with correct isActive bindings and id attributes for scroll navigation.

frontend/src/pages/api/asteria/mine-asteria.ts (1)

48-62: LGTM! Transaction generation logic is correct.

The mine-asteria transaction generation follows the established pattern from other API routes, with proper validation, encoding, and error handling.

Comment on lines +6 to +12
This transaction creates a `ShipState` UTxO locking min ada, a `ShipToken` (minted in this tx) and an `INITIAL_FUEL` amount of fuel tokens (minted in this tx), specifying in the datum the initial `pos_x` and `pos_y` coordinates of the ship, the ship and pilot token names and the `last_move_latest_time` as the upper bound of the transaction's validity range (posix time). Also adds to the `AsteriaUTxO` value the `SHIP_MINT_LOVELACE_FEE` paid by the user.

#### Rules to take into account:

- the ship number has to be exactly +1 of the last ship minted
- the tip slot must be recent because it's used during validation of the tx
- the start position has to be at a certain distance ([manhattan distance](https://en.wikipedia.org/wiki/Taxicab_geometry)) of coordinates (0,0). For the mainnet challenge the minimum distance is `50`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix outdated datum field name.

The Create Ship flow now sets the datum field to last_move_timestamp, but the doc still refers to last_move_latest_time. This mismatch will trip anyone copying the guidance into the updated tx template—please update the wording to match the current field name.

🧰 Tools
🪛 LanguageTool

[style] ~8-~8: ‘take into account’ might be wordy. Consider a shorter alternative.
Context: ...E_FEE` paid by the user. #### Rules to take into account: - the ship number has to be exactly +...

(EN_WORDINESS_PREMIUM_TAKE_INTO_ACCOUNT)

🤖 Prompt for AI Agents
In frontend/src/components/how-to-play/create-ship/Description.mdx around lines
6 to 12, the documentation references the outdated datum field name
`last_move_latest_time`; update all occurrences in this block to the current
field name `last_move_timestamp` so the text matches the updated Create Ship
flow and the transaction template (i.e., replace the phrase "the
`last_move_latest_time` as the upper bound" with "the `last_move_timestamp` as
the upper bound" and ensure any other mentions in these lines use
`last_move_timestamp`).

Comment on lines +228 to +234
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Wire the block-slot field to its own errors and keep the input controlled.
The block-slot input currently shows errors.shipNumber, so the user never sees block-slot validation issues. It also passes raw undefined, which flips the field from uncontrolled to controlled once a value arrives and triggers React warnings. Point the field at errors.blockSlot and normalise the value.

-                error={errors.shipNumber}
+                error={errors.blockSlot}
                 disabled={submitting}
                 button="fetch last"
                 onClickButton={handleFetchLastSlot}
-                value={tipSlot}
+                value={tipSlot ?? ''}
                 onChange={updateTipSlot}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
error={errors.blockSlot}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot ?? ''}
onChange={updateTipSlot}
required
🤖 Prompt for AI Agents
In frontend/src/components/how-to-play/gather-fuel/Section.tsx around lines 228
to 234, the block-slot input is incorrectly wired to errors.shipNumber and is
passing raw undefined which toggles the input between uncontrolled and
controlled; change the error prop to errors.blockSlot and normalize the value so
it is always a string (e.g. use tipSlot ?? '' or String(tipSlot || '')) to keep
the input controlled and ensure block-slot validation messages display
correctly.

Comment on lines +233 to +245
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix block slot error binding.

error={errors.shipNumber} prevents block-slot validation messages from ever showing, so users won’t learn why submission fails when that field is invalid. Please point the input at the blockSlot error key instead.

-                error={errors.shipNumber}
+                error={errors.blockSlot}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.blockSlot}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
🤖 Prompt for AI Agents
In frontend/src/components/how-to-play/gather-token/Section.tsx around lines 233
to 245, the block slot input is incorrectly wired to errors.shipNumber; change
the error binding to errors.blockSlot so validation messages for the blockSlot
field are displayed (i.e., replace the error prop value with the blockSlot error
key and ensure the form schema/key matches if necessary).

Comment on lines +236 to +248
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Bind the block slot input to its own error key.

The block-slot field pumps errors.shipNumber, so users never see validation feedback for block-slot issues. Please wire it to errors.blockSlot.

-                error={errors.shipNumber}
+                error={errors.blockSlot}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.blockSlot}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
🤖 Prompt for AI Agents
In frontend/src/components/how-to-play/mine-asteria/Section.tsx around lines 236
to 248, the block-slot input is incorrectly using errors.shipNumber so
validation feedback for the block-slot never appears; change the input's error
prop to errors.blockSlot (and ensure that the form validation/schema produces a
blockSlot error key) so the field shows its own validation messages.

Comment on lines +165 to +179
const updateDeltaX = (event: ChangeEvent<HTMLInputElement>) => {
updateDelta(parseInt(event.target.value), delta ? delta.y : 0);
}

const updatePositionY = (event: ChangeEvent<HTMLInputElement>) => {
updatePosition(position ? position.x : 0, parseInt(event.target.value));
const updateDeltaY = (event: ChangeEvent<HTMLInputElement>) => {
updateDelta(delta ? delta.x : 0, parseInt(event.target.value));
}

const updatePosition = (x: number, y: number) => {
setPosition({ x, y });
console.log({ x, y, shipNumber });
window.GODOT_BRIDGE?.send({ action: 'select_ship', shipNumber });
window.GODOT_BRIDGE?.send({ action: 'move_ship', x, y });

const updateDelta = (x: number, y: number) => {
setDelta({ x, y });
window.GODOT_BRIDGE?.send({
action: 'move_ship',
x: x + (position ? position.x : 0),
y: y + (position ? position.y : 0)
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Prevent NaN deltas from hitting Godot and the API.

When the user clears or types an intermediate value, parseInt produces NaN, which we then store in state and forward over the bridge—Godot receives { x: NaN, y: … }, and the controlled inputs display “NaN”. That breaks previews and sends invalid payloads to /api/asteria/move-ship. Please guard the conversion so we only call updateDelta with finite numbers.

-  const updateDeltaX = (event: ChangeEvent<HTMLInputElement>) => {
-    updateDelta(parseInt(event.target.value), delta ? delta.y : 0);
-  }
-
-  const updateDeltaY = (event: ChangeEvent<HTMLInputElement>) => {
-    updateDelta(delta ? delta.x : 0, parseInt(event.target.value));
-  }
+  const updateDeltaX = (event: ChangeEvent<HTMLInputElement>) => {
+    const parsed = Number(event.target.value);
+    if (Number.isNaN(parsed)) {
+      return;
+    }
+    updateDelta(parsed, delta ? delta.y : 0);
+  };
+
+  const updateDeltaY = (event: ChangeEvent<HTMLInputElement>) => {
+    const parsed = Number(event.target.value);
+    if (Number.isNaN(parsed)) {
+      return;
+    }
+    updateDelta(delta ? delta.x : 0, parsed);
+  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const updateDeltaX = (event: ChangeEvent<HTMLInputElement>) => {
updateDelta(parseInt(event.target.value), delta ? delta.y : 0);
}
const updatePositionY = (event: ChangeEvent<HTMLInputElement>) => {
updatePosition(position ? position.x : 0, parseInt(event.target.value));
const updateDeltaY = (event: ChangeEvent<HTMLInputElement>) => {
updateDelta(delta ? delta.x : 0, parseInt(event.target.value));
}
const updatePosition = (x: number, y: number) => {
setPosition({ x, y });
console.log({ x, y, shipNumber });
window.GODOT_BRIDGE?.send({ action: 'select_ship', shipNumber });
window.GODOT_BRIDGE?.send({ action: 'move_ship', x, y });
const updateDelta = (x: number, y: number) => {
setDelta({ x, y });
window.GODOT_BRIDGE?.send({
action: 'move_ship',
x: x + (position ? position.x : 0),
y: y + (position ? position.y : 0)
});
const updateDeltaX = (event: ChangeEvent<HTMLInputElement>) => {
const parsed = Number(event.target.value);
if (Number.isNaN(parsed)) {
return;
}
updateDelta(parsed, delta ? delta.y : 0);
};
const updateDeltaY = (event: ChangeEvent<HTMLInputElement>) => {
const parsed = Number(event.target.value);
if (Number.isNaN(parsed)) {
return;
}
updateDelta(delta ? delta.x : 0, parsed);
};
const updateDelta = (x: number, y: number) => {
setDelta({ x, y });
window.GODOT_BRIDGE?.send({
action: 'move_ship',
x: x + (position ? position.x : 0),
y: y + (position ? position.y : 0)
});
🤖 Prompt for AI Agents
In frontend/src/components/how-to-play/move-ship/Section.tsx around lines
165-179, the handlers and updateDelta currently let parseInt produce NaN which
is stored/sent; change the input handlers to parse the value, check
Number.isFinite(parsed) and only call updateDelta when parsed is a finite number
(otherwise return early), and also harden updateDelta to coerce its x and y
params to finite numbers (fallback to 0) before setDelta and before sending to
window.GODOT_BRIDGE so no NaN can be stored or forwarded.

Comment on lines +215 to +227
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Show block-slot validation errors on the correct field.

Same as the other sections: the block-slot input references errors.shipNumber, so it hides its own validation errors. Point it at errors.blockSlot.

-                error={errors.shipNumber}
+                error={errors.blockSlot}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.shipNumber}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
name="blockSlot"
type="number"
placeholder="Latest block slot"
containerClassName="flex-1"
label="Latest block slot"
error={errors.blockSlot}
disabled={submitting}
button="fetch last"
onClickButton={handleFetchLastSlot}
value={tipSlot}
onChange={updateTipSlot}
required
/>
🤖 Prompt for AI Agents
In frontend/src/components/how-to-play/quit-game/Section.tsx around lines 215 to
227 the block-slot input incorrectly uses errors.shipNumber for its error prop;
change that prop to errors.blockSlot so the block-slot field displays its own
validation errors (update any related prop references or types if necessary and
run typechecks/tests).

Comment on lines +41 to +43
if (Object.keys(errors).length > 0) {
return { errors };
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Return a 400 response when validation fails.

return { errors }; never sends an HTTP response, so clients hang waiting for a reply. We need to write the 400 status and JSON body through res (as with every other branch).

-  if (Object.keys(errors).length > 0) {
-    return { errors };
-  }
+  if (Object.keys(errors).length > 0) {
+    return res.status(400).json({ errors });
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (Object.keys(errors).length > 0) {
return { errors };
}
if (Object.keys(errors).length > 0) {
return res.status(400).json({ errors });
}
🤖 Prompt for AI Agents
In frontend/src/pages/api/asteria/gather-fuel.ts around lines 41 to 43, the
handler returns an object ({ errors }) instead of sending an HTTP response when
validation fails; update this branch to write a 400 status and JSON body via the
Next.js API response object (res.status(400).json({ errors })) so the client
receives the error and the request completes.

Comment on lines +50 to +52
if (Object.keys(errors).length > 0) {
return { errors };
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Send a 400 response on validation errors.
Just like the other API route, returning { errors } leaves the HTTP response open and causes the fetcher to hang. Respond via res.status(400).json(...).

-  if (Object.keys(errors).length > 0) {
-    return { errors };
-  }
+  if (Object.keys(errors).length > 0) {
+    return res.status(400).json({ errors });
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (Object.keys(errors).length > 0) {
return { errors };
}
if (Object.keys(errors).length > 0) {
return res.status(400).json({ errors });
}
🤖 Prompt for AI Agents
In frontend/src/pages/api/asteria/gather-token.ts around lines 50 to 52, the
handler currently returns an object when validation fails which leaves the HTTP
response open; instead set the HTTP status to 400 and send a JSON response.
Replace the plain return with res.status(400).json({ errors }) so the route
terminates the request properly and the client receives the validation errors.

Comment on lines +44 to +46
if (Object.keys(errors).length > 0) {
return { errors };
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix missing response method call.

Line 45 returns a plain object instead of an HTTP response. This will cause the API endpoint to fail when validation errors occur.

Apply this diff to fix:

   if (Object.keys(errors).length > 0) {
-    return { errors };
+    return res.json({ errors });
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (Object.keys(errors).length > 0) {
return { errors };
}
if (Object.keys(errors).length > 0) {
return res.json({ errors });
}
🤖 Prompt for AI Agents
In frontend/src/pages/api/asteria/mine-asteria.ts around lines 44 to 46, the
code returns a plain object ({ errors }) instead of sending an HTTP response;
replace that return with sending a proper HTTP response, e.g. call
res.status(400).json({ errors }) (and return after calling it) so the API
endpoint responds with a 400 and the validation errors.

Comment on lines +39 to +41
if (Object.keys(errors).length > 0) {
return { errors };
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Respond with an HTTP error instead of returning a plain object.
When validation fails, the handler returns { errors } without writing to res, so Next.js logs “API resolved without sending a response” and the client fetch never receives an error payload. Please send an explicit 400 response.

-  if (Object.keys(errors).length > 0) {
-    return { errors };
-  }
+  if (Object.keys(errors).length > 0) {
+    return res.status(400).json({ errors });
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (Object.keys(errors).length > 0) {
return { errors };
}
if (Object.keys(errors).length > 0) {
return res.status(400).json({ errors });
}
🤖 Prompt for AI Agents
In frontend/src/pages/api/asteria/quit-game.ts around lines 39 to 41, the
handler currently returns a plain object when validation fails which prevents
writing an HTTP response and triggers Next.js "API resolved without sending a
response"; change this to send an explicit 400 response by calling
res.status(400).json({ errors }) and then return to stop further execution so
the client receives the error payload.

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.

3 participants