Repository: rainlanguage/rain.orderbook
Pull request #1617: Replace walletAddressMatchesOrBlank and viem isAddress checks with accountIsOwner
Author: login: hardingjam
Labels: name: Tauri
description: Tauri app
name: webapp
Created: 2025-04-09T16:39:55Z | Merged: 2025-04-15T07:31:12Z

<!-- Thanks for your Pull Request, please read the contributing guidelines before submitting. -->

- This brings the frontend checks up to date with the implementation of the useAccount store. 
- Instead of optional prop from tauri, and the duplicated use of isAddress and isAddressEqual, use a tested util function accountIsOwner to check if the connected account can interact with vaults/orders.
- Use of $account as arg ensures this is reactive to wallet connect/disconnection.

Closes #1485 and #1598 
<!--
Explain the context and why you're making that change. What is the problem
you're trying to solve? In some cases there is not a problem and this can be
thought of as being the motivation for your change.
-->



## Checks
<!-- It's important you've done these, or your PR will not be considered for review -->
By submitting this for review, I'm confirming I've done the following:
- [x] made this PR as small as possible
- [x] unit-tested any new functionality
- [x] linked any relevant issues or PRs
- [ ] included screenshots (if this involves a front-end change)


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Enhanced wallet account verification now ensures that key actions (such as deposit, withdraw, and order removal) display only for the authorized user, resulting in a more intuitive interface.
	- Introduced comprehensive unit tests for the `OrdersListTable` component to validate functionality and user interactions.

- **Bug Fixes**
	- Improved reliability of tests by updating account matching logic and ensuring accurate display of action buttons based on user ownership.

- **Refactor**
	- Consolidated account matching logic across orders and vaults for improved consistency and reliability in user interactions.
	- Streamlined test setups by removing unnecessary variables and enhancing mock implementations.
	- Updated test cases to utilize new mock functions for account matching, improving clarity and focus.
	- Removed deprecated variables and props related to wallet address matching, simplifying component logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #1485: Remove walletAddressMatchesOrBlank, check against useAccount account instead

Diff:
diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts
index e1ae902658..540511da51 100644
--- a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts
+++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts
@@ -119,7 +119,8 @@ describe('DeploymentSteps', () => {
 		mockGui = guiInstance;
 		vi.mocked(useGui).mockReturnValue(mockGui);
 		vi.mocked(useAccount).mockReturnValue({
-			account: readable('0x123')
+			account: readable('0x123'),
+			matchesAccount: vi.fn()
 		});
 	});
 
@@ -442,7 +443,8 @@ describe('DeploymentSteps', () => {
 	});
 	it('passes correct arguments to handleDeployment', async () => {
 		vi.mocked(useAccount).mockReturnValue({
-			account: readable('0xTestAccount')
+			account: readable('0xTestAccount'),
+			matchesAccount: vi.fn()
 		});
 
 		(DotrainOrderGui.prototype.areAllTokensSelected as Mock).mockReturnValue({ value: true });
diff --git a/packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts b/packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
index b5d4ebe57c..4bae0175ea 100644
--- a/packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
+++ b/packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
@@ -1,12 +1,21 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null),
+		matchesAccount: vi.fn()
+	})
+}));
+
+vi.mock('@tanstack/svelte-query', () => ({
+	createInfiniteQuery: vi.fn()
+}));
+
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
 type ListViewOrderbookFiltersProps = ComponentProps<ListViewOrderbookFilters<any>>;
 
@@ -25,10 +34,6 @@ describe('ListViewOrderbookFilters', () => {
 		}
 	});
 
-	const { query } = createResolvableInfiniteQuery((pageParam) => {
-		return ['page' + pageParam];
-	});
-
 	const defaultProps = {
 		settings: mockSettings,
 		accounts: writable({}),
@@ -39,12 +44,10 @@ describe('ListViewOrderbookFilters', () => {
 		orderHash: writable(''),
 		isVaultsPage: false,
 		isOrdersPage: false,
-		query,
 		showMyItemsOnly: writable(false)
 	} as ListViewOrderbookFiltersProps;
 
 	beforeEach(() => {
-		// Reset settings to default state before each test
 		mockSettings.set({
 			networks: {
 				ethereum: {
diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.ts b/packages/ui-components/src/__tests__/OrderDetail.test.ts
index 243c04bff8..82aee96079 100644
--- a/packages/ui-components/src/__tests__/OrderDetail.test.ts
+++ b/packages/ui-components/src/__tests__/OrderDetail.test.ts
@@ -31,7 +31,6 @@ vi.mock('$lib/components/charts/OrderTradesChart.svelte', async () => {
 });
 const subgraphUrl = 'https://example.com';
 const orderbookAddress = '0x123456789012345678901234567890123456abcd';
-const chainId = 1;
 const rpcUrl = 'https://eth-mainnet.alchemyapi.io/v2/your-api-key';
 const orderHash = 'mockOrderHash';
 
@@ -40,7 +39,6 @@ const defaultProps: ComponentProps<OrderDetail> = {
 	rpcUrl,
 	subgraphUrl,
 	orderbookAddress,
-	chainId,
 	colorTheme: readable('dark'),
 	codeMirrorTheme: readable('dark'),
 	lightweightChartsTheme: readable(darkChartTheme),
@@ -119,8 +117,7 @@ const mockOrder: SgOrder = {
 	expression: '0x123456' // Your existing field
 } as unknown as SgOrder;
 
-const mockAccountStore = readable('0x1234567890123456789012345678901234567890');
-
+const mockMatchesAccount = vi.fn();
 describe('OrderDetail', () => {
 	let queryClient: QueryClient;
 
@@ -129,12 +126,10 @@ describe('OrderDetail', () => {
 		vi.resetAllMocks();
 		queryClient = new QueryClient();
 
-		// Set up account mock
 		(useAccount as Mock).mockReturnValue({
-			account: mockAccountStore
+			matchesAccount: mockMatchesAccount
 		});
 
-		// Mock getOrderByHash to return our data structure
 		(getOrderByHash as Mock).mockResolvedValue({
 			order: mockOrder,
 			vaults: new Map([
@@ -184,6 +179,7 @@ describe('OrderDetail', () => {
 	});
 
 	it('shows remove button if owner wallet matches and order is active', async () => {
+		mockMatchesAccount.mockReturnValue(true);
 		render(OrderDetail, {
 			props: defaultProps,
 			context: new Map([['$$_queryClient', queryClient]])
@@ -195,7 +191,6 @@ describe('OrderDetail', () => {
 			expect(defaultProps.onRemove).not.toHaveBeenCalled();
 		});
 
-		// Click the Remove button
 		await userEvent.click(screen.getByTestId('remove-button'));
 
 		await waitFor(() => {
@@ -204,9 +199,7 @@ describe('OrderDetail', () => {
 	});
 
 	it('does not show remove button if account does not match owner', async () => {
-		(useAccount as Mock).mockReturnValue({
-			account: readable('0x0987654321098765432109876543210987654321')
-		});
+		mockMatchesAccount.mockReturnValue(false);
 
 		render(OrderDetail, {
 			props: defaultProps,
@@ -257,6 +250,7 @@ describe('OrderDetail', () => {
 	});
 
 	it('calls onDeposit callback when deposit button is clicked', async () => {
+		mockMatchesAccount.mockReturnValue(true);
 		const user = userEvent.setup();
 		const mockOnDeposit = vi.fn();
 
@@ -285,9 +279,7 @@ describe('OrderDetail', () => {
 	});
 
 	it('calls onWithdraw callback when withdraw button is clicked', async () => {
-		(useAccount as Mock).mockReturnValue({
-			account: mockAccountStore
-		});
+		mockMatchesAccount.mockReturnValue(true);
 		const user = userEvent.setup();
 		const mockOnWithdraw = vi.fn();
 
diff --git a/packages/ui-components/src/__tests__/OrdersListTable.test.ts b/packages/ui-components/src/__tests__/OrdersListTable.test.ts
new file mode 100644
index 0000000000..7e812f5faf
--- /dev/null
+++ b/packages/ui-components/src/__tests__/OrdersListTable.test.ts
@@ -0,0 +1,341 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { render, screen, waitFor } from '@testing-library/svelte';
+import { describe, it, expect, vi, type Mock } from 'vitest';
+import OrdersListTable from '../lib/components/tables/OrdersListTable.svelte';
+import { readable } from 'svelte/store';
+import type { SgOrderWithSubgraphName } from '@rainlanguage/orderbook';
+import type { ComponentProps } from 'svelte';
+import userEvent from '@testing-library/user-event';
+import { useAccount } from '$lib/providers/wallet/useAccount';
+
+vi.mock('../lib/components/ListViewOrderbookFilters.svelte', async () => {
+	const MockComponent = (await import('../lib/__mocks__/MockComponent.svelte')).default;
+	return {
+		default: MockComponent
+	};
+});
+
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: vi.fn()
+}));
+
+const mockAccountStore = readable('0xabcdef1234567890abcdef1234567890abcdef12');
+
+const mockOrderWithSubgraph: SgOrderWithSubgraphName = {
+	order: {
+		id: '0x1234567890abcdef1234567890abcdef12345678',
+		orderHash: '0x4444444444444444444444444444444444444444',
+		owner: '0xabcdef1234567890abcdef1234567890abcdef12',
+		active: true,
+		orderbook: {
+			id: '0x2222222222222222222222222222222222222222'
+		},
+		timestampAdded: '1678901234',
+		inputs: [
+			{
+				token: {
+					symbol: 'ETH'
+				}
+			}
+		],
+		outputs: [
+			{
+				token: {
+					symbol: 'DAI'
+				}
+			}
+		],
+		trades: [
+			{
+				id: '0x5555555555555555555555555555555555555555'
+			},
+			{
+				id: '0x6666666666666666666666666666666666666666'
+			}
+		]
+	},
+	subgraphName: 'mock-subgraph-mainnet'
+} as SgOrderWithSubgraphName;
+
+vi.mock('@tanstack/svelte-query');
+
+// Hoisted mock stores
+const {
+	mockActiveNetworkRefStore,
+	mockActiveOrderbookRefStore,
+	mockHideZeroBalanceVaultsStore,
+	mockOrderHashStore,
+	mockAccountsStore,
+	mockActiveAccountsItemsStore,
+	mockActiveOrderStatusStore,
+	mockActiveSubgraphsStore,
+	mockSettingsStore,
+	mockShowMyItemsOnlyStore
+} = await vi.hoisted(() => import('../lib/__mocks__/stores'));
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type OrdersListTableProps = ComponentProps<OrdersListTable<any>>;
+
+const defaultProps: OrdersListTableProps = {
+	activeSubgraphs: mockActiveSubgraphsStore,
+	settings: mockSettingsStore,
+	accounts: mockAccountsStore,
+	activeAccountsItems: mockActiveAccountsItemsStore,
+	activeOrderStatus: mockActiveOrderStatusStore,
+	orderHash: mockOrderHashStore,
+	hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore,
+	showMyItemsOnly: mockShowMyItemsOnlyStore,
+	currentRoute: '/orders',
+	activeNetworkRef: mockActiveNetworkRefStore,
+	activeOrderbookRef: mockActiveOrderbookRefStore
+} as unknown as OrdersListTableProps;
+
+const mockMatchesAccount = vi.fn();
+
+describe('OrdersListTable', () => {
+	beforeEach(() => {
+		vi.clearAllMocks();
+		(useAccount as Mock).mockReturnValue({
+			account: mockAccountStore,
+			matchesAccount: mockMatchesAccount
+		});
+	});
+
+	it('displays order information correctly', async () => {
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[mockOrderWithSubgraph]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+		render(OrdersListTable, defaultProps as OrdersListTableProps);
+
+		expect(screen.getByTestId('orderListRowNetwork')).toHaveTextContent('mock-subgraph-mainnet');
+		expect(screen.getByTestId('orderListRowActive')).toHaveTextContent('Active');
+		expect(screen.getByTestId('orderListRowInputs')).toHaveTextContent('ETH');
+		expect(screen.getByTestId('orderListRowOutputs')).toHaveTextContent('DAI');
+		expect(screen.getByTestId('orderListRowTrades')).toHaveTextContent('2');
+	});
+
+	it('shows remove button when order is active and user is owner', async () => {
+		mockMatchesAccount.mockReturnValue(true);
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[mockOrderWithSubgraph]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true,
+					refetch: vi.fn()
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+
+		render(OrdersListTable, {
+			...defaultProps,
+			handleOrderRemoveModal: vi.fn()
+		} as OrdersListTableProps);
+
+		await waitFor(() => {
+			const menuButton = screen.getByTestId(`order-menu-${mockOrderWithSubgraph.order.id}`);
+			userEvent.click(menuButton);
+			expect(screen.getByText('Remove')).toBeInTheDocument();
+		});
+	});
+
+	it('handles remove action', async () => {
+		mockMatchesAccount.mockReturnValue(true);
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		const mockRefetch = vi.fn();
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[mockOrderWithSubgraph]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true,
+					refetch: mockRefetch
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+
+		const handleOrderRemoveModal = vi.fn();
+
+		render(OrdersListTable, {
+			...defaultProps,
+			handleOrderRemoveModal
+		} as OrdersListTableProps);
+
+		const menuButton = screen.getByTestId(`order-menu-${mockOrderWithSubgraph.order.id}`);
+		await userEvent.click(menuButton);
+
+		const removeButton = screen.getByText('Remove');
+		await userEvent.click(removeButton);
+
+		expect(handleOrderRemoveModal).toHaveBeenCalledWith(mockOrderWithSubgraph.order, mockRefetch);
+	});
+
+	it('shows inactive badge for inactive orders', async () => {
+		mockMatchesAccount.mockReturnValue(true);
+		const inactiveOrder = {
+			...mockOrderWithSubgraph,
+			order: {
+				...mockOrderWithSubgraph.order,
+				active: false
+			}
+		};
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[inactiveOrder]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+		render(OrdersListTable, defaultProps as OrdersListTableProps);
+
+		expect(screen.getByTestId('orderListRowActive')).toHaveTextContent('Inactive');
+	});
+
+	it('does not show action menu for inactive orders', async () => {
+		mockMatchesAccount.mockReturnValue(true);
+		const inactiveOrder = {
+			...mockOrderWithSubgraph,
+			order: {
+				...mockOrderWithSubgraph.order,
+				active: false
+			}
+		};
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[inactiveOrder]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+
+		const handleOrderRemoveModal = vi.fn();
+
+		render(OrdersListTable, {
+			...defaultProps,
+			handleOrderRemoveModal
+		} as OrdersListTableProps);
+
+		expect(
+			screen.queryByTestId(`order-menu-${mockOrderWithSubgraph.order.id}`)
+		).not.toBeInTheDocument();
+	});
+
+	it('displays empty state when no orders are found', async () => {
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+
+		render(OrdersListTable, defaultProps as OrdersListTableProps);
+		expect(screen.getByText('No Orders Found')).toBeInTheDocument();
+	});
+
+	it('navigates to order details on row click', async () => {
+		vi.mock('$app/navigation', () => ({
+			goto: vi.fn()
+		}));
+
+		const gotoMock = await import('$app/navigation');
+		mockMatchesAccount.mockReturnValue(true);
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[mockOrderWithSubgraph]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+
+		render(OrdersListTable, defaultProps as OrdersListTableProps);
+
+		// Simulate row click
+		const event = new CustomEvent('clickRow', {
+			detail: {
+				item: mockOrderWithSubgraph
+			}
+		});
+
+		// Find the AppTable component and dispatch the event
+		const appTable = document.querySelector('div[role="table"]');
+		if (appTable) {
+			appTable.dispatchEvent(event);
+			expect(gotoMock.goto).toHaveBeenCalledWith(
+				`/orders/${mockOrderWithSubgraph.subgraphName}-${mockOrderWithSubgraph.order.orderHash}`
+			);
+		}
+	});
+
+	it('handles large number of trades display', async () => {
+		mockMatchesAccount.mockReturnValue(true);
+
+		const orderWithManyTrades = {
+			...mockOrderWithSubgraph,
+			order: {
+				...mockOrderWithSubgraph.order,
+				trades: Array(100).fill({
+					id: '0x5555555555555555555555555555555555555555'
+				})
+			}
+		};
+
+		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
+		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
+			subscribe: (fn: (value: any) => void) => {
+				fn({
+					data: { pages: [[orderWithManyTrades]] },
+					status: 'success',
+					isFetching: false,
+					isFetched: true
+				});
+				return { unsubscribe: () => {} };
+			}
+		})) as Mock;
+
+		render(OrdersListTable, defaultProps as OrdersListTableProps);
+		expect(screen.getByTestId('orderListRowTrades')).toHaveTextContent('>99');
+	});
+});
diff --git a/packages/ui-components/src/__tests__/VaultDetail.test.ts b/packages/ui-components/src/__tests__/VaultDetail.test.ts
index 05b944151b..1abff96894 100644
--- a/packages/ui-components/src/__tests__/VaultDetail.test.ts
+++ b/packages/ui-components/src/__tests__/VaultDetail.test.ts
@@ -45,6 +45,8 @@ const defaultProps: VaultDetailProps = {
 	onWithdraw: vi.fn()
 };
 
+const mockMatchesAccount = vi.fn();
+
 describe('VaultDetail', () => {
 	let queryClient: QueryClient;
 	let mockData: SgVault;
@@ -53,8 +55,10 @@ describe('VaultDetail', () => {
 		vi.clearAllMocks();
 		queryClient = new QueryClient();
 
+		mockMatchesAccount.mockReturnValue(true);
+
 		(useAccount as Mock).mockReturnValue({
-			account: readable('0x1234567890123456789012345678901234567890')
+			matchesAccount: mockMatchesAccount
 		});
 
 		mockData = {
@@ -135,17 +139,8 @@ describe('VaultDetail', () => {
 		});
 	});
 
-	it('shows deposit/withdraw buttons when conditions are met', async () => {
-		mockData.ordersAsInput = [
-			{ id: '1', owner: '0x1234567890123456789012345678901234567890' }
-		] as unknown as SgOrderAsIO[];
-		mockData.ordersAsOutput = [
-			{ id: '2', owner: '0x1234567890123456789012345678901234567890' }
-		] as unknown as SgOrderAsIO[];
-
-		(useAccount as Mock).mockReturnValue({
-			account: readable('0x1234567890123456789012345678901234567890')
-		});
+	it('shows deposit/withdraw buttons when account matches are met', async () => {
+		mockMatchesAccount.mockReturnValue(true);
 
 		render(VaultDetail, {
 			props: defaultProps,
@@ -158,44 +153,8 @@ describe('VaultDetail', () => {
 		});
 	});
 
-	it("doesn't show deposit/withdraw buttons when account doesn't match owner", async () => {
-		(useAccount as Mock).mockReturnValue({
-			account: readable('0x456')
-		});
-
-		render(VaultDetail, {
-			props: defaultProps,
-			context: new Map([['$$_queryClient', queryClient]])
-		});
-
-		await waitFor(() => {
-			expect(screen.queryByTestId('depositOrWithdrawButton')).not.toBeInTheDocument();
-		});
-	});
-
-	it("doesn't show deposit/withdraw buttons when account isn't an address", async () => {
-		(useAccount as Mock).mockReturnValue({
-			account: readable('0x456')
-		});
-
-		render(VaultDetail, {
-			props: defaultProps,
-			context: new Map([['$$_queryClient', queryClient]])
-		});
-
-		await waitFor(() => {
-			expect(screen.queryByTestId('depositOrWithdrawButton')).not.toBeInTheDocument();
-		});
-	});
-
-	it("doesn't show deposit/withdraw buttons when vault owner isn't an address", async () => {
-		(useAccount as Mock).mockReturnValue({
-			account: readable('0x1234567890123456789012345678901234567890')
-		});
-		vi.mocked(getVault).mockResolvedValue({
-			...mockData,
-			owner: 'not an address'
-		} as unknown as SgVault);
+	it("doesn't show deposit/withdraw buttons when account doesn't match", async () => {
+		mockMatchesAccount.mockReturnValue(false);
 
 		render(VaultDetail, {
 			props: defaultProps,
diff --git a/packages/ui-components/src/__tests__/VaultsListTable.test.ts b/packages/ui-components/src/__tests__/VaultsListTable.test.ts
index f7aefe9ed8..3c7919428a 100644
--- a/packages/ui-components/src/__tests__/VaultsListTable.test.ts
+++ b/packages/ui-components/src/__tests__/VaultsListTable.test.ts
@@ -4,9 +4,20 @@ import { describe, it, expect, vi, type Mock } from 'vitest';
 import VaultsListTable from '../lib/components/tables/VaultsListTable.svelte';
 import { readable } from 'svelte/store';
 import type { SgVaultWithSubgraphName } from '@rainlanguage/orderbook';
-
 import type { ComponentProps } from 'svelte';
 import userEvent from '@testing-library/user-event';
+import { useAccount } from '$lib/providers/wallet/useAccount';
+
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: vi.fn()
+}));
+
+const mockMatchesAccount = vi.fn();
+const mockAccountStore = readable('0xabcdef1234567890abcdef1234567890abcdef12');
+
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: vi.fn()
+}));
 
 const mockVaultWithSubgraph: SgVaultWithSubgraphName = {
 	vault: {
@@ -65,7 +76,6 @@ const defaultProps = {
 	hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore,
 	activeNetworkRef: mockActiveNetworkRefStore,
 	activeOrderbookRef: mockActiveOrderbookRefStore,
-	walletAddressMatchesOrBlank: readable(() => true),
 	activeAccounts: mockActiveAccountsStore,
 	currentRoute: '/vaults'
 };
@@ -74,6 +84,13 @@ const defaultProps = {
 type VaultsListTableProps = ComponentProps<VaultsListTable<any>>;
 
 describe('VaultsListTable', () => {
+	beforeEach(() => {
+		vi.clearAllMocks();
+		(useAccount as Mock).mockReturnValue({
+			matchesAccount: mockMatchesAccount,
+			account: mockAccountStore
+		});
+	});
 	it('displays vault information correctly', async () => {
 		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
 		// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -95,8 +112,10 @@ describe('VaultsListTable', () => {
 	});
 
 	it('shows deposit/withdraw buttons when handlers are provided', async () => {
+		mockMatchesAccount.mockReturnValue(true);
 		const handleDepositModal = vi.fn();
 		const handleWithdrawModal = vi.fn();
+
 		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
 		// eslint-disable-next-line @typescript-eslint/no-unused-vars
 		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
@@ -116,9 +135,9 @@ describe('VaultsListTable', () => {
 			handleWithdrawModal
 		} as unknown as VaultsListTableProps);
 
-		const menuButton = screen.getByTestId('vault-menu');
-		await userEvent.click(menuButton);
 		await waitFor(() => {
+			const menuButton = screen.getByTestId('vault-menu');
+			userEvent.click(menuButton);
 			expect(screen.getByTestId('deposit-button')).toBeInTheDocument();
 			expect(screen.getByTestId('withdraw-button')).toBeInTheDocument();
 		});
@@ -149,6 +168,7 @@ describe('VaultsListTable', () => {
 	});
 
 	it('handles deposit action', async () => {
+		mockMatchesAccount.mockReturnValue(true);
 		const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
 		// eslint-disable-next-line @typescript-eslint/no-unused-vars
 		mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
@@ -181,9 +201,9 @@ describe('VaultsListTable', () => {
 	});
 
 	it('hides action buttons when user is not the vault owner', () => {
+		mockMatchesAccount.mockReturnValue(false);
 		render(VaultsListTable, {
-			...defaultProps,
-			walletAddressMatchesOrBlank: readable(() => false)
+			...defaultProps
 		} as unknown as VaultsListTableProps);
 
 		expect(screen.queryByTestId('vault-menu')).not.toBeInTheDocument();
diff --git a/packages/ui-components/src/__tests__/WalletConnect.test.ts b/packages/ui-components/src/__tests__/WalletConnect.test.ts
index bf4d3d8807..e2dcba1d04 100644
--- a/packages/ui-components/src/__tests__/WalletConnect.test.ts
+++ b/packages/ui-components/src/__tests__/WalletConnect.test.ts
@@ -29,7 +29,8 @@ describe('WalletConnect component', () => {
 
 	it('displays "Connect" with red icon when wallet is not connected or wrong network', () => {
 		vi.mocked(useAccount).mockReturnValue({
-			account: writable(null)
+			account: writable(null),
+			matchesAccount: vi.fn()
 		});
 		mockConnectedStore.mockSetSubscribeValue(false);
 
@@ -41,7 +42,8 @@ describe('WalletConnect component', () => {
 
 	it('displays truncated address when wallet is connected', () => {
 		vi.mocked(useAccount).mockReturnValue({
-			account: writable('0x123')
+			account: writable('0x123'),
+			matchesAccount: vi.fn()
 		});
 		mockConnectedStore.mockSetSubscribeValue(true);
 
diff --git a/packages/ui-components/src/lib/__mocks__/stores.ts b/packages/ui-components/src/lib/__mocks__/stores.ts
index c40ca5ffa0..55e6dd6e67 100644
--- a/packages/ui-components/src/lib/__mocks__/stores.ts
+++ b/packages/ui-components/src/lib/__mocks__/stores.ts
@@ -17,20 +17,12 @@ const mockActiveNetworkRefWritable = writable<string>('');
 const mockActiveOrderbookRefWritable = writable<string>('');
 const mockActiveAccountsWritable = writable<Record<string, string>>({});
 const mockSubgraphUrlWritable = writable<string>('');
-const mockWalletAddressMatchesOrBlankWritable = writable<() => boolean>(() => false);
 const mockChainIdWritable = writable<number>(0);
 const mockConnectedWritable = writable<boolean>(true);
 const mockWagmiConfigWritable = writable<Config>(mockWeb3Config);
 const mockShowMyItemsOnlyWritable = writable<boolean>(false);
 const mockPageWritable = writable<Page>();
 
-export const mockWalletAddressMatchesOrBlankStore = {
-	subscribe: mockWalletAddressMatchesOrBlankWritable.subscribe,
-	set: mockWalletAddressMatchesOrBlankWritable.set,
-	mockSetSubscribeValue: (value: () => boolean): void =>
-		mockWalletAddressMatchesOrBlankWritable.set(value)
-};
-
 export const mockSettingsStore = {
 	subscribe: mockSettingsWritable.subscribe,
 	set: mockSettingsWritable.set,
diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte
index b730d26068..21f38341af 100644
--- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte
+++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte
@@ -11,11 +11,6 @@
 	import OrderVaultsVolTable from '../tables/OrderVaultsVolTable.svelte';
 	import { QKEY_ORDER } from '../../queries/keys';
 	import CodeMirrorRainlang from '../CodeMirrorRainlang.svelte';
-	import {
-		getOrderByHash,
-		type OrderWithSortedVaults,
-		type SgOrder
-	} from '@rainlanguage/orderbook';
 	import { createQuery, useQueryClient } from '@tanstack/svelte-query';
 	import { Button, TabItem, Tabs, Tooltip } from 'flowbite-svelte';
 	import { onDestroy } from 'svelte';
@@ -27,8 +22,12 @@
 	import { invalidateIdQuery } from '$lib/queries/queryClient';
 	import { ArrowDownOutline, ArrowUpOutline, InfoCircleOutline } from 'flowbite-svelte-icons';
 	import { useAccount } from '$lib/providers/wallet/useAccount';
-	import { isAddressEqual, isAddress } from 'viem';
-	import type { SgVault } from '@rainlanguage/orderbook';
+	import {
+		getOrderByHash,
+		type OrderWithSortedVaults,
+		type SgOrder,
+		type SgVault
+	} from '@rainlanguage/orderbook';
 
 	export let handleQuoteDebugModal: QuoteDebugModalHandler | undefined = undefined;
 	export const handleDebugTradeModal: DebugTradeModalHandler | undefined = undefined;
@@ -39,7 +38,6 @@
 	export let orderHash: string;
 	export let rpcUrl: string;
 	export let subgraphUrl: string;
-	export let chainId: number | undefined;
 
 	/** Callback function when remove action is triggered for an order
 	 * @param order The order to remove
@@ -60,7 +58,7 @@
 	let codeMirrorStyles = {};
 
 	const queryClient = useQueryClient();
-	const { account } = useAccount();
+	const { matchesAccount } = useAccount();
 
 	$: orderDetailQuery = createQuery<OrderWithSortedVaults>({
 		queryKey: [orderHash, QKEY_ORDER + orderHash],
@@ -95,7 +93,7 @@
 			</div>
 
 			<div class="flex items-center gap-2">
-				{#if $account && isAddress($account) && isAddress(data.order.owner) && isAddressEqual($account, data.order.owner)}
+				{#if matchesAccount(data.order.owner)}
 					{#if data.order.active}
 						<Button
 							on:click={() => onRemove(data.order)}
@@ -153,7 +151,7 @@
 								{#each data.vaults.get(type) || [] as vault}
 									<ButtonVaultLink tokenVault={vault} {subgraphName}>
 										<svelte:fragment slot="buttons">
-											{#if $account && isAddress($account) && isAddress(vault.owner) && isAddressEqual($account, vault.owner) && chainId}
+											{#if matchesAccount(vault.owner)}
 												<div class="flex gap-1">
 													<Button
 														color="light"
diff --git a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte
index 5b65498c9f..fbc8d77548 100644
--- a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte
+++ b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte
@@ -8,7 +8,7 @@
 	import { QKEY_VAULT } from '../../queries/keys';
 	import { getVault, type SgVault } from '@rainlanguage/orderbook';
 	import type { ChartTheme } from '../../utils/lightweightChartsThemes';
-	import { formatUnits, isAddress, isAddressEqual } from 'viem';
+	import { formatUnits } from 'viem';
 	import { createQuery } from '@tanstack/svelte-query';
 	import { onDestroy } from 'svelte';
 	import type { Readable } from 'svelte/store';
@@ -42,7 +42,7 @@
 
 	const subgraphUrl = $settings?.subgraphs?.[network] || '';
 	const queryClient = useQueryClient();
-	const { account } = useAccount();
+	const { matchesAccount } = useAccount();
 
 	$: vaultDetailQuery = createQuery<SgVault>({
 		queryKey: [id, QKEY_VAULT + id],
@@ -81,7 +81,7 @@
 			{data.token.name}
 		</div>
 		<div class="flex items-center gap-2">
-			{#if $account && isAddress($account) && isAddress(data.owner) && isAddressEqual($account, data.owner)}
+			{#if matchesAccount(data.owner)}
 				<Button
 					color="light"
 					size="xs"
diff --git a/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte b/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte
index 2fdc6b7a31..fe5767de87 100644
--- a/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte
+++ b/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte
@@ -1,9 +1,12 @@
 <script lang="ts" generics="T">
 	import { goto } from '$app/navigation';
 	import { DotsVerticalOutline } from 'flowbite-svelte-icons';
-	import { type SgOrderWithSubgraphName } from '@rainlanguage/orderbook';
 	import { createInfiniteQuery } from '@tanstack/svelte-query';
-	import { getOrders, type MultiSubgraphArgs } from '@rainlanguage/orderbook';
+	import {
+		getOrders,
+		type MultiSubgraphArgs,
+		type SgOrderWithSubgraphName
+	} from '@rainlanguage/orderbook';
 	import TanstackAppTable from '../TanstackAppTable.svelte';
 	import { formatTimestampSecondsAsLocal } from '../../utils/time';
 	import ListViewOrderbookFilters from '../ListViewOrderbookFilters.svelte';
@@ -21,11 +24,8 @@
 	} from 'flowbite-svelte';
 	import { useAccount } from '$lib/providers/wallet/useAccount';
 
-	// Optional props only used in tauri-app
-	// eslint-disable-next-line @typescript-eslint/no-explicit-any
-	export const walletAddressMatchesOrBlank: any = undefined;
 	// eslint-disable-next-line @typescript-eslint/no-explicit-any
-	export const handleOrderRemoveModal: any = undefined;
+	export let handleOrderRemoveModal: any = undefined;
 	// End of optional props
 
 	export let activeSubgraphs: AppStoresInterface['activeSubgraphs'];
@@ -40,7 +40,7 @@
 	export let activeNetworkRef: AppStoresInterface['activeNetworkRef'];
 	export let activeOrderbookRef: AppStoresInterface['activeOrderbookRef'];
 
-	const { account } = useAccount();
+	const { matchesAccount, account } = useAccount();
 
 	$: multiSubgraphArgs = Object.entries(
 		Object.keys($activeSubgraphs ?? {}).length ? $activeSubgraphs : ($settings?.subgraphs ?? {})
@@ -168,10 +168,10 @@
 		<TableBodyCell data-testid="orderListRowTrades" tdClass="break-word p-2"
 			>{item.order.trades.length > 99 ? '>99' : item.order.trades.length}</TableBodyCell
 		>
-		{#if walletAddressMatchesOrBlank && handleOrderRemoveModal}
+		{#if matchesAccount(item.order.owner) && handleOrderRemoveModal}
 			<div data-testid="wallet-actions">
 				<TableBodyCell tdClass="px-0 text-right">
-					{#if $walletAddressMatchesOrBlank(item.order.owner) && item.order.active}
+					{#if item.order.active}
 						<Button
 							color="alternative"
 							outline={false}
@@ -186,7 +186,7 @@
 						</Button>
 					{/if}
 				</TableBodyCell>
-				{#if $walletAddressMatchesOrBlank(item.order.owner) && item.order.active}
+				{#if item.order.active}
 					<Dropdown placement="bottom-end" triggeredBy={`#order-menu-${item.order.id}`}>
 						<DropdownItem
 							on:click={(e) => {
diff --git a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte
index 4562511b27..95ef8917c3 100644
--- a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte
+++ b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte
@@ -36,7 +36,6 @@
 	export let activeAccounts: Readable<{
 		[k: string]: string;
 	}>;
-	export let walletAddressMatchesOrBlank: Readable<(otherAddress: string) => boolean>;
 	export let handleDepositGenericModal: (() => void) | undefined = undefined;
 	export let handleDepositModal: ((vault: SgVault, refetch: () => void) => void) | undefined =
 		undefined;
@@ -45,7 +44,7 @@
 	export let currentRoute: string;
 	export let showMyItemsOnly: AppStoresInterface['showMyItemsOnly'];
 
-	const { account } = useAccount();
+	const { account, matchesAccount } = useAccount();
 
 	$: multiSubgraphArgs = Object.entries(
 		Object.keys($activeSubgraphs ?? {}).length ? $activeSubgraphs : ($settings?.subgraphs ?? {})
@@ -202,47 +201,44 @@
 					</div>
 				{/if}
 			</TableBodyCell>
-			{#if handleDepositModal && handleWithdrawModal && $walletAddressMatchesOrBlank(item.vault.owner)}
+			{#if handleDepositModal && handleWithdrawModal && matchesAccount(item.vault.owner)}
 				<TableBodyCell tdClass="px-0 text-right">
-					{#if $walletAddressMatchesOrBlank(item.vault.owner)}
-						<Button
-							color="alternative"
-							outline={false}
-							data-testid="vault-menu"
-							id={`vault-menu-${item.vault.id}`}
-							class="mr-2 border-none px-2"
-							on:click={(e) => {
-								e.stopPropagation();
-							}}
-						>
-							<DotsVerticalOutline class="dark:text-white" />
-						</Button>
-					{/if}
-				</TableBodyCell>
-				{#if $walletAddressMatchesOrBlank(item.vault.owner)}
-					<Dropdown
-						data-testid="dropdown"
-						placement="bottom-end"
-						triggeredBy={`#vault-menu-${item.vault.id}`}
+					<Button
+						color="alternative"
+						outline={false}
+						data-testid="vault-menu"
+						id={`vault-menu-${item.vault.id}`}
+						class="mr-2 border-none px-2"
+						on:click={(e) => {
+							e.stopPropagation();
+						}}
 					>
-						<DropdownItem
-							data-testid="deposit-button"
-							on:click={(e) => {
-								e.stopPropagation();
-								handleDepositModal(item.vault, $query.refetch);
-							}}
-							>Deposit
-						</DropdownItem>
-						<DropdownItem
-							data-testid="withdraw-button"
-							on:click={(e) => {
-								e.stopPropagation();
-								handleWithdrawModal(item.vault, $query.refetch);
-							}}
-							>Withdraw
-						</DropdownItem>
-					</Dropdown>
-				{/if}
+						<DotsVerticalOutline class="dark:text-white" />
+					</Button>
+				</TableBodyCell>
+
+				<Dropdown
+					data-testid="dropdown"
+					placement="bottom-end"
+					triggeredBy={`#vault-menu-${item.vault.id}`}
+				>
+					<DropdownItem
+						data-testid="deposit-button"
+						on:click={(e) => {
+							e.stopPropagation();
+							handleDepositModal(item.vault, $query.refetch);
+						}}
+						>Deposit
+					</DropdownItem>
+					<DropdownItem
+						data-testid="withdraw-button"
+						on:click={(e) => {
+							e.stopPropagation();
+							handleWithdrawModal(item.vault, $query.refetch);
+						}}
+						>Withdraw
+					</DropdownItem>
+				</Dropdown>
 			{/if}
 		</svelte:fragment>
 	</AppTable>
diff --git a/packages/ui-components/src/lib/providers/wallet/useAccount.ts b/packages/ui-components/src/lib/providers/wallet/useAccount.ts
index acce3ce2ce..ec0513c251 100644
--- a/packages/ui-components/src/lib/providers/wallet/useAccount.ts
+++ b/packages/ui-components/src/lib/providers/wallet/useAccount.ts
@@ -1,4 +1,6 @@
 import type { Hex } from 'viem';
+import { get } from 'svelte/store';
+import { isAddress, isAddressEqual } from 'viem';
 import { getAccountContext } from './context';
 import { readable } from 'svelte/store';
 
@@ -7,35 +9,172 @@ import { readable } from 'svelte/store';
  * Must be used within a component that is a child of WalletProvider
  */
 export function useAccount() {
+	/**
+	 * The account store containing the current wallet address (as a Hex string) or null if not connected.
+	 * This is a readable Svelte store that can be subscribed to for reactive updates.
+	 * @type {import('svelte/store').Readable<Hex | null>}
+	 */
 	const account = getAccountContext();
+
+	/**
+	 * Checks if the provided address matches the currently connected account.
+	 * Returns false if no account is connected or if the provided address is invalid.
+	 */
+	const matchesAccount = (otherAddress: string): boolean => {
+		if (!otherAddress) return false;
+		const currentAccount = get(account);
+		if (!currentAccount) {
+			return false;
+		}
+
+		if (
+			isAddress(currentAccount) &&
+			isAddress(otherAddress) &&
+			isAddressEqual(currentAccount, otherAddress)
+		) {
+			return true;
+		}
+
+		return false;
+	};
+
 	return {
-		account
+		account,
+		matchesAccount
 	};
 }
 
 if (import.meta.vitest) {
 	const { describe, it, expect, vi, beforeEach } = import.meta.vitest;
 
+	vi.mock('viem', async () => {
+		const actual = await vi.importActual('viem');
+		return {
+			...actual,
+			isAddress: vi.fn(),
+			isAddressEqual: vi.fn()
+		};
+	});
+
 	vi.mock('./context', () => ({
 		getAccountContext: vi.fn()
 	}));
 
+	vi.mock('svelte/store', async () => {
+		const actual = await vi.importActual('svelte/store');
+		return {
+			...actual,
+			get: vi.fn()
+		};
+	});
+
 	describe('useAccount', () => {
 		const mockGetAccountContext = vi.mocked(getAccountContext);
+		const mockGet = vi.mocked(get);
+		const mockIsAddress = vi.mocked(isAddress);
+		const mockIsAddressEqual = vi.mocked(isAddressEqual);
 
 		beforeEach(() => {
-			mockGetAccountContext.mockReset();
+			vi.clearAllMocks();
 		});
 
 		it('should return account wrapped in an object', () => {
-			const mockAccount = readable('0x123' as unknown as Hex);
-			mockGetAccountContext.mockReturnValue(mockAccount);
+			const mockAccountStore = readable('0x123' as Hex);
+			mockGetAccountContext.mockReturnValue(mockAccountStore);
 
 			const result = useAccount();
 
 			expect(mockGetAccountContext).toHaveBeenCalled();
-			expect(result).toEqual({
-				account: mockAccount
+			expect(result.account).toBe(mockAccountStore);
+			expect(result.matchesAccount).toBeInstanceOf(Function);
+		});
+
+		describe('matchesAccount', () => {
+			const mockAccountStore = readable('0x123' as Hex);
+			const currentAccount = '0x123' as Hex;
+			const testAddress1 = '0x123' as Hex;
+			const testAddress2 = '0xdef' as Hex;
+			const invalidAddress = 'invalid';
+
+			beforeEach(() => {
+				mockGetAccountContext.mockReturnValue(mockAccountStore);
+			});
+
+			it('should return true if addresses are valid and equal', () => {
+				// Setup mocks
+				mockGet.mockReturnValue(currentAccount);
+				mockIsAddress.mockReturnValue(true);
+				mockIsAddressEqual.mockReturnValue(true);
+
+				const { matchesAccount } = useAccount();
+				const result = matchesAccount(testAddress1);
+
+				expect(mockGet).toHaveBeenCalledWith(mockAccountStore);
+				expect(mockIsAddress).toHaveBeenCalledWith(currentAccount);
+				expect(mockIsAddress).toHaveBeenCalledWith(testAddress1);
+				expect(mockIsAddressEqual).toHaveBeenCalledWith(currentAccount, testAddress1);
+				expect(result).toBe(true);
+			});
+
+			it('should return false if addresses are valid but not equal', () => {
+				// Setup mocks
+				mockGet.mockReturnValue(currentAccount);
+				mockIsAddress.mockReturnValue(true);
+				mockIsAddressEqual.mockReturnValue(false);
+
+				const { matchesAccount } = useAccount();
+				const result = matchesAccount(testAddress2);
+
+				expect(mockGet).toHaveBeenCalledWith(mockAccountStore);
+				expect(mockIsAddress).toHaveBeenCalledWith(currentAccount);
+				expect(mockIsAddress).toHaveBeenCalledWith(testAddress2);
+				expect(mockIsAddressEqual).toHaveBeenCalledWith(currentAccount, testAddress2);
+				expect(result).toBe(false);
+			});
+
+			it('should return false if current account is not set', () => {
+				// Setup mocks
+				mockGet.mockReturnValue(null);
+
+				const { matchesAccount } = useAccount();
+				const result = matchesAccount(testAddress1);
+
+				expect(mockGet).toHaveBeenCalledWith(mockAccountStore);
+				expect(mockIsAddress).not.toHaveBeenCalled();
+				expect(mockIsAddressEqual).not.toHaveBeenCalled();
+				expect(result).toBe(false);
+			});
+			it('should return false if provided address is invalid', () => {
+				// Setup mocks
+				mockGet.mockReturnValue(currentAccount);
+
+				// This is crucial: we need to ensure short-circuit evaluation works correctly
+				mockIsAddress.mockImplementation((address) => {
+					return address !== invalidAddress; // Only the invalid address returns false
+				});
+
+				// This should never be called due to short-circuit evaluation
+				mockIsAddressEqual.mockReturnValue(false);
+
+				const { matchesAccount } = useAccount();
+				const result = matchesAccount(invalidAddress);
+
+				expect(mockGet).toHaveBeenCalledWith(mockAccountStore);
+				expect(mockIsAddress).toHaveBeenCalledWith(currentAccount);
+				expect(mockIsAddress).toHaveBeenCalledWith(invalidAddress);
+				expect(mockIsAddressEqual).not.toHaveBeenCalled(); // This should now pass
+				expect(result).toBe(false);
+			});
+			it('should return false if provided address is null', () => {
+				// Setup mocks
+				mockGet.mockReturnValue(currentAccount);
+
+				const { matchesAccount } = useAccount();
+				const result = matchesAccount(null as unknown as string);
+
+				expect(mockIsAddress).not.toHaveBeenCalled();
+				expect(mockIsAddressEqual).not.toHaveBeenCalled();
+				expect(result).toBe(false);
 			});
 		});
 	});
diff --git a/packages/webapp/src/__tests__/DeployModal.test.ts b/packages/webapp/src/__tests__/DeployModal.test.ts
index 2ce7d5f70a..0643d03d4e 100644
--- a/packages/webapp/src/__tests__/DeployModal.test.ts
+++ b/packages/webapp/src/__tests__/DeployModal.test.ts
@@ -1,11 +1,11 @@
 import { describe, it, expect, vi } from 'vitest';
 import { render } from '@testing-library/svelte';
 import DeployModal from '../lib/components/DeployModal.svelte';
-import { get } from 'svelte/store';
 import type { DeployModalProps } from '@rainlanguage/ui-components';
+import { mockWeb3Config } from '$lib/__mocks__/mockWeb3Config';
 
 const { mockTransactionStore } = await vi.hoisted(() => import('@rainlanguage/ui-components'));
-const { mockWagmiConfigStore } = await vi.hoisted(() => import('$lib/__mocks__/stores'));
+const { mockWagmiConfigStore } = await vi.hoisted(() => import('../lib/__mocks__/stores'));
 vi.mock('@rainlanguage/ui-components', async (importOriginal) => {
 	return {
 		...(await importOriginal()),
@@ -37,7 +37,6 @@ describe('DeployModal', () => {
 	} as unknown as DeployModalProps;
 
 	it('renders and initiates transaction handling', () => {
-		const config = get(mockWagmiConfigStore);
 		const handleDeploymentTransactionSpy = vi.spyOn(
 			mockTransactionStore,
 			'handleDeploymentTransaction'
@@ -45,9 +44,11 @@ describe('DeployModal', () => {
 
 		render(DeployModal, { props: mockProps });
 
-		expect(handleDeploymentTransactionSpy).toHaveBeenCalledWith({
-			config,
-			...mockProps.args
-		});
+		expect(handleDeploymentTransactionSpy).toHaveBeenCalledWith(
+			expect.objectContaining({
+				config: mockWeb3Config,
+				...mockProps.args
+			})
+		);
 	});
 });
diff --git a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts
index 87b83cbe47..d8ee458e1d 100644
--- a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts
+++ b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts
@@ -6,7 +6,8 @@ import { readContract, switchChain } from '@wagmi/core';
 import type { ComponentProps } from 'svelte';
 import { getVaultApprovalCalldata, type SgVault } from '@rainlanguage/orderbook';
 import { getVaultDepositCalldata } from '@rainlanguage/orderbook';
-import { get, readable } from 'svelte/store';
+import { readable } from 'svelte/store';
+import { mockWeb3Config } from '$lib/__mocks__/mockWeb3Config';
 
 type ModalProps = ComponentProps<DepositOrWithdrawModal>;
 
@@ -65,7 +66,8 @@ describe('DepositOrWithdrawModal', () => {
 		vi.clearAllMocks();
 		transactionStore.reset();
 		vi.mocked(useAccount).mockReturnValue({
-			account: readable('0x')
+			account: readable('0x'),
+			matchesAccount: vi.fn()
 		});
 		(readContract as Mock).mockReset();
 		(switchChain as Mock).mockReset();
@@ -99,13 +101,11 @@ describe('DepositOrWithdrawModal', () => {
 		const depositButton = screen.getByText('Deposit');
 		await fireEvent.click(depositButton);
 
-		const wagmiConfig = get(mockWagmiConfigStore);
-
 		expect(handleTransactionSpy).toHaveBeenCalledWith({
 			action: 'deposit',
 			chainId: 1,
 			vault: mockVault,
-			config: wagmiConfig,
+			config: mockWeb3Config,
 			subgraphUrl: undefined,
 			approvalCalldata: { to: '0x789', data: '0xabc' },
 			transactionCalldata: { to: '0x123', data: '0x456' }
@@ -127,10 +127,9 @@ describe('DepositOrWithdrawModal', () => {
 
 		const withdrawButton = screen.getByText('Withdraw');
 		await fireEvent.click(withdrawButton);
-		const wagmiConfig = get(mockWagmiConfigStore);
 
 		expect(handleTransactionSpy).toHaveBeenCalledWith({
-			config: wagmiConfig,
+			config: mockWeb3Config,
 			transactionCalldata: { to: '0xdef', data: '0xghi' },
 			action: 'withdraw',
 			chainId: 1,
@@ -239,12 +238,12 @@ describe('DepositOrWithdrawModal', () => {
 
 		const depositButton = screen.getByText('Deposit');
 		await fireEvent.click(depositButton);
-		const wagmiConfig = get(mockWagmiConfigStore);
+
 		expect(handleTransactionSpy).toHaveBeenCalledWith({
 			action: 'deposit',
 			chainId: 1,
 			vault: mockVault,
-			config: wagmiConfig,
+			config: mockWeb3Config,
 			subgraphUrl: undefined,
 			approvalCalldata: undefined,
 			transactionCalldata: { to: '0x123', data: '0x456' }
diff --git a/packages/webapp/src/routes/orders/[network]-[orderHash]/+page.svelte b/packages/webapp/src/routes/orders/[network]-[orderHash]/+page.svelte
index bb3b11fa3c..575082c54a 100644
--- a/packages/webapp/src/routes/orders/[network]-[orderHash]/+page.svelte
+++ b/packages/webapp/src/routes/orders/[network]-[orderHash]/+page.svelte
@@ -109,7 +109,6 @@
 	{lightweightChartsTheme}
 	{colorTheme}
 	{orderbookAddress}
-	{chainId}
 	{onRemove}
 	{onDeposit}
 	{onWithdraw}
diff --git a/packages/webapp/src/routes/vaults/+page.svelte b/packages/webapp/src/routes/vaults/+page.svelte
index c278ef3417..e61823d8ba 100644
--- a/packages/webapp/src/routes/vaults/+page.svelte
+++ b/packages/webapp/src/routes/vaults/+page.svelte
@@ -18,7 +18,6 @@
 		activeNetworkRef,
 		activeOrderbookRef,
 		activeAccounts,
-		walletAddressMatchesOrBlank,
 		activeNetworkOrderbooks,
 		showMyItemsOnly = writable(false)
 	} = $page.data.stores;
@@ -49,6 +48,7 @@
 			resetActiveOrderbookRef();
 		}
 	});
+
 	$: showMyItemsOnly.set($connected);
 </script>
 
@@ -68,6 +68,5 @@
 	{activeNetworkRef}
 	{activeOrderbookRef}
 	{activeAccounts}
-	{walletAddressMatchesOrBlank}
 	currentRoute={$page.url.pathname}
 />
diff --git a/tauri-app/src/lib/mocks/wallets.ts b/tauri-app/src/lib/mocks/wallets.ts
deleted file mode 100644
index 32b754ae8b..0000000000
--- a/tauri-app/src/lib/mocks/wallets.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { writable } from 'svelte/store';
-
-const mockWalletAddressMatchesOrBlankWritable = writable<() => boolean>(() => false);
-
-export const mockWalletAddressMatchesOrBlankStore = {
-  subscribe: mockWalletAddressMatchesOrBlankWritable.subscribe,
-  set: mockWalletAddressMatchesOrBlankWritable.set,
-  mockSetSubscribeValue: (value: () => boolean): void =>
-    mockWalletAddressMatchesOrBlankWritable.set(value),
-};
diff --git a/tauri-app/src/lib/stores/settings.test.ts b/tauri-app/src/lib/stores/settings.test.ts
index e8f6ce4373..7181176c9a 100644
--- a/tauri-app/src/lib/stores/settings.test.ts
+++ b/tauri-app/src/lib/stores/settings.test.ts
@@ -1,29 +1,91 @@
 import { expect, test, beforeEach, describe } from 'vitest';
 import { settings, activeAccountsItems, activeSubgraphs } from './settings';
-import { mockConfigSource } from '@rainlanguage/ui-components';
 import { get } from 'svelte/store';
 
-describe('Settings active accounts items', async () => {
+// Import the ConfigSource type
+import type { ConfigSource } from '@rainlanguage/orderbook';
+
+// Define the mock directly in the tests
+const mockConfigSource: ConfigSource = {
+  networks: {
+    mainnet: {
+      rpc: 'https://mainnet.infura.io/v3/YOUR-PROJECT-ID',
+      'chain-id': 1,
+      label: 'Ethereum Mainnet',
+      currency: 'ETH',
+    },
+  },
+  subgraphs: {
+    mainnet: 'https://api.thegraph.com/subgraphs/name/mainnet',
+  },
+  orderbooks: {
+    orderbook1: {
+      address: '0xOrderbookAddress1',
+      network: 'mainnet',
+      subgraph: 'uniswap',
+      label: 'Orderbook 1',
+    },
+  },
+  deployers: {
+    deployer1: {
+      address: '0xDeployerAddress1',
+      network: 'mainnet',
+      label: 'Deployer 1',
+    },
+  },
+  metaboards: {
+    metaboard1: 'https://example.com/metaboard1',
+  },
+  accounts: {
+    name_one: 'address_one',
+    name_two: 'address_two',
+  },
+};
+
+describe('Settings active accounts items', () => {
+  // Reset store values before each test to prevent state leakage
   beforeEach(() => {
+    // Reset all store values
+    settings.set(undefined);
+    activeAccountsItems.set({});
+    activeSubgraphs.set({});
+
+    // Then set our initial test values
+    settings.set(mockConfigSource);
+    activeAccountsItems.set({
+      name_one: 'address_one',
+      name_two: 'address_two',
+    });
     activeSubgraphs.set({
-      mainnet: 'mainnet',
+      mainnet: 'https://api.thegraph.com/subgraphs/name/mainnet',
+    });
+
+    // Verify initial state
+    expect(get(settings)).toEqual(mockConfigSource);
+    expect(get(activeAccountsItems)).toEqual({
+      name_one: 'address_one',
+      name_two: 'address_two',
+    });
+    expect(get(activeSubgraphs)).toEqual({
+      mainnet: 'https://api.thegraph.com/subgraphs/name/mainnet',
     });
-    activeAccountsItems.set(mockConfigSource.accounts as Record<string, string>);
-    expect(get(activeAccountsItems)).toEqual(mockConfigSource.accounts);
   });
 
   test('should remove account if that account is removed', () => {
+    // Test removing an account
     const newSettings = {
       ...mockConfigSource,
       accounts: {
-        name_one: mockConfigSource.accounts?.name_one as string,
+        name_one: 'address_one',
       },
     };
 
+    // Update settings - this should trigger the subscription
     settings.set(newSettings);
 
+    // Check the expected result
     expect(get(activeAccountsItems)).toEqual({
-      name_one: mockConfigSource.accounts?.name_one as string,
+      name_one: 'address_one',
     });
   });
 
@@ -31,7 +93,7 @@ describe('Settings active accounts items', async () => {
     const newSettings = {
       ...mockConfigSource,
       accounts: {
-        name_one: mockConfigSource.accounts?.name_one as string,
+        name_one: 'address_one',
         name_two: 'new_value',
       },
     };
@@ -39,11 +101,11 @@ describe('Settings active accounts items', async () => {
     settings.set(newSettings);
 
     expect(get(activeAccountsItems)).toEqual({
-      name_one: mockConfigSource.accounts?.name_one as string,
+      name_one: 'address_one',
     });
   });
 
-  test('should update active subgraphs when subgraph value change', () => {
+  test('should update active subgraphs when subgraph value changes', () => {
     const newSettings = {
       ...mockConfigSource,
       subgraphs: {
@@ -70,10 +132,13 @@ describe('Settings active accounts items', async () => {
   });
 
   test('should reset active subgraphs when subgraphs are undefined', () => {
-    settings.set({
+    const newSettings = {
       ...mockConfigSource,
       subgraphs: undefined,
-    });
+    };
+
+    settings.set(newSettings);
+
     expect(get(activeSubgraphs)).toEqual({});
   });
 });
diff --git a/tauri-app/src/lib/stores/wallets.ts b/tauri-app/src/lib/stores/wallets.ts
index d072e2a554..0fbd7c14f1 100644
--- a/tauri-app/src/lib/stores/wallets.ts
+++ b/tauri-app/src/lib/stores/wallets.ts
@@ -1,20 +1,5 @@
-import { derived } from 'svelte/store';
-import { walletconnectAccount } from '$lib/stores/walletconnect';
 import { writable } from '@square/svelte-store';
 import type { Hex } from 'viem';
 
 export const ledgerWalletAddress = writable<Hex | null>(null);
 export const ledgerWalletDerivationIndex = writable<number>(0);
-
-export const walletAddressMatchesOrBlank = derived(
-  [ledgerWalletAddress, walletconnectAccount],
-  ([$ledgerWalletAddress, $walletconnectAccount]) => {
-    return (otherAddress: string) => {
-      const otherAddressLowercase = otherAddress.toLowerCase();
-      return (
-        $ledgerWalletAddress?.toLowerCase() === otherAddressLowercase ||
-        $walletconnectAccount?.toLowerCase() === otherAddressLowercase
-      );
-    };
-  },
-);
diff --git a/tauri-app/src/routes/orders/+page.svelte b/tauri-app/src/routes/orders/+page.svelte
index 9d74a40232..7b448e7b1c 100644
--- a/tauri-app/src/routes/orders/+page.svelte
+++ b/tauri-app/src/routes/orders/+page.svelte
@@ -2,7 +2,6 @@
   import { PageHeader } from '@rainlanguage/ui-components';
   import { onMount } from 'svelte';
   import { OrdersListTable } from '@rainlanguage/ui-components';
-  import { walletAddressMatchesOrBlank } from '$lib/stores/wallets';
   import { handleOrderRemoveModal } from '$lib/services/modal';
 
   import {
@@ -37,7 +36,6 @@
 <OrdersListTable
   {activeNetworkRef}
   {activeOrderbookRef}
-  {walletAddressMatchesOrBlank}
   {handleOrderRemoveModal}
   {activeSubgraphs}
   {settings}
diff --git a/tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte b/tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte
index 53f7263552..c1b154595c 100644
--- a/tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte
+++ b/tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte
@@ -21,7 +21,6 @@
   const orderbookAddress = $settings?.orderbooks?.[network]?.address as Hex;
   const subgraphUrl = $settings?.subgraphs?.[network];
   const rpcUrl = $settings?.networks?.[network]?.rpc;
-  const chainId = $settings?.networks?.[network]?.['chain-id'];
 
   function invalidateOrderDetailQuery() {
     queryClient.invalidateQueries({
@@ -63,7 +62,6 @@
     {handleQuoteDebugModal}
     {handleDebugTradeModal}
     {orderbookAddress}
-    {chainId}
     {onRemove}
     {onDeposit}
     {onWithdraw}
diff --git a/tauri-app/src/routes/vaults/+page.svelte b/tauri-app/src/routes/vaults/+page.svelte
index b279a59410..3257ccb55c 100644
--- a/tauri-app/src/routes/vaults/+page.svelte
+++ b/tauri-app/src/routes/vaults/+page.svelte
@@ -2,7 +2,6 @@
   import { PageHeader, VaultsListTable } from '@rainlanguage/ui-components';
   import { onMount } from 'svelte';
   import { page } from '$app/stores';
-  import { walletAddressMatchesOrBlank } from '$lib/stores/wallets';
 
   import {
     activeOrderbook,
@@ -41,7 +40,6 @@
 <PageHeader title="Vaults" pathname={$page.url.pathname} />
 
 <VaultsListTable
-  {walletAddressMatchesOrBlank}
   {activeAccounts}
   {activeOrderbook}
   {subgraphUrl}


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f17d1ca88c3712be2cfaf7e695e1e4188c7a6c55 and 6b05001b8b23ffb8c17f4074ccd9d589aca3086b.

</details>

<details>
<summary>📒 Files selected for processing (8)</summary>

* `packages/ui-components/src/__tests__/OrderDetail.test.ts` (0 hunks)
* `packages/ui-components/src/lib/__mocks__/stores.ts` (0 hunks)
* `packages/ui-components/src/lib/components/detail/OrderDetail.svelte` (3 hunks)
* `packages/ui-components/src/lib/components/detail/VaultDetail.svelte` (3 hunks)
* `packages/ui-components/src/lib/components/tables/OrdersListTable.svelte` (3 hunks)
* `packages/ui-components/src/lib/components/tables/VaultsListTable.svelte` (2 hunks)
* `packages/webapp/src/routes/orders/[network]-[orderHash]/+page.svelte` (0 hunks)
* `tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte` (0 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (4)</summary>

* tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte
* packages/webapp/src/routes/orders/[network]-[orderHash]/+page.svelte
* packages/ui-components/src/__tests__/OrderDetail.test.ts
* packages/ui-components/src/lib/__mocks__/stores.ts

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
* GitHub Check: Deploy-Preview
* GitHub Check: build-tauri (ubuntu-22.04, true)
* GitHub Check: test
* GitHub Check: test

</details>

<details>
<summary>🔇 Additional comments (9)</summary><blockquote>

<details>
<summary>packages/ui-components/src/lib/components/detail/OrderDetail.svelte (3)</summary>

`30-31`: **Clean import of accountIsOwner service**

Good addition of the new `accountIsOwner` import to replace the previous address checks.

---

`97-97`: **Simplified ownership verification logic**

Great improvement replacing the complex address verification logic with the `accountIsOwner` function call. This makes the code more readable and maintainable while keeping the same functionality.

---

`155-155`: **Consistent ownership check for vault actions**

Nice job applying the same `accountIsOwner` pattern for checking vault ownership before showing deposit/withdraw buttons. This creates consistency across the codebase.

</details>
<details>
<summary>packages/ui-components/src/lib/components/detail/VaultDetail.svelte (2)</summary>

`11-12`: **Clean import changes**

Good cleanup of imports - removing unnecessary viem functions and adding the new `accountIsOwner` utility.



Also applies to: 23-23

---

`85-85`: **Simplified vault ownership check**

Great improvement replacing the previous address validation logic with the concise `accountIsOwner` function. This makes the code more maintainable while preserving the same functionality.

</details>
<details>
<summary>packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (2)</summary>

`22-23`: **Added accountIsOwner import**

Good addition of the `accountIsOwner` import to replace the previous wallet address matching checks.

---

`169-169`: **Improved owner validation for wallet actions**

Good replacement of the `walletAddressMatchesOrBlank` check with the new `accountIsOwner` function, which provides a cleaner and more consistent approach to ownership verification.

</details>
<details>
<summary>packages/ui-components/src/lib/components/tables/VaultsListTable.svelte (2)</summary>

`2-2`: **Added accountIsOwner import**

Good addition of the `accountIsOwner` import at the top of the file.

---

`206-244`: **Improved vault actions UI logic**

Excellent refactoring of the vault actions section:

1. Replaced the `walletAddressMatchesOrBlank` check with the cleaner `accountIsOwner` function
2. Restructured the UI to consistently display the menu button and dropdown when the user is the vault owner
3. Improved the organization of the deposit and withdraw options in the dropdown menu

This change makes the code more maintainable and the UX more consistent.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T09:22:30Z
user: login: hardingjam
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T10:04:03Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T10:04:21Z
user: login: hardyjosh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T19:31:00Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (1)</summary><blockquote>

`189-189`: **Redundant condition successfully removed**

Excellent job removing the redundant ownership check. This code correctly relies on the outer condition (line 171) to determine if the user is the owner, simplifying the logic.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3b48aad8ba3ad2aa277d8ed033a1f2c8d4832217 and adba3484dee1e22bdbf8b9aa84b2a73e09dde088.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `packages/ui-components/src/__tests__/OrderDetail.test.ts` (6 hunks)
* `packages/ui-components/src/__tests__/OrdersListTable.test.ts` (1 hunks)
* `packages/ui-components/src/__tests__/VaultDetail.test.ts` (4 hunks)
* `packages/ui-components/src/__tests__/VaultsListTable.test.ts` (6 hunks)
* `packages/ui-components/src/lib/components/detail/OrderDetail.svelte` (4 hunks)
* `packages/ui-components/src/lib/components/detail/VaultDetail.svelte` (3 hunks)
* `packages/ui-components/src/lib/components/tables/OrdersListTable.svelte` (5 hunks)
* `packages/ui-components/src/lib/components/tables/VaultsListTable.svelte` (2 hunks)
* `packages/ui-components/src/lib/providers/wallet/useAccount.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>packages/ui-components/src/__tests__/OrdersListTable.test.ts (3)</summary><blockquote>

<details>
<summary>packages/ui-components/src/lib/__mocks__/stores.ts (9)</summary>

* `mockActiveSubgraphsStore` (32-37)
* `mockAccountsStore` (39-41)
* `mockActiveAccountsItemsStore` (43-48)
* `mockActiveOrderStatusStore` (50-55)
* `mockOrderHashStore` (57-61)
* `mockHideZeroBalanceVaultsStore` (63-67)
* `mockShowMyItemsOnlyStore` (114-118)
* `mockActiveNetworkRefStore` (69-73)
* `mockActiveOrderbookRefStore` (75-79)

</details>
<details>
<summary>packages/ui-components/src/lib/providers/wallet/useAccount.ts (1)</summary>

* `useAccount` (11-44)

</details>
<details>
<summary>tauri-app/src/lib/services/modal.ts (1)</summary>

* `handleOrderRemoveModal` (22-24)

</details>

</blockquote></details>
<details>
<summary>packages/ui-components/src/__tests__/VaultDetail.test.ts (1)</summary><blockquote>

<details>
<summary>packages/ui-components/src/lib/providers/wallet/useAccount.ts (1)</summary>

* `useAccount` (11-44)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (30)</summary><blockquote>

<details>
<summary>packages/ui-components/src/lib/components/detail/OrderDetail.svelte (3)</summary>

`61-61`: **LGTM: Used matchesAccount from useAccount**

The code correctly adopts the new account matching pattern by using the `matchesAccount` function from the `useAccount` hook instead of directly accessing the account.

---

`96-96`: **Simplified ownership verification**

Excellent refactoring of the ownership check using the new `matchesAccount` function, which replaces the previous implementation that likely used multiple functions (`isAddress` and `isAddressEqual`) from the viem library.

---

`154-154`: **Consistent application of matchesAccount**

Good job consistently applying the new `matchesAccount` pattern for checking vault ownership, which aligns with the PR objective of modernizing frontend checks.

</details>
<details>
<summary>packages/ui-components/src/lib/components/detail/VaultDetail.svelte (3)</summary>

`11-11`: **Removed unnecessary viem imports**

Successfully removed the viem library imports for address validation, keeping only the required `formatUnits` function.

---

`45-45`: **LGTM: Implemented matchesAccount pattern**

Correctly implemented the new account matching pattern by destructuring `matchesAccount` from the `useAccount` hook.

---

`84-84`: **Simplified conditional logic**

Good job replacing complex address validation logic with the more straightforward `matchesAccount` function call.

</details>
<details>
<summary>packages/ui-components/src/lib/components/tables/VaultsListTable.svelte (2)</summary>

`47-47`: **Added matchesAccount to useAccount destructuring**

Correctly updated the destructuring to include both `account` and `matchesAccount` from the `useAccount` hook.

---

`204-242`: **Improved conditional rendering logic**

Excellent refactoring of the vault action buttons rendering logic. The code now uses a single conditional check with `matchesAccount(item.vault.owner)` to determine if the vault actions should be displayed, making the code more maintainable and easier to understand.

</details>
<details>
<summary>packages/ui-components/src/__tests__/VaultDetail.test.ts (4)</summary>

`48-48`: **Added mockMatchesAccount function**

Good addition of the mock function for testing the new account matching functionality.

---

`58-62`: **Updated test setup for new pattern**

Correctly updated the test setup to mock the `matchesAccount` function and incorporated it into the `useAccount` mock return value.

---

`142-144`: **Updated test description and implementation**

Well done updating the test case to reflect the new account matching pattern, with a clearer description that focuses on account matches rather than general conditions.

---

`156-157`: **Updated negative test case**

Properly consolidated the negative test cases into a single test that verifies the behavior when the account doesn't match, using the new `mockMatchesAccount` function.

</details>
<details>
<summary>packages/ui-components/src/lib/components/tables/OrdersListTable.svelte (3)</summary>

`28-28`: **Export let is the correct pattern for props**

The change from `export const` to `export let` is appropriate here, as it properly defines this as a component prop that can be set by the parent component. In Svelte, `export let` is the standard way to define component props.

---

`43-43`: **Improved account access with useAccount hook**

Using the destructured `matchesAccount` and `account` from the useAccount hook provides a cleaner and more reactive way to handle wallet interactions.

---

`171-171`: **Simplified ownership check with matchesAccount**

Replacing the deprecated `walletAddressMatchesOrBlank` with `matchesAccount` improves code quality by using a single, tested utility function for ownership verification.

</details>
<details>
<summary>packages/ui-components/src/lib/providers/wallet/useAccount.ts (1)</summary>

`91-166`: **Comprehensive test coverage for matchesAccount**

The test suite provides excellent coverage for the `matchesAccount` function, including tests for:
- Valid matching addresses
- Valid non-matching addresses 
- No connected account
- Invalid address inputs
- Short-circuit evaluation behavior

This thorough testing approach ensures the function behaves correctly in all scenarios.

</details>
<details>
<summary>packages/ui-components/src/__tests__/VaultsListTable.test.ts (3)</summary>

`11-20`: **Proper mocking of useAccount hook**

The useAccount hook is correctly mocked to provide control over the account state in tests. This approach allows for precise testing of account-related component behavior.

---

`87-93`: **Well-structured test setup with beforeEach**

Using beforeEach to reset mocks and configure the useAccount mock for each test ensures test isolation and prevents test interdependencies. This is a best practice for maintaining reliable tests.

---

`204-207`: **Testing negative ownership scenarios**

This test correctly verifies that action buttons are hidden when the user is not the vault owner by mocking `matchesAccount` to return false. This is an important edge case to test.

</details>
<details>
<summary>packages/ui-components/src/__tests__/OrdersListTable.test.ts (5)</summary>

`1-74`: **Comprehensive test setup and mocking**

The test setup is well-structured with appropriate mocks for all dependencies, including the useAccount hook, navigation, and the query client. The mock order data is comprehensive and covers all necessary fields for testing.

---

`95-102`: **Proper test isolation with beforeEach**

Using beforeEach to clear mocks and configure the useAccount mock ensures each test runs in isolation, preventing test interdependencies and making tests more reliable and maintainable.

---

`127-154`: **Thorough testing of order actions and ownership**

These tests correctly verify that:
1. The remove button is only shown for active orders owned by the current user
2. The remove action correctly calls the handler with the right parameters

This ensures the ownership-based UI controls work correctly, which is critical for the security of the application.



Also applies to: 156-188

---

`217-250`: **Proper testing of inactive order UI**

This test correctly verifies that action menus are not displayed for inactive orders, even when the user is the owner. This is an important edge case to test for UI correctness.

---

`311-340`: **Edge case testing for large trade counts**

Testing the display handling for more than 99 trades demonstrates attention to detail and ensures the UI handles edge cases appropriately. This is good practice for comprehensive test coverage.

</details>
<details>
<summary>packages/ui-components/src/__tests__/OrderDetail.test.ts (6)</summary>

`120-120`: **Well-structured mock function implementation**

The introduction of `mockMatchesAccount` as a dedicated mock function makes the testing approach more explicit and maintainable. This aligns well with the PR's objective to replace the old wallet address matching logic with the new `accountIsOwner` approach.

---

`129-131`: **Good refactoring of the account mock**

The updated mock correctly returns the new `matchesAccount` function instead of the previous account object. This change properly reflects the implementation of the new account ownership verification approach through the `useAccount` hook.

---

`182-182`: **Clear testing of the ownership-dependent UI behavior**

Using `mockMatchesAccount.mockReturnValue(true)` provides a clear and explicit way to test how the UI responds when the current user is the owner. This makes the test more readable and maintainable compared to the previous approach.

---

`202-202`: **Good negative case testing**

This test case properly verifies that the remove button doesn't appear when the account doesn't match the owner. The explicit mock return value of `false` makes the test intent very clear.

---

`253-253`: **Consistent application of account ownership checks**

The deposit functionality correctly uses the same account ownership verification pattern as other owner-dependent actions. This ensures consistent behavior across the component.

---

`282-282`: **Consistent application of account ownership checks for withdrawal**

Similar to the deposit functionality, the withdrawal action correctly uses the same account ownership verification approach, maintaining consistency across the component's interactive features.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:37:29Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between adba3484dee1e22bdbf8b9aa84b2a73e09dde088 and 685bf30bf0ac91b6ac3a50b37b5130c4bb706c93.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `packages/ui-components/src/__tests__/DeploymentSteps.test.ts` (2 hunks)
* `packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts` (1 hunks)
* `packages/ui-components/src/__tests__/WalletConnect.test.ts` (2 hunks)
* `packages/webapp/src/__tests__/DeployModal.test.ts` (2 hunks)
* `packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts` (5 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (1)</summary><blockquote>

<details>
<summary>packages/webapp/src/lib/__mocks__/mockWeb3Config.ts (1)</summary>

* `mockWeb3Config` (5-16)

</details>

</blockquote></details>
<details>
<summary>packages/webapp/src/__tests__/DeployModal.test.ts (1)</summary><blockquote>

<details>
<summary>packages/webapp/src/lib/__mocks__/mockWeb3Config.ts (1)</summary>

* `mockWeb3Config` (5-16)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (16)</summary>

* GitHub Check: test
* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
* GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
* GitHub Check: build-tauri (ubuntu-22.04, true)
* GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
* GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
* GitHub Check: test
* GitHub Check: Deploy-Preview
* GitHub Check: git-clean
* GitHub Check: test

</details>

<details>
<summary>🔇 Additional comments (14)</summary><blockquote>

<details>
<summary>packages/ui-components/src/__tests__/WalletConnect.test.ts (2)</summary>

`32-33`: **Added `matchesAccount` mock function to support account ownership checks.**

The addition of `matchesAccount: vi.fn()` to the mock return value aligns with the PR's objective of replacing wallet address matching logic with a new account ownership verification approach.

---

`45-46`: **Added `matchesAccount` mock function for the connected wallet test case.**

This change maintains consistency with the updated `useAccount` hook interface, properly mocking the new account ownership verification method.

</details>
<details>
<summary>packages/webapp/src/__tests__/DeployModal.test.ts (2)</summary>

`5-5`: **Added import for the mockWeb3Config.**

Good addition of the mockWeb3Config import to directly use the mock object in the tests.

---

`47-52`: **Simplified test expectations using mockWeb3Config.**

The test has been improved by:
1. Using `expect.objectContaining()` for clearer partial object matching
2. Directly referencing `mockWeb3Config` instead of retrieving it from a store
3. Using spread operator for cleaner code

This approach is more maintainable and aligns with the PR's objective of modernizing the frontend checks.

</details>
<details>
<summary>packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (5)</summary>

`9-10`: **Updated imports to use mockWeb3Config directly.**

Good refactoring to remove the unused `get` import and add the `mockWeb3Config` import, which simplifies the test code.

---

`69-70`: **Added `matchesAccount` mock function to support account ownership checks.**

Properly updated the `useAccount` mock to include the new `matchesAccount` method, aligning with the PR's objective of implementing consistent account ownership verification.

---

`106-106`: **Updated deposit test expectations to use mockWeb3Config directly.**

Good simplification of the test by directly using the mock config object rather than retrieving it from a store.

---

`130-130`: **Updated withdraw test expectations to use mockWeb3Config directly.**

Consistent with the other changes, this simplifies the withdraw test by directly using the mock config object.

---

`244-244`: **Updated approval fallback test to use mockWeb3Config directly.**

This change maintains consistency with the other test cases and further simplifies the test code.

</details>
<details>
<summary>packages/ui-components/src/__tests__/DeploymentSteps.test.ts (2)</summary>

`122-123`: **Added `matchesAccount` mock function in the beforeEach setup.**

Good addition of the `matchesAccount` method to the `useAccount` mock return value, maintaining consistency with the updated interface across the codebase.

---

`446-447`: **Updated the mock account in the handleDeployment test.**

This change properly implements the updated `useAccount` interface with the new `matchesAccount` method in the test that verifies the correct arguments are passed to `handleDeployment`.

</details>
<details>
<summary>packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts (3)</summary>

`3-3`: **Added necessary import for mocking.**

The import of `vi` from `vitest` is appropriately added to enable the mock implementations that follow.

---

`14-16`: **Simplified query mocking.**

The mock for `createInfiniteQuery` appropriately replaces the previous implementation that created a resolvable infinite query. This simplifies the test setup by eliminating the need for a query variable in the defaultProps.

---

`36-47`: <details>
<summary>✅ Verification successful</summary>

**Verify that defaultProps no longer needs a query property.**

The test props no longer include the query property that was likely present before. Confirm that the component doesn't require this property with the new implementation.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if ListViewOrderbookFilters component requires a query prop
grep -r "export let query" packages/ui-components/src/lib/components/ListViewOrderbookFilters.svelte || echo "No query prop required"
```

Length of output: 157

---



</details>

**Verified Removal of Query Property from ListViewOrderbookFilters**

We confirmed via the grep script that the component in `packages/ui-components/src/lib/components/ListViewOrderbookFilters.svelte` no longer exports a `query` property. Consequently, the defaultProps in `ListViewOrderbookFilters.test.ts` are correctly updated by excluding it. No further modifications are required.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:01:56Z
user: login: hardingjam
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:01:57Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:02:15Z
user: login: hardingjam
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:02:19Z
user: login: hardingjam
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:03:16Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:03:36Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7b69d463e98104ba3ec9d647828aae42ef5ee315 and e8e20899c8be9d14c800c7b4761a32bf760117f1.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts` (1 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (16)</summary>

* GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
* GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
* GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
* GitHub Check: test
* GitHub Check: test
* GitHub Check: Deploy-Preview
* GitHub Check: git-clean
* GitHub Check: build-tauri (ubuntu-22.04, true)
* GitHub Check: test

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts (4)</summary>

`8-13`: **Good implementation of the previously suggested mock.**

The `useAccount` mock now properly includes the `matchesAccount` method, which aligns with the PR objective of replacing old wallet address checks with the new account ownership verification functionality.

---

`15-17`: **New mock for createInfiniteQuery added.**

The addition of this mock is good for test isolation. Consider whether any tests need to control the behavior of this function (e.g., returning specific data or simulating errors).

If tests depend on this function's behavior, you might need to add test-specific implementations:

```javascript
// Example of setting behavior in specific tests
import { createInfiniteQuery } from '@tanstack/svelte-query';
(createInfiniteQuery as jest.Mock).mockImplementation(() => ({ /* test data */ }));
```

---

`3-3`: **Updated imports to include vi from vitest.**

Good addition of the `vi` import needed for the mock implementations.

---

`37-48`: **Props setup looks appropriate for testing component rendering.**

The default props configuration remains unchanged and appears appropriate for testing the component with the new account handling implementation.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:58:58Z
user: login: hardingjam
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T15:26:52Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T15:27:11Z
user: login: hardyjosh
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T06:52:21Z

Review comments:
diff_hunk: @@ -186,7 +184,7 @@
 						</Button>
 					{/if}
 				</TableBodyCell>
-				{#if $walletAddressMatchesOrBlank(item.order.owner) && item.order.active}
+				{#if $account && accountIsOwner($account, item.order.owner) && item.order.active}
path: packages/ui-components/src/lib/components/tables/OrdersListTable.svelte
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Redundant ownership check**

There's redundancy in ownership verification between lines 169 and 187. Both lines check for the same conditions (`$account && accountIsOwner($account, item.order.owner)`).


Consider refactoring to avoid duplicate checks:

```diff
-{#if $account && accountIsOwner($account, item.order.owner) && handleOrderRemoveModal}
+{#if $account && accountIsOwner($account, item.order.owner) && handleOrderRemoveModal}
  <div data-testid="wallet-actions">
    <TableBodyCell tdClass="px-0 text-right">
      {#if item.order.active}
        <Button
          color="alternative"
          outline={false}
          data-testid={`order-menu-${item.order.id}`}
          id={`order-menu-${item.order.id}`}
          class="mr-2 border-none px-2"
          on:click={(e) => {
            e.stopPropagation();
          }}
        >
          <DotsVerticalOutline class="dark:text-white" />
        </Button>
      {/if}
    </TableBodyCell>
-   {#if $account && accountIsOwner($account, item.order.owner) && item.order.active}
+   {#if item.order.active}
      <Dropdown placement="bottom-end" triggeredBy={`#order-menu-${item.order.id}`}>
        <DropdownItem
          on:click={(e) => {
            e.stopPropagation();
            handleOrderRemoveModal(item.order, $query.refetch);
          }}>Remove</DropdownItem
        >
      </Dropdown>
    {/if}
  </div>
{/if}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
{#if $account && accountIsOwner($account, item.order.owner) && handleOrderRemoveModal}
  <div data-testid="wallet-actions">
    <TableBodyCell tdClass="px-0 text-right">
      {#if item.order.active}
        <Button
          color="alternative"
          outline={false}
          data-testid={`order-menu-${item.order.id}`}
          id={`order-menu-${item.order.id}`}
          class="mr-2 border-none px-2"
          on:click={(e) => {
            e.stopPropagation();
          }}
        >
          <DotsVerticalOutline class="dark:text-white" />
        </Button>
      {/if}
    </TableBodyCell>
    {#if item.order.active}
      <Dropdown placement="bottom-end" triggeredBy={`#order-menu-${item.order.id}`}>
        <DropdownItem
          on:click={(e) => {
            e.stopPropagation();
            handleOrderRemoveModal(item.order, $query.refetch);
          }}>Remove</DropdownItem>
      </Dropdown>
    {/if}
  </div>
{/if}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-10T09:22:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -186,7 +184,7 @@
 						</Button>
 					{/if}
 				</TableBodyCell>
-				{#if $walletAddressMatchesOrBlank(item.order.owner) && item.order.active}
+				{#if $account && accountIsOwner($account, item.order.owner) && item.order.active}
path: packages/ui-components/src/lib/components/tables/OrdersListTable.svelte
user: login: hardingjam
body: done
created_at: 2025-04-10T10:04:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -186,7 +184,7 @@
 						</Button>
 					{/if}
 				</TableBodyCell>
-				{#if $walletAddressMatchesOrBlank(item.order.owner) && item.order.active}
+				{#if $account && accountIsOwner($account, item.order.owner) && item.order.active}
path: packages/ui-components/src/lib/components/tables/OrdersListTable.svelte
user: login: coderabbitai[bot]
body: @hardingjam Great! The redundant check has been removed, which simplifies the code. Thanks for implementing the suggested change.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-10T10:04:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,28 @@
+import { isAddress, isAddressEqual } from 'viem';
+
+export const accountIsOwner = (account: string, owner: string) => {
path: packages/ui-components/src/lib/services/accountIsOwner.ts
user: login: hardyjosh
body: i kinda think this is misnamed - the function itself doesn't care what the two strings means. as it is it's just a `areAddressesAndEqual` fn

alternatively this could be a fn returned by useAccount

`const { matchesAccount } = useAccount()`

if there was no account it would return false, so you'd replace

`$account && accountIsOwner($account, item.vault.owner)`

with simply

`matchesAccount(item.vault.owner)`



created_at: 2025-04-10T19:31:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,35 +9,160 @@ import { readable } from 'svelte/store';
  * Must be used within a component that is a child of WalletProvider
  */
 export function useAccount() {
+	/**
+	 * The account store containing the current wallet address (as a Hex string) or null if not connected.
+	 * This is a readable Svelte store that can be subscribed to for reactive updates.
+	 * @type {import('svelte/store').Readable<Hex | null>}
+	 */
 	const account = getAccountContext();
+
+	/**
+	 * Checks if the provided address matches the currently connected account.
+	 * Returns false if no account is connected or if the provided address is invalid.
+	 */
+	const matchesAccount = (otherAddress: string): boolean => {
+		const currentAccount = get(account);
+		if (!currentAccount) {
+			return false;
+		}
+
+		if (
+			isAddress(currentAccount) &&
+			isAddress(otherAddress) &&
+			isAddressEqual(currentAccount, otherAddress)
+		) {
+			return true;
+		}
+
+		return false;
+	};
path: packages/ui-components/src/lib/providers/wallet/useAccount.ts
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Well-implemented account matching function**

The `matchesAccount` function is well-implemented with proper validation checks. It correctly handles cases where no account is connected and ensures both addresses are valid before comparison.

Consider adding a null/undefined check for `otherAddress` for additional robustness:

```diff
const matchesAccount = (otherAddress: string): boolean => {
+  if (!otherAddress) return false;
  const currentAccount = get(account);
  if (!currentAccount) {
    return false;
  }

  if (
    isAddress(currentAccount) &&
    isAddress(otherAddress) &&
    isAddressEqual(currentAccount, otherAddress)
  ) {
    return true;
  }

  return false;
};
```




<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
	const matchesAccount = (otherAddress: string): boolean => {
		if (!otherAddress) return false;
		const currentAccount = get(account);
		if (!currentAccount) {
			return false;
		}

		if (
			isAddress(currentAccount) &&
			isAddress(otherAddress) &&
			isAddressEqual(currentAccount, otherAddress)
		) {
			return true;
		}

		return false;
	};
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 7b69d46
created_at: 2025-04-11T09:37:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,12 +1,20 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null)
+	})
+}));
+
+vi.mock('@tanstack/svelte-query', () => ({
+	createInfiniteQuery: vi.fn()
+}));
path: packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Consider adding the matchesAccount method to the useAccount mock.**

The useAccount mock returns a basic store without the `matchesAccount` method mentioned in the PR objectives. This might not fully test the component's interaction with the new account matching functionality.

```diff
vi.mock('$lib/providers/wallet/useAccount', () => ({
	useAccount: () => ({
-		account: writable(null)
+		account: writable(null),
+		matchesAccount: vi.fn().mockReturnValue(false)
	})
}));
```

This would ensure the test covers the new account ownership verification functionality that this PR introduces.



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
vi.mock('$lib/providers/wallet/useAccount', () => ({
	useAccount: () => ({
		account: writable(null),
		matchesAccount: vi.fn().mockReturnValue(false)
	})
}));

vi.mock('@tanstack/svelte-query', () => ({
	createInfiniteQuery: vi.fn()
}));
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-11T10:01:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,35 +9,160 @@ import { readable } from 'svelte/store';
  * Must be used within a component that is a child of WalletProvider
  */
 export function useAccount() {
+	/**
+	 * The account store containing the current wallet address (as a Hex string) or null if not connected.
+	 * This is a readable Svelte store that can be subscribed to for reactive updates.
+	 * @type {import('svelte/store').Readable<Hex | null>}
+	 */
 	const account = getAccountContext();
+
+	/**
+	 * Checks if the provided address matches the currently connected account.
+	 * Returns false if no account is connected or if the provided address is invalid.
+	 */
+	const matchesAccount = (otherAddress: string): boolean => {
+		const currentAccount = get(account);
+		if (!currentAccount) {
+			return false;
+		}
+
+		if (
+			isAddress(currentAccount) &&
+			isAddress(otherAddress) &&
+			isAddressEqual(currentAccount, otherAddress)
+		) {
+			return true;
+		}
+
+		return false;
+	};
path: packages/ui-components/src/lib/providers/wallet/useAccount.ts
user: login: hardingjam
body: done
created_at: 2025-04-11T10:01:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,35 +9,160 @@ import { readable } from 'svelte/store';
  * Must be used within a component that is a child of WalletProvider
  */
 export function useAccount() {
+	/**
+	 * The account store containing the current wallet address (as a Hex string) or null if not connected.
+	 * This is a readable Svelte store that can be subscribed to for reactive updates.
+	 * @type {import('svelte/store').Readable<Hex | null>}
+	 */
 	const account = getAccountContext();
+
+	/**
+	 * Checks if the provided address matches the currently connected account.
+	 * Returns false if no account is connected or if the provided address is invalid.
+	 */
+	const matchesAccount = (otherAddress: string): boolean => {
+		const currentAccount = get(account);
+		if (!currentAccount) {
+			return false;
+		}
+
+		if (
+			isAddress(currentAccount) &&
+			isAddress(otherAddress) &&
+			isAddressEqual(currentAccount, otherAddress)
+		) {
+			return true;
+		}
+
+		return false;
+	};
path: packages/ui-components/src/lib/providers/wallet/useAccount.ts
user: login: coderabbitai[bot]
body: @hardingjam Thanks for implementing the null check! The `matchesAccount` function is now more robust against empty or undefined inputs.



<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@hardingjam Thanks for implementing the null check! The `matchesAccount` function is now more robust against empty or undefined inputs.</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-11T10:02:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,28 @@
+import { isAddress, isAddressEqual } from 'viem';
+
+export const accountIsOwner = (account: string, owner: string) => {
path: packages/ui-components/src/lib/services/accountIsOwner.ts
user: login: hardingjam
body: changed implementation
created_at: 2025-04-11T10:02:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,12 +1,20 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null)
+	})
+}));
+
+vi.mock('@tanstack/svelte-query', () => ({
+	createInfiniteQuery: vi.fn()
+}));
path: packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
user: login: hardingjam
body: done
created_at: 2025-04-11T10:03:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,12 +1,20 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null)
+	})
+}));
+
+vi.mock('@tanstack/svelte-query', () => ({
+	createInfiniteQuery: vi.fn()
+}));
path: packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
user: login: coderabbitai[bot]
body: @hardingjam Thanks for implementing the suggestion! Adding the `matchesAccount` mock will ensure the tests properly cover the new account ownership verification functionality introduced in this PR.



<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@hardingjam Thanks for implementing the suggestion! Adding the `matchesAccount` mock will ensure the tests properly cover the new account ownership verification functionality introduced in this PR.</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-11T10:03:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,12 +1,21 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null),
+		matchesAccount: vi.fn()
path: packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Consider setting a default return value for the matchesAccount mock.**

While the mock function is implemented, it doesn't have a default return value. If the component relies on this function in some test cases, you might want to set a default behavior:

```diff
-		matchesAccount: vi.fn()
+		matchesAccount: vi.fn().mockReturnValue(false)
```

This would provide predictable behavior in tests that don't explicitly set expectations for this function.



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
		matchesAccount: vi.fn().mockReturnValue(false)
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-11T10:58:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,12 +1,21 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null),
+		matchesAccount: vi.fn()
path: packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
user: login: hardingjam
body: not necessary
created_at: 2025-04-11T15:26:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,12 +1,21 @@
 import { render, screen } from '@testing-library/svelte';
 import { writable } from 'svelte/store';
-import { beforeEach, expect, test, describe } from 'vitest';
+import { beforeEach, expect, test, describe, vi } from 'vitest';
 import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte';
 import type { ConfigSource } from '@rainlanguage/orderbook';
-import { createResolvableInfiniteQuery } from '../lib/__mocks__/queries';
 import type { ComponentProps } from 'svelte';
 
-// Get the props type from the component
+vi.mock('$lib/providers/wallet/useAccount', () => ({
+	useAccount: () => ({
+		account: writable(null),
+		matchesAccount: vi.fn()
path: packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts
user: login: coderabbitai[bot]
body: @hardingjam Understood! I'll respect your judgment on this matter.



<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@hardingjam Understood! I'll respect your judgment on this matter.</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-11T15:27:11Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-09T16:40:03Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

"""
## Walkthrough

This pull request removes the deprecated wallet address matching logic across the codebase. It eliminates references to the `walletAddressMatchesOrBlank` variable and the unnecessary `chainId` constant from tests and route components. In its place, the `useAccount` hook has been updated to include a new `matchesAccount` method that is now used in components and tests to verify account ownership. Additionally, obsolete mock stores and derived values have been removed, and new tests have been added to ensure that the updated account matching functionality behaves as expected.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `packages/ui-components/.../__tests__/OrderDetail.test.ts`, `packages/ui-components/.../__tests__/VaultsListTable.test.ts`, `packages/ui-components/.../__tests__/OrdersListTable.test.ts`, `packages/ui-components/.../__tests__/VaultDetail.test.ts`, `packages/ui-components/.../__tests__/DeploymentSteps.test.ts`, `packages/ui-components/.../__tests__/ListViewOrderbookFilters.test.ts`, `packages/ui-components/.../__tests__/WalletConnect.test.ts`, `packages/webapp/src/__tests__/DeployModal.test.ts`, `packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts` | Removed unused constants (`chainId`, `mockAccountStore`) and replaced `walletAddressMatchesOrBlank` logic with a new `mockMatchesAccount` function. Updated mocks of `useAccount` to include `matchesAccount`. Tests have been updated to simulate account matching scenarios and use the new method. Added new test file for `OrdersListTable`. |
| `packages/ui-components/.../components/detail/OrderDetail.svelte`, `packages/ui-components/.../components/detail/VaultDetail.svelte`, `packages/ui-components/.../components/tables/OrdersListTable.svelte`, `packages/ui-components/.../components/tables/VaultsListTable.svelte` | Removed `chainId` and `walletAddressMatchesOrBlank` props and associated logic; replaced `viem`’s address validation functions with a call to `matchesAccount` from `useAccount`. Simplified ownership checks and conditional rendering accordingly. |
| `packages/webapp/.../routes/orders/[network]-[orderHash]/+page.svelte`, `packages/webapp/.../routes/vaults/+page.svelte`, `tauri-app/.../routes/orders/+page.svelte`, `tauri-app/.../routes/orders/[network]-[orderHash]/+page.svelte`, `tauri-app/.../routes/vaults/+page.svelte` | Removed `chainId` and `walletAddressMatchesOrBlank` variables/props passed to components in route pages, ensuring consistency with updated component contracts. |
| `packages/ui-components/.../lib/__mocks__/stores.ts`, `tauri-app/.../lib/mocks/wallets.ts`, `tauri-app/.../lib/stores/wallets.ts` | Removed the writable and derived stores for `walletAddressMatchesOrBlank` along with their exports, eliminating obsolete mock functionality. |
| `packages/ui-components/.../lib/providers/wallet/useAccount.ts` | Added a new `matchesAccount(otherAddress: string): boolean` method that checks account ownership using existing utilities. Expanded test coverage to validate the new functionality. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant UI as UI Component
    participant UA as useAccount Hook

    UI->>UA: Call matchesAccount(address)
    UA-->>UI: Return boolean (true/false)
    alt Account Matches
       UI->>UI: Render action buttons (e.g., deposit/withdraw)
    else Account does not match
       UI->>UI: Hide action buttons
    end
```

## Assessment against linked issues

| Objective                                                                 | Addressed | Explanation |
|---------------------------------------------------------------------------|-----------|-------------|
| Remove walletAddressMatchesOrBlank, check against useAccount account instead (#1485) | ✅        |             |

## Possibly related PRs

- rainlanguage/rain.orderbook#1504: Refactors VaultDetail component and tests to replace modal-based deposit/withdraw handling with event-driven callbacks and uses a mock `matchesAccount` function, closely related to account matching logic changes.
- rainlanguage/rain.orderbook#1597: Improves `OrderDetail` component tests by mocking and using `useAccount` hook’s `matchesAccount` function, aligning closely with test refactoring in this PR.
- rainlanguage/rain.orderbook#1496: Replaces use of signer address and `chainId` constants with `matchesAccount` from `useAccount` provider for account matching across components and tests, directly connected to the changes here.

## Suggested labels

`rust`, `enhancement`, `test`
"""

<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡💬 Agentic Chat (Pro Plan, General Availability)</summary>
> 
> - We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e65aebc63fda8b09ded528b0fc27539f04b4473f and d70ba84a541e9dc835673e809ecfd086536b7bec.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `packages/ui-components/src/__tests__/OrderDetail.test.ts` (6 hunks)
* `packages/ui-components/src/lib/components/detail/OrderDetail.svelte` (4 hunks)
* `packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts` (5 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (1)</summary><blockquote>

<details>
<summary>packages/webapp/src/lib/__mocks__/mockWeb3Config.ts (1)</summary>

* `mockWeb3Config` (5-16)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (15)</summary>

* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
* GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
* GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
* GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
* GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
* GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
* GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
* GitHub Check: test
* GitHub Check: git-clean
* GitHub Check: Deploy-Preview
* GitHub Check: build-tauri (ubuntu-22.04, true)
* GitHub Check: test

</details>

<details>
<summary>🔇 Additional comments (15)</summary><blockquote>

<details>
<summary>packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts (5)</summary>

`9-10`: **Improved configuration import approach**

The code now directly imports `mockWeb3Config` instead of accessing it through a store, which simplifies the test setup and aligns with modern practices.

---

`69-70`: **Updated wallet provider mock to include matchesAccount method**

Correctly updated the mock to include the new `matchesAccount` method, supporting the codebase's transition to a single, unified account ownership verification approach.

---

`108-108`: **Updated to use direct config reference**

Changed from accessing the config through a store to using the imported `mockWeb3Config` directly, which is cleaner and more maintainable.

---

`131-131`: **Consistent use of direct config reference**

This change maintains consistency with other updates in the file by using the directly imported config object.

---

`246-246`: **Completed migration to direct config reference**

Final instance of updating to the direct config reference pattern, maintaining consistency throughout the test file.

</details>
<details>
<summary>packages/ui-components/src/lib/components/detail/OrderDetail.svelte (4)</summary>

`25-30`: **Simplified imports with more focused scope**

The imports have been restructured to only include what's actually needed, removing unnecessary references to viem-specific imports for address validation.

---

`61-61`: **Implemented unified account matching approach**

Using the `matchesAccount` function from `useAccount` centralizes ownership logic and improves maintainability.

---

`96-96`: **Streamlined owner verification**

Replaced complex address validation with the more straightforward `matchesAccount` function, improving readability and maintainability.

---

`154-154`: **Consistent account ownership verification**

Uses the same `matchesAccount` approach for vault ownership checks, maintaining a consistent pattern throughout the component.

</details>
<details>
<summary>packages/ui-components/src/__tests__/OrderDetail.test.ts (6)</summary>

`120-120`: **Added mock for matchesAccount function**

Created a mock function for `matchesAccount` to facilitate testing of ownership-dependent UI elements.

---

`130-130`: **Updated useAccount mock implementation**

Now returns the mock `matchesAccount` function to align with the updated `useAccount` provider interface.

---

`182-182`: **Simulating matching account for owner tests**

Uses the mock function to simulate an account matching scenario for testing owner-specific functionality.

---

`202-202`: **Simulating non-matching account for boundary tests**

Uses the mock function to simulate a non-matching account to verify correct behavior when a user is not the owner.

---

`253-253`: **Mock setup for deposit action test**

Properly configures the account match scenario for testing deposit functionality.

---

`282-282`: **Mock setup for withdraw action test**

Properly configures the account match scenario for testing withdraw functionality.

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=rainlanguage/rain.orderbook&utm_content=1617):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: hardingjam
created_at: 2025-04-11T10:49:38Z
body: Why are the tests in tauri-app's settings.test.ts failing on this branch, but not on main? It seems that getting and setting the mock  isn't working as intended.

https://github.com/rainlanguage/rain.orderbook/blob/7b69d463e98104ba3ec9d647828aae42ef5ee315/tauri-app/src/lib/stores/settings.test.ts#L1-L79

These tests fail now, but i can't see any changes that would have caused that.
author_association: CONTRIBUTOR