Skip to content

Commit 182d47b

Browse files
authored
chore: replace ens image with starknet (#666)
1 parent 74fcb56 commit 182d47b

File tree

10 files changed

+161
-83
lines changed

10 files changed

+161
-83
lines changed

.cursorrules

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ import { Balance } from "~~/components/scaffold-stark";
265265
<description>
266266
Show a blockie (bar code profile icon) component for a given Starknet address.
267267

268-
The autogenerated blockie can be manually replaced by another image that we pass through the `ensImage` prop.
268+
If a Starknet ID profile picture is available, prefer rendering that image in the parent and fallback to `BlockieAvatar` otherwise. `BlockieAvatar` itself always renders a blo-generated identicon for the provided address.
269269

270270
If you want more control over styling the blockie, you can directly use blo (pre-installed in Scaffold-Stark 2) and internally used by `BlockieAvatar` component to get the image URL.
271271
</description>
@@ -294,10 +294,45 @@ import { BlockieAvatar } from "~~/components/scaffold-stark";
294294
|------|------|---------------|-------------|
295295
| `address` | `string` | `undefined` | The address for which you want to display its blockie. Ensure it's in the `0x___` format. |
296296
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
297-
| `ensImage` (optional) | `string` | `undefined` | An arbitrary image url to render instead of the blockie. |
298297
</props>
299298
</blockie_avatar_component>
300299

300+
<avatar_component>
301+
302+
<description>
303+
Reusable avatar component that renders a Starknet ID profile picture when provided; otherwise falls back to a blo-generated blockie for the given address.
304+
</description>
305+
306+
<import_statement>
307+
308+
```tsx
309+
import { Avatar } from "~~/components/scaffold-stark";
310+
```
311+
312+
</import_statement>
313+
314+
<usage_example>
315+
316+
```tsx
317+
<Avatar
318+
address="0x034aA3F359A9D614239015126635CE7732c18fDF3"
319+
size={30}
320+
profilePicture={profile?.profilePicture}
321+
/>
322+
```
323+
324+
</usage_example>
325+
326+
<props>
327+
| Prop | Type | Default Value | Description |
328+
|------|------|---------------|-------------|
329+
| `address` | `string` | `undefined` | The address used to render a fallback blockie if no profile picture is available. Must be in `0x___` format. |
330+
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
331+
| `profilePicture` (optional) | `string` | `undefined` | Starknet ID profile picture URL. If present, it will be rendered. |
332+
| `className` (optional) | `string` | `undefined` | Extra class names applied to the rendered image. |
333+
</props>
334+
</avatar_component>
335+
301336
<stark_input_component>
302337

303338
<source>https://www.scaffoldstark.com/docs/components/StarkInput</source>

.github/copilot-instructions.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ Source: https://www.scaffoldstark.com/docs/components/BlockieAvatar
204204

205205
Show a blockie (bar code profile icon) component for a given Starknet address.
206206

207-
The autogenerated blockie can be manually replaced by another image that we pass through the `ensImage` prop.
207+
If a Starknet ID profile picture is available, prefer rendering that image in the parent and fallback to `BlockieAvatar` otherwise. `BlockieAvatar` itself always renders a blo-generated identicon for the provided address.
208208

209209
If you want more control over styling the blockie, you can directly use [blo](https://github.com/bpierre/blo) (pre-installed in Scaffold-Stark 2) and internally used by `BlockieAvatar` component to get the image URL.
210210

@@ -225,11 +225,39 @@ import { BlockieAvatar } from "~~/components/scaffold-stark";
225225

226226
#### Props
227227

228-
| Prop | Type | Default Value | Description |
229-
| --------------------- | -------- | ------------- | ----------------------------------------------------------------------------------------- |
230-
| `address` | `string` | `undefined` | The address for which you want to display its blockie. Ensure it's in the `0x___` format. |
231-
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
232-
| `ensImage` (optional) | `string` | `undefined` | An arbitrary image url to render instead of the blockie. |
228+
| Prop | Type | Default Value | Description |
229+
| --------- | -------- | ------------- | ----------------------------------------------------------------------------------------- |
230+
| `address` | `string` | `undefined` | The address for which you want to display its blockie. Ensure it's in the `0x___` format. |
231+
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
232+
233+
### Avatar
234+
235+
Reusable avatar component that renders a Starknet ID profile picture when provided; otherwise falls back to a blo-generated blockie for the given address.
236+
237+
#### Import
238+
239+
```tsx
240+
import { Avatar } from "~~/components/scaffold-stark";
241+
```
242+
243+
#### Usage
244+
245+
```tsx
246+
<Avatar
247+
address="0x034aA3F359A9D614239015126635CE7732c18fDF3"
248+
size={30}
249+
profilePicture={profile?.profilePicture}
250+
/>
251+
```
252+
253+
#### Props
254+
255+
| Prop | Type | Default Value | Description |
256+
| ------------------ | -------- | ------------- | ------------------------------------------------------------------------------------------------------------ |
257+
| `address` | `string` | `undefined` | The address used to render a fallback blockie if no profile picture is available. Must be in `0x___` format. |
258+
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
259+
| `profilePicture` | `string` | `undefined` | Starknet ID profile picture URL. If present, it will be rendered. |
260+
| `className` (opt.) | `string` | `undefined` | Extra class names applied to the rendered image. |
233261

234262
### StarkInput
235263

global_rules.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ Source: https://www.scaffoldstark.com/docs/components/BlockieAvatar
204204

205205
Show a blockie (bar code profile icon) component for a given Starknet address.
206206

207-
The autogenerated blockie can be manually replaced by another image that we pass through the `ensImage` prop.
207+
If a Starknet ID profile picture is available, prefer rendering that image in the parent and fallback to `BlockieAvatar` otherwise. `BlockieAvatar` itself always renders a blo-generated identicon for the provided address.
208208

209209
If you want more control over styling the blockie, you can directly use [blo](https://github.com/bpierre/blo) (pre-installed in Scaffold-Stark 2) and internally used by `BlockieAvatar` component to get the image URL.
210210

@@ -225,11 +225,39 @@ import { BlockieAvatar } from "~~/components/scaffold-stark";
225225

226226
#### Props
227227

228-
| Prop | Type | Default Value | Description |
229-
| --------------------- | -------- | ------------- | ----------------------------------------------------------------------------------------- |
230-
| `address` | `string` | `undefined` | The address for which you want to display its blockie. Ensure it's in the `0x___` format. |
231-
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
232-
| `ensImage` (optional) | `string` | `undefined` | An arbitrary image url to render instead of the blockie. |
228+
| Prop | Type | Default Value | Description |
229+
| --------- | -------- | ------------- | ----------------------------------------------------------------------------------------- |
230+
| `address` | `string` | `undefined` | The address for which you want to display its blockie. Ensure it's in the `0x___` format. |
231+
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
232+
233+
### Avatar
234+
235+
Reusable avatar component that renders a Starknet ID profile picture when provided; otherwise falls back to a blo-generated blockie for the given address.
236+
237+
#### Import
238+
239+
```tsx
240+
import { Avatar } from "~~/components/scaffold-stark";
241+
```
242+
243+
#### Usage
244+
245+
```tsx
246+
<Avatar
247+
address="0x034aA3F359A9D614239015126635CE7732c18fDF3"
248+
size={30}
249+
profilePicture={profile?.profilePicture}
250+
/>
251+
```
252+
253+
#### Props
254+
255+
| Prop | Type | Default Value | Description |
256+
| ------------------ | -------- | ------------- | ------------------------------------------------------------------------------------------------------------ |
257+
| `address` | `string` | `undefined` | The address used to render a fallback blockie if no profile picture is available. Must be in `0x___` format. |
258+
| `size` | `number` | `undefined` | Width and Height in pixels (square). |
259+
| `profilePicture` | `string` | `undefined` | Starknet ID profile picture URL. If present, it will be rendered. |
260+
| `className` (opt.) | `string` | `undefined` | Extra class names applied to the rendered image. |
233261

234262
### StarkInput
235263

packages/nextjs/components/scaffold-stark/Address.tsx

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import {
1212
} from "@heroicons/react/24/outline";
1313
import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork";
1414
import { getBlockExplorerAddressLink } from "~~/utils/scaffold-stark";
15-
import { BlockieAvatar } from "~~/components/scaffold-stark/BlockieAvatar";
16-
import { getStarknetPFPIfExists } from "~~/utils/profile";
17-
import { default as NextImage } from "next/image";
15+
import { Avatar } from "~~/components/scaffold-stark/Avatar";
1816
import CopyToClipboard from "react-copy-to-clipboard";
1917

2018
type AddressProps = {
@@ -123,21 +121,11 @@ export const Address = ({
123121
return (
124122
<div className="flex items-center">
125123
<div className="shrink-0">
126-
{getStarknetPFPIfExists(profile?.profilePicture) ? (
127-
<NextImage
128-
src={profile?.profilePicture || ""}
129-
alt="Profile Picture"
130-
className="rounded-full"
131-
width={24}
132-
height={24}
133-
/>
134-
) : (
135-
<BlockieAvatar
136-
address={checkSumAddress}
137-
size={(blockieSizeMap[size] * 24) / blockieSizeMap["base"]}
138-
ensImage={ensAvatar}
139-
/>
140-
)}
124+
<Avatar
125+
address={checkSumAddress}
126+
size={(blockieSizeMap[size] * 24) / blockieSizeMap["base"]}
127+
profilePicture={profile?.profilePicture}
128+
/>
141129
</div>
142130
{disableAddressLink ? (
143131
<span className={`ml-1.5 text-${size} font-normal`}>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"use client";
2+
3+
import { default as NextImage } from "next/image";
4+
import { BlockieAvatar } from "./BlockieAvatar";
5+
import { getStarknetPFPIfExists } from "~~/utils/profile";
6+
7+
type AvatarProps = {
8+
address: string;
9+
size: number;
10+
profilePicture?: string;
11+
className?: string;
12+
};
13+
14+
export const Avatar = ({
15+
address,
16+
size,
17+
profilePicture,
18+
className,
19+
}: AvatarProps) => {
20+
const pfp = getStarknetPFPIfExists(profilePicture);
21+
if (pfp) {
22+
return (
23+
<NextImage
24+
src={pfp}
25+
alt="Profile Picture"
26+
className={`rounded-full ${className ?? ""}`}
27+
width={size}
28+
height={size}
29+
/>
30+
);
31+
}
32+
return <BlockieAvatar address={address} size={size} />;
33+
};

packages/nextjs/components/scaffold-stark/BlockieAvatar.tsx

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,15 @@
11
"use client";
22

33
import { blo } from "blo";
4-
import { useState, useEffect } from "react";
54

65
interface BlockieAvatarProps {
76
address: string;
8-
ensImage?: string | null;
97
size: number;
108
}
119

1210
// Custom Avatar for RainbowKit
13-
export const BlockieAvatar = ({
14-
address,
15-
ensImage,
16-
size,
17-
}: BlockieAvatarProps) => {
18-
const [avatarSrc, setAvatarSrc] = useState<string>("");
19-
const [isLoading, setIsLoading] = useState(true);
20-
21-
useEffect(() => {
22-
if (ensImage) {
23-
setAvatarSrc(ensImage);
24-
setIsLoading(false);
25-
} else {
26-
const avatarUrl = blo(address as `0x${string}`);
27-
setAvatarSrc(avatarUrl);
28-
setIsLoading(false);
29-
}
30-
}, [address, ensImage]);
31-
32-
if (isLoading) {
33-
return (
34-
<div
35-
className="rounded-full bg-gray-200 dark:bg-gray-700 animate-pulse"
36-
style={{ width: size, height: size }}
37-
/>
38-
);
39-
}
40-
11+
export const BlockieAvatar = ({ address, size }: BlockieAvatarProps) => {
12+
const avatarSrc = blo(address as `0x${string}`);
4113
return (
4214
// Don't want to use nextJS Image here (and adding remote patterns for the URL)
4315
// eslint-disable-next-line @next/next/no-img-element

packages/nextjs/components/scaffold-stark/CustomConnectButton/AddressInfoDropdown.tsx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,29 @@ import {
1212
UserCircleIcon,
1313
} from "@heroicons/react/24/outline";
1414
import { useLocalStorage } from "usehooks-ts";
15-
import { BlockieAvatar, isENS } from "~~/components/scaffold-stark";
15+
import {
16+
Avatar,
17+
BlockieAvatar,
18+
isStarknetName,
19+
} from "~~/components/scaffold-stark";
1620
import { useOutsideClick } from "~~/hooks/scaffold-stark";
1721
import { BurnerConnector, burnerAccounts } from "@scaffold-stark/stark-burner";
1822
import { getTargetNetworks, notification } from "~~/utils/scaffold-stark";
1923
import { Address } from "@starknet-react/chains";
2024
import { useDisconnect, useNetwork, useConnect } from "@starknet-react/core";
21-
import { getStarknetPFPIfExists } from "~~/utils/profile";
2225
import { useScaffoldStarkProfile } from "~~/hooks/scaffold-stark/useScaffoldStarkProfile";
2326
import { useTheme } from "next-themes";
24-
import { default as NextImage } from "next/image";
2527

2628
const allowedNetworks = getTargetNetworks();
2729

2830
type AddressInfoDropdownProps = {
2931
address: Address;
3032
blockExplorerAddressLink: string | undefined;
3133
displayName: string;
32-
ensAvatar?: string;
3334
};
3435

3536
export const AddressInfoDropdown = ({
3637
address,
37-
ensAvatar,
3838
displayName,
3939
blockExplorerAddressLink,
4040
}: AddressInfoDropdownProps) => {
@@ -102,20 +102,14 @@ export const AddressInfoDropdown = ({
102102
<details ref={dropdownRef} className="dropdown dropdown-end leading-3">
103103
<summary className="btn bg-transparent btn-sm px-2 py-[0.35rem] dropdown-toggle gap-0 !h-auto border border-[#5c4fe5] ">
104104
<div className="hidden [@media(min-width:412px)]:block">
105-
{getStarknetPFPIfExists(profile?.profilePicture) ? (
106-
<NextImage
107-
src={profile?.profilePicture || ""}
108-
alt="Profile Picture"
109-
className="rounded-full"
110-
width={30}
111-
height={30}
112-
/>
113-
) : (
114-
<BlockieAvatar address={address} size={28} ensImage={ensAvatar} />
115-
)}
105+
<Avatar
106+
address={address}
107+
size={30}
108+
profilePicture={profile?.profilePicture}
109+
/>
116110
</div>
117111
<span className="ml-2 mr-2 text-sm">
118-
{isENS(displayName)
112+
{isStarknetName(displayName)
119113
? displayName
120114
: profile?.name ||
121115
address?.slice(0, 6) + "..." + address?.slice(-4)}

packages/nextjs/components/scaffold-stark/CustomConnectButton/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ export const CustomConnectButton = () => {
101101
<AddressInfoDropdown
102102
address={accountAddress as Address}
103103
displayName=""
104-
ensAvatar=""
105104
blockExplorerAddressLink={blockExplorerAddressLink}
106105
/>
107106
<AddressQRCodeModal

packages/nextjs/components/scaffold-stark/Input/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,6 @@ const fitsWithinBitCount = (
7676

7777
return true;
7878
};
79-
// Treat any dot-separated string as a potential ENS name
80-
const ensRegex = /.+\..+/;
81-
export const isENS = (address = "") => ensRegex.test(address);
79+
// Treat any dot-separated string as a potential starknet name
80+
const starknetNameRegex = /.+\..+/;
81+
export const isStarknetName = (address = "") => starknetNameRegex.test(address);

packages/nextjs/components/scaffold-stark/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ export * from "./Address";
22
export * from "./Balance";
33
export * from "./Input";
44
export * from "./BlockieAvatar";
5+
export * from "./Avatar";
56
export * from "./Faucet";
67
export * from "./SearchBar";

0 commit comments

Comments
 (0)