Skip to content

Conversation

@findolor
Copy link
Collaborator

@findolor findolor commented Dec 22, 2025

Motivation

See issues:

The owner address in the Order Detail and Vault Detail pages currently only supports copy-to-clipboard functionality. Navigating directly to the network's block explorer provides a more useful experience, allowing users to immediately view the address details, transaction history, and token holdings without manual copy-paste workflows.

Solution

Updated the owner address display in both OrderDetail.svelte and VaultDetail.svelte components to render as a clickable link that opens the block explorer in a new tab:

  • Uses the existing getExplorerLink service to dynamically generate the explorer URL based on the network's chain ID
  • Link opens in a new tab with proper security attributes (target="_blank", rel="noopener noreferrer")
  • Preserves backward compatibility: when no block explorer is configured for a network, falls back to the original Hash component with copy-to-clipboard functionality
  • Added comprehensive tests for both components covering:
    • Explorer link rendering with correct attributes
    • Fallback behavior when no explorer is available

Files changed:

  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
Screenshot 2025-12-22 at 11 04 41

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

fix #1393

Summary by CodeRabbit

  • New Features

    • Owner addresses now appear as clickable links to blockchain explorers with a wallet icon when available; otherwise they show the plain address/hash.
  • Tests

    • Added tests covering explorer-link rendering and fallback behavior across relevant detail views.

✏️ Tip: You can customize this high-level summary in your review settings.

@findolor findolor requested review from 0xgleb and hardyjosh December 22, 2025 08:10
@findolor findolor self-assigned this Dec 22, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Walkthrough

Owner address rendering in OrderDetail and VaultDetail was changed to use getExplorerLink synchronously: when an explorer URL exists the owner displays as an external link (with WalletOutline icon), otherwise it falls back to the existing Hash/plain text. Tests were added/updated to cover both cases.

Changes

Cohort / File(s) Summary
Tests
packages/ui-components/src/__tests__/OrderDetail.test.ts, packages/ui-components/src/__tests__/VaultDetail.test.ts, packages/ui-components/src/__tests__/getExplorerLink.test.ts
Added/updated tests to mock getExplorerLink and verify owner renders as an external anchor when a URL is returned and falls back to Hash/plain text when an empty string is returned. Updated getExplorerLink tests to use the synchronous API.
Components
packages/ui-components/src/lib/components/detail/OrderDetail.svelte, packages/ui-components/src/lib/components/detail/VaultDetail.svelte
Import getExplorerLink and WalletOutline; replace direct Hash rendering with a conditional that calls getExplorerLink(data.owner, chainId, 'address') and renders an external link (with icon) when present, otherwise falls back to Hash/plain text.
Service
packages/ui-components/src/lib/services/getExplorerLink.ts
Changed getExplorerLink from an async function returning a Promise to a synchronous function returning a string (URL or empty string).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to the synchronous API change for getExplorerLink and all call sites (tests and components).
  • Verify correct handling of empty string vs falsy values when deciding fallback rendering.
  • Confirm imports (WalletOutline grouping) and any bundler/tree-shaking implications.
  • Check tests' mocks and assertions for target/rel attributes and for absence/presence of anchor elements.

Possibly related PRs

Suggested labels

webapp, test

Suggested reviewers

  • hardyjosh
  • 0xgleb

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the PR - converting owner address displays to block explorer links in two specific detail pages.
Linked Issues check ✅ Passed The PR implementation fully addresses issue #1393 by converting owner addresses to clickable block explorer links in OrderDetail and VaultDetail with appropriate fallback handling.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue objective. The refactoring of getExplorerLink from async to synchronous is an implementation detail necessary to support the feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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 2025-12-22-order-detail-owner-link

📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 493dd56 and 09e9b17.

📒 Files selected for processing (6)
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/services/getExplorerLink.ts
🧰 Additional context used
📓 Path-based instructions (7)
packages/ui-components/**/*.{svelte,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For UI components (packages/ui-components), run lints and format checks using nix develop -c npm run svelte-lint-format-check -w @rainlanguage/ui-components

Files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/services/getExplorerLink.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
packages/ui-components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For UI components (packages/ui-components), run tests using nix develop -c npm run test -w @rainlanguage/ui-components

Files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/services/getExplorerLink.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
packages/{webapp,ui-components}/**/*.{svelte,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

If you modify frontend code or functionality affecting the frontend, you MUST provide a screenshot of the built webapp reflecting your change.

Files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/services/getExplorerLink.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
packages/**/*.{js,ts,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

JavaScript/Svelte organized as packages/* including webapp, ui-components, and orderbook (wasm wrapper published to npm)

Files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/services/getExplorerLink.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,svelte}: TypeScript/Svelte: format with nix develop -c npm run format
TypeScript/Svelte: lint with nix develop -c npm run lint
TypeScript/Svelte: type-check with nix develop -c npm run check

Files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/services/getExplorerLink.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
**/*.{test,spec}.ts

📄 CodeRabbit inference engine (AGENTS.md)

TypeScript/Svelte: run tests with nix develop -c npm run test (Vitest). Name test files *.test.ts or *.spec.ts

Files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
**/*.svelte

📄 CodeRabbit inference engine (AGENTS.md)

Svelte components should use PascalCase.svelte naming convention; other files use kebab or snake case as appropriate

Files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
🧠 Learnings (18)
📓 Common learnings
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1512
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:125-143
Timestamp: 2025-04-08T12:56:03.272Z
Learning: The OrderDetail component in the Rain orderbook UI doesn't currently have error handling tests, but issue #1605 has been created to address this in the future.
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2083
File: packages/ui-components/src/lib/components/tables/VaultsListTable.svelte:205-205
Timestamp: 2025-08-14T14:16:34.044Z
Learning: In the VaultsListTable component, the `matchesAccount` function from the wallet provider may not properly update on wallet connect/disconnect events, making direct comparison with the reactive `$account` variable more reliable for UI visibility checks. The `matchesAccount` function needs future refactoring to handle wallet state changes properly.
📚 Learning: 2025-07-11T08:46:07.606Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1925
File: packages/ui-components/src/__tests__/DeploymentSteps.test.ts:519-554
Timestamp: 2025-07-11T08:46:07.606Z
Learning: In packages/ui-components/src/__tests__/DeploymentSteps.test.ts, findolor prefers to keep hardcoded timeout values (like 50ms and 100ms) inline in test cases rather than extracting them to named constants, viewing such refactoring as unnecessary for test maintainability.

Applied to files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
📚 Learning: 2025-07-09T12:35:45.699Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1974
File: packages/ui-components/src/__tests__/DeploymentSteps.test.ts:123-126
Timestamp: 2025-07-09T12:35:45.699Z
Learning: In packages/ui-components/src/__tests__/DeploymentSteps.test.ts, findolor prefers to keep mock initializations (like setSelectToken) in individual test cases rather than consolidating them into shared beforeEach blocks, even when it results in duplication.

Applied to files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-09-02T08:04:44.814Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2117
File: packages/ui-components/src/__tests__/VaultIdInformation.test.ts:9-13
Timestamp: 2025-09-02T08:04:44.814Z
Learning: In packages/ui-components/src/__tests__/VaultIdInformation.test.ts and similar test files in the rain.orderbook project, the passthrough vi.mock('rainlanguage/orderbook', async (importOriginal) => { return { ...(await importOriginal()) }; }); block is required for tests to run properly, even when not overriding any exports. This is needed due to the specific Vitest configuration or test environment setup in the project.

Applied to files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-07-17T10:36:02.846Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1996
File: packages/ui-components/src/__tests__/VaultIdInformation.test.ts:6-6
Timestamp: 2025-07-17T10:36:02.846Z
Learning: In packages/ui-components/src/__tests__/VaultIdInformation.test.ts, findolor prefers to keep exported type aliases like `VaultIdInformationComponentProps` in test files, even when static analysis tools flag this as discouraged practice.

Applied to files:

  • packages/ui-components/src/__tests__/getExplorerLink.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-08-14T14:16:34.044Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2083
File: packages/ui-components/src/lib/components/tables/VaultsListTable.svelte:205-205
Timestamp: 2025-08-14T14:16:34.044Z
Learning: In the VaultsListTable component, the `matchesAccount` function from the wallet provider may not properly update on wallet connect/disconnect events, making direct comparison with the reactive `$account` variable more reliable for UI visibility checks. The `matchesAccount` function needs future refactoring to handle wallet state changes properly.

Applied to files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
📚 Learning: 2025-06-27T17:34:15.825Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 1957
File: packages/ui-components/src/lib/components/tables/VaultsListTable.svelte:60-60
Timestamp: 2025-06-27T17:34:15.825Z
Learning: In the VaultsListTable.svelte component, the `activeAccounts` store is redundant in query keys when the `owners` variable (derived from `activeAccountsItems`) is already included, as `owners` is what's actually used in the query function while `activeAccounts` is just a transformed version of the same data.

Applied to files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
📚 Learning: 2025-05-20T12:03:18.032Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1870
File: packages/webapp/src/lib/components/WithdrawModal.svelte:31-31
Timestamp: 2025-05-20T12:03:18.032Z
Learning: The VaultActionArgs type no longer contains an action property after refactoring the deposit/withdraw modals into separate components.

Applied to files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
📚 Learning: 2025-08-14T18:29:32.933Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2083
File: packages/ui-components/src/__tests__/VaultsListTable.test.ts:16-19
Timestamp: 2025-08-14T18:29:32.933Z
Learning: In the rain.orderbook project's UI components tests, mocking hooks like useToasts is often required as infrastructure even when not directly asserting on their calls, because components internally depend on these hooks. Removing such mocks would break component rendering in tests and require more complex test setup with providers.

Applied to files:

  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-06-30T14:17:16.626Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1926
File: packages/ui-components/src/lib/__mocks__/stores.ts:13-17
Timestamp: 2025-06-30T14:17:16.626Z
Learning: User findolor reports that vi.mock(import('rainlanguage/orderbook'), async (importOriginal) => { ... }) syntax works in their testing environment, despite official Vitest documentation indicating the first argument should be a string. This suggests there may be specific Vitest versions or configurations that support dynamic import() as the first argument to vi.mock().

Applied to files:

  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-04-04T11:25:21.518Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1559
File: packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts:94-94
Timestamp: 2025-04-04T11:25:21.518Z
Learning: In the rain.orderbook project, minimal test fixtures are preferred over complete mocks that implement the entire interface. Type casting (e.g., `as unknown as SgVault`) is an acceptable approach to maintain both minimal fixtures and TypeScript type compatibility.

Applied to files:

  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-06-04T10:21:01.388Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1907
File: packages/orderbook/test/common/test.test.ts:75-77
Timestamp: 2025-06-04T10:21:01.388Z
Learning: The DotrainOrder.create API in packages/orderbook/test/common/test.test.ts is internal and not used directly in consumer applications, so API changes here don't require external breaking change documentation.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-04-08T12:56:03.272Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1512
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:125-143
Timestamp: 2025-04-08T12:56:03.272Z
Learning: The OrderDetail component in the Rain orderbook UI doesn't currently have error handling tests, but issue #1605 has been created to address this in the future.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
📚 Learning: 2025-06-17T14:55:22.914Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1936
File: packages/ui-components/vite.config.ts:21-23
Timestamp: 2025-06-17T14:55:22.914Z
Learning: In the rain.orderbook project, the Vite configuration uses `'import.meta.vitest': 'undefined'` (as a string) combined with conditional `if (import.meta.vitest)` checks for in-source testing. The mock files are excluded from test execution using `exclude: ['src/lib/__mocks__/**/*.ts']`. This configuration successfully allows dev builds to work without `vi` undefined errors, despite the theoretical expectation that the string "undefined" would be truthy and cause issues.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-03-31T10:16:53.544Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1469
File: packages/ui-components/src/__tests__/CodeMirrorDotrain.test.ts:75-98
Timestamp: 2025-03-31T10:16:53.544Z
Learning: In the rainlanguage/rain.orderbook project, direct manipulation of Svelte's internal state (component.$$.ctx) in tests is an acceptable approach for testing component behavior, as demonstrated in the CodeMirrorDotrain tests.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-04-28T10:58:11.124Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1700
File: tauri-app/src/lib/mocks/mockConfigSource.ts:6-6
Timestamp: 2025-04-28T10:58:11.124Z
Learning: In mock data for testing in this codebase, it's acceptable to use URL placeholders like 'https://mainnet.infura.io/v3/YOUR-PROJECT-ID' as they clearly indicate the expected format for actual implementation.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-04-09T09:28:05.097Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1512
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:0-0
Timestamp: 2025-04-09T09:28:05.097Z
Learning: The OrderDetail component has been refactored to use an `onRemove` callback approach instead of the previous `handleOrderRemoveModal` pattern for order removal functionality, as part of PR #1512.

Applied to files:

  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
📚 Learning: 2025-04-08T12:31:23.761Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1597
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:263-275
Timestamp: 2025-04-08T12:31:23.761Z
Learning: The OrderDetail component's refresh functionality doesn't currently have error handling, but issue #1604 has been created to address this in the future.

Applied to files:

  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
🧬 Code graph analysis (3)
packages/ui-components/src/__tests__/getExplorerLink.test.ts (1)
packages/ui-components/src/lib/services/getExplorerLink.ts (1)
  • getExplorerLink (3-9)
packages/ui-components/src/__tests__/VaultDetail.test.ts (1)
packages/ui-components/src/lib/index.ts (1)
  • getExplorerLink (100-100)
packages/ui-components/src/lib/services/getExplorerLink.ts (1)
packages/webapp/src/lib/stores/wagmi.ts (1)
  • chainId (22-22)
⏰ 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). (14)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
  • GitHub Check: test
  • GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-browser-test)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
  • GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
  • GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
  • GitHub Check: git-clean
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: Deploy-Docs-Preview
  • GitHub Check: build-tauri (ubuntu-22.04, true)
  • GitHub Check: Deploy-Preview-Push
🔇 Additional comments (10)
packages/ui-components/src/lib/services/getExplorerLink.ts (1)

3-8: LGTM! Appropriate conversion to synchronous function.

The function contains no asynchronous operations, so removing the async keyword is correct. The logic remains sound: it returns an explorer URL when available or an empty string otherwise.

packages/ui-components/src/__tests__/getExplorerLink.test.ts (1)

15-20: LGTM! Tests correctly updated for synchronous function.

The tests properly reflect the function's synchronous behavior and cover both the success case (returning an explorer URL) and the fallback case (returning an empty string).

packages/ui-components/src/__tests__/OrderDetail.test.ts (2)

19-19: LGTM! Proper mock setup for the new functionality.

The mock configuration correctly sets up getExplorerLink to return a URL by default in beforeEach, which allows individual tests to override as needed.

Also applies to: 51-53, 166-168


348-382: LGTM! Comprehensive test coverage for explorer link feature.

The tests thoroughly validate both scenarios:

  1. When an explorer URL is available: verifies the link is rendered with correct href, target="_blank", and rel="noopener noreferrer" attributes
  2. When no explorer URL is available: confirms fallback to the Hash component with no link rendered
packages/ui-components/src/lib/components/detail/VaultDetail.svelte (2)

26-31: LGTM! Appropriate imports for the explorer link feature.

The imports for WalletOutline icon and getExplorerLink service are correctly added to support the new functionality.


136-149: LGTM! Correct implementation of conditional explorer link rendering.

The implementation properly:

  • Uses {@const} to synchronously compute the explorer link
  • Renders a secure external link (with target="_blank" and rel="noopener noreferrer") when an explorer URL is available
  • Falls back to the existing Hash component when no explorer is configured

Note: The past review comment about adding error handling for {#await} is no longer applicable since getExplorerLink is now a synchronous function that returns a string and cannot throw errors in normal operation.

packages/ui-components/src/__tests__/VaultDetail.test.ts (2)

15-15: LGTM! Proper mock setup for explorer link testing.

The mock configuration is set up correctly, with a default explorer URL in beforeEach that can be overridden in individual tests.

Also applies to: 48-50, 86-88


227-261: LGTM! Comprehensive test coverage for the explorer link feature.

The tests validate both scenarios thoroughly:

  1. Explorer available: verifies link rendering with correct href, target="_blank", and rel="noopener noreferrer" attributes
  2. No explorer: confirms fallback to Hash component with no link element
packages/ui-components/src/lib/components/detail/OrderDetail.svelte (2)

24-27: LGTM! Appropriate imports for the explorer link feature.

The imports for WalletOutline icon and getExplorerLink service are correctly added, maintaining consistency with the VaultDetail component.


160-173: LGTM! Correct implementation of conditional explorer link rendering.

The implementation properly:

  • Uses {@const} to synchronously compute the explorer link
  • Renders a secure external link (with target="_blank" and rel="noopener noreferrer") when an explorer URL is available
  • Includes the WalletOutline icon for visual clarity
  • Falls back to the existing Hash component when no explorer is configured

Note: The past review comment about adding error handling for {#await} is no longer applicable since getExplorerLink is now a synchronous function that returns a string and cannot throw errors in normal operation.


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

Copy link
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: 2

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7aa6155 and 493dd56.

📒 Files selected for processing (4)
  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
🧰 Additional context used
📓 Path-based instructions (7)
packages/ui-components/**/*.{svelte,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For UI components (packages/ui-components), run lints and format checks using nix develop -c npm run svelte-lint-format-check -w @rainlanguage/ui-components

Files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
packages/ui-components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For UI components (packages/ui-components), run tests using nix develop -c npm run test -w @rainlanguage/ui-components

Files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
packages/{webapp,ui-components}/**/*.{svelte,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

If you modify frontend code or functionality affecting the frontend, you MUST provide a screenshot of the built webapp reflecting your change.

Files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
packages/**/*.{js,ts,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

JavaScript/Svelte organized as packages/* including webapp, ui-components, and orderbook (wasm wrapper published to npm)

Files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,svelte}: TypeScript/Svelte: format with nix develop -c npm run format
TypeScript/Svelte: lint with nix develop -c npm run lint
TypeScript/Svelte: type-check with nix develop -c npm run check

Files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
**/*.{test,spec}.ts

📄 CodeRabbit inference engine (AGENTS.md)

TypeScript/Svelte: run tests with nix develop -c npm run test (Vitest). Name test files *.test.ts or *.spec.ts

Files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
**/*.svelte

📄 CodeRabbit inference engine (AGENTS.md)

Svelte components should use PascalCase.svelte naming convention; other files use kebab or snake case as appropriate

Files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
🧠 Learnings (18)
📓 Common learnings
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1512
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:125-143
Timestamp: 2025-04-08T12:56:03.272Z
Learning: The OrderDetail component in the Rain orderbook UI doesn't currently have error handling tests, but issue #1605 has been created to address this in the future.
📚 Learning: 2025-09-02T08:04:44.814Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2117
File: packages/ui-components/src/__tests__/VaultIdInformation.test.ts:9-13
Timestamp: 2025-09-02T08:04:44.814Z
Learning: In packages/ui-components/src/__tests__/VaultIdInformation.test.ts and similar test files in the rain.orderbook project, the passthrough vi.mock('rainlanguage/orderbook', async (importOriginal) => { return { ...(await importOriginal()) }; }); block is required for tests to run properly, even when not overriding any exports. This is needed due to the specific Vitest configuration or test environment setup in the project.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-07-09T12:35:45.699Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1974
File: packages/ui-components/src/__tests__/DeploymentSteps.test.ts:123-126
Timestamp: 2025-07-09T12:35:45.699Z
Learning: In packages/ui-components/src/__tests__/DeploymentSteps.test.ts, findolor prefers to keep mock initializations (like setSelectToken) in individual test cases rather than consolidating them into shared beforeEach blocks, even when it results in duplication.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-06-04T10:21:01.388Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1907
File: packages/orderbook/test/common/test.test.ts:75-77
Timestamp: 2025-06-04T10:21:01.388Z
Learning: The DotrainOrder.create API in packages/orderbook/test/common/test.test.ts is internal and not used directly in consumer applications, so API changes here don't require external breaking change documentation.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-04-08T12:56:03.272Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1512
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:125-143
Timestamp: 2025-04-08T12:56:03.272Z
Learning: The OrderDetail component in the Rain orderbook UI doesn't currently have error handling tests, but issue #1605 has been created to address this in the future.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-07-17T10:36:02.846Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1996
File: packages/ui-components/src/__tests__/VaultIdInformation.test.ts:6-6
Timestamp: 2025-07-17T10:36:02.846Z
Learning: In packages/ui-components/src/__tests__/VaultIdInformation.test.ts, findolor prefers to keep exported type aliases like `VaultIdInformationComponentProps` in test files, even when static analysis tools flag this as discouraged practice.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
📚 Learning: 2025-08-14T18:29:32.933Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2083
File: packages/ui-components/src/__tests__/VaultsListTable.test.ts:16-19
Timestamp: 2025-08-14T18:29:32.933Z
Learning: In the rain.orderbook project's UI components tests, mocking hooks like useToasts is often required as infrastructure even when not directly asserting on their calls, because components internally depend on these hooks. Removing such mocks would break component rendering in tests and require more complex test setup with providers.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-06-30T14:17:16.626Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1926
File: packages/ui-components/src/lib/__mocks__/stores.ts:13-17
Timestamp: 2025-06-30T14:17:16.626Z
Learning: User findolor reports that vi.mock(import('rainlanguage/orderbook'), async (importOriginal) => { ... }) syntax works in their testing environment, despite official Vitest documentation indicating the first argument should be a string. This suggests there may be specific Vitest versions or configurations that support dynamic import() as the first argument to vi.mock().

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-06-17T14:55:22.914Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1936
File: packages/ui-components/vite.config.ts:21-23
Timestamp: 2025-06-17T14:55:22.914Z
Learning: In the rain.orderbook project, the Vite configuration uses `'import.meta.vitest': 'undefined'` (as a string) combined with conditional `if (import.meta.vitest)` checks for in-source testing. The mock files are excluded from test execution using `exclude: ['src/lib/__mocks__/**/*.ts']`. This configuration successfully allows dev builds to work without `vi` undefined errors, despite the theoretical expectation that the string "undefined" would be truthy and cause issues.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-03-31T10:16:53.544Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1469
File: packages/ui-components/src/__tests__/CodeMirrorDotrain.test.ts:75-98
Timestamp: 2025-03-31T10:16:53.544Z
Learning: In the rainlanguage/rain.orderbook project, direct manipulation of Svelte's internal state (component.$$.ctx) in tests is an acceptable approach for testing component behavior, as demonstrated in the CodeMirrorDotrain tests.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-04-28T10:58:11.124Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1700
File: tauri-app/src/lib/mocks/mockConfigSource.ts:6-6
Timestamp: 2025-04-28T10:58:11.124Z
Learning: In mock data for testing in this codebase, it's acceptable to use URL placeholders like 'https://mainnet.infura.io/v3/YOUR-PROJECT-ID' as they clearly indicate the expected format for actual implementation.

Applied to files:

  • packages/ui-components/src/__tests__/OrderDetail.test.ts
📚 Learning: 2025-08-14T14:16:34.044Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2083
File: packages/ui-components/src/lib/components/tables/VaultsListTable.svelte:205-205
Timestamp: 2025-08-14T14:16:34.044Z
Learning: In the VaultsListTable component, the `matchesAccount` function from the wallet provider may not properly update on wallet connect/disconnect events, making direct comparison with the reactive `$account` variable more reliable for UI visibility checks. The `matchesAccount` function needs future refactoring to handle wallet state changes properly.

Applied to files:

  • packages/ui-components/src/__tests__/VaultDetail.test.ts
  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
📚 Learning: 2025-04-04T11:25:21.518Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1559
File: packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts:94-94
Timestamp: 2025-04-04T11:25:21.518Z
Learning: In the rain.orderbook project, minimal test fixtures are preferred over complete mocks that implement the entire interface. Type casting (e.g., `as unknown as SgVault`) is an acceptable approach to maintain both minimal fixtures and TypeScript type compatibility.

Applied to files:

  • packages/ui-components/src/__tests__/VaultDetail.test.ts
📚 Learning: 2025-06-27T17:34:15.825Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 1957
File: packages/ui-components/src/lib/components/tables/VaultsListTable.svelte:60-60
Timestamp: 2025-06-27T17:34:15.825Z
Learning: In the VaultsListTable.svelte component, the `activeAccounts` store is redundant in query keys when the `owners` variable (derived from `activeAccountsItems`) is already included, as `owners` is what's actually used in the query function while `activeAccounts` is just a transformed version of the same data.

Applied to files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
📚 Learning: 2025-05-20T12:03:18.032Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1870
File: packages/webapp/src/lib/components/WithdrawModal.svelte:31-31
Timestamp: 2025-05-20T12:03:18.032Z
Learning: The VaultActionArgs type no longer contains an action property after refactoring the deposit/withdraw modals into separate components.

Applied to files:

  • packages/ui-components/src/lib/components/detail/VaultDetail.svelte
📚 Learning: 2025-04-09T09:28:05.097Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1512
File: packages/ui-components/src/__tests__/OrderDetail.test.ts:0-0
Timestamp: 2025-04-09T09:28:05.097Z
Learning: The OrderDetail component has been refactored to use an `onRemove` callback approach instead of the previous `handleOrderRemoveModal` pattern for order removal functionality, as part of PR #1512.

Applied to files:

  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
📚 Learning: 2025-03-22T21:11:34.405Z
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1496
File: packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte:164-164
Timestamp: 2025-03-22T21:11:34.405Z
Learning: The refactoring to replace signerAddress with account from useAccount hook is being done in stages - shared UI components first (PR #1496), with webapp-specific components to be handled in a separate future PR.

Applied to files:

  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
📚 Learning: 2025-08-19T04:15:33.633Z
Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2036
File: packages/ui-components/src/lib/components/ListViewVaultFilters.svelte:33-52
Timestamp: 2025-08-19T04:15:33.633Z
Learning: In the ListViewVaultFilters.svelte component, the "Show my items only" filter is intentionally destructive for the owners field. When toggled, it should replace any existing owner filters (including those from URL parameters) rather than being additive. This is by design because the UI doesn't provide capability to filter by other owner addresses or remove specific owners from a list. The toggle serves as both a filter and a way for users to clear URL-based owner filters and switch to filtering by their own address only.

Applied to files:

  • packages/ui-components/src/lib/components/detail/OrderDetail.svelte
🧬 Code graph analysis (1)
packages/ui-components/src/__tests__/OrderDetail.test.ts (1)
packages/ui-components/src/lib/index.ts (1)
  • getExplorerLink (100-100)
⏰ 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). (3)
  • GitHub Check: Deploy-Docs-Preview
  • GitHub Check: build-tauri (ubuntu-22.04, true)
  • GitHub Check: Deploy-Preview-Push
🔇 Additional comments (8)
packages/ui-components/src/lib/components/detail/OrderDetail.svelte (1)

24-27: LGTM: Clean imports for explorer link functionality.

The import additions are minimal and well-organized, bringing in the WalletOutline icon and getExplorerLink service needed for the owner address link feature.

packages/ui-components/src/__tests__/OrderDetail.test.ts (3)

19-19: LGTM: Proper mock setup for getExplorerLink.

The mock follows the project's established testing patterns and allows per-test override of the return value, providing good flexibility for testing both explorer-available and unavailable scenarios.

Also applies to: 51-53, 165-168


348-366: LGTM: Comprehensive test for explorer link rendering.

The test thoroughly validates the explorer link functionality, including proper security attributes (target="_blank" and rel="noopener noreferrer"), which is essential for preventing security vulnerabilities.


368-382: LGTM: Proper fallback test coverage.

The test correctly validates that when no explorer link is available, the component falls back to displaying the address as plain text without creating a link element.

packages/ui-components/src/__tests__/VaultDetail.test.ts (3)

15-15: LGTM: Consistent mock setup with OrderDetail tests.

The mock configuration mirrors the OrderDetail test setup, maintaining consistency across the test suite and making the codebase easier to maintain.

Also applies to: 48-50, 86-88


227-245: LGTM: Thorough explorer link test.

The test validates all critical aspects including security attributes, maintaining consistency with the OrderDetail test approach.


247-261: LGTM: Proper fallback validation.

The test correctly verifies the fallback behavior when no explorer link is available, ensuring graceful degradation of the feature.

packages/ui-components/src/lib/components/detail/VaultDetail.svelte (1)

26-31: LGTM: Imports align with OrderDetail pattern.

The import changes are clean and consistent with the OrderDetail component, maintaining a unified approach across both detail views.

Comment on lines 160 to 174
{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink}
{#if explorerLink}
<a
href={explorerLink}
target="_blank"
rel="noopener noreferrer"
class="flex items-center justify-start space-x-2 text-left text-blue-500 hover:underline"
>
<WalletOutline size="sm" />
<span>{data.owner}</span>
</a>
{:else}
<Hash type={HashType.Wallet} shorten={false} value={data.owner} />
{/if}
{/await}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling to the explorer link resolution.

The {#await} block lacks a :catch clause. If getExplorerLink throws an error (e.g., network issues, misconfigured explorer service), the Owner field may fail to render entirely.

🔎 Proposed fix with error handling
-{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink}
+{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink catch}
 	{#if explorerLink}
 		<a
 			href={explorerLink}
 			target="_blank"
 			rel="noopener noreferrer"
 			class="flex items-center justify-start space-x-2 text-left text-blue-500 hover:underline"
 		>
 			<WalletOutline size="sm" />
 			<span>{data.owner}</span>
 		</a>
 	{:else}
 		<Hash type={HashType.Wallet} shorten={false} value={data.owner} />
 	{/if}
 {/await}
📝 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
{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink}
{#if explorerLink}
<a
href={explorerLink}
target="_blank"
rel="noopener noreferrer"
class="flex items-center justify-start space-x-2 text-left text-blue-500 hover:underline"
>
<WalletOutline size="sm" />
<span>{data.owner}</span>
</a>
{:else}
<Hash type={HashType.Wallet} shorten={false} value={data.owner} />
{/if}
{/await}
{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink}
{#if explorerLink}
<a
href={explorerLink}
target="_blank"
rel="noopener noreferrer"
class="flex items-center justify-start space-x-2 text-left text-blue-500 hover:underline"
>
<WalletOutline size="sm" />
<span>{data.owner}</span>
</a>
{:else}
<Hash type={HashType.Wallet} shorten={false} value={data.owner} />
{/if}
{:catch error}
<Hash type={HashType.Wallet} shorten={false} value={data.owner} />
{/await}
🤖 Prompt for AI Agents
packages/ui-components/src/lib/components/detail/OrderDetail.svelte lines
160-174: the {#await getExplorerLink(...)} block has no :catch branch so a
thrown error will break rendering; add a :catch block that handles errors by
rendering the fallback Hash component (Hash type Wallet, shorten false, value
data.owner) and optionally log the error (console.error or a logger) so the
Owner field still displays when getExplorerLink fails.

Comment on lines 136 to 150
{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink}
{#if explorerLink}
<a
href={explorerLink}
target="_blank"
rel="noopener noreferrer"
class="flex items-center justify-start space-x-2 text-left text-blue-500 hover:underline"
>
<WalletOutline size="sm" />
<span>{data.owner}</span>
</a>
{:else}
<Hash type={HashType.Wallet} value={data.owner} />
{/if}
{/await}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling to the explorer link resolution.

The {#await} block lacks a :catch clause. If getExplorerLink throws an error (e.g., network issues, misconfigured explorer service), the Owner address field may fail to render entirely.

🔎 Proposed fix with error handling
-{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink}
+{#await getExplorerLink(data.owner, chainId, 'address') then explorerLink catch}
 	{#if explorerLink}
 		<a
 			href={explorerLink}
 			target="_blank"
 			rel="noopener noreferrer"
 			class="flex items-center justify-start space-x-2 text-left text-blue-500 hover:underline"
 		>
 			<WalletOutline size="sm" />
 			<span>{data.owner}</span>
 		</a>
 	{:else}
 		<Hash type={HashType.Wallet} value={data.owner} />
 	{/if}
 {/await}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/ui-components/src/lib/components/detail/VaultDetail.svelte around
lines 136 to 150 the {#await getExplorerLink(...)} block has no :catch branch so
a thrown error will break rendering; add error handling by adding a :catch
clause that renders a safe fallback (e.g., the <Hash type={HashType.Wallet}
value={data.owner} /> component or a non-blocking disabled link) and optionally
log the error; ensure you preserve the existing then branch and keep :catch last
before {/await} so the Owner field always renders even if getExplorerLink fails.

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.

owner should be a link on the strategy page

2 participants