From 9adf8d79c97209ce8a3cdf476ce80e37e57fbc87 Mon Sep 17 00:00:00 2001 From: Rafael Date: Wed, 16 Apr 2025 16:03:45 -0300 Subject: [PATCH 1/6] fix(ens): change provider to get ens data --- apps/ui/package.json | 1 + apps/ui/src/hooks/useGetENSData.ts | 4 +- apps/ui/src/modules/ens/services/ens.ts | 91 ++++++++----------------- pnpm-lock.yaml | 76 +++++++++++++++++---- 4 files changed, 94 insertions(+), 78 deletions(-) diff --git a/apps/ui/package.json b/apps/ui/package.json index cf6c7436..cf9c595d 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -26,6 +26,7 @@ "@wagmi/core": "2.13.4", "date-fns": "^3.6.0", "dayjs": "^1.11.11", + "ethers": "^6.13.5", "framer-motion": "^11.3.4", "fuels": "0.100.1", "lodash": "^4.17.21", diff --git a/apps/ui/src/hooks/useGetENSData.ts b/apps/ui/src/hooks/useGetENSData.ts index 408c6a38..34f0f213 100644 --- a/apps/ui/src/hooks/useGetENSData.ts +++ b/apps/ui/src/hooks/useGetENSData.ts @@ -1,12 +1,12 @@ import { useQuery } from '@tanstack/react-query'; -import { ensCheckRegister } from '../modules/ens/services'; +import { getEnsMetadata } from '../modules/ens/services'; const useGetENSData = (ensName: string) => { const { data, ...rest } = useQuery({ queryKey: ['get-ens', ensName], queryFn: async () => { try { - const result = await ensCheckRegister(ensName); + const result = await getEnsMetadata(ensName); if (!result) { // Need to throw this error to activate the "retry" method. throw new Error('Expected null value. Activating Retry method'); diff --git a/apps/ui/src/modules/ens/services/ens.ts b/apps/ui/src/modules/ens/services/ens.ts index 6f04746e..edd792a8 100644 --- a/apps/ui/src/modules/ens/services/ens.ts +++ b/apps/ui/src/modules/ens/services/ens.ts @@ -1,77 +1,42 @@ import { MetadataKeys } from '@bako-id/sdk'; -import { createEnsPublicClient } from '@ensdomains/ensjs'; -import { http } from 'viem'; -import { mainnet } from 'viem/chains'; -import { type ENSMetadataKeys, ensToMetadataMap } from './types'; -const { VITE_ENS_API_KEY } = import.meta.env; +import { ENSMetadataKeys, ensToMetadataMap } from './types'; +import { ethers } from 'ethers'; -const client = createEnsPublicClient({ - chain: mainnet, - transport: http('https://web3.ens.domains/v1/mainnet'), - key: VITE_ENS_API_KEY, -}); +const ethersProvider = new ethers.JsonRpcProvider( + 'https://mainnet.infura.io/v3/a44094c3208b48f5bbdd76c7c83212fc' +); -const graphql_url = `https://gateway.thegraph.com/api/${VITE_ENS_API_KEY}/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH`; +export async function getEnsMetadata(name: string) { + const resolver = await ethersProvider.getResolver(name); -export const ensCheckRegister = async (name: string) => { - const records = await fetchEnsData(name); - if (!records) return null; - - const keys = records.resolver.texts; - - const request = await client.getRecords({ - name, - texts: [...keys], - }); - - const mappedResult: Record = {}; - - for (const { key, value } of request.texts) { - const ensKey = key as ENSMetadataKeys; - const metadataKey = ensToMetadataMap[ensKey]; - - if (metadataKey) { - mappedResult[metadataKey] = value; + try { + if (!resolver) { + return null; } - } - mappedResult[MetadataKeys.ENS_DOMAIN] = name; + const metadata: Record = {}; - return mappedResult; -}; + for (const key of Object.keys(ENSMetadataKeys)) { + const enumKey = key as keyof typeof ENSMetadataKeys; + const recordKey = ENSMetadataKeys[enumKey]; + const metadataKey = ensToMetadataMap[recordKey]; -async function fetchEnsData(name: string) { - const ensQuery = `query { - domains( - where: { - name: "${name}" - } - ) { - name - expiryDate - registration { - expiryDate - registrationDate - } - resolver { - texts - contentHash - id - + try { + const value = await resolver.getText(recordKey); + if (value) { + metadata[metadataKey] = value; + } + } catch (error) { + console.error(`Error fetching ${recordKey} for ${name}:`, error); } } - }`; - const response = await fetch(graphql_url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query: ensQuery }), - }); - const lklk = await response.json(); - const d = lklk.data?.domains[0] ?? undefined; + metadata[MetadataKeys.ENS_DOMAIN] = name; - return d; + return metadata; + } catch (error) { + console.error(`Error fetching metadata for ${name}:`, error); + return null; + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 27a00f8f..02923707 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,7 +177,7 @@ importers: version: 14.2.5(eslint@8.57.1)(typescript@5.4.5) ts-jest: specifier: ^29.1.1 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.25.0)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.17.19)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: ^5 version: 5.4.5 @@ -232,6 +232,9 @@ importers: dayjs: specifier: ^1.11.11 version: 1.11.13 + ethers: + specifier: ^6.13.5 + version: 6.13.5(bufferutil@4.0.8)(utf-8-validate@5.0.10) framer-motion: specifier: ^11.3.4 version: 11.11.11(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3682,6 +3685,9 @@ packages: cpu: [x64] os: [win32] + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + '@noble/curves@1.4.0': resolution: {integrity: sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==} @@ -3692,6 +3698,10 @@ packages: resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} @@ -4891,6 +4901,9 @@ packages: '@types/node@20.8.8': resolution: {integrity: sha512-YRsdVxq6OaLfmR9Hy816IMp33xOBjfyOgUd77ehqg96CFywxAPbDbXvAsuN2KVg2HOT8Eh6uAfU+l4WffwPVrQ==} + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + '@types/node@22.8.7': resolution: {integrity: sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==} @@ -5511,6 +5524,9 @@ packages: resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} engines: {node: '>=12.0'} + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -7288,6 +7304,10 @@ packages: ethereum-cryptography@2.2.1: resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} + ethers@6.13.5: + resolution: {integrity: sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==} + engines: {node: '>=14.0.0'} + event-emitter@0.3.5: resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} @@ -11435,6 +11455,9 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -17253,6 +17276,10 @@ snapshots: '@next/swc-win32-x64-msvc@15.0.2': optional: true + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + '@noble/curves@1.4.0': dependencies: '@noble/hashes': 1.4.0 @@ -17265,6 +17292,8 @@ snapshots: dependencies: '@noble/hashes': 1.7.1 + '@noble/hashes@1.3.2': {} + '@noble/hashes@1.4.0': {} '@noble/hashes@1.7.1': {} @@ -18778,6 +18807,10 @@ snapshots: dependencies: undici-types: 5.25.3 + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + '@types/node@22.8.7': dependencies: undici-types: 6.19.8 @@ -20319,6 +20352,8 @@ snapshots: adm-zip@0.5.16: {} + aes-js@4.0.0-beta.5: {} + agent-base@6.0.2(supports-color@8.1.1): dependencies: debug: 4.4.0(supports-color@8.1.1) @@ -22671,6 +22706,19 @@ snapshots: '@scure/bip32': 1.4.0 '@scure/bip39': 1.3.0 + ethers@6.13.5(bufferutil@4.0.8)(utf-8-validate@5.0.10): + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + event-emitter@0.3.5: dependencies: d: 1.0.2 @@ -28109,12 +28157,12 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.17.19)(jest@29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.17.19)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -28129,18 +28177,18 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.26.0) esbuild: 0.17.19 - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.17.19)(jest@29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.6.3)))(typescript@5.6.3): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.17.19)(jest@29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.6.3)) + jest: 29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.6.3 + typescript: 5.4.5 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.26.0 @@ -28149,12 +28197,12 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.26.0) esbuild: 0.17.19 - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.24.0)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.17.19)(jest@29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.6.3)))(typescript@5.6.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)) + jest: 29.7.0(@types/node@22.8.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.6.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -28167,27 +28215,27 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.26.0) - esbuild: 0.24.0 + esbuild: 0.17.19 - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.25.0)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.24.0)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.4.5 + typescript: 5.6.3 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.26.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.26.0) - esbuild: 0.25.0 + esbuild: 0.24.0 ts-log@2.2.7: {} @@ -28317,6 +28365,8 @@ snapshots: tslib@2.6.3: {} + tslib@2.7.0: {} + tslib@2.8.1: {} tsup@6.7.0(postcss@8.4.47)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.4.5))(typescript@5.4.5): From 794b109791a114cdb36f5229c53a2f057bf2c45f Mon Sep 17 00:00:00 2001 From: Rafael Date: Wed, 16 Apr 2025 18:26:34 -0300 Subject: [PATCH 2/6] chore(profile): added skeletons to avatar and account inputs after importing data from ens --- apps/ui/src/components/card/accountsCard.tsx | 12 ++++++-- apps/ui/src/components/card/profileCard.tsx | 10 +++++-- .../src/components/inputs/verifiedAccount.tsx | 14 ++++++++-- apps/ui/src/hooks/useMetadata.ts | 8 ++++-- .../profile/components/profileCards.tsx | 28 +++++++++++++------ 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/apps/ui/src/components/card/accountsCard.tsx b/apps/ui/src/components/card/accountsCard.tsx index b022a32e..7006f15d 100644 --- a/apps/ui/src/components/card/accountsCard.tsx +++ b/apps/ui/src/components/card/accountsCard.tsx @@ -19,6 +19,7 @@ import { NSDialog } from '../../modules/ens/components/dialog'; interface AccountsCardProps { metadata: { key: string; value: string | undefined }[] | undefined; addAction: () => void; + isMetadataLoading: boolean; } const EmptyAccounts = ({ ensAction }: { ensAction: () => void }) => { @@ -49,7 +50,11 @@ const EmptyAccounts = ({ ensAction }: { ensAction: () => void }) => { ); }; -export const AccountsCard = ({ metadata, addAction }: AccountsCardProps) => { +export const AccountsCard = ({ + metadata, + addAction, + isMetadataLoading, +}: AccountsCardProps) => { const { isMyDomain } = useSidebar(); const ensDialogState = useDisclosure(); @@ -93,7 +98,7 @@ export const AccountsCard = ({ metadata, addAction }: AccountsCardProps) => { {metadata?.filter( - (data) => !avoidKeys.includes(data.key as MetadataKeys), + (data) => !avoidKeys.includes(data.key as MetadataKeys) ).length ? ( {metadata?.map((m) => { @@ -104,11 +109,12 @@ export const AccountsCard = ({ metadata, addAction }: AccountsCardProps) => { key={m.key} value={m.value} variant={variant} + isMetadataLoading={isMetadataLoading} isVerified rightAddon rightAddonName={getInputIcon( m.key as MetadataKeys, - m.value ?? '', + m.value ?? '' )} /> ); diff --git a/apps/ui/src/components/card/profileCard.tsx b/apps/ui/src/components/card/profileCard.tsx index f99c9475..2f986d63 100644 --- a/apps/ui/src/components/card/profileCard.tsx +++ b/apps/ui/src/components/card/profileCard.tsx @@ -9,6 +9,7 @@ import { MenuButton, MenuItem, MenuList, + Skeleton, Text, useClipboard, useMediaQuery, @@ -35,6 +36,7 @@ interface IProfileCard { domain: string; metadata: { key: string; value: string | undefined }[] | undefined; editAction: () => void; + isMetadataLoading: boolean; } const ButtonAction = ({ rightIcon, ...props }: ButtonProps) => ( @@ -64,12 +66,13 @@ export const ProfileCard = ({ domainName, metadata, editAction, + isMetadataLoading, }: IProfileCard) => { const [isLowerThanMobile] = useMediaQuery('(max-width: 25em)'); const { isMyDomain: isOwner } = useSidebar(); const nickname = metadata?.find( - (m) => m.key === MetadataKeys.CONTACT_NICKNAME, + (m) => m.key === MetadataKeys.CONTACT_NICKNAME ); const shortBio = metadata?.find((m) => m.key === MetadataKeys.CONTACT_BIO); const avatar = metadata?.find((m) => m.key === MetadataKeys.AVATAR); @@ -152,7 +155,7 @@ export const ProfileCard = ({ twitterLink(profileLink, { title: 'Check my Bako ID profile!', related: [], - }), + }) ); }} icon={} @@ -212,7 +215,8 @@ export const ProfileCard = ({ > {avatar ? ( - { @@ -133,7 +135,15 @@ const VerifiedAccountInput = (props: CustomInputProps) => { if (currentVariant) { return ( - + { Verify now )} - + ); } }; diff --git a/apps/ui/src/hooks/useMetadata.ts b/apps/ui/src/hooks/useMetadata.ts index 3ba31670..0918a986 100644 --- a/apps/ui/src/hooks/useMetadata.ts +++ b/apps/ui/src/hooks/useMetadata.ts @@ -25,7 +25,7 @@ export type MetadataResponse = export const useMetadata = (handleOnSuccess?: () => void) => { const [updatedMetadata, setUpdatedMetadata] = useState( - [], + [] ); const { domain } = useParams({ strict: false }); const { provider } = useProvider(); @@ -63,6 +63,9 @@ export const useMetadata = (handleOnSuccess?: () => void) => { } }, enabled: !!domain, + refetchOnWindowFocus: false, + refetchOnMount: true, + staleTime: 1000 * 60 * 60 * 2, }); const handleSaveRequest = useMutation({ @@ -74,7 +77,7 @@ export const useMetadata = (handleOnSuccess?: () => void) => { ...updatedMetadata.reduce( // biome-ignore lint/performance/noAccumulatingSpread: (acc, { key, value }) => ({ ...acc, [key]: value }), - {}, + {} ), }; @@ -115,6 +118,7 @@ export const useMetadata = (handleOnSuccess?: () => void) => { return { metadata: handleListRequest.data, loadingMetadata: handleListRequest.isLoading, + fetchingMetadata: handleListRequest.isFetching, metadataModal, transactionModal, handleSaveRequest, diff --git a/apps/ui/src/modules/profile/components/profileCards.tsx b/apps/ui/src/modules/profile/components/profileCards.tsx index 0f220016..17cbdd77 100644 --- a/apps/ui/src/modules/profile/components/profileCards.tsx +++ b/apps/ui/src/modules/profile/components/profileCards.tsx @@ -128,7 +128,7 @@ const NFTCard = (props: { asset: FuelAsset & { image?: string } }) => { queryFn: async (): Promise> => { let metadata: Record = defaultMetadata ?? {}; const metadataEntries = Object.entries(metadata).filter( - ([key]) => !key.toLowerCase().includes('uri'), + ([key]) => !key.toLowerCase().includes('uri') ); if (metadataEntries.length === 0 && uri?.endsWith('.json')) { @@ -163,7 +163,7 @@ const NFTCard = (props: { asset: FuelAsset & { image?: string } }) => { if (metadata) { const imageKeys = ['image']; const imageKey = Object.keys(metadata).find((key) => - imageKeys.includes(key.split(':').at(0)!), + imageKeys.includes(key.split(':').at(0)!) ); const nftImageURI = parseURI(metadata[imageKey!]); imageUri = nftImageURI || imageUri; @@ -358,7 +358,7 @@ export const NFTCollections = ({ for (const nft of nfts) { let metadata: Record = nft.metadata ?? {}; const metadataEntries = Object.entries(metadata).filter( - ([key]) => !key.toLowerCase().includes('uri'), + ([key]) => !key.toLowerCase().includes('uri') ); if (metadataEntries.length === 0 && nft.uri?.endsWith('.json')) { @@ -385,7 +385,7 @@ export const NFTCollections = ({ nft.metadata = metadata; const image = Object.entries(metadata).find(([key]) => - key.includes('image'), + key.includes('image') )?.[1]; nft.image = image ? parseURI(image) : undefined; @@ -430,7 +430,7 @@ export const NFTCollections = ({ assets: (FuelAsset & { image?: string; })[]; - }[], + }[] ) .sort((a, b) => { if (a.name === 'Other') return 1; @@ -450,7 +450,7 @@ export const NFTCollections = ({ } return a.name.localeCompare(b.name); }) ?? [], - [data], + [data] ); if (isLoading) { @@ -531,8 +531,13 @@ export const ProfileCards = ({ isLoading: loadingDomain, owner, }: ProfileCardsProps) => { - const { metadataModal, metadata, setUpdatedMetadata, loadingMetadata } = - useMetadata(); + const { + metadataModal, + metadata, + setUpdatedMetadata, + loadingMetadata, + fetchingMetadata, + } = useMetadata(); const loading = loadingDomain || loadingMetadata; @@ -570,6 +575,7 @@ export const ProfileCards = ({ domain={domain ?? ''} metadata={metadata} editAction={metadataModal.onOpen} + isMetadataLoading={fetchingMetadata || loadingMetadata} /> - + From eef706b9a86f4d7f0dc10bb390316403b0a19b5a Mon Sep 17 00:00:00 2001 From: Rafael Date: Thu, 24 Apr 2025 10:23:22 -0300 Subject: [PATCH 3/6] fix(build): fix build --- apps/ui/src/components/card/profileCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ui/src/components/card/profileCard.tsx b/apps/ui/src/components/card/profileCard.tsx index e7d2fb21..ca0ba38d 100644 --- a/apps/ui/src/components/card/profileCard.tsx +++ b/apps/ui/src/components/card/profileCard.tsx @@ -4,6 +4,7 @@ import { Button, type ButtonProps, Flex, + Icon, Menu, MenuButton, MenuItem, @@ -18,7 +19,7 @@ import { ExplorerTypes } from '../../types'; import { twitterLink } from '../../utils/formatter.ts'; import { getExplorer } from '../../utils/getExplorer'; import { MetadataKeys } from '../../utils/metadataKeys'; -import { EditIcon, ExploreIcon, TwitterIcon } from '../icons'; +import { AvatarIcon, EditIcon, ExploreIcon, TwitterIcon } from '../icons'; import { CopyIcon } from '../icons/copyIcon.tsx'; import { ShareIcon } from '../icons/shareicon.tsx'; import { useSidebar } from '../sidebar/hooks/useSidebar'; @@ -30,7 +31,6 @@ interface IProfileCard { metadata: { key: string; value: string | undefined }[] | undefined; isMetadataLoading: boolean; editAction: () => void; - isMetadataLoading: boolean; } const ButtonAction = ({ rightIcon, ...props }: ButtonProps) => ( From c2ba5ddc27c21895987a79604e7f6366dd890d72 Mon Sep 17 00:00:00 2001 From: Rafael Date: Thu, 24 Apr 2025 15:28:12 -0300 Subject: [PATCH 4/6] feat(profile): enable user to add his ens from profile social tab --- apps/ui/src/components/sidebar/profile.tsx | 6 +++++- apps/ui/src/utils/metadatas.tsx | 10 +++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/ui/src/components/sidebar/profile.tsx b/apps/ui/src/components/sidebar/profile.tsx index 3d1e1f38..4818baf5 100644 --- a/apps/ui/src/components/sidebar/profile.tsx +++ b/apps/ui/src/components/sidebar/profile.tsx @@ -20,13 +20,17 @@ import { DropdownAutocomplete } from '../inputs/dropdownAutocomplete'; import { useSidebar } from './hooks/useSidebar'; import { ENSBanner } from '../buttons/ensBanner'; import { NSDialog } from '../../modules/ens/components/dialog'; +import { useMetadata } from '../../hooks/useMetadata'; +import { MetadataKeys } from '@bako-id/sdk'; interface ProfileSidebarProps extends BoxProps {} const ProfileSidebar = (props: ProfileSidebarProps) => { + const { metadata } = useMetadata(); const { isMyDomain } = useSidebar(); const [active, setActive] = useState(''); const ensDialogState = useDisclosure(); + const hasEns = !!metadata?.find((m) => m.key === MetadataKeys.ENS_DOMAIN); return ( <> @@ -105,7 +109,7 @@ const ProfileSidebar = (props: ProfileSidebarProps) => { )} - + {!hasEns && } window.open('https://www.bako.global', '_blank')} diff --git a/apps/ui/src/utils/metadatas.tsx b/apps/ui/src/utils/metadatas.tsx index 96a27d6b..92e61d1d 100644 --- a/apps/ui/src/utils/metadatas.tsx +++ b/apps/ui/src/utils/metadatas.tsx @@ -11,10 +11,11 @@ import { UserIcon, WebsiteIcon, } from '../components/icons/'; +import { ENSIcon } from '../components/icons/ensicon'; export const getMetadataRedirects = ( key: MetadataKeys, - value: string, + value: string ): string | null => { const metaDatas: Partial> = { 'social:x': `https://x.com/${value}`, @@ -113,6 +114,13 @@ export const Metadatas: Metadatas = { description: 'Your email address', validated: false, }, + { + key: MetadataKeys.ENS_DOMAIN, + title: 'ENS', + icon: , + description: 'Your ENS domain', + validated: false, + }, ], Address: [ { From cc2a01036018a61fd46f6b090a7fb75811f3e46d Mon Sep 17 00:00:00 2001 From: Rafael Date: Thu, 24 Apr 2025 15:52:23 -0300 Subject: [PATCH 5/6] feat(profile): show ens banner only if is the domain owner or theres no ens imported --- apps/ui/src/components/sidebar/profile.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/ui/src/components/sidebar/profile.tsx b/apps/ui/src/components/sidebar/profile.tsx index 4818baf5..049f84b4 100644 --- a/apps/ui/src/components/sidebar/profile.tsx +++ b/apps/ui/src/components/sidebar/profile.tsx @@ -1,7 +1,6 @@ import { Box, Divider, - Flex, FormControl, Text, useDisclosure, @@ -26,11 +25,12 @@ import { MetadataKeys } from '@bako-id/sdk'; interface ProfileSidebarProps extends BoxProps {} const ProfileSidebar = (props: ProfileSidebarProps) => { - const { metadata } = useMetadata(); + const { metadata, loadingMetadata } = useMetadata(); const { isMyDomain } = useSidebar(); const [active, setActive] = useState(''); const ensDialogState = useDisclosure(); const hasEns = !!metadata?.find((m) => m.key === MetadataKeys.ENS_DOMAIN); + const showEnsBanner = !hasEns && isMyDomain && !loadingMetadata; return ( <> @@ -93,23 +93,23 @@ const ProfileSidebar = (props: ProfileSidebarProps) => { /> - {isMyDomain && ( + {/* {isMyDomain && ( - {/* */} + /> - {/* */} + /> - )} + )} */} - {!hasEns && } + {showEnsBanner && } window.open('https://www.bako.global', '_blank')} From a6e9a974a7abf72608d91d8e2f248ff2ca60d739 Mon Sep 17 00:00:00 2001 From: Rafael Date: Thu, 24 Apr 2025 18:31:17 -0300 Subject: [PATCH 6/6] chore(update-profile): change text Registration to Update profile when set user profile data --- apps/ui/src/components/modal/transactionDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui/src/components/modal/transactionDetails.tsx b/apps/ui/src/components/modal/transactionDetails.tsx index e18cadeb..9056cf30 100644 --- a/apps/ui/src/components/modal/transactionDetails.tsx +++ b/apps/ui/src/components/modal/transactionDetails.tsx @@ -101,7 +101,7 @@ export const TransactionsDetailsModal = ({ justifyContent="start" textColor="grey.100" leftAction={'action'} - content="Registration" + content="Update profile" />