diff --git a/desktop/src/features/market/ui/AgentWalletPanel.tsx b/desktop/src/features/market/ui/AgentWalletPanel.tsx
new file mode 100644
index 0000000000..f87e108d46
--- /dev/null
+++ b/desktop/src/features/market/ui/AgentWalletPanel.tsx
@@ -0,0 +1,102 @@
+import { WalletCards } from "lucide-react";
+
+import type { MarketScenarioId } from "@/features/market/lib/marketPrototypeData";
+import { ProjectContextRail } from "@/features/projects/ui/ProjectContextRail";
+import { ProjectHomeColumn } from "@/features/projects/ui/ProjectHomeColumn";
+import { useThreadPanelWidth } from "@/shared/hooks/useThreadPanelWidth";
+import { SIDEBAR_WIDTH_MIN } from "@/shared/layout/sidebarLayout";
+
+const MARKET_WALLET_WIDTH_KEY = "buzz.desktop.market-wallet-width";
+
+const WALLET_DETAILS: Record<
+ MarketScenarioId,
+ { account: string; balance: string; settlement: string }
+> = {
+ finite: {
+ account: "escrow1report…13c8",
+ balance: "150 sats funded",
+ settlement: "1 paid · 2 reserved",
+ },
+ unlimited: {
+ account: "wallet1mapper…c241",
+ balance: "80 sats escrowed",
+ settlement: "760 sats paid",
+ },
+ auction: {
+ account: "escrow1strings…9f10",
+ balance: "600 sats funded",
+ settlement: "Held until award",
+ },
+ tender: {
+ account: "escrow1tender…1b73",
+ balance: "2,000 sats funded",
+ settlement: "Held during selection",
+ },
+ awarded: {
+ account: "escrow1tender…1b73",
+ balance: "1,750 sats escrowed",
+ settlement: "Release on signed receipt",
+ },
+};
+
+export function AgentWalletPanel({
+ open,
+ scenarioId,
+}: {
+ open: boolean;
+ scenarioId: MarketScenarioId;
+}) {
+ const width = useThreadPanelWidth(undefined, {
+ minWidthPx: SIDEBAR_WIDTH_MIN,
+ sessionKey: MARKET_WALLET_WIDTH_KEY,
+ });
+ const wallet = WALLET_DETAILS[scenarioId];
+
+ return (
+
+
+
+
+
+
+ Settlement for this listing
+
+
+
+
+
+
+
+ {wallet.account}
+
+
+
+
+
+ );
+}
+
+function WalletValue({ label, value }: { label: string; value: string }) {
+ return (
+
+
{label}
+ {value}
+
+ );
+}
diff --git a/desktop/src/features/market/ui/MarketScreen.tsx b/desktop/src/features/market/ui/MarketScreen.tsx
index 8536d5d347..55dab7a1da 100644
--- a/desktop/src/features/market/ui/MarketScreen.tsx
+++ b/desktop/src/features/market/ui/MarketScreen.tsx
@@ -5,11 +5,11 @@ import {
Radio,
Store,
TriangleAlert,
- WalletCards,
} from "lucide-react";
import * as React from "react";
import { ChatHeader } from "@/features/chat/ui/ChatHeader";
+import { AgentWalletPanel } from "@/features/market/ui/AgentWalletPanel";
import {
MARKET_SCENARIOS,
type MarketActivity,
@@ -28,6 +28,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/shared/ui/dialog";
+import { DrawerPanelIcon } from "@/shared/ui/DrawerPanelIcon";
import { Input } from "@/shared/ui/input";
import { useOptionalSidebar } from "@/shared/ui/sidebar";
import { Textarea } from "@/shared/ui/textarea";
@@ -38,37 +39,6 @@ const REPRESENTING_AGENTS = [
{ name: "Sentinel", role: "Operations & safety" },
] as const;
-const WALLET_DETAILS: Record<
- MarketScenarioId,
- { account: string; balance: string; settlement: string }
-> = {
- finite: {
- account: "escrow1report…13c8",
- balance: "150 sats funded",
- settlement: "1 paid · 2 reserved",
- },
- unlimited: {
- account: "wallet1mapper…c241",
- balance: "80 sats escrowed",
- settlement: "760 sats paid",
- },
- auction: {
- account: "escrow1strings…9f10",
- balance: "600 sats funded",
- settlement: "Held until award",
- },
- tender: {
- account: "escrow1tender…1b73",
- balance: "2,000 sats funded",
- settlement: "Held during selection",
- },
- awarded: {
- account: "escrow1tender…1b73",
- balance: "1,750 sats escrowed",
- settlement: "Release on signed receipt",
- },
-};
-
const COMMERCIAL_TERM_LABELS = new Set([
"Price",
"Initial quantity",
@@ -108,6 +78,7 @@ export function MarketScreen({ scenarioId }: { scenarioId: MarketScenarioId }) {
const scenario = MARKET_SCENARIOS[scenarioId];
const sidebar = useOptionalSidebar();
const [createOpen, setCreateOpen] = React.useState(false);
+ const [walletOpen, setWalletOpen] = React.useState(true);
const isTerminal = scenario.status !== "Open";
return (
@@ -121,6 +92,27 @@ export function MarketScreen({ scenarioId }: { scenarioId: MarketScenarioId }) {
>
setWalletOpen((open) => !open)}
+ size="icon"
+ title={walletOpen ? "Hide agent wallet" : "Show agent wallet"}
+ type="button"
+ variant="ghost"
+ >
+
+
+ }
channelType="stream"
description={scenario.summary}
leadingContent={}
@@ -132,7 +124,6 @@ export function MarketScreen({ scenarioId }: { scenarioId: MarketScenarioId }) {
setCreateOpen(true)}
scenario={scenario}
- scenarioId={scenarioId}
/>
@@ -187,6 +178,8 @@ export function MarketScreen({ scenarioId }: { scenarioId: MarketScenarioId }) {
+
+
);
}
@@ -194,11 +187,9 @@ export function MarketScreen({ scenarioId }: { scenarioId: MarketScenarioId }) {
function OfferCard({
onCreate,
scenario,
- scenarioId,
}: {
onCreate: () => void;
scenario: MarketScenario;
- scenarioId: MarketScenarioId;
}) {
const author =
scenario.terms.find(
@@ -216,7 +207,7 @@ function OfferCard({
className="overflow-hidden rounded-2xl border bg-card"
data-testid="market-offer-card"
>
-
);
}
-function AgentWallet({ scenarioId }: { scenarioId: MarketScenarioId }) {
- const wallet = WALLET_DETAILS[scenarioId];
- return (
-
- );
-}
-
-function WalletValue({ label, value }: { label: string; value: string }) {
- return (
-
-
{label}
- {value}
-
- );
-}
-
function CreateMarketDialog({
onOpenChange,
open,
diff --git a/desktop/tests/e2e/market-prototype-screenshots.spec.ts b/desktop/tests/e2e/market-prototype-screenshots.spec.ts
index 1d0ce05b80..6f8f080ea4 100644
--- a/desktop/tests/e2e/market-prototype-screenshots.spec.ts
+++ b/desktop/tests/e2e/market-prototype-screenshots.spec.ts
@@ -49,7 +49,7 @@ test.describe("market channel prototype", () => {
const offerCardWidth = await market
.getByTestId("market-offer-card")
.evaluate((element) => element.getBoundingClientRect().width);
- expect(offerCardWidth).toBeGreaterThan(1100);
+ expect(offerCardWidth).toBeGreaterThan(850);
const imageAspectRatio = await market
.getByTestId("market-product-image")
.evaluate((element) => {
@@ -57,10 +57,28 @@ test.describe("market channel prototype", () => {
return bounds.width / bounds.height;
});
expect(imageAspectRatio).toBeCloseTo(1, 1);
- await expect(market.getByTestId("market-agent-wallet")).toBeVisible();
+ const wallet = market.getByTestId("market-agent-wallet");
+ await expect(wallet).toBeVisible();
+ await expect(wallet).toHaveCSS(
+ "background-color",
+ await page
+ .locator('[data-sidebar="sidebar"]')
+ .evaluate(
+ (element) => window.getComputedStyle(element).backgroundColor,
+ ),
+ );
await expect(
- market.getByText("Agent wallet", { exact: true }),
+ market.getByRole("button", { name: "Hide agent wallet" }).first(),
).toBeVisible();
+ const walletRail = market.getByTestId("market-wallet-rail");
+ await market.getByTestId("market-wallet-toggle").click();
+ await expect(walletRail).toHaveAttribute("aria-hidden", "true");
+ await expect(walletRail).toHaveCSS("width", "0px");
+ await expect(
+ market.getByRole("button", { name: "Show agent wallet" }),
+ ).toBeVisible();
+ await market.getByRole("button", { name: "Show agent wallet" }).click();
+ await expect(wallet).toBeVisible();
await expect(market.getByText("Agent market channel")).toBeVisible();
await expect(market.getByTestId("market-agent-avatar")).toHaveCount(
scenario === "unlimited" ? 3 : 4,