diff --git a/JoyboyCommunity/src/hooks/api/index.ts b/JoyboyCommunity/src/hooks/api/index.ts index 0a7dbb8d..0bcc62a9 100644 --- a/JoyboyCommunity/src/hooks/api/index.ts +++ b/JoyboyCommunity/src/hooks/api/index.ts @@ -1,2 +1,3 @@ export {useClaim} from './useClaim'; export {useEstimateClaim} from './useEstimateClaim'; +export {useFileUpload} from './useFileUpload'; diff --git a/JoyboyCommunity/src/hooks/api/useFileUpload.ts b/JoyboyCommunity/src/hooks/api/useFileUpload.ts new file mode 100644 index 00000000..c3ee49c6 --- /dev/null +++ b/JoyboyCommunity/src/hooks/api/useFileUpload.ts @@ -0,0 +1,32 @@ +import {ImagePickerAsset} from 'expo-image-picker'; +import {Platform} from 'react-native'; + +import {ApiInstance} from '../../services/api'; +import {dataURLToBlob} from '../../utils/helpers'; +import {useApiMutation} from './useApiMutation'; + +export const useFileUpload = () => { + return useApiMutation({ + mutationKey: ['fileUpload'], + mutationFn: (file: ImagePickerAsset) => { + const formData = new FormData(); + + formData.append( + 'file', + Platform.OS === 'web' + ? dataURLToBlob(file.uri) + : ({ + uri: file.uri, + name: 'file', + type: file.mimeType, + } as any), + ); + + return ApiInstance.post('/file', formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + }, + }); +}; diff --git a/JoyboyCommunity/src/modules/Post/index.tsx b/JoyboyCommunity/src/modules/Post/index.tsx index 56ac98bf..3304268d 100644 --- a/JoyboyCommunity/src/modules/Post/index.tsx +++ b/JoyboyCommunity/src/modules/Post/index.tsx @@ -112,7 +112,12 @@ export const Post: React.FC = ({asComment, event}) => { handleProfilePress(event?.pubkey)}> - + diff --git a/JoyboyCommunity/src/screens/Auth/SaveKeys.tsx b/JoyboyCommunity/src/screens/Auth/SaveKeys.tsx index 0e6816dd..ca420754 100644 --- a/JoyboyCommunity/src/screens/Auth/SaveKeys.tsx +++ b/JoyboyCommunity/src/screens/Auth/SaveKeys.tsx @@ -32,7 +32,7 @@ export const SaveKeys: React.FC = ({route}) => { - Your secret key + Your private key = ({route}) => { - Your private key is your password, if you lose this key, you will lose access to your + Your private key is your identity, if you lose this key, you will lose access to your account. diff --git a/JoyboyCommunity/src/screens/EditProfile/index.tsx b/JoyboyCommunity/src/screens/EditProfile/index.tsx index f86c5579..103f2a58 100644 --- a/JoyboyCommunity/src/screens/EditProfile/index.tsx +++ b/JoyboyCommunity/src/screens/EditProfile/index.tsx @@ -8,6 +8,7 @@ import {ScrollView, TouchableOpacity, View} from 'react-native'; import {CopyIconStack} from '../../assets/icons'; import {Button, SquareInput, Text} from '../../components'; import {useEditProfile, useProfile, useStyles, useTheme} from '../../hooks'; +import {useFileUpload} from '../../hooks/api'; import {useToast} from '../../hooks/modals'; import {useAuth} from '../../store/auth'; import {EditProfileScreenProps} from '../../types'; @@ -21,6 +22,8 @@ const UsernameInputLeft = ( ); type FormValues = { + image: string | undefined; + banner: string | undefined; username: string; displayName: string; bio: string; @@ -40,6 +43,7 @@ export const EditProfile: React.FC = () => { const publicKey = useAuth((state) => state.publicKey); const profile = useProfile({publicKey}); + const fileUpload = useFileUpload(); const editProfile = useEditProfile(); const queryClient = useQueryClient(); const {showToast} = useToast(); @@ -51,7 +55,7 @@ export const EditProfile: React.FC = () => { showToast({type: 'info', title: 'Public Key Copied to clipboard'}); }; - const handlePhotoUpload = async (type: 'profile' | 'cover') => { + const handlePhotoSelect = async (type: 'profile' | 'cover') => { const pickerResult = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, aspect: type === 'profile' ? [1, 1] : [16, 9], @@ -67,20 +71,18 @@ export const EditProfile: React.FC = () => { }; const onProfilePhotoUpload = async () => { - const file = await handlePhotoUpload('profile'); + const file = await handlePhotoSelect('profile'); if (file) setProfilePhoto(file); - - // TODO: upload file }; const onCoverPhotoUpload = async () => { - const file = await handlePhotoUpload('cover'); + const file = await handlePhotoSelect('cover'); if (file) setCoverPhoto(file); - - // TODO: upload file }; const initialFormValues: FormValues = { + image: profile.data?.image ?? undefined, + banner: profile.data?.banner ?? undefined, username: profile.data?.nip05 ?? '', displayName: profile.data?.displayName ?? profile.data?.name ?? '', bio: profile.data?.about ?? '', @@ -102,18 +104,36 @@ export const EditProfile: React.FC = () => { }; const onFormSubmit = async (values: FormValues) => { - await editProfile.mutateAsync({ - nip05: values.username, - displayName: values.displayName, - about: values.bio, - telegram: values.telegram, - github: values.github, - twitter: values.twitter, - }); - - queryClient.invalidateQueries({queryKey: ['profile', publicKey]}); - - showToast({type: 'success', title: 'Profile updated successfully'}); + let {image, banner} = values; + + try { + if (profilePhoto) { + const result = await fileUpload.mutateAsync(profilePhoto); + if (result.data.url) image = result.data.url; + } + + if (coverPhoto) { + const result = await fileUpload.mutateAsync(coverPhoto); + if (result.data.url) banner = result.data.url; + } + + await editProfile.mutateAsync({ + image, + banner, + nip05: values.username || undefined, + displayName: values.displayName || undefined, + about: values.bio || undefined, + telegram: values.telegram || undefined, + github: values.github || undefined, + twitter: values.twitter || undefined, + }); + + queryClient.invalidateQueries({queryKey: ['profile', publicKey]}); + + showToast({type: 'success', title: 'Profile updated successfully'}); + } catch (error) { + showToast({type: 'error', title: 'Failed to update profile'}); + } }; return ( diff --git a/JoyboyCommunity/src/utils/helpers.ts b/JoyboyCommunity/src/utils/helpers.ts index d81d30b2..837421ec 100644 --- a/JoyboyCommunity/src/utils/helpers.ts +++ b/JoyboyCommunity/src/utils/helpers.ts @@ -43,3 +43,17 @@ export const decimalsScale = (decimals: number) => `1${Array(decimals).fill('0') export const shortenPubkey = (pubkey?: string, length = 6) => pubkey ? `${pubkey.slice(0, length)}...${pubkey.slice(-length)}` : undefined; + +export const dataURLToBlob = (dataURL: string) => { + const byteString = atob(dataURL.split(',')[1]); + const mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]; + + const ab = new ArrayBuffer(byteString.length); + const ia = new Uint8Array(ab); + + for (let i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + + return new Blob([ab], {type: mimeString}); +}; diff --git a/website/.env.example b/website/.env.example index 314988a7..855305c1 100644 --- a/website/.env.example +++ b/website/.env.example @@ -3,3 +3,7 @@ ACCOUNT_PRIVATE_KEY="0x" PROVIDER_URL="https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/your_api_key" NETWORK_NAME="SN_SEPOLIA" # SN_SEPOLIA, SN_MAIN + +PINATA_API_KEY="YOUR_PINATA_API_KEY" +PINATA_SECRET_API_KEY="YOUR_PINATA_SECRET_API_KEY" +IPFS_GATEWAT="https://your.ipfs.gateway.url/ipfs" \ No newline at end of file diff --git a/website/package.json b/website/package.json index 53c31729..00d86630 100644 --- a/website/package.json +++ b/website/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@avnu/avnu-sdk": "^2.0.0", + "@pinata/sdk": "^2.1.0", "ethers": "^6.13.1", "framer-motion": "^11.2.4", "next": "^14.2.3", diff --git a/website/src/app/api/deposit/claim/route.ts b/website/src/app/api/deposit/claim/route.ts index 2aa31ef0..d3d7d5d7 100644 --- a/website/src/app/api/deposit/claim/route.ts +++ b/website/src/app/api/deposit/claim/route.ts @@ -117,7 +117,6 @@ export async function POST(request: NextRequest) { return NextResponse.json({transaction_hash}, {status: HTTPStatus.OK}); } } catch (error) { - console.log(error); return NextResponse.json( {code: ErrorCode.TRANSACTION_ERROR, error}, {status: HTTPStatus.InternalServerError}, diff --git a/website/src/app/api/file/route.ts b/website/src/app/api/file/route.ts new file mode 100644 index 00000000..914fd6e2 --- /dev/null +++ b/website/src/app/api/file/route.ts @@ -0,0 +1,37 @@ +import {Readable} from 'node:stream'; + +import {NextRequest, NextResponse} from 'next/server'; + +import {pinata} from '@/services/pinata'; +import {ErrorCode} from '@/utils/errors'; +import {HTTPStatus} from '@/utils/http'; + +export async function POST(request: NextRequest) { + const data = await request.formData(); + const file: File | null = data.get('file') as unknown as File; + + if (!file) { + return NextResponse.json({code: ErrorCode.BAD_REQUEST}, {status: HTTPStatus.BadRequest}); + } + + try { + const stream = Readable.fromWeb(file.stream() as any); + + const {IpfsHash} = await pinata.pinFileToIPFS(stream, { + pinataMetadata: { + name: file.name, + }, + }); + + return NextResponse.json( + {hash: IpfsHash, url: `${process.env.IPFS_GATEWAY}/${IpfsHash}`}, + {status: HTTPStatus.OK}, + ); + } catch (error) { + console.log(error); + return NextResponse.json( + {code: ErrorCode.TRANSACTION_ERROR, error}, + {status: HTTPStatus.InternalServerError}, + ); + } +} diff --git a/website/src/services/pinata.ts b/website/src/services/pinata.ts new file mode 100644 index 00000000..ffc1eef1 --- /dev/null +++ b/website/src/services/pinata.ts @@ -0,0 +1,12 @@ +import PinataSDK from '@pinata/sdk'; + +if (!process.env.PINATA_API_KEY) throw new Error('PINATA_API_KEY is not set'); +if (!process.env.PINATA_SECRET_API_KEY) throw new Error('PINATA_SECRET_API_KEY is not set'); +if (!process.env.IPFS_GATEWAY) throw new Error('IPFS_GATEWAY is not set'); + +export const pinata = new PinataSDK({ + pinataApiKey: process.env.PINATA_API_KEY, + pinataSecretApiKey: process.env.PINATA_SECRET_API_KEY, +}); + +pinata.testAuthentication(); diff --git a/website/yarn.lock b/website/yarn.lock index 0c0a2f06..c61f1b63 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -243,6 +243,16 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pinata/sdk@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@pinata/sdk/-/sdk-2.1.0.tgz#d61aa8f21ec1206e867f4b65996db52b70316945" + integrity sha512-hkS0tcKtsjf9xhsEBs2Nbey5s+Db7x5rlOH9TaWHBXkJ7IwwOs2xnEDigNaxAHKjYAwcw+m2hzpO5QgOfeF7Zw== + dependencies: + axios "^0.21.1" + form-data "^2.3.3" + is-ipfs "^0.6.0" + path "^0.12.7" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -709,6 +719,11 @@ ast-types-flow@^0.0.8: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + autoprefixer@^10.4.19: version "10.4.19" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" @@ -733,6 +748,13 @@ axe-core@^4.9.1: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.9.1.tgz#fcd0f4496dad09e0c899b44f6c4bb7848da912ae" integrity sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw== +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + axobject-query@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -745,6 +767,18 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.10" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" + integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -782,6 +816,21 @@ browserslist@^4.23.0: node-releases "^2.0.14" update-browserslist-db "^1.0.16" +bs58@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + busboy@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -846,6 +895,33 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +cids@~0.7.0: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cids@~0.8.0: + version "0.8.3" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.8.3.tgz#aaf48ac8ed857c3d37dad94d8db1d8c9407b92db" + integrity sha512-yoXTbV3llpm+EBGWKeL9xKtksPE/s6DPoDSY4fn8I8TEW1zehWXPSB0pwAXVDlLaOlrw+sNynj995uD9abmPhA== + dependencies: + buffer "^5.6.0" + class-is "^1.1.0" + multibase "^1.0.0" + multicodec "^1.0.1" + multihashes "^1.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + client-only@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -872,6 +948,13 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -994,6 +1077,11 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + didyoumean@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" @@ -1558,6 +1646,11 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== +follow-redirects@^1.14.0: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -1573,6 +1666,15 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +form-data@^2.3.3: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + fraction.js@^4.3.7: version "4.3.7" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" @@ -1797,6 +1899,11 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -1828,6 +1935,11 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -1837,6 +1949,11 @@ internal-slot@^1.0.4, internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +ip-regex@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -1939,6 +2056,25 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-ip@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" + integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== + dependencies: + ip-regex "^4.0.0" + +is-ipfs@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/is-ipfs/-/is-ipfs-0.6.3.tgz#82a5350e0a42d01441c40b369f8791e91404c497" + integrity sha512-HyRot1dvLcxImtDqPxAaY1miO6WsiP/z7Yxpg2qpaLWv5UdhAPtLvHJ4kMLM0w8GSl8AFsVF23PHe1LzuWrUlQ== + dependencies: + bs58 "^4.0.1" + cids "~0.7.0" + mafmt "^7.0.0" + multiaddr "^7.2.1" + multibase "~0.6.0" + multihashes "~0.4.13" + is-map@^2.0.2, is-map@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" @@ -2203,6 +2339,13 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.3.0.tgz#4a4aaf10c84658ab70f79a85a9a3f1e1fb11196b" integrity sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ== +mafmt@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/mafmt/-/mafmt-7.1.0.tgz#4126f6d0eded070ace7dbbb6fb04977412d380b5" + integrity sha512-vpeo9S+hepT3k2h5iFxzEHvvR0GPBx9uKaErmnRzYNcaKb03DgOArjEMlgG4a9LcuZZ89a3I8xbeto487n26eA== + dependencies: + multiaddr "^7.3.0" + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -2216,6 +2359,18 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.3" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -2257,6 +2412,68 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multiaddr@^7.2.1, multiaddr@^7.3.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-7.5.0.tgz#976c88e256e512263445ab03b3b68c003d5f485e" + integrity sha512-GvhHsIGDULh06jyb6ev+VfREH9evJCFIRnh3jUt9iEZ6XDbyoisZRFEI9bMvK/AiR6y66y6P+eoBw9mBYMhMvw== + dependencies: + buffer "^5.5.0" + cids "~0.8.0" + class-is "^1.1.0" + is-ip "^3.1.0" + multibase "^0.7.0" + varint "^5.0.0" + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@^1.0.0, multibase@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-1.0.1.tgz#4adbe1de0be8a1ab0274328b653c3f1903476724" + integrity sha512-KcCxpBVY8fdVKu4dJMAahq4F/2Z/9xqEjIiR7PiMe7LRGeorFn2NLmicN6nLBCqQvft6MG2Lc9X5P0IdyvnxEw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^1.0.0, multicodec@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-1.0.1.tgz#a89415d68283cf6287c6e219e304e75ce7fb73fe" + integrity sha512-S27Tepg4i8atNiFaU5ZOm3+gl3KQlUanLs/jWcBxQHFttgq+5x1OgbQmf2d8axJ/48zYGBd/wT9d723USMFduw== + dependencies: + buffer "^5.6.0" + multibase "^1.0.1" + varint "^5.0.0" + +multihashes@~0.4.13, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -2512,6 +2729,14 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +path@^0.12.7: + version "0.12.7" + resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" + integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== + dependencies: + process "^0.11.1" + util "^0.10.3" + picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -2616,6 +2841,11 @@ prettier@^2.8.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +process@^0.11.1: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2783,6 +3013,11 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" @@ -3277,6 +3512,18 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@^0.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + web-vitals@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c"