Skip to content

feat: add post-deployment success panel with explorer link#1613

Open
Dark-Brain07 wants to merge 1 commit intogenlayerlabs:mainfrom
Dark-Brain07:feat/post-deployment-success-panel
Open

feat: add post-deployment success panel with explorer link#1613
Dark-Brain07 wants to merge 1 commit intogenlayerlabs:mainfrom
Dark-Brain07:feat/post-deployment-success-panel

Conversation

@Dark-Brain07
Copy link
Copy Markdown

@Dark-Brain07 Dark-Brain07 commented Apr 26, 2026

Resolves #1610

What this does

This PR improves the post-deployment experience in GenLayer Studio by giving developers an immediate, clear path forward once a contract successfully deploys.

Previously, users had to manually find the Explorer, search for the transaction hash, and figure out how to interact with their contract. This creates a friction point, especially during onboarding.

This PR introduces a Deployment Success Panel that appears automatically when a deployment transaction reaches FINALIZED + SUCCESS.

Changes

  • New Component: DeploymentSuccessPanel.vue shows the deployed contract address and transaction hash with one-click copy buttons.
  • Explorer Deep-link: Added a "View on Explorer" button that directly opens the transaction on the GenLayer Explorer (resolves based on connected network).
  • Smooth Flow: Added an "Interact Now" button that scrolls the developer directly down to the Read/Write methods.
  • Store Updates: useContractListener now extracts and stores the deployTxHash when a deployment finalizes, allowing the UI to link directly to the transaction.
  • Sidebar Context: The shortened contract address is now displayed directly under the contract file name in the sidebar for quick visual reference.

Acceptance Criteria Met

  • Post-deployment success panel renders when a contract reaches FINALIZED + SUCCESS
  • Contract address is displayed and has a working one-click copy button
  • Transaction hash is displayed and has a working one-click copy button
  • "View on Explorer" button opens the correct explorer URL in a new tab
  • "Interact Now" button scrolls to / focuses the Read/Write methods section
  • Panel persists until manually dismissed — does not auto-hide
  • Contract address is shown in the sidebar under the contract filename after deployment
  • Explorer link resolves correctly based on connected network (no link for local networks)

Testing

  1. Deploy any contract.
  2. Observe the success panel appearing at the top of the Run & Debug view once finalized.
  3. Verify the Explorer deep link resolves to the correct transaction hash.
  4. Verify the Interact Now button smoothly scrolls to the method execution section.
  5. Check the Files sidebar to see the shortened address under the contract file name.

Summary by CodeRabbit

  • New Features
    • Added a deployment success panel displaying contract address and transaction hash with copy-to-clipboard functionality.
    • Added external explorer link for deployed transactions.
    • Added "Interact Now" button to quickly navigate to contract interaction after deployment.
    • Contract items now display deployed addresses with smaller muted styling.

Closes genlayerlabs#1610

Added a new DeploymentSuccessPanel component that renders automatically
upon successful contract deployment. It provides:
- The deployed contract address (with quick-copy)
- The deployment transaction hash (with quick-copy)
- A View on Explorer button that deep-links to the transaction on the connected network
- An Interact Now button that smoothly scrolls to the Read/Write methods
- Additionally, the contract address is now displayed under the file name in the sidebar for deployed contracts.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

📝 Walkthrough

Walkthrough

This PR introduces a post-deployment success experience by adding a new DeploymentSuccessPanel component, updating contract displays to show deployed addresses, capturing deployment transaction hashes, and integrating a success panel into the deployment flow that enables users to copy contract details and interact with deployed contracts.

Changes

Cohort / File(s) Summary
New Deployment Success Component
frontend/src/components/Simulator/DeploymentSuccessPanel.vue
New component displaying contract address and transaction hash with copy-to-clipboard buttons, optional explorer link, and "Interact Now" action that emits events for panel dismissal and contract interaction.
Contract Display Updates
frontend/src/components/Simulator/ContractItem.vue
Refactored layout to show deployed contract address on a second line with muted styling; added computed deployedContract lookup and conditional address rendering when available.
Data Model Enhancement
frontend/src/types/store.ts
Added optional deployTxHash property to DeployedContract interface to store the transaction hash associated with a contract deployment.
Event Listener Integration
frontend/src/hooks/useContractListener.ts
Captures deployment transaction hash when matching deployed_contract websocket events and passes it to contractsStore.addDeployedContract as deployTxHash.
Main View Integration
frontend/src/views/Simulator/RunDebugView.vue
Displays DeploymentSuccessPanel upon successful deployment, looks up corresponding deployTxHash from store, and implements scroll-to-interact behavior for Read/Write methods sections when user selects "Interact Now".

Sequence Diagram

sequenceDiagram
    participant User
    participant RunDebugView
    participant WebSocket as WebSocket/Listener
    participant contractsStore as Contracts Store
    participant DeploymentSuccessPanel
    
    User->>RunDebugView: Deploys contract
    WebSocket->>contractsStore: deployed_contract event received
    contractsStore->>contractsStore: addDeployedContract(contractId, address, deployTxHash)
    contractsStore->>RunDebugView: deployedContracts updated
    RunDebugView->>RunDebugView: Detects isDeployed transition (false→true)
    RunDebugView->>RunDebugView: Looks up deployedContract & txHash
    RunDebugView->>DeploymentSuccessPanel: Show panel with contractAddress & txHash
    
    alt User action
        User->>DeploymentSuccessPanel: Copy address or hash
        DeploymentSuccessPanel->>User: Clipboard updated
    else Explorer link
        User->>DeploymentSuccessPanel: Click "View on Explorer"
        DeploymentSuccessPanel->>WebSocket: Opens explorer URL in new tab
    else Interact
        User->>DeploymentSuccessPanel: Click "Interact Now"
        DeploymentSuccessPanel->>RunDebugView: Emit interact event
        RunDebugView->>RunDebugView: Scroll to Read/Write methods
    else Dismiss
        User->>DeploymentSuccessPanel: Click dismiss
        DeploymentSuccessPanel->>RunDebugView: Emit close event
        RunDebugView->>RunDebugView: Hide panel
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

run-tests

Suggested reviewers

  • kstroobants
  • cristiam86
  • epsjunior

Poem

🐰 A contract deploys with digital cheer,
Its address now glows for all to see clear!
Copy and explore, then interact with might,
The bunny hops code to success! ✨🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add post-deployment success panel with explorer link' directly summarizes the main feature addition and follows conventional commit format.
Description check ✅ Passed The description covers all required template sections: issue reference, detailed What/Why sections, acceptance criteria, and testing instructions with thorough explanations.
Linked Issues check ✅ Passed All coding requirements from #1610 are met: success panel renders on FINALIZED+SUCCESS, copy buttons implemented, explorer deep-link works with network resolution, Interact Now scrolls to methods, sidebar displays address, and persistence is maintained.
Out of Scope Changes check ✅ Passed All code changes are directly aligned with #1610 requirements: new DeploymentSuccessPanel component, ContractItem sidebar address display, useContractListener deployTxHash capture, store type updates, and RunDebugView integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown
Contributor

@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: 3

Caution

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

⚠️ Outside diff range comments (1)
frontend/src/hooks/useContractListener.ts (1)

22-27: ⚠️ Potential issue | 🔴 Critical

Critical: deployTxHash is silently dropped by the store and never persisted.

The type DeployedContract includes deployTxHash?: 0x${string}``, and useContractListener.ts correctly passes it when calling `addDeployedContract`, but the store function at lines 106–121 of `frontend/src/stores/contracts.ts` only destructures `{ contractId, address, defaultState }` and constructs `newItem` without `deployTxHash`. As a result:

  • RunDebugView.vue line ~69 — deployedContract?.deployTxHash is always undefined, so newlyDeployedTxHash becomes ''.
  • DeploymentSuccessPanel.vue line ~57 — the explorer link becomes ${explorerUrl}/tx/ (broken), and the copy button copies an empty string.

The store function must be updated to destructure and persist deployTxHash for the success panel and explorer link to work.

🛠️ Proposed fix in frontend/src/stores/contracts.ts
 function addDeployedContract({
     contractId,
     address,
     defaultState,
+    deployTxHash,
   }: DeployedContract): void {
     const index = deployedContracts.value.findIndex(
       (c) => c.contractId === contractId,
     );

-    const newItem = { contractId, address, defaultState };
+    const newItem = { contractId, address, defaultState, deployTxHash };

     if (index === -1) {
       deployedContracts.value.push(newItem);
     } else {
       deployedContracts.value.splice(index, 1, newItem);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/useContractListener.ts` around lines 22 - 27, The store
currently drops deployTxHash when handling added contracts: update the contracts
store's addDeployedContract handler (the function that destructures {
contractId, address, defaultState } and constructs newItem) to also destructure
deployTxHash and include it on newItem so the DeployedContract type is honored;
ensure the same key (deployTxHash) is persisted into the store's state so
consumers like RunDebugView and DeploymentSuccessPanel receive the tx hash.
🧹 Nitpick comments (3)
frontend/src/views/Simulator/RunDebugView.vue (1)

64-65: Optional: tighten newlyDeployedTxHash typing.

DeployedContract.deployTxHash is \0x${string}`; consider ref<`0x${string}` | ''>('')(orref('')is fine if the panel prop staysstring`). Not a correctness issue today, but it would catch any future drift between store/panel typings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/views/Simulator/RunDebugView.vue` around lines 64 - 65, Tighten
the ref typing for the deployment hash: change the declaration of
newlyDeployedTxHash to use a more specific generic so it matches
DeployedContract.deployTxHash (e.g., ref<`0x${string}` | ''>('') or
ref<string>('') if you prefer); update any consumers/props that read
newlyDeployedTxHash to accept that union type so the component and store typings
stay aligned (refer to newlyDeployedTxHash and DeployedContract.deployTxHash to
locate places to update).
frontend/src/components/Simulator/DeploymentSuccessPanel.vue (1)

36-50: Optional: truncate the displayed address/hash per spec.

The issue mentions "truncated contract address and tx hash" for display; the panel currently renders both in full with break-all. Consider using the existing useShortAddress().shorten(...) helper for visual display while still copying the full value via CopyTextButton.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/Simulator/DeploymentSuccessPanel.vue` around lines 36
- 50, Render shortened visuals for contractAddress and txHash using the existing
useShortAddress().shorten helper while keeping the full values for copying:
replace the displayed text inside the two <span> elements (currently showing {{
contractAddress }} and {{ txHash }}) with the shortened versions from
useShortAddress().shorten(contractAddress) and
useShortAddress().shorten(txHash), but keep CopyTextButton :text bound to the
full contractAddress and txHash values so the clipboard gets the full strings;
ensure you import/use the useShortAddress composable in the component and leave
the copy buttons unchanged.
frontend/src/components/Simulator/ContractItem.vue (1)

11-14: Optional: consolidate the two vue imports.

Minor cleanup — computed can be merged into the existing vue import on line 11.

♻️ Proposed cleanup
-import { ref, onMounted, nextTick } from 'vue';
+import { ref, onMounted, nextTick, computed } from 'vue';
 import { notify } from '@kyvg/vue3-notification';
-import { computed } from 'vue';
 import { useShortAddress } from '@/hooks';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/Simulator/ContractItem.vue` around lines 11 - 14, The
import list unnecessarily imports from 'vue' twice; consolidate into a single
import by merging computed into the existing import that already brings in ref,
onMounted, and nextTick (i.e., replace the two separate imports with one: import
{ ref, onMounted, nextTick, computed } from 'vue'), leaving the other imports
(notify and useShortAddress) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/components/Simulator/DeploymentSuccessPanel.vue`:
- Around line 53-61: The explorer link currently renders when explorerUrl exists
but may create a broken URL if txHash is empty; update the v-if condition on the
<a> that constructs `${explorerUrl}/tx/${txHash}` to require a non-empty txHash
as well (e.g., change the conditional to check both explorerUrl and txHash) so
the link only renders when both explorerUrl and txHash are present, or
alternatively render the "not available" hint when txHash is falsy; locate the
anchor in DeploymentSuccessPanel.vue (the element using
:href="`${explorerUrl}/tx/${txHash}`") and apply the conditional change.
- Line 14: The explorer link currently always shows because getExplorerUrl()
falls back to localhost; update getExplorerUrl to accept (or read) the active
network identifier (VITE_GENLAYER_NETWORK) and return null/empty for 'localnet'
and 'studionet' so it does not produce a usable URL for local networks, then
change the computed property explorerUrl in DeploymentSuccessPanel.vue to call
getExplorerUrl(activeNetwork) (or rely on the updated behavior) and update the
template to guard with v-if="explorerUrl && txHash" and render a fallback text
"Explorer not available for local networks" when explorerUrl is falsy; ensure
references to getExplorerUrl, explorerUrl, txHash and the VITE_GENLAYER_NETWORK
env var are used so the logic only shows the "View on Explorer" button for
supported networks.

In `@frontend/src/views/Simulator/RunDebugView.vue`:
- Around line 67-80: The watcher that reacts to isDeployed and contract.id
currently opens the success panel even when the found deployedContract has no
deployTxHash (due to the store dropping it), because newlyDeployedTxHash is set
with a silent '' fallback; change the logic in the watcher (the function
watching [() => isDeployed.value, () => contract.value?.id]) to only set
showDeploymentSuccessPanel.value = true and assign newlyDeployedTxHash.value
when a deployedContract is found AND deployedContract.deployTxHash is a
non-empty string; otherwise ensure showDeploymentSuccessPanel.value = false and
newlyDeployedTxHash.value is cleared, and add a warning log (e.g., console.warn)
indicating the lookup miss (reference contractsStore.deployedContracts and
useContractListener note) so QA can see missing hashes.

---

Outside diff comments:
In `@frontend/src/hooks/useContractListener.ts`:
- Around line 22-27: The store currently drops deployTxHash when handling added
contracts: update the contracts store's addDeployedContract handler (the
function that destructures { contractId, address, defaultState } and constructs
newItem) to also destructure deployTxHash and include it on newItem so the
DeployedContract type is honored; ensure the same key (deployTxHash) is
persisted into the store's state so consumers like RunDebugView and
DeploymentSuccessPanel receive the tx hash.

---

Nitpick comments:
In `@frontend/src/components/Simulator/ContractItem.vue`:
- Around line 11-14: The import list unnecessarily imports from 'vue' twice;
consolidate into a single import by merging computed into the existing import
that already brings in ref, onMounted, and nextTick (i.e., replace the two
separate imports with one: import { ref, onMounted, nextTick, computed } from
'vue'), leaving the other imports (notify and useShortAddress) unchanged.

In `@frontend/src/components/Simulator/DeploymentSuccessPanel.vue`:
- Around line 36-50: Render shortened visuals for contractAddress and txHash
using the existing useShortAddress().shorten helper while keeping the full
values for copying: replace the displayed text inside the two <span> elements
(currently showing {{ contractAddress }} and {{ txHash }}) with the shortened
versions from useShortAddress().shorten(contractAddress) and
useShortAddress().shorten(txHash), but keep CopyTextButton :text bound to the
full contractAddress and txHash values so the clipboard gets the full strings;
ensure you import/use the useShortAddress composable in the component and leave
the copy buttons unchanged.

In `@frontend/src/views/Simulator/RunDebugView.vue`:
- Around line 64-65: Tighten the ref typing for the deployment hash: change the
declaration of newlyDeployedTxHash to use a more specific generic so it matches
DeployedContract.deployTxHash (e.g., ref<`0x${string}` | ''>('') or
ref<string>('') if you prefer); update any consumers/props that read
newlyDeployedTxHash to accept that union type so the component and store typings
stay aligned (refer to newlyDeployedTxHash and DeployedContract.deployTxHash to
locate places to update).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1b3e995-0a69-48eb-aab3-4569e96b0e1e

📥 Commits

Reviewing files that changed from the base of the PR and between 2ae6e87 and 3f82d79.

📒 Files selected for processing (5)
  • frontend/src/components/Simulator/ContractItem.vue
  • frontend/src/components/Simulator/DeploymentSuccessPanel.vue
  • frontend/src/hooks/useContractListener.ts
  • frontend/src/types/store.ts
  • frontend/src/views/Simulator/RunDebugView.vue


const emit = defineEmits(['close', 'interact']);

const explorerUrl = computed(() => getExplorerUrl());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm explorer URL helper has no local-network gating and inspect any network store/util that could drive the resolution.
fd -t f 'explorerUrl.ts' frontend/src -x cat {}
echo '---'
rg -nP '(VITE_GENLAYER_NETWORK|asimov|bradbury|studionet)' frontend/src --type=ts --type=vue -C2

Repository: genlayerlabs/genlayer-studio

Length of output: 917


🏁 Script executed:

cat -n frontend/src/components/Simulator/DeploymentSuccessPanel.vue

Repository: genlayerlabs/genlayer-studio

Length of output: 4149


🏁 Script executed:

fd -t f 'runtimeConfig.ts' frontend/src -x cat {}

Repository: genlayerlabs/genlayer-studio

Length of output: 2093


🏁 Script executed:

rg -n 'network|Network' frontend/src/stores -t ts --max-count=20

Repository: genlayerlabs/genlayer-studio

Length of output: 54


🏁 Script executed:

find frontend/src/stores -name '*[Ss]imulator*' -o -name '*[Nn]etwork*' | head -20

Repository: genlayerlabs/genlayer-studio

Length of output: 54


🏁 Script executed:

rg -n 'SimulatorStore' frontend/src --type ts --type vue -l | head -5

Repository: genlayerlabs/genlayer-studio

Length of output: 100


🏁 Script executed:

rg -n 'VITE_GENLAYER_NETWORK' frontend/src --type ts -C3

Repository: genlayerlabs/genlayer-studio

Length of output: 1204


🏁 Script executed:

rg -n 'local.*network|studionet' frontend/src --type ts --type vue -i -C2

Repository: genlayerlabs/genlayer-studio

Length of output: 100


🏁 Script executed:

cat -n frontend/src/hooks/useGenlayer.ts | head -60

Repository: genlayerlabs/genlayer-studio

Length of output: 2142


🏁 Script executed:

rg -n 'chains\s*=' frontend/src/hooks -A 15

Repository: genlayerlabs/genlayer-studio

Length of output: 54


🏁 Script executed:

rg -n 'localnet|studionet|explorer.*not.*available' frontend/src -i

Repository: genlayerlabs/genlayer-studio

Length of output: 1289


🏁 Script executed:

rg -n 'github.com|gitlab.com|issue|#[0-9]+' frontend/src/components/Simulator/DeploymentSuccessPanel.vue

Repository: genlayerlabs/genlayer-studio

Length of output: 54


🏁 Script executed:

git log --oneline -20 -- frontend/src/components/Simulator/DeploymentSuccessPanel.vue 2>/dev/null | head -10

Repository: genlayerlabs/genlayer-studio

Length of output: 139


🏁 Script executed:

rg -n 'isStudio|is_studio|isstudio' frontend/src --type ts -C2

Repository: genlayerlabs/genlayer-studio

Length of output: 1042


Major: explorer link is shown for local networks, contradicting the intended design.

getExplorerUrl() always returns a non-empty string — it falls back to http://localhost:3001 when neither VITE_EXPLORER_URL nor a *.genlayer.com host is present. Therefore v-if="explorerUrl" is always truthy, and on local/studionet the "View on Explorer" button will appear and link to http://localhost:3001/tx/....

The intended behavior (per component design) requires:

  • Hide the explorer link for local/studionet deployments
  • Show "Explorer not available for local networks" placeholder instead

The current implementation doesn't consult the active network at all. Although VITE_GENLAYER_NETWORK is available (providing 'localnet', 'studionet', 'testnetAsimov'), getExplorerUrl() derives the explorer purely from window.location.hostname, so a Studio session on studio.genlayer.com connected to local/studionet would still expose the wrong link.

Suggested fix:

  • Update getExplorerUrl() to accept or access the active network identifier and return null/'' for local/studionet.
  • Guard the template with v-if="explorerUrl && txHash" to also handle empty txHash cases.
  • Show "Explorer not available for local networks" as a fallback in the template.
Template sketch
         <a
-          v-if="explorerUrl"
+          v-if="explorerUrl && txHash"
           :href="`${explorerUrl}/tx/${txHash}`"
           target="_blank"
           class="..."
         >
           <ExternalLink class="h-3.5 w-3.5" />
           View on Explorer
         </a>
+        <span
+          v-else
+          class="inline-flex items-center text-xs text-slate-500 dark:text-zinc-400"
+        >
+          Explorer not available for local networks
+        </span>

Also applies to: 52-61

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/Simulator/DeploymentSuccessPanel.vue` at line 14, The
explorer link currently always shows because getExplorerUrl() falls back to
localhost; update getExplorerUrl to accept (or read) the active network
identifier (VITE_GENLAYER_NETWORK) and return null/empty for 'localnet' and
'studionet' so it does not produce a usable URL for local networks, then change
the computed property explorerUrl in DeploymentSuccessPanel.vue to call
getExplorerUrl(activeNetwork) (or rely on the updated behavior) and update the
template to guard with v-if="explorerUrl && txHash" and render a fallback text
"Explorer not available for local networks" when explorerUrl is falsy; ensure
references to getExplorerUrl, explorerUrl, txHash and the VITE_GENLAYER_NETWORK
env var are used so the logic only shows the "View on Explorer" button for
supported networks.

Comment on lines +53 to +61
<a
v-if="explorerUrl"
:href="`${explorerUrl}/tx/${txHash}`"
target="_blank"
class="inline-flex items-center gap-1.5 rounded-lg bg-white px-4 py-2 text-xs font-medium text-slate-700 shadow-sm ring-1 ring-inset ring-slate-300 transition-colors hover:bg-slate-50 dark:bg-zinc-800 dark:text-zinc-200 dark:ring-zinc-600 dark:hover:bg-zinc-700"
>
<ExternalLink class="h-3.5 w-3.5" />
View on Explorer
</a>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard the explorer link against an empty txHash.

If txHash is ever empty (which is the current state — see the store/listener comment), the link resolves to ${explorerUrl}/tx/ and silently navigates to a broken page. Add && txHash to the v-if (or fall through to the "not available" hint suggested above).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/Simulator/DeploymentSuccessPanel.vue` around lines 53
- 61, The explorer link currently renders when explorerUrl exists but may create
a broken URL if txHash is empty; update the v-if condition on the <a> that
constructs `${explorerUrl}/tx/${txHash}` to require a non-empty txHash as well
(e.g., change the conditional to check both explorerUrl and txHash) so the link
only renders when both explorerUrl and txHash are present, or alternatively
render the "not available" hint when txHash is falsy; locate the anchor in
DeploymentSuccessPanel.vue (the element using
:href="`${explorerUrl}/tx/${txHash}`") and apply the conditional change.

Comment on lines +67 to +80
watch(
[() => isDeployed.value, () => contract.value?.id],
([newIsDeployed, newId], [oldIsDeployed, oldId]) => {
if (newIsDeployed && !oldIsDeployed && newId === oldId) {
showDeploymentSuccessPanel.value = true;
const deployedContract = contractsStore.deployedContracts.find(
(c) => c.contractId === newId,
);
newlyDeployedTxHash.value = deployedContract?.deployTxHash || '';
} else if (newId !== oldId) {
showDeploymentSuccessPanel.value = false;
}
},
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Watcher swallows the missing-hash case behind an empty-string fallback.

newlyDeployedTxHash.value = deployedContract?.deployTxHash || ''; will silently set an empty hash whenever the lookup fails (which today is always, due to the store dropping deployTxHash — see comment in useContractListener.ts). The panel still opens, leading to an empty Transaction Hash row, an empty-clipboard copy, and a broken /tx/ explorer link.

Consider not opening the panel when no hash is available, or at least logging the lookup miss so it surfaces during QA:

🛡️ Defensive variant
-    if (newIsDeployed && !oldIsDeployed && newId === oldId) {
-      showDeploymentSuccessPanel.value = true;
-      const deployedContract = contractsStore.deployedContracts.find(
-        (c) => c.contractId === newId,
-      );
-      newlyDeployedTxHash.value = deployedContract?.deployTxHash || '';
-    } else if (newId !== oldId) {
+    if (newIsDeployed && !oldIsDeployed && newId === oldId) {
+      const deployedContract = contractsStore.deployedContracts.find(
+        (c) => c.contractId === newId,
+      );
+      if (!deployedContract?.deployTxHash) {
+        // Avoid surfacing a panel with an empty tx hash / broken explorer link.
+        return;
+      }
+      newlyDeployedTxHash.value = deployedContract.deployTxHash;
+      showDeploymentSuccessPanel.value = true;
+    } else if (newId !== oldId) {
       showDeploymentSuccessPanel.value = false;
     }
📝 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
watch(
[() => isDeployed.value, () => contract.value?.id],
([newIsDeployed, newId], [oldIsDeployed, oldId]) => {
if (newIsDeployed && !oldIsDeployed && newId === oldId) {
showDeploymentSuccessPanel.value = true;
const deployedContract = contractsStore.deployedContracts.find(
(c) => c.contractId === newId,
);
newlyDeployedTxHash.value = deployedContract?.deployTxHash || '';
} else if (newId !== oldId) {
showDeploymentSuccessPanel.value = false;
}
},
);
watch(
[() => isDeployed.value, () => contract.value?.id],
([newIsDeployed, newId], [oldIsDeployed, oldId]) => {
if (newIsDeployed && !oldIsDeployed && newId === oldId) {
const deployedContract = contractsStore.deployedContracts.find(
(c) => c.contractId === newId,
);
if (!deployedContract?.deployTxHash) {
// Avoid surfacing a panel with an empty tx hash / broken explorer link.
return;
}
newlyDeployedTxHash.value = deployedContract.deployTxHash;
showDeploymentSuccessPanel.value = true;
} else if (newId !== oldId) {
showDeploymentSuccessPanel.value = false;
}
},
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/views/Simulator/RunDebugView.vue` around lines 67 - 80, The
watcher that reacts to isDeployed and contract.id currently opens the success
panel even when the found deployedContract has no deployTxHash (due to the store
dropping it), because newlyDeployedTxHash is set with a silent '' fallback;
change the logic in the watcher (the function watching [() => isDeployed.value,
() => contract.value?.id]) to only set showDeploymentSuccessPanel.value = true
and assign newlyDeployedTxHash.value when a deployedContract is found AND
deployedContract.deployTxHash is a non-empty string; otherwise ensure
showDeploymentSuccessPanel.value = false and newlyDeployedTxHash.value is
cleared, and add a warning log (e.g., console.warn) indicating the lookup miss
(reference contractsStore.deployedContracts and useContractListener note) so QA
can see missing hashes.

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.

Add "View on Explorer" button and contract address display after deployment

1 participant