@b3dotfun/sdk 0.0.63-alpha.0 → 0.0.63-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/cjs/global-account/react/components/B3DynamicModal.js +7 -3
  2. package/dist/cjs/global-account/react/components/ManageAccount/BalanceContent.js +3 -3
  3. package/dist/cjs/global-account/react/components/ProfileEditor/ProfileEditor.d.ts +6 -0
  4. package/dist/cjs/global-account/react/components/ProfileEditor/ProfileEditor.js +141 -0
  5. package/dist/cjs/global-account/react/components/index.d.ts +2 -0
  6. package/dist/cjs/global-account/react/components/index.js +7 -2
  7. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +7 -1
  8. package/dist/cjs/global-account/react/utils/profileDisplay.d.ts +6 -0
  9. package/dist/cjs/global-account/react/utils/profileDisplay.js +60 -4
  10. package/dist/esm/global-account/react/components/B3DynamicModal.js +7 -3
  11. package/dist/esm/global-account/react/components/ManageAccount/BalanceContent.js +3 -3
  12. package/dist/esm/global-account/react/components/ProfileEditor/ProfileEditor.d.ts +6 -0
  13. package/dist/esm/global-account/react/components/ProfileEditor/ProfileEditor.js +135 -0
  14. package/dist/esm/global-account/react/components/index.d.ts +2 -0
  15. package/dist/esm/global-account/react/components/index.js +3 -0
  16. package/dist/esm/global-account/react/stores/useModalStore.d.ts +7 -1
  17. package/dist/esm/global-account/react/utils/profileDisplay.d.ts +6 -0
  18. package/dist/esm/global-account/react/utils/profileDisplay.js +59 -4
  19. package/dist/types/global-account/react/components/ProfileEditor/ProfileEditor.d.ts +6 -0
  20. package/dist/types/global-account/react/components/index.d.ts +2 -0
  21. package/dist/types/global-account/react/stores/useModalStore.d.ts +7 -1
  22. package/dist/types/global-account/react/utils/profileDisplay.d.ts +6 -0
  23. package/package.json +2 -2
  24. package/src/global-account/react/components/B3DynamicModal.tsx +7 -3
  25. package/src/global-account/react/components/ManageAccount/BalanceContent.tsx +4 -4
  26. package/src/global-account/react/components/ProfileEditor/ProfileEditor.tsx +265 -0
  27. package/src/global-account/react/components/index.ts +4 -0
  28. package/src/global-account/react/stores/useModalStore.ts +9 -1
  29. package/src/global-account/react/utils/profileDisplay.ts +67 -4
@@ -1,5 +1,68 @@
1
+ import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
1
2
  import { type Profile } from "thirdweb/wallets";
2
3
 
4
+ const debug = debugB3React("profileDisplay");
5
+
6
+ /**
7
+ * Validates that an image URL uses an allowed schema
8
+ * @param url - The URL to validate
9
+ * @returns The URL if valid, null otherwise
10
+ */
11
+ export function validateImageUrl(url: string | null | undefined): string | null {
12
+ if (!url) return null;
13
+
14
+ try {
15
+ // For blob URLs (from createObjectURL)
16
+ if (url.startsWith("blob:")) {
17
+ return url;
18
+ }
19
+
20
+ // For IPFS protocol URLs
21
+ if (url.startsWith("ipfs://")) {
22
+ return url;
23
+ }
24
+
25
+ // Parse URL to validate protocol and hostname
26
+ const parsedUrl = new URL(url);
27
+
28
+ // Only allow http and https protocols
29
+ if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
30
+ debug("Rejected unsafe protocol:", parsedUrl.protocol, url);
31
+ return null;
32
+ }
33
+
34
+ // Whitelist of allowed IPFS gateway hostnames
35
+ const allowedIpfsGateways = [
36
+ "ipfs.io",
37
+ "gateway.pinata.cloud",
38
+ "cloudflare-ipfs.com",
39
+ "dweb.link",
40
+ "nftstorage.link",
41
+ "w3s.link",
42
+ ];
43
+
44
+ // Check if hostname matches allowed IPFS gateways
45
+ const hostname = parsedUrl.hostname.toLowerCase();
46
+ const isAllowedIpfsGateway = allowedIpfsGateways.some(gateway => {
47
+ // Exact match or subdomain of the gateway
48
+ return hostname === gateway || hostname.endsWith(`.${gateway}`);
49
+ });
50
+
51
+ if (isAllowedIpfsGateway) {
52
+ return url;
53
+ }
54
+
55
+ // For standard HTTP(S) URLs from trusted sources
56
+ // Add additional hostname validation here if needed
57
+ // For now, allow all HTTP(S) URLs (can be restricted further if needed)
58
+ return url;
59
+ } catch (error) {
60
+ // Invalid URL format
61
+ debug("Invalid image URL format:", url, error);
62
+ return null;
63
+ }
64
+ }
65
+
3
66
  export interface ExtendedProfileDetails {
4
67
  id?: string;
5
68
  email?: string;
@@ -40,7 +103,7 @@ export function getProfileDisplayInfo(profile: ExtendedProfile): ProfileDisplayI
40
103
  displayInfo = {
41
104
  title: details.name || details.username || "Unknown",
42
105
  subtitle: details.username ? `@${details.username}` : "X Account",
43
- imageUrl: details.profileImageUrl || null,
106
+ imageUrl: validateImageUrl(details.profileImageUrl),
44
107
  initial: "X",
45
108
  type,
46
109
  };
@@ -49,7 +112,7 @@ export function getProfileDisplayInfo(profile: ExtendedProfile): ProfileDisplayI
49
112
  displayInfo = {
50
113
  title: details.name || details.username || "Unknown",
51
114
  subtitle: details.username ? `@${details.username}` : "Farcaster Account",
52
- imageUrl: details.profileImageUrl || null,
115
+ imageUrl: validateImageUrl(details.profileImageUrl),
53
116
  initial: "F",
54
117
  type,
55
118
  };
@@ -58,7 +121,7 @@ export function getProfileDisplayInfo(profile: ExtendedProfile): ProfileDisplayI
58
121
  displayInfo = {
59
122
  title: details.name || details.email || "Unknown",
60
123
  subtitle: details.email || "Google Account",
61
- imageUrl: details.profileImageUrl || null,
124
+ imageUrl: validateImageUrl(details.profileImageUrl),
62
125
  initial: "G",
63
126
  type,
64
127
  };
@@ -67,7 +130,7 @@ export function getProfileDisplayInfo(profile: ExtendedProfile): ProfileDisplayI
67
130
  displayInfo = {
68
131
  title: details.username || details.name || "Unknown",
69
132
  subtitle: "Discord Account",
70
- imageUrl: details.profileImageUrl || null,
133
+ imageUrl: validateImageUrl(details.profileImageUrl),
71
134
  initial: "D",
72
135
  type,
73
136
  };