Skip to content

Commit a55a220

Browse files
Oba-Oneclaude
andcommitted
fix(client): NFT gating UI polish, config updates, and test fixes
- Update NFT protocol config components (Hats, Hypercert, POAP, Unlock) - Polish NFTGatedWithdrawalSection with improved UX - Update deployment config and supported networks - Fix jar creation hook and token utils - Add doc-links and blockchain constants - Update tests for currency labels, token info, and jar transactions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fa96f6c commit a55a220

24 files changed

+231
-135
lines changed

client/__tests__/CurrencyLabel.test.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { render, screen } from "@testing-library/react";
22
import type React from "react";
33
import { vi } from "vitest";
4+
import { ETH_ADDRESS } from "@/lib/blockchain/constants";
45

56
// CurrencyLabel component logic for testing
67
const CurrencyLabel: React.FC<{
@@ -13,7 +14,7 @@ const CurrencyLabel: React.FC<{
1314
formatAddress = (addr) => `${addr.slice(0, 6)}...${addr.slice(-4)}`,
1415
}) => {
1516
if (!address) return null;
16-
if (address === "0x0000000000000000000000000000000000000003")
17+
if (address.toLowerCase() === ETH_ADDRESS.toLowerCase())
1718
return <span>ETH</span>;
1819

1920
return <span>{tokenSymbol || formatAddress(address)}</span>;
@@ -26,9 +27,7 @@ describe("CurrencyLabel", () => {
2627
});
2728

2829
it("renders ETH for ETH address", () => {
29-
render(
30-
<CurrencyLabel address="0x0000000000000000000000000000000000000003" />,
31-
);
30+
render(<CurrencyLabel address={ETH_ADDRESS} />);
3231
expect(screen.getByText("ETH")).toBeInTheDocument();
3332
});
3433

@@ -55,7 +54,7 @@ describe("CurrencyLabel", () => {
5554
it("handles different ETH address formats", () => {
5655
render(
5756
<CurrencyLabel
58-
address="0x0000000000000000000000000000000000000003"
57+
address={ETH_ADDRESS}
5958
tokenSymbol="SHOULD_NOT_SHOW"
6059
/>,
6160
);

client/__tests__/TokenInfoHook.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Test for the token info resolution functionality
2+
import { ETH_ADDRESS } from "@/lib/blockchain/constants";
23

34
describe("Token Info Hook Logic", () => {
45
// Mock the hook behavior for testing
56
const mockTokenInfo = (address: string, mockData: any) => {
6-
const ETH_ADDRESS = "0x0000000000000000000000000000000000000003";
77
const _isERC20 = address && address !== ETH_ADDRESS;
88

99
if (address === ETH_ADDRESS) {
@@ -31,10 +31,7 @@ describe("Token Info Hook Logic", () => {
3131

3232
describe("Token Info Resolution", () => {
3333
it("returns ETH info for ETH address", () => {
34-
const result = mockTokenInfo(
35-
"0x0000000000000000000000000000000000000003",
36-
null,
37-
);
34+
const result = mockTokenInfo(ETH_ADDRESS, null);
3835

3936
expect(result).toEqual({
4037
symbol: "ETH",

client/__tests__/hooks/jar/useJarTransactions.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ describe("useJarTransactions - Unit Tests", () => {
5757
const validPurpose = "Team expenses for development work";
5858
const invalidPurpose = "short";
5959

60-
expect(validPurpose.length).toBeGreaterThan(10);
61-
expect(invalidPurpose.length).toBeLessThan(10);
60+
expect(validPurpose.length).toBeGreaterThan(27);
61+
expect(invalidPurpose.length).toBeLessThan(27);
6262
});
6363
});
6464

client/__tests__/hooks/useJarCreation.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ vi.mock("@/config/deployments.auto", () => ({
1919
}));
2020

2121
import { useJarCreation } from "@/hooks/jar/useJarCreation";
22+
import { ETH_ADDRESS } from "@/lib/blockchain/constants";
2223

2324
// Mock wagmi hooks
2425
vi.mock("wagmi", () => ({
@@ -98,17 +99,13 @@ describeOrSkip("useJarCreation", () => {
9899
it("should use address(3) for ETH address", () => {
99100
const { result } = renderHookWithProviders();
100101

101-
expect(result.current.ETH_ADDRESS).toBe(
102-
"0x0000000000000000000000000000000000000003",
103-
);
102+
expect(result.current.ETH_ADDRESS).toBe(ETH_ADDRESS);
104103
});
105104

106105
it("should initialize supportedCurrency with correct ETH address", () => {
107106
const { result } = renderHookWithProviders();
108107

109-
expect(result.current.supportedCurrency).toBe(
110-
"0x0000000000000000000000000000000000000003",
111-
);
108+
expect(result.current.supportedCurrency).toBe(ETH_ADDRESS);
112109
});
113110
});
114111

client/__tests__/utils/ProtocolValidation.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ describe("Protocol Validation Utilities", () => {
263263
return { isValid: false, error: "Purpose is required" };
264264
}
265265

266-
if (purpose.length < 10) {
266+
if (purpose.length < 27) {
267267
return {
268268
isValid: false,
269-
error: "Purpose must be at least 10 characters",
269+
error: "Purpose must be at least 27 characters",
270270
};
271271
}
272272

client/app/profile/page.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
getExplorerAddressUrl,
3939
getNetworkName,
4040
} from "@/lib/blockchain/networks";
41+
import { ETH_ADDRESS } from "@/lib/blockchain/token-utils";
4142
import { getAccessTypeName } from "@/lib/jar/access-types";
4243

4344
export default function ProfilePage() {
@@ -253,8 +254,8 @@ function DesktopProfile() {
253254
Currency:
254255
</span>
255256
<span className="text-[hsl(var(--cj-dark-brown))]">
256-
{jar.currency ===
257-
"0x0000000000000000000000000000000000000003"
257+
{jar.currency?.toLowerCase() ===
258+
ETH_ADDRESS.toLowerCase()
258259
? `${nativeCurrency.symbol} (Native)`
259260
: "ERC20"}
260261
</span>

client/components/create/StepContent.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ const BasicConfigStep: React.FC<{ formData: any }> = ({ formData }) => {
127127
</svg>
128128
</Button>
129129
</div>
130-
<p className="text-sm text-gray-600 mt-1">
130+
<p className="text-sm text-muted-foreground mt-1">
131131
{formData.jarOwnerAddress &&
132132
formData.jarOwnerAddress !==
133133
"0x0000000000000000000000000000000000000000"
@@ -157,7 +157,7 @@ const BasicConfigStep: React.FC<{ formData: any }> = ({ formData }) => {
157157
<SelectItem key={option.value} value={option.value}>
158158
<div>
159159
<div className="font-medium">{option.label}</div>
160-
<div className="text-sm text-gray-600">
160+
<div className="text-sm text-muted-foreground">
161161
{option.description}
162162
</div>
163163
</div>
@@ -332,7 +332,7 @@ const WithdrawalSettingsStep: React.FC<{ formData: any }> = ({ formData }) => {
332332
)}
333333
/>
334334
<Label htmlFor="strictPurpose" className="text-sm">
335-
Require purpose description (minimum 20 characters)
335+
Require purpose description (minimum 27 characters)
336336
</Label>
337337
</div>
338338

@@ -381,6 +381,7 @@ const AccessControlStep: React.FC<{ formData: any }> = ({ formData }) => {
381381
<ProtocolSelector
382382
onConfigChange={formData.handleProtocolConfigChange}
383383
initialConfig={formData.protocolConfig}
384+
showViewToggle={false}
384385
/>
385386

386387
{formData.accessType === AccessType.NFTGated && (

client/components/jar/AllowlistWithdrawalSection.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
useTokenInfo,
1414
} from "@/lib/blockchain/token-utils";
1515

16+
const PURPOSE_MIN_LENGTH = 27;
17+
1618
interface AllowlistWithdrawalSectionProps {
1719
config: any; // Ideally this would be more specifically typed
1820
withdrawPurpose: string;
@@ -34,6 +36,7 @@ export const AllowlistWithdrawalSection: React.FC<
3436
handleWithdrawAllowlist,
3537
handleWithdrawAllowlistVariable,
3638
}) => {
39+
3740
// Get token information using the token utils
3841
const { symbol: tokenSymbol, decimals: tokenDecimals } = useTokenInfo(
3942
config?.currency || ETH_ADDRESS,
@@ -70,7 +73,7 @@ export const AllowlistWithdrawalSection: React.FC<
7073
className="w-full bg-[#ff5e14] hover:bg-[#e54d00] text-white py-6 text-lg"
7174
disabled={
7275
!withdrawPurpose ||
73-
withdrawPurpose.length < 10 ||
76+
withdrawPurpose.length < PURPOSE_MIN_LENGTH ||
7477
config.isWithdrawPending
7578
}
7679
>
@@ -210,7 +213,7 @@ export const AllowlistWithdrawalSection: React.FC<
210213
!withdrawAmount ||
211214
Number(withdrawAmount) <= 0 ||
212215
!withdrawPurpose ||
213-
withdrawPurpose.length < 10 ||
216+
withdrawPurpose.length < PURPOSE_MIN_LENGTH ||
214217
config.isWithdrawPending
215218
}
216219
>

client/components/jar/JarDepositSection.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Input } from "@/components/ui/input";
77
import { getNativeCurrency } from "@/config/supported-networks";
88
import { useCookieJarConfig } from "@/hooks/jar/useJar";
99
import { useJarTransactions } from "@/hooks/jar/useJarTransactions";
10+
import { ETH_ADDRESS } from "@/lib/blockchain/token-utils";
1011

1112
export function JarDepositSection() {
1213
const params = useParams();
@@ -27,6 +28,9 @@ export function JarDepositSection() {
2728

2829
if (!config) return null;
2930

31+
const isNativeCurrency =
32+
config.currency?.toLowerCase() === ETH_ADDRESS.toLowerCase();
33+
3034
return (
3135
<div className="space-y-6">
3236
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
@@ -61,7 +65,7 @@ export function JarDepositSection() {
6165
id="fundAmount"
6266
type="text"
6367
placeholder={
64-
config.currency === "0x0000000000000000000000000000000000000003"
68+
isNativeCurrency
6569
? `0.1 ${nativeCurrency.symbol}`
6670
: `1${`.${"0".repeat(tokenDecimals > 0 ? 0 : tokenDecimals)}`} ${tokenSymbol || "Tokens"}`
6771
}
@@ -81,7 +85,7 @@ export function JarDepositSection() {
8185
</div>
8286
</div>
8387

84-
{config.currency !== "0x0000000000000000000000000000000000000003" && (
88+
{!isNativeCurrency && (
8589
<div className="pt-2">
8690
<p className="text-sm text-[#8b7355]">
8791
Note: For ERC20 tokens, you&apos;ll need to approve the token

0 commit comments

Comments
 (0)