@b3dotfun/sdk 0.0.10-alpha.7 → 0.0.11

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.
@@ -20,6 +20,7 @@ export { useMediaQuery } from "./useMediaQuery";
20
20
  export { useNativeBalance, useNativeBalanceFromRPC } from "./useNativeBalance";
21
21
  export { useOnchainName } from "./useOnchainName";
22
22
  export { useOneBalance } from "./useOneBalance";
23
+ export { useProfile, useProfilePreference, type Profile, type CombinedProfile, type PreferenceRequestBody, } from "./useProfile";
23
24
  export { useQueryB3 } from "./useQueryB3";
24
25
  export { useQueryBSMNT } from "./useQueryBSMNT";
25
26
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useURLParams = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalance = exports.useSiwe = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useOneBalance = exports.useOnchainName = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGetGeo = exports.useGetAllTWSigners = exports.useExchangeRate = exports.useConnect = exports.useClaim = exports.useChainSwitchWithAction = exports.useBsmntProfile = exports.useBestTransactionPath = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = void 0;
3
+ exports.useURLParams = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalance = exports.useSiwe = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useProfilePreference = exports.useProfile = exports.useOneBalance = exports.useOnchainName = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGetGeo = exports.useGetAllTWSigners = exports.useExchangeRate = exports.useConnect = exports.useClaim = exports.useChainSwitchWithAction = exports.useBsmntProfile = exports.useBestTransactionPath = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = void 0;
4
4
  var useAccountAssets_1 = require("./useAccountAssets");
5
5
  Object.defineProperty(exports, "useAccountAssets", { enumerable: true, get: function () { return useAccountAssets_1.useAccountAssets; } });
6
6
  var useAccountWallet_1 = require("./useAccountWallet");
@@ -46,6 +46,9 @@ var useOnchainName_1 = require("./useOnchainName");
46
46
  Object.defineProperty(exports, "useOnchainName", { enumerable: true, get: function () { return useOnchainName_1.useOnchainName; } });
47
47
  var useOneBalance_1 = require("./useOneBalance");
48
48
  Object.defineProperty(exports, "useOneBalance", { enumerable: true, get: function () { return useOneBalance_1.useOneBalance; } });
49
+ var useProfile_1 = require("./useProfile");
50
+ Object.defineProperty(exports, "useProfile", { enumerable: true, get: function () { return useProfile_1.useProfile; } });
51
+ Object.defineProperty(exports, "useProfilePreference", { enumerable: true, get: function () { return useProfile_1.useProfilePreference; } });
49
52
  var useQueryB3_1 = require("./useQueryB3");
50
53
  Object.defineProperty(exports, "useQueryB3", { enumerable: true, get: function () { return useQueryB3_1.useQueryB3; } });
51
54
  var useQueryBSMNT_1 = require("./useQueryBSMNT");
@@ -0,0 +1,38 @@
1
+ export interface Profile {
2
+ type: string;
3
+ address?: string;
4
+ name?: string;
5
+ avatar?: string | null;
6
+ bio?: string | null;
7
+ displayName?: string | null;
8
+ }
9
+ export interface CombinedProfile {
10
+ name: string | null;
11
+ address: string | null;
12
+ avatar: string | null;
13
+ bio: string | null;
14
+ displayName: string | null;
15
+ profiles: Profile[];
16
+ }
17
+ export interface PreferenceRequestBody {
18
+ key: string;
19
+ preferredType: string;
20
+ signature: string;
21
+ signer: string;
22
+ timestamp: number;
23
+ }
24
+ export declare function useProfile({ address, name, fresh, }: {
25
+ address?: string;
26
+ name?: string;
27
+ fresh?: boolean;
28
+ }, options?: {
29
+ enabled?: boolean;
30
+ refetchInterval?: number;
31
+ staleTime?: number;
32
+ }): import("@tanstack/react-query").UseQueryResult<CombinedProfile, Error>;
33
+ export declare function useProfilePreference(): {
34
+ setPreference: (key: string, preferredType: string, signerAddress: string, signMessage: (message: string) => Promise<string>) => Promise<{
35
+ success: boolean;
36
+ }>;
37
+ };
38
+ export default useProfile;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useProfile = useProfile;
4
+ exports.useProfilePreference = useProfilePreference;
5
+ const react_query_1 = require("@tanstack/react-query");
6
+ const PROFILES_API_URL = "https://profiles.b3.fun";
7
+ async function fetchProfile({ address, name, fresh = false, }) {
8
+ if (!address && !name) {
9
+ throw new Error("Either address or name must be provided");
10
+ }
11
+ const params = new URLSearchParams();
12
+ if (address)
13
+ params.append("address", address);
14
+ if (name)
15
+ params.append("name", name);
16
+ if (fresh)
17
+ params.append("fresh", "true");
18
+ const response = await fetch(`${PROFILES_API_URL}?${params.toString()}`);
19
+ if (!response.ok) {
20
+ throw new Error(`Failed to fetch profile: ${response.statusText}`);
21
+ }
22
+ return response.json();
23
+ }
24
+ async function setProfilePreference({ key, preferredType, signature, signer, timestamp, }) {
25
+ const response = await fetch(`${PROFILES_API_URL}/preference`, {
26
+ method: "POST",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ },
30
+ body: JSON.stringify({
31
+ key,
32
+ preferredType,
33
+ signature,
34
+ signer,
35
+ timestamp,
36
+ }),
37
+ });
38
+ if (!response.ok) {
39
+ throw new Error(`Failed to set preference: ${response.statusText}`);
40
+ }
41
+ return response.json();
42
+ }
43
+ function useProfile({ address, name, fresh = false, }, options) {
44
+ return (0, react_query_1.useQuery)({
45
+ queryKey: ["profile", address || name, fresh],
46
+ queryFn: () => fetchProfile({ address, name, fresh }),
47
+ enabled: (options?.enabled ?? true) && (!!address || !!name),
48
+ refetchInterval: options?.refetchInterval,
49
+ staleTime: options?.staleTime ?? 5 * 60 * 1000, // 5 minutes default
50
+ });
51
+ }
52
+ function useProfilePreference() {
53
+ const setPreference = async (key, preferredType, signerAddress, signMessage) => {
54
+ const timestamp = Math.floor(Date.now() / 1000);
55
+ const message = `SetProfilePreference:${key}:${preferredType}:${timestamp}`;
56
+ try {
57
+ const signature = await signMessage(message);
58
+ return setProfilePreference({
59
+ key,
60
+ preferredType,
61
+ signature,
62
+ signer: signerAddress,
63
+ timestamp,
64
+ });
65
+ }
66
+ catch (error) {
67
+ throw new Error(`Failed to set profile preference: ${error}`);
68
+ }
69
+ };
70
+ return { setPreference };
71
+ }
72
+ exports.default = useProfile;
@@ -20,6 +20,7 @@ export { useMediaQuery } from "./useMediaQuery";
20
20
  export { useNativeBalance, useNativeBalanceFromRPC } from "./useNativeBalance";
21
21
  export { useOnchainName } from "./useOnchainName";
22
22
  export { useOneBalance } from "./useOneBalance";
23
+ export { useProfile, useProfilePreference, type Profile, type CombinedProfile, type PreferenceRequestBody, } from "./useProfile";
23
24
  export { useQueryB3 } from "./useQueryB3";
24
25
  export { useQueryBSMNT } from "./useQueryBSMNT";
25
26
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
@@ -20,6 +20,7 @@ export { useMediaQuery } from "./useMediaQuery.js";
20
20
  export { useNativeBalance, useNativeBalanceFromRPC } from "./useNativeBalance.js";
21
21
  export { useOnchainName } from "./useOnchainName.js";
22
22
  export { useOneBalance } from "./useOneBalance.js";
23
+ export { useProfile, useProfilePreference, } from "./useProfile.js";
23
24
  export { useQueryB3 } from "./useQueryB3.js";
24
25
  export { useQueryBSMNT } from "./useQueryBSMNT.js";
25
26
  export { useRemoveSessionKey } from "./useRemoveSessionKey.js";
@@ -0,0 +1,38 @@
1
+ export interface Profile {
2
+ type: string;
3
+ address?: string;
4
+ name?: string;
5
+ avatar?: string | null;
6
+ bio?: string | null;
7
+ displayName?: string | null;
8
+ }
9
+ export interface CombinedProfile {
10
+ name: string | null;
11
+ address: string | null;
12
+ avatar: string | null;
13
+ bio: string | null;
14
+ displayName: string | null;
15
+ profiles: Profile[];
16
+ }
17
+ export interface PreferenceRequestBody {
18
+ key: string;
19
+ preferredType: string;
20
+ signature: string;
21
+ signer: string;
22
+ timestamp: number;
23
+ }
24
+ export declare function useProfile({ address, name, fresh, }: {
25
+ address?: string;
26
+ name?: string;
27
+ fresh?: boolean;
28
+ }, options?: {
29
+ enabled?: boolean;
30
+ refetchInterval?: number;
31
+ staleTime?: number;
32
+ }): import("@tanstack/react-query").UseQueryResult<CombinedProfile, Error>;
33
+ export declare function useProfilePreference(): {
34
+ setPreference: (key: string, preferredType: string, signerAddress: string, signMessage: (message: string) => Promise<string>) => Promise<{
35
+ success: boolean;
36
+ }>;
37
+ };
38
+ export default useProfile;
@@ -0,0 +1,68 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ const PROFILES_API_URL = "https://profiles.b3.fun";
3
+ async function fetchProfile({ address, name, fresh = false, }) {
4
+ if (!address && !name) {
5
+ throw new Error("Either address or name must be provided");
6
+ }
7
+ const params = new URLSearchParams();
8
+ if (address)
9
+ params.append("address", address);
10
+ if (name)
11
+ params.append("name", name);
12
+ if (fresh)
13
+ params.append("fresh", "true");
14
+ const response = await fetch(`${PROFILES_API_URL}?${params.toString()}`);
15
+ if (!response.ok) {
16
+ throw new Error(`Failed to fetch profile: ${response.statusText}`);
17
+ }
18
+ return response.json();
19
+ }
20
+ async function setProfilePreference({ key, preferredType, signature, signer, timestamp, }) {
21
+ const response = await fetch(`${PROFILES_API_URL}/preference`, {
22
+ method: "POST",
23
+ headers: {
24
+ "Content-Type": "application/json",
25
+ },
26
+ body: JSON.stringify({
27
+ key,
28
+ preferredType,
29
+ signature,
30
+ signer,
31
+ timestamp,
32
+ }),
33
+ });
34
+ if (!response.ok) {
35
+ throw new Error(`Failed to set preference: ${response.statusText}`);
36
+ }
37
+ return response.json();
38
+ }
39
+ export function useProfile({ address, name, fresh = false, }, options) {
40
+ return useQuery({
41
+ queryKey: ["profile", address || name, fresh],
42
+ queryFn: () => fetchProfile({ address, name, fresh }),
43
+ enabled: (options?.enabled ?? true) && (!!address || !!name),
44
+ refetchInterval: options?.refetchInterval,
45
+ staleTime: options?.staleTime ?? 5 * 60 * 1000, // 5 minutes default
46
+ });
47
+ }
48
+ export function useProfilePreference() {
49
+ const setPreference = async (key, preferredType, signerAddress, signMessage) => {
50
+ const timestamp = Math.floor(Date.now() / 1000);
51
+ const message = `SetProfilePreference:${key}:${preferredType}:${timestamp}`;
52
+ try {
53
+ const signature = await signMessage(message);
54
+ return setProfilePreference({
55
+ key,
56
+ preferredType,
57
+ signature,
58
+ signer: signerAddress,
59
+ timestamp,
60
+ });
61
+ }
62
+ catch (error) {
63
+ throw new Error(`Failed to set profile preference: ${error}`);
64
+ }
65
+ };
66
+ return { setPreference };
67
+ }
68
+ export default useProfile;
@@ -20,6 +20,7 @@ export { useMediaQuery } from "./useMediaQuery";
20
20
  export { useNativeBalance, useNativeBalanceFromRPC } from "./useNativeBalance";
21
21
  export { useOnchainName } from "./useOnchainName";
22
22
  export { useOneBalance } from "./useOneBalance";
23
+ export { useProfile, useProfilePreference, type Profile, type CombinedProfile, type PreferenceRequestBody, } from "./useProfile";
23
24
  export { useQueryB3 } from "./useQueryB3";
24
25
  export { useQueryBSMNT } from "./useQueryBSMNT";
25
26
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
@@ -0,0 +1,38 @@
1
+ export interface Profile {
2
+ type: string;
3
+ address?: string;
4
+ name?: string;
5
+ avatar?: string | null;
6
+ bio?: string | null;
7
+ displayName?: string | null;
8
+ }
9
+ export interface CombinedProfile {
10
+ name: string | null;
11
+ address: string | null;
12
+ avatar: string | null;
13
+ bio: string | null;
14
+ displayName: string | null;
15
+ profiles: Profile[];
16
+ }
17
+ export interface PreferenceRequestBody {
18
+ key: string;
19
+ preferredType: string;
20
+ signature: string;
21
+ signer: string;
22
+ timestamp: number;
23
+ }
24
+ export declare function useProfile({ address, name, fresh, }: {
25
+ address?: string;
26
+ name?: string;
27
+ fresh?: boolean;
28
+ }, options?: {
29
+ enabled?: boolean;
30
+ refetchInterval?: number;
31
+ staleTime?: number;
32
+ }): import("@tanstack/react-query").UseQueryResult<CombinedProfile, Error>;
33
+ export declare function useProfilePreference(): {
34
+ setPreference: (key: string, preferredType: string, signerAddress: string, signMessage: (message: string) => Promise<string>) => Promise<{
35
+ success: boolean;
36
+ }>;
37
+ };
38
+ export default useProfile;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.10-alpha.7",
3
+ "version": "0.0.11",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -189,6 +189,27 @@
189
189
  "utils",
190
190
  "constants"
191
191
  ],
192
+ "scripts": {
193
+ "clean": "rm -rf dist",
194
+ "prebuild": "pnpm clean",
195
+ "fix-dist": "[ -d ./dist/react/src ] && cp -r ./dist/react/src/* ./dist/ && rm -rf ./dist/react || echo \"No react directory found\"",
196
+ "build": "pnpm clean && pnpm lint && pnpm build:types && pnpm build:cjs && pnpm build:esm && pnpm build:css",
197
+ "build:types": "tsc -p tsconfig.cjs.json --emitDeclarationOnly --declarationDir dist/types",
198
+ "build:cjs": "tsc -p tsconfig.cjs.json --outDir dist/cjs --module commonjs && tsc-alias -p tsconfig.cjs.json --outDir dist/cjs && mkdir -p dist/cjs/shared/generated && cp src/shared/generated/chain-networks.json src/shared/generated/coingecko-chains.json dist/cjs/shared/generated/",
199
+ "build:esm": "tsc -p tsconfig.esm.json --outDir dist/esm --module esnext && tsc-alias -p tsconfig.esm.json --outDir dist/esm && mkdir -p dist/esm/shared/generated && cp src/shared/generated/chain-networks.json src/shared/generated/coingecko-chains.json dist/esm/shared/generated/ && node scripts/fix-esm-imports.js",
200
+ "build:css": "postcss src/styles/index.css -o dist/styles/index.css",
201
+ "dev:cjs": "tsc-watch -p tsconfig.cjs.json --onSuccess \"tsc-alias -p tsconfig.cjs.json --outDir dist/cjs\"",
202
+ "dev:esm": "tsc-watch -p tsconfig.esm.json --onSuccess \"tsc-alias -p tsconfig.esm.json --outDir dist/esm\"",
203
+ "dev": "concurrently \"pnpm dev:cjs\" \"pnpm dev:esm\" \"pnpm dev:css\"",
204
+ "dev:css": "postcss src/styles/index.css -o dist/styles/index.css --watch",
205
+ "prepublishOnly": "pnpm build",
206
+ "release:test": "pnpm version prerelease --preid test && git push --follow-tags && pnpm publish --tag test --no-git-checks",
207
+ "release:alpha": "pnpm version prerelease --preid alpha && git push --follow-tags && pnpm publish --tag alpha --no-git-checks",
208
+ "typecheck": "tsc --noEmit",
209
+ "generate:thirdweb": "npx @hey-api/openapi-ts --file src/thirdweb/openapi-ts.config.ts --input src/thirdweb/insight-service.json",
210
+ "lint": "eslint 'src/**/*.{ts,tsx}'",
211
+ "lint:fix": "eslint 'src/**/*.{ts,tsx}' --fix"
212
+ },
192
213
  "dependencies": {
193
214
  "@amplitude/analytics-browser": "2.14.0",
194
215
  "@b3dotfun/b3-api": "0.0.28",
@@ -306,25 +327,5 @@
306
327
  "three": {
307
328
  "optional": true
308
329
  }
309
- },
310
- "scripts": {
311
- "clean": "rm -rf dist",
312
- "prebuild": "pnpm clean",
313
- "fix-dist": "[ -d ./dist/react/src ] && cp -r ./dist/react/src/* ./dist/ && rm -rf ./dist/react || echo \"No react directory found\"",
314
- "build": "pnpm clean && pnpm lint && pnpm build:types && pnpm build:cjs && pnpm build:esm && pnpm build:css",
315
- "build:types": "tsc -p tsconfig.cjs.json --emitDeclarationOnly --declarationDir dist/types",
316
- "build:cjs": "tsc -p tsconfig.cjs.json --outDir dist/cjs --module commonjs && tsc-alias -p tsconfig.cjs.json --outDir dist/cjs && mkdir -p dist/cjs/shared/generated && cp src/shared/generated/chain-networks.json src/shared/generated/coingecko-chains.json dist/cjs/shared/generated/",
317
- "build:esm": "tsc -p tsconfig.esm.json --outDir dist/esm --module esnext && tsc-alias -p tsconfig.esm.json --outDir dist/esm && mkdir -p dist/esm/shared/generated && cp src/shared/generated/chain-networks.json src/shared/generated/coingecko-chains.json dist/esm/shared/generated/ && node scripts/fix-esm-imports.js",
318
- "build:css": "postcss src/styles/index.css -o dist/styles/index.css",
319
- "dev:cjs": "tsc-watch -p tsconfig.cjs.json --onSuccess \"tsc-alias -p tsconfig.cjs.json --outDir dist/cjs\"",
320
- "dev:esm": "tsc-watch -p tsconfig.esm.json --onSuccess \"tsc-alias -p tsconfig.esm.json --outDir dist/esm\"",
321
- "dev": "concurrently \"pnpm dev:cjs\" \"pnpm dev:esm\" \"pnpm dev:css\"",
322
- "dev:css": "postcss src/styles/index.css -o dist/styles/index.css --watch",
323
- "release:test": "pnpm version prerelease --preid test && git push --follow-tags && pnpm publish --tag test --no-git-checks",
324
- "release:alpha": "pnpm version prerelease --preid alpha && git push --follow-tags && pnpm publish --tag alpha --no-git-checks",
325
- "typecheck": "tsc --noEmit",
326
- "generate:thirdweb": "npx @hey-api/openapi-ts --file src/thirdweb/openapi-ts.config.ts --input src/thirdweb/insight-service.json",
327
- "lint": "eslint 'src/**/*.{ts,tsx}'",
328
- "lint:fix": "eslint 'src/**/*.{ts,tsx}' --fix"
329
330
  }
330
- }
331
+ }
@@ -20,6 +20,13 @@ export { useMediaQuery } from "./useMediaQuery";
20
20
  export { useNativeBalance, useNativeBalanceFromRPC } from "./useNativeBalance";
21
21
  export { useOnchainName } from "./useOnchainName";
22
22
  export { useOneBalance } from "./useOneBalance";
23
+ export {
24
+ useProfile,
25
+ useProfilePreference,
26
+ type Profile,
27
+ type CombinedProfile,
28
+ type PreferenceRequestBody,
29
+ } from "./useProfile";
23
30
  export { useQueryB3 } from "./useQueryB3";
24
31
  export { useQueryBSMNT } from "./useQueryBSMNT";
25
32
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
@@ -0,0 +1,141 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+
3
+ // TypeScript interface for profile data
4
+ export interface Profile {
5
+ type: string;
6
+ address?: string;
7
+ name?: string;
8
+ avatar?: string | null;
9
+ bio?: string | null;
10
+ displayName?: string | null;
11
+ }
12
+
13
+ export interface CombinedProfile {
14
+ name: string | null;
15
+ address: string | null;
16
+ avatar: string | null;
17
+ bio: string | null;
18
+ displayName: string | null;
19
+ profiles: Profile[];
20
+ }
21
+
22
+ // TypeScript interface for preference request body
23
+ export interface PreferenceRequestBody {
24
+ key: string;
25
+ preferredType: string;
26
+ signature: string;
27
+ signer: string;
28
+ timestamp: number;
29
+ }
30
+
31
+ const PROFILES_API_URL = "https://profiles.b3.fun";
32
+
33
+ async function fetchProfile({
34
+ address,
35
+ name,
36
+ fresh = false,
37
+ }: {
38
+ address?: string;
39
+ name?: string;
40
+ fresh?: boolean;
41
+ }): Promise<CombinedProfile> {
42
+ if (!address && !name) {
43
+ throw new Error("Either address or name must be provided");
44
+ }
45
+
46
+ const params = new URLSearchParams();
47
+ if (address) params.append("address", address);
48
+ if (name) params.append("name", name);
49
+ if (fresh) params.append("fresh", "true");
50
+
51
+ const response = await fetch(`${PROFILES_API_URL}?${params.toString()}`);
52
+
53
+ if (!response.ok) {
54
+ throw new Error(`Failed to fetch profile: ${response.statusText}`);
55
+ }
56
+
57
+ return response.json();
58
+ }
59
+
60
+ async function setProfilePreference({
61
+ key,
62
+ preferredType,
63
+ signature,
64
+ signer,
65
+ timestamp,
66
+ }: PreferenceRequestBody): Promise<{ success: boolean }> {
67
+ const response = await fetch(`${PROFILES_API_URL}/preference`, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ },
72
+ body: JSON.stringify({
73
+ key,
74
+ preferredType,
75
+ signature,
76
+ signer,
77
+ timestamp,
78
+ }),
79
+ });
80
+
81
+ if (!response.ok) {
82
+ throw new Error(`Failed to set preference: ${response.statusText}`);
83
+ }
84
+
85
+ return response.json();
86
+ }
87
+
88
+ export function useProfile(
89
+ {
90
+ address,
91
+ name,
92
+ fresh = false,
93
+ }: {
94
+ address?: string;
95
+ name?: string;
96
+ fresh?: boolean;
97
+ },
98
+ options?: {
99
+ enabled?: boolean;
100
+ refetchInterval?: number;
101
+ staleTime?: number;
102
+ },
103
+ ) {
104
+ return useQuery({
105
+ queryKey: ["profile", address || name, fresh],
106
+ queryFn: () => fetchProfile({ address, name, fresh }),
107
+ enabled: (options?.enabled ?? true) && (!!address || !!name),
108
+ refetchInterval: options?.refetchInterval,
109
+ staleTime: options?.staleTime ?? 5 * 60 * 1000, // 5 minutes default
110
+ });
111
+ }
112
+
113
+ export function useProfilePreference() {
114
+ const setPreference = async (
115
+ key: string,
116
+ preferredType: string,
117
+ signerAddress: string,
118
+ signMessage: (message: string) => Promise<string>,
119
+ ) => {
120
+ const timestamp = Math.floor(Date.now() / 1000);
121
+ const message = `SetProfilePreference:${key}:${preferredType}:${timestamp}`;
122
+
123
+ try {
124
+ const signature = await signMessage(message);
125
+
126
+ return setProfilePreference({
127
+ key,
128
+ preferredType,
129
+ signature,
130
+ signer: signerAddress,
131
+ timestamp,
132
+ });
133
+ } catch (error) {
134
+ throw new Error(`Failed to set profile preference: ${error}`);
135
+ }
136
+ };
137
+
138
+ return { setPreference };
139
+ }
140
+
141
+ export default useProfile;