diff --git a/cypress/e2e/front/landing.cy.ts b/cypress/e2e/front/landing.cy.ts index 1889ee49..44d7e0f6 100644 --- a/cypress/e2e/front/landing.cy.ts +++ b/cypress/e2e/front/landing.cy.ts @@ -1,55 +1,64 @@ -describe('Good front for Landing', () => { - it('Go to landing', () => { - cy.visit(''); - }); - - it ('Good text', () => { - cy.get('#ipc-landing-navigation-name').should('contain', 'Inter Planetary Cloud'); - cy.get("#ipc-landing-headline").should('contain', 'The first distributed cloud unsealing your data.'); - cy.get("#ipc-landing-subHeadline").should('contain', 'Build on top of Aleph, the next generation network of distributed big data applications.'); - cy.get("#ipc-landing-services-title").should('contain', 'Inter Planetary Cloud offers two services'); - cy.get("#ipc-landing-features-title").should('contain', 'Our Features'); - }) - - it('Good text for features cards', () => { - cy.get("#ipc-landing-feature-upload-files").should('contain', 'Upload & Download Files'); - cy.get("#ipc-landing-folder-management").should('contain', 'Folder Management'); - cy.get("#ipc-landing-share-files").should('contain', 'Share Files'); - cy.get("#ipc-landing-programs").should('contain', 'Upload & Run Programs'); - cy.get("#ipc-landing-contact-management").should('contain', 'Contact Management'); - }) - - it('Good text for services cards', () => { - cy.get("#ipc-landing-services-cloud-storage-title").should('contain', 'Cloud Storage'); - cy.get("#ipc-landing-services-cloud-storage-description").should('contain', 'A distributed personal file storage and management system platform, protecting your data.'); - cy.get('#ipc-landing-services-cloud-computing-title').should('contain', 'Cloud Computing'); - cy.get('#ipc-landing-services-cloud-computing-description').should('contain', 'A distributed personal cloud computing platform for HTTP servers.'); - }); - - it('Good text for start buttons', () => { - cy.get("#ipc-landing-heading-start-button").should('contain', 'Start the experiment'); - cy.get("#ipc-landing-features-start-button").should('contain', 'Start the experiment'); - }) - - it('Good number of elements', () => { - cy.get("button").should('have.length', 2); - cy.get('img').should('have.length', 7); - cy.get('svg').should('have.length', 14); - cy.get('#ipc-landing-services-cloud-storage').should('have.length', 1); - cy.get('#ipc-landing-services-cloud-computing').should('have.length', 1); - }) -}); - -describe('Good redirect for Landing', () => { - beforeEach(() => { - cy.visit(''); - }); - - it('Good redirection for heading button', () => { - cy.get("#ipc-landing-heading-start-button").click().url().should('eq', `${Cypress.config().baseUrl}/connection`); - }); - - it('Good redirection for features button', () => { - cy.get("#ipc-landing-features-start-button").click().url().should('eq', `${Cypress.config().baseUrl}/connection`); - }); -}); \ No newline at end of file +describe('Good front for Landing', () => { + it('Go to landing', () => { + cy.visit(''); + }); + + it('Good text', () => { + cy.get('#ipc-landing-navigation-name').should('contain', 'Inter Planetary Cloud'); + cy.get('#ipc-landing-headline').should('contain', 'The first distributed cloud unsealing your data.'); + cy.get('#ipc-landing-subHeadline').should( + 'contain', + 'Build on top of Aleph, the next generation network of distributed big data applications.', + ); + cy.get('#ipc-landing-services-title').should('contain', 'Inter Planetary Cloud offers two services'); + cy.get('#ipc-landing-features-title').should('contain', 'Our Features'); + }); + + it('Good text for features cards', () => { + cy.get('#ipc-landing-feature-upload-files').should('contain', 'Upload & Download Files'); + cy.get('#ipc-landing-folder-management').should('contain', 'Folder Management'); + cy.get('#ipc-landing-share-files').should('contain', 'Share Files'); + cy.get('#ipc-landing-programs').should('contain', 'Upload & Run Programs'); + cy.get('#ipc-landing-contact-management').should('contain', 'Contact Management'); + }); + + it('Good text for services cards', () => { + cy.get('#ipc-landing-services-cloud-storage-title').should('contain', 'Cloud Storage'); + cy.get('#ipc-landing-services-cloud-storage-description').should( + 'contain', + 'A distributed personal file storage and management system platform, protecting your data.', + ); + cy.get('#ipc-landing-services-cloud-computing-title').should('contain', 'Cloud Computing'); + cy.get('#ipc-landing-services-cloud-computing-description').should( + 'contain', + 'A distributed personal cloud computing platform for HTTP servers.', + ); + }); + + it('Good text for start buttons', () => { + cy.get('#ipc-landing-heading-start-button').should('contain', 'Start the experiment'); + cy.get('#ipc-landing-features-start-button').should('contain', 'Start the experiment'); + }); + + it('Good number of elements', () => { + cy.get('button').should('have.length', 2); + cy.get('img').should('have.length', 7); + cy.get('svg').should('have.length', 14); + cy.get('#ipc-landing-services-cloud-storage').should('have.length', 1); + cy.get('#ipc-landing-services-cloud-computing').should('have.length', 1); + }); +}); + +describe('Good redirect for Landing', () => { + beforeEach(() => { + cy.visit(''); + }); + + it('Good redirection for heading button', () => { + cy.get('#ipc-landing-heading-start-button').click().url().should('eq', `${Cypress.config().baseUrl}/connection`); + }); + + it('Good redirection for features button', () => { + cy.get('#ipc-landing-features-start-button').click().url().should('eq', `${Cypress.config().baseUrl}/connection`); + }); +}); diff --git a/cypress/e2e/front/signup.cy.ts b/cypress/e2e/front/signup.cy.ts index d99cefcc..b3ac16d0 100644 --- a/cypress/e2e/front/signup.cy.ts +++ b/cypress/e2e/front/signup.cy.ts @@ -29,7 +29,7 @@ describe('Good front for Signup', () => { it('Good name for go to dashboard button', () => { cy.get('#ipc-signup-go-to-dashboard-button').should('contain', 'Go to my dashboard'); - }) + }); }); describe('Signup with credentials Button for Signup', () => { diff --git a/package.json b/package.json index 584c88fd..e939d3b7 100644 --- a/package.json +++ b/package.json @@ -3,29 +3,29 @@ "version": "0.1.0", "private": true, "dependencies": { - "@babel/core": "^7.21.8", + "@babel/core": "^7.22.5", "@chakra-ui/icons": "^2.0.19", - "@chakra-ui/react": "^2.6.1", - "@chakra-ui/styled-system": "^2.9.0", - "@chakra-ui/system": "^2.5.7", - "@chakra-ui/theme-tools": "^2.0.16", - "@emotion/react": "^11.11.0", + "@chakra-ui/react": "^2.7.1", + "@chakra-ui/styled-system": "^2.9.1", + "@chakra-ui/system": "^2.5.8", + "@chakra-ui/theme-tools": "^2.0.18", + "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "aleph-sdk-ts": "^3.2.0", "axios": "^1.4.0", - "boring-avatars": "^1.7.0", + "boring-avatars": "^1.10.1", "crypto-js": "^4.1.1", "eth-crypto": "^2.6.0", "ethers": "^5.7.2", - "framer-motion": "^10.12.12", + "framer-motion": "^10.12.17", "git-clone": "^0.2.0", "js-file-download": "^0.4.12", "next": "^12.3.4", "next-auth": "4.10.3", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-icons": "^4.8.0", - "typescript": "^5.0.4", + "react-icons": "^4.10.1", + "typescript": "^5.1.3", "zod": "^3.21.4" }, "scripts": { @@ -54,13 +54,13 @@ "@types/crypto-js": "^4.1.1", "@types/git-clone": "^0.2.0", "@types/node": "^16.18.31", - "@types/react": "^18.2.6", - "@types/react-dom": "^18.2.4", - "@typescript-eslint/eslint-plugin": "^5.59.6", - "@typescript-eslint/parser": "^5.59.6", + "@types/react": "^18.2.14", + "@types/react-dom": "^18.2.6", + "@typescript-eslint/eslint-plugin": "^5.60.0", + "@typescript-eslint/parser": "^5.60.0", "cypress": "^11.2.0", "cypress-file-upload": "^5.0.8", - "eslint": "^8.40.0", + "eslint": "^8.43.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-prettier": "^8.8.0", diff --git a/pages/_app.tsx b/pages/_app.tsx index b9636758..af183eec 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -33,6 +33,7 @@ const App = ({ const [sharedFiles, setSharedFiles] = useState([]); const [folders, setFolders] = useState([]); const [programs, setPrograms] = useState([]); + const [sharedPrograms, setSharedPrograms] = useState([]); const [contacts, setContacts] = useState([]); const [path, setPath] = useState('/'); const toast = useToast(); @@ -89,6 +90,8 @@ const App = ({ setSharedFiles, folders, setFolders, + sharedPrograms, + setSharedPrograms, programs, setPrograms, contacts, diff --git a/pages/drive/index.tsx b/pages/drive/index.tsx index e2a548c2..422f39b0 100644 --- a/pages/drive/index.tsx +++ b/pages/drive/index.tsx @@ -15,7 +15,8 @@ const Dashboard = (): JSX.Element => { const { setConfig } = useConfigContext(); const { colorMode, toggleColorMode } = useColorMode(); - const { path, folders, files, setFiles, setFolders, setContacts, setPrograms, setSharedFiles } = useDriveContext(); + const { path, folders, files, setFiles, setFolders, setContacts, setPrograms, setSharedFiles, setSharedPrograms } = + useDriveContext(); useEffect(() => { (async () => { @@ -27,22 +28,23 @@ const Dashboard = (): JSX.Element => { }, []); const loadContact = async () => { - const load = await user.contact.load(); + const load = await user.fullContact.contact.load(); toast({ title: load.message, status: load.success ? 'success' : 'error' }); - setContacts(user.contact.contacts); + setContacts(user.fullContact.contact.contacts); }; const loadUserContents = async () => { - const loadShared = await user.drive.loadShared(user.contact.contacts); + const loadShared = await user.drive.loadShared(user.fullContact.contact.contacts); toast({ title: loadShared.message, status: loadShared.success ? 'success' : 'error' }); setFiles(user.drive.files); setFolders(user.drive.folders); setSharedFiles(user.drive.sharedFiles); + setSharedPrograms(user.drive.sharedPrograms); - const loadedPrograms = await user.computing.load(); + const loadedPrograms = await user.fullContact.computing.load(); toast({ title: loadedPrograms.message, status: loadedPrograms.success ? 'success' : 'error' }); - setPrograms(user.computing.programs); + setPrograms(user.fullContact.computing.programs); const loadedConfig = await user.loadConfig(); setConfig(user.config); diff --git a/pages/drive/shared.tsx b/pages/drive/shared.tsx index 42fee177..3ef2e915 100644 --- a/pages/drive/shared.tsx +++ b/pages/drive/shared.tsx @@ -8,12 +8,13 @@ import { useDriveContext } from 'contexts/drive'; const Shared = (): JSX.Element => { const { sharedFiles } = useDriveContext(); + const { sharedPrograms } = useDriveContext(); return ( - !elem.deletedAt)} /> + !elem.deletedAt)} programs={sharedPrograms} /> ); diff --git a/src/components/account/AccountCard.tsx b/src/components/account/AccountCard.tsx index 1d15110a..49270bbd 100644 --- a/src/components/account/AccountCard.tsx +++ b/src/components/account/AccountCard.tsx @@ -15,7 +15,6 @@ import { import Avatar from 'boring-avatars'; import { ChangeEvent, useState } from 'react'; import { BsClipboard } from 'react-icons/bs'; - import Card from 'components/cards/Card'; import { useUserContext } from 'contexts/user'; @@ -29,7 +28,7 @@ import Modal from '../Modal'; const AccountCard = (): JSX.Element => { const { user } = useUserContext(); const [isOpen, setIsOpen] = useState(false); - const [input, setInput] = useState(user.contact.username || ''); + const [input, setInput] = useState(user.fullContact.contact.username || ''); const [isLoading, setIsLoading] = useState(false); const toast = useToast({ duration: 2000, isClosable: true }); @@ -37,7 +36,7 @@ const AccountCard = (): JSX.Element => { const changeName = async () => { setIsLoading(true); try { - const config1 = await user.contact.update(user.account.address, input); + const config1 = await user.fullContact.manage.update(user.account.address, input); setIsOpen(false); toast({ title: config1.message, status: config1.success ? 'success' : 'error' }); } catch (error) { @@ -92,7 +91,7 @@ const AccountCard = (): JSX.Element => { ]} /> - {user.contact.username} + {user.fullContact.contact.username} diff --git a/src/components/account/ConfigCard.tsx b/src/components/account/ConfigCard.tsx index 4ffc883e..ddca4dc1 100644 --- a/src/components/account/ConfigCard.tsx +++ b/src/components/account/ConfigCard.tsx @@ -34,7 +34,7 @@ const ConfigCard = (): JSX.Element => { const changeConfig = async (key: string, value: string) => { setIsLoading(true); try { - const config1 = await user.contact.updateConfig(key, value); + const config1 = await user.fullContact.manage.updateConfig(key, value); setConfig({ ...user.config, [key]: { diff --git a/src/components/cards/FileCard.tsx b/src/components/cards/FileCard.tsx index 4a34ba92..c7f0fd89 100644 --- a/src/components/cards/FileCard.tsx +++ b/src/components/cards/FileCard.tsx @@ -22,7 +22,9 @@ const FileCard = ({ file }: { file: IPCFile }): JSX.Element => { const { files } = useDriveContext(); const { user: { - contact: { username }, + fullContact: { + contact: { username }, + }, }, } = useUserContext(); @@ -33,7 +35,6 @@ const FileCard = ({ file }: { file: IPCFile }): JSX.Element => { const isDrawer = useBreakpointValue({ base: true, sm: false }) || false; const textColor = useColorModeValue(textColorMode.light, textColorMode.dark); - return ( <> { const { path, setPath } = useDriveContext(); const { user: { - contact: { username }, + fullContact: { + contact: { username }, + }, }, } = useUserContext(); diff --git a/src/components/cards/ProgramCard.tsx b/src/components/cards/ProgramCard.tsx index 79ef2cf1..2834c60f 100644 --- a/src/components/cards/ProgramCard.tsx +++ b/src/components/cards/ProgramCard.tsx @@ -19,7 +19,9 @@ import Card from './Card'; const ProgramCard = ({ program }: { program: IPCProgram }): JSX.Element => { const { user: { - contact: { username }, + fullContact: { + contact: { username }, + }, }, } = useUserContext(); const { isOpen: isOpenFile, onOpen: onOpenFile, onClose: onCloseFile } = useDisclosure(); diff --git a/src/components/computing/github/GithubModal.tsx b/src/components/computing/github/GithubModal.tsx index aa8d1bbf..399247bf 100644 --- a/src/components/computing/github/GithubModal.tsx +++ b/src/components/computing/github/GithubModal.tsx @@ -63,6 +63,7 @@ const GithubModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void hash: result.data.item_hash, createdAt: Date.now(), entrypoint: result.data.entrypoint, + permission: 'owner', size: 0, logs: [ { @@ -70,10 +71,11 @@ const GithubModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void date: Date.now(), }, ], + hashFile: '', }; - user.computing.programs.push(newProgram); - await user.computing.publishAggregate(); - setPrograms(user.computing.programs); + user.fullContact.computing.programs.push(newProgram); + await user.fullContact.computing.publishAggregate(); + setPrograms(user.fullContact.computing.programs); toast({ title: 'Upload succeeded', status: 'success' }); onClose(); } catch (err) { diff --git a/src/components/computing/programs/ProgramModal.tsx b/src/components/computing/programs/ProgramModal.tsx index 2f9c4164..46eed022 100644 --- a/src/components/computing/programs/ProgramModal.tsx +++ b/src/components/computing/programs/ProgramModal.tsx @@ -1,10 +1,10 @@ +import { Input, Text, VStack, useColorModeValue, useToast } from '@chakra-ui/react'; import { ChangeEvent, useState } from 'react'; -import { Input, Text, useColorModeValue, useToast, VStack } from '@chakra-ui/react'; import Modal from 'components/Modal'; -import { useUserContext } from 'contexts/user'; import { useDriveContext } from 'contexts/drive'; +import { useUserContext } from 'contexts/user'; import { extractFilename } from 'utils/fileManipulation'; @@ -36,19 +36,20 @@ const ProgramModal = ({ const toast = useToast({ duration: 2000, isClosable: true }); const uploadProgram = async (oldProgram: IPCProgram | undefined) => { - if (!fileEvent || !fileEvent.target.files) return; + if (!fileEvent?.target.files) return; const filename = extractFilename(fileEvent.target.value); if (!filename) return; setIsDeployLoading(true); try { - const upload = await user.computing.uploadProgram( + const upload = await user.fullContact.computing.upload( { id: crypto.randomUUID(), name: customName || filename, hash: '', createdAt: Date.now(), entrypoint: customEntrypoint || user.config?.defaultEntrypoint.value || 'main:app', + permission: 'owner', size: fileEvent.target.files[0].size, logs: [ { @@ -56,13 +57,14 @@ const ProgramModal = ({ date: Date.now(), }, ], + hashFile: '', }, fileEvent.target.files[0], !!oldProgram, oldProgram, ); toast({ title: upload.message, status: upload.success ? 'success' : 'error' }); - setPrograms(user.computing.programs); + setPrograms(user.fullContact.computing.programs); onClose(); } catch (error) { console.error(error); diff --git a/src/components/contact/AddContact.tsx b/src/components/contact/AddContact.tsx index c21929fe..1fb9bdf1 100644 --- a/src/components/contact/AddContact.tsx +++ b/src/components/contact/AddContact.tsx @@ -22,7 +22,7 @@ const AddContact = (): JSX.Element => { try { if (name && contactPublicKey) { const address = EthCrypto.publicKey.toAddress(contactPublicKey.slice(2)); - const add = await user.contact.add({ + const add = await user.fullContact.manage.add({ name, address, publicKey: contactPublicKey, @@ -34,7 +34,7 @@ const AddContact = (): JSX.Element => { }); toast({ title: add.message, status: add.success ? 'success' : 'error' }); - setContacts(user.contact.contacts); + setContacts(user.fullContact.contact.contacts); } else { toast({ title: 'Bad contact infos', status: 'error' }); } diff --git a/src/components/contact/DeleteContact.tsx b/src/components/contact/DeleteContact.tsx index 7ce6fcd7..53109785 100644 --- a/src/components/contact/DeleteContact.tsx +++ b/src/components/contact/DeleteContact.tsx @@ -16,13 +16,13 @@ const DeleteContact = ({ contact }: DeleteContactProps): JSX.Element => { const toast = useToast({ duration: 2000, isClosable: true }); const deleteContact = async () => { - const deletedContact = user.contact.contacts.find((c) => c === contact); + const deletedContact = user.fullContact.contact.contacts.find((c) => c === contact); if (deletedContact) { - const deleteResponse = await user.contact.remove(contact.address); + const deleteResponse = await user.fullContact.manage.remove(contact.address); toast({ title: deleteResponse.message, status: deleteResponse.success ? 'success' : 'error' }); - setContacts(user.contact.contacts); + setContacts(user.fullContact.contact.contacts); } else { toast({ title: 'Unable to find this contact', status: 'error' }); } diff --git a/src/components/contact/UpdateContact.tsx b/src/components/contact/UpdateContact.tsx index f3b33b08..52a7c4ec 100644 --- a/src/components/contact/UpdateContact.tsx +++ b/src/components/contact/UpdateContact.tsx @@ -28,9 +28,9 @@ const UpdateContact = ({ contact }: UpdateContactProps): JSX.Element => { const updateContact = async () => { setIsLoading(true); if (name) { - const update = await user.contact.update(contact.address, name); + const update = await user.fullContact.manage.update(contact.address, name); toast({ title: update.message, status: update.success ? 'success' : 'error' }); - setContacts(user.contact.contacts); + setContacts(user.fullContact.contact.contacts); } else { toast({ title: 'Invalid name', status: 'error' }); } diff --git a/src/components/dashboardPage/ProgramOptions.tsx b/src/components/dashboardPage/ProgramOptions.tsx index 0d9f3cf7..3430268e 100644 --- a/src/components/dashboardPage/ProgramOptions.tsx +++ b/src/components/dashboardPage/ProgramOptions.tsx @@ -21,8 +21,10 @@ import { useConfigContext } from 'contexts/config'; import DeployProgram from 'components/computing/programs/DeployProgram'; import DeleteProgram from 'components/programs/DeleteProgram'; +import DownloadProgram from 'components/programs/DownloadProgram'; import GoToWebsiteProgram from 'components/programs/GoToWebsiteProgram'; import RenameProgram from 'components/programs/RenameProgram'; +import ShareProgram from 'components/programs/ShareProgram'; const ProgramOptionsContent = ({ program }: { program: IPCProgram }) => ( <> @@ -30,6 +32,8 @@ const ProgramOptionsContent = ({ program }: { program: IPCProgram }) => ( + + ); @@ -101,4 +105,4 @@ const ProgramOptionsDrawer = ({ ); -export { ProgramOptionsPopover, ProgramOptionsDrawer }; +export { ProgramOptionsDrawer, ProgramOptionsPopover }; diff --git a/src/components/file/DeleteBin.tsx b/src/components/file/DeleteBin.tsx index 04babf02..f7a3ecc4 100644 --- a/src/components/file/DeleteBin.tsx +++ b/src/components/file/DeleteBin.tsx @@ -32,7 +32,7 @@ const DeleteBin = ({ files, folders, concernedFiles }: DeleteBinProps): JSX.Elem if (user.account) { const deleted = await user.drive.delete(files.map((file) => file.hash)); if (deleted.success) { - const removed = await user.contact.deleteFiles( + const removed = await user.fullContact.files.delete( files.map((file) => file.id), concernedFiles, ); diff --git a/src/components/file/DeleteFile.tsx b/src/components/file/DeleteFile.tsx index e1338a2a..9e89f2d9 100644 --- a/src/components/file/DeleteFile.tsx +++ b/src/components/file/DeleteFile.tsx @@ -3,10 +3,10 @@ import { Icon, Text, useBreakpointValue, - useDisclosure, - useToast, useColorMode, useColorModeValue, + useDisclosure, + useToast, } from '@chakra-ui/react'; import { useState } from 'react'; import { IoTrashSharp } from 'react-icons/io5'; @@ -43,7 +43,7 @@ const DeleteFile = ({ file, concernedFiles, onClosePopover }: DeleteFileProps): const deleted = await user.drive.delete([file.hash]); toast({ title: deleted.message, status: deleted.success ? 'success' : 'error' }); if (deleted.success) { - const removed = await user.contact.deleteFiles([file.id], concernedFiles); + const removed = await user.fullContact.files.delete([file.id], concernedFiles); if (!removed.success) { toast({ title: removed.message, status: 'error' }); @@ -61,7 +61,7 @@ const DeleteFile = ({ file, concernedFiles, onClosePopover }: DeleteFileProps): const moveToBin = async (deletedAt: number) => { setIsLoading(true); if (user.account) { - const moved = await user.contact.moveFileToBin(file, deletedAt, concernedFiles); + const moved = await user.fullContact.files.moveToBin(file, deletedAt, concernedFiles); toast({ title: moved.message, status: moved.success ? 'success' : 'error' }); const index = files.indexOf(file); diff --git a/src/components/file/MoveFile.tsx b/src/components/file/MoveFile.tsx index 32fb056a..7968148b 100644 --- a/src/components/file/MoveFile.tsx +++ b/src/components/file/MoveFile.tsx @@ -5,10 +5,10 @@ import { Icon, Text, useBreakpointValue, - useDisclosure, - useToast, useColorMode, useColorModeValue, + useDisclosure, + useToast, } from '@chakra-ui/react'; import { useState } from 'react'; import { FcFolder } from 'react-icons/fc'; @@ -41,7 +41,7 @@ const MoveFile = ({ file, onClosePopover }: MoveFileProps): JSX.Element => { const moveFile = async () => { setIsLoading(true); - const moved = await user.contact.moveFile(file, newPath); + const moved = await user.fullContact.files.move(file, newPath); toast({ title: moved.message, status: moved.success ? 'success' : 'error' }); const index = files.indexOf(file); diff --git a/src/components/file/RenameFile.tsx b/src/components/file/RenameFile.tsx index 706b0041..fd6b2276 100644 --- a/src/components/file/RenameFile.tsx +++ b/src/components/file/RenameFile.tsx @@ -6,10 +6,10 @@ import { Input, Text, useBreakpointValue, - useDisclosure, - useToast, useColorMode, useColorModeValue, + useDisclosure, + useToast, } from '@chakra-ui/react'; import { ChangeEvent, useState } from 'react'; @@ -43,7 +43,7 @@ const RenameFile = ({ file, concernedFiles, onClosePopover }: RenameFileProps): const renameFile = async () => { setIsLoading(true); if (name) { - const update = await user.contact.updateFileName(file, name, concernedFiles); + const update = await user.fullContact.files.updateName(file, name, concernedFiles); toast({ title: update.message, status: update.success ? 'success' : 'error' }); if (update.success) { const index = files.indexOf(file); diff --git a/src/components/file/RestoreFile.tsx b/src/components/file/RestoreFile.tsx index 81747657..b868e5be 100644 --- a/src/components/file/RestoreFile.tsx +++ b/src/components/file/RestoreFile.tsx @@ -1,4 +1,4 @@ -import { HStack, Icon, Text, useBreakpointValue, useToast, useColorMode, useColorModeValue } from '@chakra-ui/react'; +import { HStack, Icon, Text, useBreakpointValue, useColorMode, useColorModeValue, useToast } from '@chakra-ui/react'; import { BiUndo } from 'react-icons/bi'; import { useDriveContext } from 'contexts/drive'; @@ -25,7 +25,7 @@ const DeleteFile = ({ file, concernedFiles, onClose }: DeleteFileProps): JSX.Ele const restoreFile = async () => { if (user.account) { - const moved = await user.contact.moveFileToBin(file, null, concernedFiles); + const moved = await user.fullContact.files.moveToBin(file, null, concernedFiles); toast({ title: moved.message, status: moved.success ? 'success' : 'error' }); const index = files.indexOf(file); diff --git a/src/components/file/ShareFile.tsx b/src/components/file/ShareFile.tsx index 4ab5447f..f64d66d2 100644 --- a/src/components/file/ShareFile.tsx +++ b/src/components/file/ShareFile.tsx @@ -43,7 +43,7 @@ const ShareFile = ({ file, onClosePopover }: ShareFileProps): JSX.Element => { const shareFile = async () => { setIsLoading(true); - const share = await user.contact.addFileToContact(contact!.address, { ...file, permission }); + const share = await user.fullContact.files.addToContact(contact!.address, { ...file, permission }); toast({ title: share.message, status: share.success ? 'success' : 'error' }); onUnmount(); @@ -116,7 +116,7 @@ const ShareFile = ({ file, onClosePopover }: ShareFileProps): JSX.Element => { > {!contact && - user.contact.contacts.map((c) => { + user.fullContact.contact.contacts.map((c) => { if (c.address !== user.account.address) return ( { setFiles([...files, upload.file]); user.drive.files.push(upload.file); - const shared = await user.contact.addFileToContact(user.account.address, upload.file); + const shared = await user.fullContact.files.addToContact(user.account.address, upload.file); toast({ title: upload.message, status: shared.success ? 'success' : 'error' }); } } else toast({ title: 'Failed to load account', status: 'error' }); diff --git a/src/components/file/detailsFile/DrawerDetailsFile.tsx b/src/components/file/detailsFile/DrawerDetailsFile.tsx index 26ebf32e..d495d891 100644 --- a/src/components/file/detailsFile/DrawerDetailsFile.tsx +++ b/src/components/file/detailsFile/DrawerDetailsFile.tsx @@ -39,7 +39,7 @@ const DrawerDetailsFile = ({ const isDrawer = useBreakpointValue({ base: true, sm: false }) || false; const list: { name: string; address: string }[] = []; - user.contact.contacts.forEach((contact: IPCContact) => { + user.fullContact.contact.contacts.forEach((contact: IPCContact) => { contact.files.forEach((contactFile: IPCFile) => { if (contactFile.hash === file.hash) { list.push({ name: contact.name, address: contact.address }); diff --git a/src/components/folder/CreateFolder.tsx b/src/components/folder/CreateFolder.tsx index af33f9af..f02626a4 100644 --- a/src/components/folder/CreateFolder.tsx +++ b/src/components/folder/CreateFolder.tsx @@ -53,7 +53,7 @@ const CreateFolder = (): JSX.Element => { ], }; - const created = await user.contact.createFolder(folder); + const created = await user.fullContact.folders.create(folder); toast({ title: created.message, status: created.success ? 'success' : 'error' }); if (created.success) { setFolders([...folders, folder]); diff --git a/src/components/folder/DeleteFolder.tsx b/src/components/folder/DeleteFolder.tsx index 088e62cf..e3edb085 100644 --- a/src/components/folder/DeleteFolder.tsx +++ b/src/components/folder/DeleteFolder.tsx @@ -45,7 +45,7 @@ const DeleteFolder = ({ folder }: DeleteFolderProps): JSX.Element => { const fullPath = `${folder.path}${folder.name}/`; if (user.account) { - const foldersResponse = await user.contact.deleteFolder(folder); + const foldersResponse = await user.fullContact.folders.delete(folder); setFolders( folders.filter( (f) => !f.path.startsWith(fullPath) && (f.path !== folder.path || f.createdAt !== folder.createdAt), @@ -56,7 +56,7 @@ const DeleteFolder = ({ folder }: DeleteFolderProps): JSX.Element => { const filesToDelete = user.drive.files.filter((file) => file.path.startsWith(fullPath)); if (filesToDelete.length > 0) { const filesResponse = await user.drive.delete(filesToDelete.map((file) => file.hash)); - await user.contact.deleteFiles( + await user.fullContact.files.delete( filesToDelete.map((file) => file.id), [], ); diff --git a/src/components/folder/MoveFolder.tsx b/src/components/folder/MoveFolder.tsx index db848a97..52c2da21 100644 --- a/src/components/folder/MoveFolder.tsx +++ b/src/components/folder/MoveFolder.tsx @@ -5,10 +5,10 @@ import { Icon, Text, useBreakpointValue, - useDisclosure, - useToast, useColorMode, useColorModeValue, + useDisclosure, + useToast, } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import { FcFolder } from 'react-icons/fc'; @@ -51,7 +51,7 @@ const MoveFolder = ({ folder }: MoveFolderProps): JSX.Element => { setIsLoading(true); const fullPath = `${folder.path}${folder.name}/`; - const moved = await user.contact.moveFolder(folder, newPath); + const moved = await user.fullContact.folders.move(folder, newPath); toast({ title: moved.message, status: moved.success ? 'success' : 'error' }); setFiles( diff --git a/src/components/navigation/ResponsiveBar.tsx b/src/components/navigation/ResponsiveBar.tsx index a86420ba..c05ec1f0 100644 --- a/src/components/navigation/ResponsiveBar.tsx +++ b/src/components/navigation/ResponsiveBar.tsx @@ -83,8 +83,8 @@ export const ResponsiveBar = (): JSX.Element => { {!isDrawerNeeded && ( )} diff --git a/src/components/navigation/SideBar.tsx b/src/components/navigation/SideBar.tsx index d0db56d3..94feeb60 100644 --- a/src/components/navigation/SideBar.tsx +++ b/src/components/navigation/SideBar.tsx @@ -116,8 +116,8 @@ const SideBar = (): JSX.Element => { {isDrawerNeeded && ( )} diff --git a/src/components/programs/DeleteProgram.tsx b/src/components/programs/DeleteProgram.tsx index cabd7c43..91b89e34 100644 --- a/src/components/programs/DeleteProgram.tsx +++ b/src/components/programs/DeleteProgram.tsx @@ -3,9 +3,9 @@ import { Icon, Text, useBreakpointValue, - useDisclosure, useColorMode, useColorModeValue, + useDisclosure, } from '@chakra-ui/react'; import { useState } from 'react'; import { IoTrashSharp } from 'react-icons/io5'; @@ -35,7 +35,7 @@ const DeleteProgram = ({ program }: DeleteProgramProps): JSX.Element => { const deleteActualProgram = async () => { setIsLoading(true); - const update = await user.computing.deleteProgram(program.hash); + const update = await user.fullContact.computing.delete(program.hash); if (update.success) setPrograms(programs.filter((f) => f.hash !== program.hash)); setIsLoading(false); onClose(); diff --git a/src/components/programs/DownloadProgram.tsx b/src/components/programs/DownloadProgram.tsx new file mode 100644 index 00000000..3807ac2d --- /dev/null +++ b/src/components/programs/DownloadProgram.tsx @@ -0,0 +1,66 @@ +import { HStack, Icon, Text, useBreakpointValue, useColorMode, useColorModeValue, useToast } from '@chakra-ui/react'; +import { FiDownload } from 'react-icons/fi'; + +import { useUserContext } from 'contexts/user'; + +import { textColorMode } from 'config/colorMode'; +import type { IPCProgram } from 'types/types'; + +type DownloadProgramProps = { + program: IPCProgram; +}; + +const DownloadProgram = ({ program }: DownloadProgramProps): JSX.Element => { + const { user } = useUserContext(); + const textColor = useColorModeValue(textColorMode.light, textColorMode.dark); + const { colorMode } = useColorMode(); + + const isDrawer = useBreakpointValue({ base: true, sm: false }) || false; + const toast = useToast({ duration: 2000, isClosable: true, id: 'ipc-download-program' }); + + const downloadProgram = async () => { + try { + const download = await user.computing.download(program); + toast({ title: download.message, status: download.success ? 'success' : 'error' }); + } catch (error) { + console.error(error); + toast({ title: 'Unable to download program', status: 'error' }); + } + }; + + return ( + + + + Download + + + ); +}; + +export default DownloadProgram; diff --git a/src/components/programs/RenameProgram.tsx b/src/components/programs/RenameProgram.tsx index 30296d2d..078b4223 100644 --- a/src/components/programs/RenameProgram.tsx +++ b/src/components/programs/RenameProgram.tsx @@ -43,7 +43,7 @@ const RenameProgram = ({ program }: RenameProgramProps) => { const updateProgramName = async () => { setIsLoading(true); if (name) { - const update = await user.computing.updateProgramName(program, name); + const update = await user.fullContact.computing.updateName(program, name); if (update.success) { const index = programs.indexOf(program); if (index !== -1) { diff --git a/src/components/programs/ShareProgram.tsx b/src/components/programs/ShareProgram.tsx new file mode 100644 index 00000000..c6fe734a --- /dev/null +++ b/src/components/programs/ShareProgram.tsx @@ -0,0 +1,165 @@ +import { + Divider, + HStack, + Icon, + Select, + Text, + useBreakpointValue, + useColorMode, + useColorModeValue, + useDisclosure, + useToast, + VStack, +} from '@chakra-ui/react'; +import { ChangeEvent, useState } from 'react'; +import { BsShareFill } from 'react-icons/bs'; + +import Modal from 'components/Modal'; + +import { useUserContext } from 'contexts/user'; + +import Avatar from 'boring-avatars'; +import Button from 'components/Button'; +import Card from 'components/cards/Card'; +import { hoverColorMode, textColorMode } from 'config/colorMode'; +import colors from 'theme/foundations/colors'; +import type { IPCContact, IPCProgram, IPCPermission } from 'types/types'; + +type ShareProgramProps = { + program: IPCProgram; +}; + +const ShareProgram = ({ program }: ShareProgramProps): JSX.Element => { + const { user } = useUserContext(); + + const [contact, setContact] = useState(null); + const [permission, setPermission] = useState('viewer'); + const [isLoading, setIsLoading] = useState(false); + const { isOpen, onOpen, onClose } = useDisclosure(); + + const isDrawer = useBreakpointValue({ base: true, sm: false }) || false; + const toast = useToast({ duration: 2000, isClosable: true }); + + const shareProgram = async () => { + setIsLoading(true); + const share = await user.fullContact.computing.addToContact(contact!.address, { ...program, permission }); + toast({ title: share.message, status: share.success ? 'success' : 'error' }); + onUnmount(); + }; + + const onUnmount = () => { + setIsLoading(false); + setContact(null); + setPermission('viewer'); + onClose(); + }; + + const textColor = useColorModeValue(textColorMode.light, textColorMode.dark); + const hoverColor = useColorModeValue(hoverColorMode.light, hoverColorMode.dark); + const { colorMode } = useColorMode(); + + return ( + + + + Share + + + Share + + ) : ( + <> + ) + } + > + + {!contact && + user.fullContact.contact.contacts.map((c) => { + if (c.address !== user.account.address) + return ( + setContact(c)} + cursor="pointer" + _hover={{ bg: hoverColor }} + > + + + + + {c.name} + + + {c.address} + + + + + ); + return ; + })} + {contact && ( + + )} + + + + ); +}; + +export default ShareProgram; diff --git a/src/contexts/drive.ts b/src/contexts/drive.ts index 447c9f2c..aa007905 100644 --- a/src/contexts/drive.ts +++ b/src/contexts/drive.ts @@ -12,6 +12,8 @@ type DriveContextProps = { setFolders: Dispatch; programs: IPCProgram[]; setPrograms: Dispatch; + sharedPrograms: IPCProgram[]; + setSharedPrograms: Dispatch; contacts: IPCContact[]; setContacts: Dispatch; path: string; diff --git a/src/lib/contact.ts b/src/lib/contact.ts deleted file mode 100644 index 8941ae93..00000000 --- a/src/lib/contact.ts +++ /dev/null @@ -1,536 +0,0 @@ -import { accounts } from 'aleph-sdk-ts'; -import { aggregate, forget, post } from 'aleph-sdk-ts/dist/messages'; -import { AggregateMessage, ItemType } from 'aleph-sdk-ts/dist/messages/message'; - -import type { - AggregateContentType, - AggregateType, - IPCContact, - IPCFile, - IPCFolder, - IPCUpdateContent, - ResponseType, -} from 'types/types'; - -import { ALEPH_CHANNEL } from 'config/constants'; - -class Contact { - public contacts: IPCContact[]; - - public username: string; - - private readonly account: accounts.ethereum.ETHAccount; - - constructor(importedAccount: accounts.ethereum.ETHAccount) { - this.contacts = []; - this.account = importedAccount; - this.username = ''; - } - - private async publishAggregate(): Promise> { - const aggr = await aggregate.Get({ - address: this.account.address, - keys: ['InterPlanetaryCloud'], - }); - - const content = aggr.InterPlanetaryCloud; - content.contacts = this.contacts; - - return aggregate.Publish({ - channel: ALEPH_CHANNEL, - storageEngine: ItemType.ipfs, - account: this.account, - key: 'InterPlanetaryCloud', - content, - }); - } - - private async getFileOwner(fileId: string): Promise { - let owner; - await Promise.all( - this.contacts.map(async (contact) => { - const aggr = await aggregate.Get({ - address: contact.address, - keys: ['InterPlanetaryCloud'], - }); - - const myContact = aggr.InterPlanetaryCloud.contacts.find((c) => c.address === this.account.address); - if (myContact?.files.find((f) => f.id === fileId)) { - owner = contact.publicKey; - } - }), - ); - return owner; - } - - public async load(): Promise { - try { - const aggr = await aggregate.Get({ - address: this.account.address, - keys: ['InterPlanetaryCloud'], - }); - - this.contacts = aggr.InterPlanetaryCloud.contacts; - this.username = this.contacts.find((c) => c.address === this.account.address)?.name || ''; - - await this.loadUpdates(); - - return { success: true, message: 'Contacts loaded' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to load contacts' }; - } - } - - private async loadUpdates(): Promise { - try { - await Promise.all( - this.contacts.map(async (contact) => { - const updatableIds = contact.files.filter((file) => file.permission === 'editor').map((file) => file.id); - - const updates = await post.Get({ - types: ['InterPlanetaryCloud'], - pagination: 200, - addresses: [contact.address], - tags: updatableIds, - }); - await Promise.all( - updates.posts.map(async (update) => { - const { tags, file } = update.content; - const [type, fileId] = tags; - - await Promise.all( - this.contacts.map(async (c) => { - const foundFile = c.files.find((f) => f.id === fileId); - - if (foundFile && this.account) { - if (type === 'rename') foundFile.name = file.name; - else if (type === 'update') { - foundFile.hash = file.hash; - foundFile.size = file.size; - foundFile.encryptInfos = { - key: ( - await this.account.encrypt( - await this.account.decrypt(Buffer.from(file.encryptInfos.key, 'hex')), - c.publicKey, - ) - ).toString('hex'), - iv: ( - await this.account.encrypt( - await this.account.decrypt(Buffer.from(file.encryptInfos.iv, 'hex')), - c.publicKey, - ) - ).toString('hex'), - }; - } else if (type === 'delete') { - const owner = this.contacts.find((co) => co.address === c.address)!; - owner.files = owner.files.filter((f) => f.id !== fileId); - } else if (type === 'bin') foundFile.deletedAt = file.deletedAt; - } - }), - ); - }), - ); - await this.publishAggregate(); - - const hashes = updates.posts.map((p) => p.hash); - await forget.Publish({ - account: this.account, - channel: ALEPH_CHANNEL, - storageEngine: ItemType.ipfs, - hashes, - }); - }), - ); - } catch (err) { - console.error(err); - } - } - - public async add(contactToAdd: IPCContact): Promise { - try { - if (this.contacts.find((contact) => contact.address === contactToAdd.address)) { - return { success: false, message: 'Contact already exist' }; - } - this.contacts.push(contactToAdd); - - await this.publishAggregate(); - return { success: true, message: 'Contact added' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to add this contact' }; - } - } - - public async remove(contactAddress: string): Promise { - try { - if (contactAddress !== this.account.address) { - this.contacts.forEach((contact, index) => { - if (contact.address === contactAddress) { - this.contacts.splice(index, 1); - } - }); - - await this.publishAggregate(); - return { success: true, message: 'Contact deleted' }; - } - return { success: false, message: "You can't delete your account" }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to delete this contact' }; - } - } - - public async update(contactAddress: string, newName: string): Promise { - try { - const contact = this.contacts.find((c) => c.address === contactAddress); - - if (contact) { - contact.name = newName; - await this.publishAggregate(); - return { success: true, message: 'Contact updated' }; - } - return { success: false, message: 'Contact does not exist' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to update this contact' }; - } - } - - public async updateFileContent(newFile: IPCFile): Promise { - try { - let fileFound = false; - await Promise.all( - this.contacts.map(async (contact) => { - const file = contact.files.find((f) => f.id === newFile.id); - - if (file && this.account) { - file.hash = newFile.hash; - file.encryptInfos = { - key: ( - await this.account.encrypt( - await this.account.decrypt(Buffer.from(newFile.encryptInfos.key, 'hex')), - contact.publicKey, - ) - ).toString('hex'), - iv: ( - await this.account.encrypt( - await this.account.decrypt(Buffer.from(newFile.encryptInfos.iv, 'hex')), - contact.publicKey, - ) - ).toString('hex'), - }; - fileFound = true; - await this.publishAggregate(); - } - }), - ); - - if (!fileFound && this.account) { - const owner = await this.getFileOwner(newFile.id); - if (!owner) { - return { success: false, message: 'File not found' }; - } - // const fileKey = ( - // await this.account.encrypt(await this.account.decrypt(Buffer.from(newFile.encryptKey, 'hex'))) - // ).toString('hex'); - - const encryptInfos = { - key: ( - await this.account.encrypt(await this.account.decrypt(Buffer.from(newFile.encryptInfos.key, 'hex')), owner) - ).toString('hex'), - iv: ( - await this.account.encrypt(await this.account.decrypt(Buffer.from(newFile.encryptInfos.iv, 'hex')), owner) - ).toString('hex'), - }; - await post.Publish({ - account: this.account, - postType: 'InterPlanetaryCloud', - content: { file: { ...newFile, encryptInfos }, tags: ['update', newFile.id] }, - channel: 'TEST', - storageEngine: ItemType.ipfs, - }); - } - return { success: true, message: 'File content updated' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to update the file content' }; - } - } - - public async updateFileName(concernedFile: IPCFile, newName: string, sharedFiles: IPCFile[]): Promise { - try { - let fileFound = false; - await Promise.all( - this.contacts.map(async (contact) => { - const file = contact.files.find((f) => f.id === concernedFile.id); - if (file) { - file.name = newName; - file.logs.push({ - action: `Renamed file to ${newName}`, - date: Date.now(), - }); - fileFound = true; - await this.publishAggregate(); - } - }), - ); - if (!fileFound) { - const file = sharedFiles.find((f) => f.id === concernedFile.id); - if (!file) { - return { success: false, message: 'File not found' }; - } - await post.Publish({ - account: this.account, - postType: 'InterPlanetaryCloud', - content: { file: { ...concernedFile, name: newName }, tags: ['rename', concernedFile.id] }, - channel: 'TEST', - storageEngine: ItemType.ipfs, - }); - } - return { success: true, message: 'Filename updated' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to update this filename' }; - } - } - - public async moveFileToBin( - concernedFile: IPCFile, - deletedAt: number | null, - sharedFiles: IPCFile[], - ): Promise { - try { - let fileFound = false; - this.contacts.forEach(async (contact) => { - const file = contact.files.find((f) => f.id === concernedFile.id); - if (file) { - file.deletedAt = deletedAt; - file.logs.push({ - action: deletedAt ? 'Moved file to bin' : 'Restored file', - date: Date.now(), - }); - fileFound = true; - await this.publishAggregate(); - } - }); - if (!fileFound) { - const file = sharedFiles.find((f) => f.id === concernedFile.id); - if (!file) { - return { success: false, message: 'File not found' }; - } - await post.Publish({ - account: this.account, - postType: 'InterPlanetaryCloud', - content: { file: { ...concernedFile, deletedAt }, tags: ['bin', concernedFile.id] }, - channel: 'TEST', - storageEngine: ItemType.ipfs, - }); - } - return { success: true, message: `File ${deletedAt === null ? 'removed from' : 'moved to'} the bin` }; - } catch (err) { - console.error(err); - return { - success: false, - message: `Failed to ${deletedAt === null ? 'remove the file from' : 'move the file to'} the bin`, - }; - } - } - - public async addFileToContact(contactAddress: string, mainFile: IPCFile): Promise { - try { - const index = this.contacts.findIndex((contact) => contact.address === contactAddress); - - if (index !== -1) { - if (this.contacts[index].files.find((file) => file.id === mainFile.id)) { - return { success: false, message: 'The file is already shared' }; - } - const newFile: IPCFile = { - ...mainFile, - logs: [ - ...mainFile.logs, - { - action: `Shared file with ${this.contacts[index].name}`, - date: Date.now(), - }, - ], - // encryptKey: ( - // await this.account.encrypt( - // await this.account.decrypt(Buffer.from(mainFile.encryptKey, 'hex')), - // this.contacts[index].publicKey, - // ) - // ).toString('hex'), - encryptInfos: { - key: ( - await this.account.encrypt( - await this.account.decrypt(Buffer.from(mainFile.encryptInfos.key, 'hex')), - this.contacts[index].publicKey, - ) - ).toString('hex'), - iv: ( - await this.account.encrypt( - await this.account.decrypt(Buffer.from(mainFile.encryptInfos.iv, 'hex')), - this.contacts[index].publicKey, - ) - ).toString('hex'), - }, - }; - - this.contacts[index].files.push(newFile); - this.publishAggregate(); - return { success: true, message: 'File shared with the contact' }; - } - return { success: false, message: 'Contact does not exist' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to share the file with the contact' }; - } - } - - public async deleteFiles(ids: string[], sharedFiles: IPCFile[]): Promise { - try { - ids.forEach(async (id) => { - const me = this.contacts.find((c) => c.address === this.account.address)!; - const file = me.files.find((f) => f.id === id); - - if (file) { - me.files = me.files.filter((f) => f.id !== id); - } else { - const sharedFile = sharedFiles.find((f) => f.id === id); - if (sharedFile) { - post.Publish({ - account: this.account, - postType: 'InterPlanetaryCloud', - content: { file, tags: ['delete', id] }, - channel: 'TEST', - storageEngine: ItemType.ipfs, - }); - } - } - }); - this.publishAggregate(); - return { success: true, message: 'File deleted from the contact' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to delete the file from the contact' }; - } - } - - public async createFolder(folder: IPCFolder): Promise { - try { - const contact = this.contacts.find((c) => c.address === this.account.address); - - if (contact) { - contact.folders.push(folder); - await this.publishAggregate(); - return { success: true, message: 'Folder created' }; - } - return { success: false, message: 'Failed to load contact' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to create the folder' }; - } - } - - public async moveFolder(folder: IPCFolder, newPath: string): Promise { - try { - const contact = this.contacts.find((c) => c.address === this.account.address); - const fullPath = `${folder.path}${folder.name}/`; - - if (contact) { - contact.folders = contact.folders.map((f) => { - if (f.path.startsWith(fullPath)) - return { - ...f, - path: f.path.replace(folder.path, newPath), - logs: [ - ...f.logs, - { - action: `Moved folder to ${fullPath}`, - date: Date.now(), - }, - ], - }; - if (f === folder) return { ...f, path: newPath }; - return f; - }); - contact.files = contact.files.map((f) => { - if (f.path.startsWith(fullPath)) return { ...f, path: f.path.replace(folder.path, newPath) }; - return f; - }); - - await this.publishAggregate(); - return { success: true, message: 'Folder created' }; - } - return { success: false, message: 'Failed to load contact' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to create the folder' }; - } - } - - public async deleteFolder(folder: IPCFolder): Promise { - try { - const contact = this.contacts.find((c) => c.address === this.account.address); - - if (contact) { - const fullPath = `${folder.path}${folder.name}/`; - contact.folders = contact.folders.filter( - (f) => !f.path.startsWith(fullPath) && (f.path !== folder.path || f.createdAt !== folder.createdAt), - ); - - await this.publishAggregate(); - - return { success: true, message: 'Folder deleted' }; - } - return { success: false, message: 'Failed to find your contact' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to delete the folder' }; - } - } - - public async moveFile(file: IPCFile, newPath: string): Promise { - try { - const contact = this.contacts.find((c) => c.address === this.account.address); - - if (contact) { - const currentFile = contact.files.find((f) => f.id === file.id); - if (currentFile) { - currentFile.path = newPath; - currentFile.logs.push({ - action: `Moved file to ${newPath}`, - date: Date.now(), - }); - await this.publishAggregate(); - return { success: true, message: 'File moved' }; - } - return { success: false, message: 'File does not exist' }; - } - return { success: false, message: 'Failed to load contact' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to move the file' }; - } - } - - public async updateConfig(key: string, value: string): Promise { - try { - const contact = this.contacts.find((c) => c.address === this.account.address); - if (contact?.config) { - if (!contact.config[key]) { - return { success: false, message: 'Invalid config key' }; - } - contact.config[key].value = value; - await this.publishAggregate(); - return { success: true, message: `${contact.config[key].name} changed` }; - } - return { success: false, message: 'Failed to find account' }; - } catch (err) { - console.error(err); - return { success: false, message: 'Failed to change name' }; - } - } -} - -export default Contact; diff --git a/src/lib/contact/contact.ts b/src/lib/contact/contact.ts new file mode 100644 index 00000000..3ef23eaa --- /dev/null +++ b/src/lib/contact/contact.ts @@ -0,0 +1,121 @@ +import { accounts } from 'aleph-sdk-ts'; +import { aggregate, forget, post } from 'aleph-sdk-ts/dist/messages'; +import { AggregateMessage, ItemType } from 'aleph-sdk-ts/dist/messages/message'; + +import type { AggregateContentType, AggregateType, IPCContact, IPCUpdateContent, ResponseType } from 'types/types'; + +import { ALEPH_CHANNEL } from 'config/constants'; + +class Contact { + public contacts: IPCContact[]; + + public username: string; + + constructor(public readonly account: accounts.ethereum.ETHAccount) { + this.contacts = []; + this.username = ''; + } + + public async publishAggregate(): Promise> { + const aggr = await aggregate.Get({ + address: this.account.address, + keys: ['InterPlanetaryCloud'], + }); + + const content = aggr.InterPlanetaryCloud; + content.contacts = this.contacts; + + return aggregate.Publish({ + channel: ALEPH_CHANNEL, + storageEngine: ItemType.ipfs, + account: this.account, + key: 'InterPlanetaryCloud', + content, + }); + } + + public async load(): Promise { + try { + const aggr = await aggregate.Get({ + address: this.account.address, + keys: ['InterPlanetaryCloud'], + }); + + this.contacts = aggr.InterPlanetaryCloud.contacts; + this.username = this.contacts.find((c) => c.address === this.account.address)?.name ?? ''; + + await this.loadUpdates(); + + return { success: true, message: 'Contacts loaded' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to load contacts' }; + } + } + + private async loadUpdates(): Promise { + try { + await Promise.all( + this.contacts.map(async (contact) => { + const updatableIds = contact.files.filter((file) => file.permission === 'editor').map((file) => file.id); + + const updates = await post.Get({ + types: ['InterPlanetaryCloud'], + pagination: 200, + addresses: [contact.address], + tags: updatableIds, + }); + await Promise.all( + updates.posts.map(async (update) => { + const { tags, file } = update.content; + const [type, fileId] = tags; + await Promise.all( + this.contacts.map(async (c) => { + const foundFile = c.files.find((f) => f.id === fileId); + + if (foundFile && this.account) { + if (type === 'rename') foundFile.name = file.name; + else if (type === 'update') { + foundFile.hash = file.hash; + foundFile.size = file.size; + foundFile.encryptInfos = { + key: ( + await this.account.encrypt( + await this.account.decrypt(Buffer.from(file.encryptInfos.key, 'hex')), + c.publicKey, + ) + ).toString('hex'), + iv: ( + await this.account.encrypt( + await this.account.decrypt(Buffer.from(file.encryptInfos.iv, 'hex')), + c.publicKey, + ) + ).toString('hex'), + }; + } else if (type === 'delete') { + const owner = this.contacts.find((co) => co.address === c.address)!; + owner.files = owner.files.filter((f) => f.id !== fileId); + } else if (type === 'bin') foundFile.deletedAt = file.deletedAt; + } + }), + ); + }), + ); + await this.publishAggregate(); + + const hashes = updates.posts.map((p) => p.hash); + await forget.Publish({ + account: this.account, + channel: ALEPH_CHANNEL, + storageEngine: ItemType.ipfs, + hashes, + }); + }), + ); + } catch (err) { + console.error(err); + } + } +} + +export default Contact; diff --git a/src/lib/contact/contactClasses/fileContact.ts b/src/lib/contact/contactClasses/fileContact.ts new file mode 100644 index 00000000..15fc7ea4 --- /dev/null +++ b/src/lib/contact/contactClasses/fileContact.ts @@ -0,0 +1,279 @@ +import { aggregate, post } from 'aleph-sdk-ts/dist/messages'; +import { ItemType } from 'aleph-sdk-ts/dist/messages/message'; + +import type { AggregateType, IPCFile, ResponseType } from 'types/types'; + +import Contact from '../contact'; + +class ContactFile { + constructor(private contact: Contact) {} + + public async updateName(concernedFile: IPCFile, newName: string, sharedFiles: IPCFile[]): Promise { + try { + let fileFound = false; + await Promise.all( + this.contact.contacts.map(async (c) => { + const file = c.files.find((f) => f.id === concernedFile.id); + if (file) { + file.name = newName; + file.logs.push({ + action: `Renamed file to ${newName}`, + date: Date.now(), + }); + fileFound = true; + await this.contact.publishAggregate(); + } + }), + ); + if (!fileFound) { + const file = sharedFiles.find((f) => f.id === concernedFile.id); + if (!file) { + return { success: false, message: 'File not found' }; + } + await post.Publish({ + account: this.contact.account, + postType: 'InterPlanetaryCloud', + content: { file: { ...concernedFile, name: newName }, tags: ['rename', concernedFile.id] }, + channel: 'TEST', + storageEngine: ItemType.ipfs, + }); + } + return { success: true, message: 'Filename updated' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to update this filename' }; + } + } + + public async getOwner(fileId: string): Promise { + let owner; + await Promise.all( + this.contact.contacts.map(async (contact) => { + const aggr = await aggregate.Get({ + address: contact.address, + keys: ['InterPlanetaryCloud'], + }); + const myContact = aggr.InterPlanetaryCloud.contacts.find((c) => c.address === this.contact.account.address); + if (myContact?.files.find((f) => f.id === fileId)) { + owner = contact.publicKey; + } + }), + ); + return owner; + } + + public async updateContent(newFile: IPCFile): Promise { + try { + let fileFound = false; + await Promise.all( + this.contact.contacts.map(async (contact) => { + const file = contact.files.find((f) => f.id === newFile.id); + + if (file && this.contact.account) { + file.hash = newFile.hash; + file.encryptInfos = { + key: ( + await this.contact.account.encrypt( + await this.contact.account.decrypt(Buffer.from(newFile.encryptInfos.key, 'hex')), + contact.publicKey, + ) + ).toString('hex'), + iv: ( + await this.contact.account.encrypt( + await this.contact.account.decrypt(Buffer.from(newFile.encryptInfos.iv, 'hex')), + contact.publicKey, + ) + ).toString('hex'), + }; + fileFound = true; + await this.contact.publishAggregate(); + } + }), + ); + + if (!fileFound && this.contact.account) { + const owner = await this.getOwner(newFile.id); + + if (!owner) { + return { success: false, message: 'File not found' }; + } + // const fileKey = ( + // await this.account.encrypt(await this.account.decrypt(Buffer.from(newFile.encryptKey, 'hex'))) + // ).toString('hex'); + + const encryptInfos = { + key: ( + await this.contact.account.encrypt( + await this.contact.account.decrypt(Buffer.from(newFile.encryptInfos.key, 'hex')), + owner, + ) + ).toString('hex'), + iv: ( + await this.contact.account.encrypt( + await this.contact.account.decrypt(Buffer.from(newFile.encryptInfos.iv, 'hex')), + owner, + ) + ).toString('hex'), + }; + await post.Publish({ + account: this.contact.account, + postType: 'InterPlanetaryCloud', + content: { file: { ...newFile, encryptInfos }, tags: ['update', newFile.id] }, + channel: 'TEST', + storageEngine: ItemType.ipfs, + }); + } + return { success: true, message: 'File content updated' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to update the file content' }; + } + } + + public async delete(ids: string[], sharedFiles: IPCFile[]): Promise { + try { + ids.forEach((id) => { + const me = this.contact.contacts.find((c) => c.address === this.contact.account.address)!; + const file = me.files.find((f) => f.id === id); + + if (file) { + me.files = me.files.filter((f) => f.id !== id); + } else { + const sharedFile = sharedFiles.find((f) => f.id === id); + if (sharedFile) { + post.Publish({ + account: this.contact.account, + postType: 'InterPlanetaryCloud', + content: { file, tags: ['delete', id] }, + channel: 'TEST', + storageEngine: ItemType.ipfs, + }); + } + } + }); + this.contact.publishAggregate(); + return { success: true, message: 'File deleted from the contact' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to delete the file from the contact' }; + } + } + + public async move(file: IPCFile, newPath: string): Promise { + try { + const contact = this.contact.contacts.find((c) => c.address === this.contact.account.address); + + if (contact) { + const currentFile = contact.files.find((f) => f.id === file.id); + if (currentFile) { + currentFile.path = newPath; + currentFile.logs.push({ + action: `Moved file to ${newPath}`, + date: Date.now(), + }); + await this.contact.publishAggregate(); + return { success: true, message: 'File moved' }; + } + return { success: false, message: 'File does not exist' }; + } + return { success: false, message: 'Failed to load contact' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to move the file' }; + } + } + + public async moveToBin( + concernedFile: IPCFile, + deletedAt: number | null, + sharedFiles: IPCFile[], + ): Promise { + try { + let fileFound = false; + this.contact.contacts.forEach((contact) => { + const file = contact.files.find((f) => f.id === concernedFile.id); + if (file) { + file.deletedAt = deletedAt; + file.logs.push({ + action: deletedAt ? 'Moved file to bin' : 'Restored file', + date: Date.now(), + }); + fileFound = true; + } + }); + this.contact.publishAggregate(); + if (!fileFound) { + const file = sharedFiles.find((f) => f.id === concernedFile.id); + if (!file) { + return { success: false, message: 'File not found' }; + } + await post.Publish({ + account: this.contact.account, + postType: 'InterPlanetaryCloud', + content: { file: { ...concernedFile, deletedAt }, tags: ['bin', concernedFile.id] }, + channel: 'TEST', + storageEngine: ItemType.ipfs, + }); + } + return { success: true, message: `File ${deletedAt === null ? 'removed from' : 'moved to'} the bin` }; + } catch (err) { + console.error(err); + return { + success: false, + message: `Failed to ${deletedAt === null ? 'remove the file from' : 'move the file to'} the bin`, + }; + } + } + + public async addToContact(contactAddress: string, mainFile: IPCFile): Promise { + try { + const index = this.contact.contacts.findIndex((contact) => contact.address === contactAddress); + + if (index !== -1) { + if (this.contact.contacts[index].files.find((file) => file.id === mainFile.id)) { + return { success: false, message: 'The file is already shared' }; + } + const newFile: IPCFile = { + ...mainFile, + logs: [ + ...mainFile.logs, + { + action: `Shared file with ${this.contact.contacts[index].name}`, + date: Date.now(), + }, + ], + // encryptKey: ( + // await this.account.encrypt( + // await this.account.decrypt(Buffer.from(mainFile.encryptKey, 'hex')), + // this.contact.contacts[index].publicKey, + // ) + // ).toString('hex'), + encryptInfos: { + key: ( + await this.contact.account.encrypt( + await this.contact.account.decrypt(Buffer.from(mainFile.encryptInfos.key, 'hex')), + this.contact.contacts[index].publicKey, + ) + ).toString('hex'), + iv: ( + await this.contact.account.encrypt( + await this.contact.account.decrypt(Buffer.from(mainFile.encryptInfos.iv, 'hex')), + this.contact.contacts[index].publicKey, + ) + ).toString('hex'), + }, + }; + + this.contact.contacts[index].files.push(newFile); + this.contact.publishAggregate(); + return { success: true, message: 'File shared with the contact' }; + } + return { success: false, message: 'Contact does not exist' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to share the file with the contact' }; + } + } +} + +export default ContactFile; diff --git a/src/lib/contact/contactClasses/folderContact.ts b/src/lib/contact/contactClasses/folderContact.ts new file mode 100644 index 00000000..d7f8d777 --- /dev/null +++ b/src/lib/contact/contactClasses/folderContact.ts @@ -0,0 +1,83 @@ +import type { IPCFolder, ResponseType } from 'types/types'; + +import Contact from '../contact'; + +class ContactFolder { + constructor(private contact: Contact) {} + + public async create(folder: IPCFolder): Promise { + try { + const contact = this.contact.contacts.find((c) => c.address === this.contact.account.address); + + if (contact) { + contact.folders.push(folder); + await this.contact.publishAggregate(); + return { success: true, message: 'Folder created' }; + } + return { success: false, message: 'Failed to load contact' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to create the folder' }; + } + } + + public async move(folder: IPCFolder, newPath: string): Promise { + try { + const contact = this.contact.contacts.find((c) => c.address === this.contact.account.address); + const fullPath = `${folder.path}${folder.name}/`; + + if (contact) { + contact.folders = contact.folders.map((f) => { + if (f.path.startsWith(fullPath)) + return { + ...f, + path: f.path.replace(folder.path, newPath), + logs: [ + ...f.logs, + { + action: `Moved folder to ${fullPath}`, + date: Date.now(), + }, + ], + }; + if (f === folder) return { ...f, path: newPath }; + return f; + }); + contact.files = contact.files.map((f) => { + if (f.path.startsWith(fullPath)) return { ...f, path: f.path.replace(folder.path, newPath) }; + return f; + }); + + await this.contact.publishAggregate(); + return { success: true, message: 'Folder created' }; + } + return { success: false, message: 'Failed to load contact' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to create the folder' }; + } + } + + public async delete(folder: IPCFolder): Promise { + try { + const contact = this.contact.contacts.find((c) => c.address === this.contact.account.address); + + if (contact) { + const fullPath = `${folder.path}${folder.name}/`; + contact.folders = contact.folders.filter( + (f) => !f.path.startsWith(fullPath) && (f.path !== folder.path || f.createdAt !== folder.createdAt), + ); + + await this.contact.publishAggregate(); + + return { success: true, message: 'Folder deleted' }; + } + return { success: false, message: 'Failed to find your contact' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to delete the folder' }; + } + } +} + +export default ContactFolder; diff --git a/src/lib/contact/contactClasses/manageContact.ts b/src/lib/contact/contactClasses/manageContact.ts new file mode 100644 index 00000000..5ff23541 --- /dev/null +++ b/src/lib/contact/contactClasses/manageContact.ts @@ -0,0 +1,77 @@ +import type { IPCContact, ResponseType } from 'types/types'; + +import Contact from '../contact'; + +class ManageContact { + constructor(private contact: Contact) {} + + public async add(contactToAdd: IPCContact): Promise { + try { + if (this.contact.contacts.find((contact) => contact.address === contactToAdd.address)) { + return { success: false, message: 'Contact already exist' }; + } + this.contact.contacts.push(contactToAdd); + + await this.contact.publishAggregate(); + return { success: true, message: 'Contact added' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to add this contact' }; + } + } + + public async remove(contactAddress: string): Promise { + try { + if (contactAddress !== this.contact.account.address) { + this.contact.contacts.forEach((contact, index) => { + if (contact.address === contactAddress) { + this.contact.contacts.splice(index, 1); + } + }); + + await this.contact.publishAggregate(); + return { success: true, message: 'Contact deleted' }; + } + return { success: false, message: "You can't delete your account" }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to delete this contact' }; + } + } + + public async update(contactAddress: string, newName: string): Promise { + try { + const contact = this.contact.contacts.find((c) => c.address === contactAddress); + + if (contact) { + contact.name = newName; + await this.contact.publishAggregate(); + return { success: true, message: 'Contact updated' }; + } + return { success: false, message: 'Contact does not exist' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to update this contact' }; + } + } + + public async updateConfig(key: string, value: string): Promise { + try { + const contact = this.contact.contacts.find((c) => c.address === this.contact.account.address); + if (contact?.config) { + if (!contact.config[key]) { + return { success: false, message: 'Invalid config key' }; + } + contact.config[key].value = value; + await this.contact.publishAggregate(); + return { success: true, message: `${contact.config[key].name} changed` }; + } + return { success: false, message: 'Failed to find account' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to change name' }; + } + } +} + +export default ManageContact; diff --git a/src/lib/computing.ts b/src/lib/contact/contactClasses/programContact.ts similarity index 62% rename from src/lib/computing.ts rename to src/lib/contact/contactClasses/programContact.ts index 248c8440..52d45326 100644 --- a/src/lib/computing.ts +++ b/src/lib/contact/contactClasses/programContact.ts @@ -1,19 +1,19 @@ import { accounts } from 'aleph-sdk-ts'; -import { aggregate, forget, program } from 'aleph-sdk-ts/dist/messages'; +import { aggregate, forget, program, store } from 'aleph-sdk-ts/dist/messages'; import { AggregateMessage, ItemType } from 'aleph-sdk-ts/dist/messages/message'; +import fileDownload from 'js-file-download'; import type { AggregateContentType, AggregateType, IPCProgram, ResponseType } from 'types/types'; import { ALEPH_CHANNEL } from 'config/constants'; +import Contact from '../contact'; + class Computing { public programs: IPCProgram[]; - private readonly account: accounts.ethereum.ETHAccount; - - constructor(importedAccount: accounts.ethereum.ETHAccount) { + constructor(private readonly account: accounts.ethereum.ETHAccount, private contact: Contact) { this.programs = []; - this.account = importedAccount; } public async publishAggregate(): Promise> { @@ -50,7 +50,7 @@ class Computing { } } - public async deleteProgram(programHash: string): Promise { + public async delete(programHash: string): Promise { try { await forget.Publish({ channel: ALEPH_CHANNEL, @@ -67,7 +67,7 @@ class Computing { } } - public async updateProgramName(concernedProgram: IPCProgram, newName: string): Promise { + public async updateName(concernedProgram: IPCProgram, newName: string): Promise { try { this.programs = this.programs.map((prog) => { if (prog.id === concernedProgram.id) { @@ -93,7 +93,7 @@ class Computing { } } - public async uploadProgram( + public async upload( myProgram: IPCProgram, uploadFile: File, isRedeploy: boolean, @@ -117,6 +117,7 @@ class Computing { const newProgram: IPCProgram = { ...myProgram, hash: programHashPublishProgram.item_hash, + hashFile: programHashPublishProgram.content.code.ref, }; this.programs.push(newProgram); @@ -129,6 +130,47 @@ class Computing { return { success: false, message: 'Failed to upload program' }; } } + + public async addToContact(contactAddress: string, mainProgram: IPCProgram): Promise { + try { + const index = this.contact.contacts.findIndex((contact) => contact.address === contactAddress); + + if (index !== -1) { + if (this.contact.contacts[index].programs.find((pg) => pg.id === mainProgram.id)) { + return { success: false, message: 'The program is already shared' }; + } + const newProgram: IPCProgram = { + ...mainProgram, + logs: [ + ...mainProgram.logs, + { + action: `Shared program with ${this.contact.contacts[index].name}`, + date: Date.now(), + }, + ], + }; + this.contact.contacts[index].programs.push(newProgram); + this.contact.publishAggregate(); + return { success: true, message: 'Program shared with the contact' }; + } + return { success: false, message: 'Contact does not exist' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to share the program with the contact' }; + } + } + + public async download(toDownload: IPCProgram): Promise { + try { + const programStore = await store.Get({ fileHash: toDownload.hashFile }); + + fileDownload(programStore, toDownload.name); + return { success: true, message: 'Program downloaded' }; + } catch (err) { + console.error(err); + return { success: false, message: 'Failed to download the program' }; + } + } } export default Computing; diff --git a/src/lib/contact/fullContact.ts b/src/lib/contact/fullContact.ts new file mode 100644 index 00000000..f77a8495 --- /dev/null +++ b/src/lib/contact/fullContact.ts @@ -0,0 +1,29 @@ +import { accounts } from 'aleph-sdk-ts'; +import Contact from './contact'; +import ContactFile from './contactClasses/fileContact'; +import ContactFolder from './contactClasses/folderContact'; +import ManageContact from './contactClasses/manageContact'; +import Computing from './contactClasses/programContact'; + +class FullContact { + public contact: Contact; + + public files: ContactFile; + + public folders: ContactFolder; + + public manage: ManageContact; + + public computing: Computing; + + constructor(public readonly account: accounts.ethereum.ETHAccount) { + this.contact = new Contact(this.account); + this.contact.load(); + this.files = new ContactFile(this.contact); + this.folders = new ContactFolder(this.contact); + this.manage = new ManageContact(this.contact); + this.computing = new Computing(this.account, this.contact); + } +} + +export default FullContact; diff --git a/src/lib/drive.ts b/src/lib/drive.ts index fcd873ce..d250f4f9 100644 --- a/src/lib/drive.ts +++ b/src/lib/drive.ts @@ -7,31 +7,45 @@ import fileDownload from 'js-file-download'; import { ALEPH_CHANNEL } from 'config/constants'; -import type { AggregateType, IPCContact, IPCFile, IPCFolder, ResponseType, UploadResponse } from 'types/types'; +import type { + AggregateType, + IPCContact, + IPCFile, + IPCFolder, + IPCProgram, + ResponseType, + UploadResponse, +} from 'types/types'; export const MONTH_MILLIS = 86400 * 30 * 1000; class Drive { - public files: IPCFile[]; + public programs: IPCProgram[]; + public folders: IPCFolder[]; public sharedFiles: IPCFile[]; + public sharedPrograms: IPCProgram[]; + private readonly account: accounts.ethereum.ETHAccount; constructor(importedAccount: accounts.ethereum.ETHAccount) { this.files = []; - this.folders = []; this.sharedFiles = []; + this.folders = []; this.account = importedAccount; + this.programs = []; + this.sharedPrograms = []; } public async loadShared(contacts: IPCContact[]): Promise { try { if (this.account) { this.sharedFiles = []; + this.sharedPrograms = []; await Promise.all( contacts.map(async (contact) => { const aggr = await aggregate.Get({ @@ -44,8 +58,10 @@ class Drive { if (contact.address === this.account.address) { this.files = found.files; this.folders = found.folders; + this.programs = found.programs; } else { this.sharedFiles = this.sharedFiles.concat(found.files); + this.sharedPrograms = this.sharedPrograms.concat(found.programs); } } }), diff --git a/src/lib/user.ts b/src/lib/user.ts index 01cfeae9..c2150e8a 100644 --- a/src/lib/user.ts +++ b/src/lib/user.ts @@ -1,11 +1,11 @@ import { accounts } from 'aleph-sdk-ts'; import { aggregate } from 'aleph-sdk-ts/dist/messages'; -import Computing from 'lib/computing'; -import Contact from 'lib/contact'; import Drive from 'lib/drive'; import { AggregateType, IPCConfig, IPCContact } from 'types/types'; +import Computing from './contact/contactClasses/programContact'; +import FullContact from './contact/fullContact'; class User { public account: accounts.ethereum.ETHAccount; @@ -14,7 +14,7 @@ class User { public computing: Computing; - public contact: Contact; + public fullContact: FullContact; public config: IPCConfig; @@ -22,14 +22,14 @@ class User { this.account = importedAccount; this.config = importedConfig; this.drive = new Drive(this.account); - this.computing = new Computing(this.account); - this.contact = new Contact(this.account); + this.fullContact = new FullContact(this.account); + this.computing = new Computing(this.account, this.fullContact.contact); } public async loadConfig() { try { await Promise.all( - this.contact.contacts.map(async (contact) => { + this.fullContact.contact.contacts.map(async (contact) => { const aggr = await aggregate.Get({ address: contact.address, keys: ['InterPlanetaryCloud'], diff --git a/src/types/types.ts b/src/types/types.ts index b3c16ca5..20bf3707 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -29,8 +29,10 @@ export type IPCProgram = { name: string; createdAt: number; entrypoint: string; + permission: IPCPermission; size: number; logs: Log[]; + hashFile: string; }; export type IPCConfig = { diff --git a/yarn.lock b/yarn.lock index 55175e2c..60e9f00b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -79,86 +79,86 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": +"@babel/code-frame@^7.0.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" -"@babel/code-frame@^7.21.4": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" - integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== +"@babel/code-frame@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" + integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.22.5" -"@babel/compat-data@^7.21.5": - version "7.21.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.7.tgz#61caffb60776e49a57ba61a88f02bedd8714f6bc" - integrity sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA== +"@babel/compat-data@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" + integrity sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA== -"@babel/core@^7.21.8": - version "7.21.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.8.tgz#2a8c7f0f53d60100ba4c32470ba0281c92aa9aa4" - integrity sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ== +"@babel/core@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.5.tgz#d67d9747ecf26ee7ecd3ebae1ee22225fe902a89" + integrity sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.21.4" - "@babel/generator" "^7.21.5" - "@babel/helper-compilation-targets" "^7.21.5" - "@babel/helper-module-transforms" "^7.21.5" - "@babel/helpers" "^7.21.5" - "@babel/parser" "^7.21.8" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.5" - "@babel/types" "^7.21.5" + "@babel/code-frame" "^7.22.5" + "@babel/generator" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helpers" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.2" semver "^6.3.0" -"@babel/generator@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.5.tgz#c0c0e5449504c7b7de8236d99338c3e2a340745f" - integrity sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w== +"@babel/generator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" + integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA== dependencies: - "@babel/types" "^7.21.5" + "@babel/types" "^7.22.5" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz#631e6cc784c7b660417421349aac304c94115366" - integrity sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w== +"@babel/helper-compilation-targets@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02" + integrity sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw== dependencies: - "@babel/compat-data" "^7.21.5" - "@babel/helper-validator-option" "^7.21.0" + "@babel/compat-data" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" browserslist "^4.21.3" lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz#c769afefd41d171836f7cb63e295bedf689d48ba" - integrity sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ== +"@babel/helper-environment-visitor@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" + integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== -"@babel/helper-function-name@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" - integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== +"@babel/helper-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" + integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== dependencies: - "@babel/template" "^7.20.7" - "@babel/types" "^7.21.0" + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.5" -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" "@babel/helper-module-imports@^7.16.7": version "7.18.6" @@ -167,69 +167,74 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-imports@^7.21.4": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" - integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== +"@babel/helper-module-imports@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" + integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== dependencies: - "@babel/types" "^7.21.4" + "@babel/types" "^7.22.5" -"@babel/helper-module-transforms@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz#d937c82e9af68d31ab49039136a222b17ac0b420" - integrity sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw== +"@babel/helper-module-transforms@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" + integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw== dependencies: - "@babel/helper-environment-visitor" "^7.21.5" - "@babel/helper-module-imports" "^7.21.4" - "@babel/helper-simple-access" "^7.21.5" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.5" - "@babel/types" "^7.21.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" -"@babel/helper-simple-access@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz#d697a7971a5c39eac32c7e63c0921c06c8a249ee" - integrity sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg== +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== dependencies: - "@babel/types" "^7.21.5" + "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== +"@babel/helper-split-export-declaration@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz#88cf11050edb95ed08d596f7a044462189127a08" + integrity sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" "@babel/helper-string-parser@^7.19.4": version "7.19.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== -"@babel/helper-string-parser@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd" - integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w== +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== -"@babel/helper-validator-option@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" - integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + +"@babel/helper-validator-option@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" + integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== -"@babel/helpers@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.5.tgz#5bac66e084d7a4d2d9696bdf0175a93f7fb63c08" - integrity sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA== +"@babel/helpers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820" + integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q== dependencies: - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.5" - "@babel/types" "^7.21.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" "@babel/highlight@^7.18.6": version "7.18.6" @@ -240,15 +245,19 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.20.7": - version "7.21.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" - integrity sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ== +"@babel/highlight@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" + integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.0.0" + js-tokens "^4.0.0" -"@babel/parser@^7.21.5", "@babel/parser@^7.21.8": - version "7.21.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.8.tgz#642af7d0333eab9c0ad70b14ac5e76dbde7bfdf8" - integrity sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA== +"@babel/parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" + integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== "@babel/runtime@7.20.13": version "7.20.13" @@ -264,32 +273,32 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/template@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/traverse@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.5.tgz#ad22361d352a5154b498299d523cf72998a4b133" - integrity sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw== - dependencies: - "@babel/code-frame" "^7.21.4" - "@babel/generator" "^7.21.5" - "@babel/helper-environment-visitor" "^7.21.5" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.5" - "@babel/types" "^7.21.5" +"@babel/template@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" + integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/traverse@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1" + integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/generator" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.0": +"@babel/types@^7.18.6": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.3.tgz#4865a5357ce40f64e3400b0f3b737dc6d4f64d05" integrity sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg== @@ -298,13 +307,13 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@babel/types@^7.21.4", "@babel/types@^7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.5.tgz#18dfbd47c39d3904d5db3d3dc2cc80bedb60e5b6" - integrity sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q== +"@babel/types@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" + integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== dependencies: - "@babel/helper-string-parser" "^7.21.5" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" "@chainsafe/as-sha256@^0.3.1": @@ -328,10 +337,10 @@ "@chainsafe/persistent-merkle-tree" "^0.4.2" case "^1.6.3" -"@chakra-ui/accordion@2.1.11": - version "2.1.11" - resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.1.11.tgz#c6df0100c543645d0631df3aefde2ea2b8ed6313" - integrity sha512-mfVPmqETp9pyRDHJ33AdF19oHv/LyxVzQJtlxUByuvs8Cj9QQZ2LQLg5kejm+b3mj03A7A6yfbuo3RNaI4Bhsg== +"@chakra-ui/accordion@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.2.0.tgz#a38ed8e7d0a7ccc6910282f913c42cf6deea7215" + integrity sha512-2IK1iLzTZ22u8GKPPPn65mqJdZidn4AvkgAbv17ISdKA07VHJ8jSd4QF1T5iCXjKfZ0XaXozmhP4kDhjwF2IbQ== dependencies: "@chakra-ui/descendant" "3.0.14" "@chakra-ui/icon" "3.0.16" @@ -351,20 +360,15 @@ "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/spinner" "2.0.13" -"@chakra-ui/anatomy@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.1.1.tgz#819a1458ff727157e5500a69fc26bfea6e944495" - integrity sha512-LUHAoqJAgxAqmyckG5bUpBrfEo1FleEyY+1A8hkWciy58gZ+h3GoY9oBpHcdo7XdHPpy3G+3hieK/7i9NLwxAw== - "@chakra-ui/anatomy@2.1.2": version "2.1.2" resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.1.2.tgz#ea66b1841e7195da08ddc862daaa3f3e56e565f5" integrity sha512-pKfOS/mztc4sUXHNc8ypJ1gPWSolWT770jrgVRfolVbYlki8y5Y+As996zMF6k5lewTu6j9DQequ7Cc9a69IVQ== -"@chakra-ui/avatar@2.2.10": - version "2.2.10" - resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.10.tgz#b73cb4712927102aa8239c08f7169741eee774df" - integrity sha512-Scc0qJtJcxoGOaSS4TkoC2PhVLMacrBcfaNfLqV6wES56BcsjegHvpxREFunZkgVNph/XRHW6J1xOclnsZiPBQ== +"@chakra-ui/avatar@2.2.11": + version "2.2.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.11.tgz#1e5ded963ab3209fe1d16bba21f0aec616be56da" + integrity sha512-CJFkoWvlCTDJTUBrKA/aVyG5Zz6TBEIVmmsJtqC6VcQuVDTxkWod8ruXnjb0LT2DUveL7xR5qZM9a5IXcsH3zg== dependencies: "@chakra-ui/image" "2.0.16" "@chakra-ui/react-children-utils" "2.0.6" @@ -457,10 +461,10 @@ "@chakra-ui/react-use-callback-ref" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/css-reset@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.1.1.tgz#c61f3d2103c13e62a86fd2d359682092e961852c" - integrity sha512-jwEOfIAWmQsnChHQTW/eRE+dfE4MjmhvSvoUug5nkV1pI7veC/20noFlIZxzi82EbiQI8Fs0+Jnusgxr2yaOHA== +"@chakra-ui/css-reset@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.1.2.tgz#a4cd1601e8376a74b8dd62a9089cb8aaac1ee800" + integrity sha512-4ySTLd+3iRpp4lX0yI9Yo2uQm2f+qwYGNOZF0cNcfN+4UJCd3IsaWxYRR/Anz+M51NVldZbYzC+TEYC/kpJc4A== "@chakra-ui/descendant@3.0.14": version "3.0.14" @@ -470,10 +474,10 @@ "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-merge-refs" "2.0.7" -"@chakra-ui/dom-utils@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.0.6.tgz#68f49f3b4a0bdebd5e416d6fd2c012c9ad64b76a" - integrity sha512-PVtDkPrDD5b8aoL6Atg7SLjkwhWb7BwMcLOF1L449L3nZN+DAO3nyAh6iUhZVJyunELj9d0r65CDlnMREyJZmA== +"@chakra-ui/dom-utils@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.1.0.tgz#d15df89e458ef19756db04c7cfd084eb552454f0" + integrity sha512-ZmF2qRa1QZ0CMLU8M1zCfmw29DmPNtfjR9iTo74U5FPr3i1aoAh7fbJ4qAlZ197Xw9eAW28tvzQuoVWeL5C7fQ== "@chakra-ui/editable@3.0.0": version "3.0.0" @@ -495,13 +499,13 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/event-utils/-/event-utils-2.0.8.tgz#e6439ba200825a2f15d8f1973d267d1c00a6d1b4" integrity sha512-IGM/yGUHS+8TOQrZGpAKOJl/xGBrmRYJrmbHfUE7zrG3PpQyXvbLDP1M+RggkCFVgHlJi2wpYIf0QtQlU0XZfw== -"@chakra-ui/focus-lock@2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.0.16.tgz#bfb705b565d70b2f908d7c7a27f40426ac48dff8" - integrity sha512-UuAdGCPVrCa1lecoAvpOQD7JFT7a9RdmhKWhFt5ioIcekSLJcerdLHuuL3w0qz//8kd1/SOt7oP0aJqdAJQrCw== +"@chakra-ui/focus-lock@2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.0.17.tgz#c1896a80896e752b88e8681f9c9d626046de6dd5" + integrity sha512-V+m4Ml9E8QY66DUpHX/imInVvz5XJ5zx59Tl0aNancXgeVY1Rt/ZdxuZdPLCAmPC/MF3GUOgnEA+WU8i+VL6Gw== dependencies: - "@chakra-ui/dom-utils" "2.0.6" - react-focus-lock "^2.9.2" + "@chakra-ui/dom-utils" "2.1.0" + react-focus-lock "^2.9.4" "@chakra-ui/form-control@2.0.18": version "2.0.18" @@ -557,10 +561,10 @@ "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/layout@2.1.19": - version "2.1.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.1.19.tgz#4cd07c64239bf83c89a49487fdbd44227737b4eb" - integrity sha512-g7xMVKbQFCODwKCkEF4/OmdPsr/fAavWUV+DGc1ZWVPdroUlg1FGTpK9bOTwkC/gnko7cMClILA+BIPR3Ylu9Q== +"@chakra-ui/layout@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.2.0.tgz#a0832ba419743d8d7e442acfce59740626664d2f" + integrity sha512-WvfsWQjqzbCxv7pbpPGVKxj9eQr7MC2i37ag4Wn7ClIG7uPuwHYTUWOnjnu27O3H/zA4cRVZ4Hs3GpSPbojZFQ== dependencies: "@chakra-ui/breakpoint-utils" "2.0.8" "@chakra-ui/icon" "3.0.16" @@ -588,10 +592,10 @@ "@chakra-ui/react-env" "3.0.0" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/menu@2.1.14": - version "2.1.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.14.tgz#021c9f6f483b9de2e86d1da268e4d27723df4e26" - integrity sha512-z4YzlY/ub1hr4Ee2zCnZDs4t43048yLTf5GhEVYDO+SI92WlOfHlP9gYEzR+uj/CiRZglVFwUDKb3UmFtmKPyg== +"@chakra-ui/menu@2.1.15": + version "2.1.15" + resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.15.tgz#116520a2746d848e2a44fdbf03d66353cd1e1b39" + integrity sha512-+1fh7KBKZyhy8wi7Q6nQAzrvjM6xggyhGMnSna0rt6FJVA2jlfkjb5FozyIVPnkfJKjkKd8THVhrs9E7pHNV/w== dependencies: "@chakra-ui/clickable" "2.0.14" "@chakra-ui/descendant" "3.0.14" @@ -599,23 +603,23 @@ "@chakra-ui/popper" "3.0.14" "@chakra-ui/react-children-utils" "2.0.6" "@chakra-ui/react-context" "2.0.8" - "@chakra-ui/react-use-animation-state" "2.0.8" + "@chakra-ui/react-use-animation-state" "2.0.9" "@chakra-ui/react-use-controllable-state" "2.0.8" "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-focus-effect" "2.0.10" + "@chakra-ui/react-use-focus-effect" "2.0.11" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/react-use-outside-click" "2.1.0" "@chakra-ui/react-use-update-effect" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/transition" "2.0.16" -"@chakra-ui/modal@2.2.11": - version "2.2.11" - resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.11.tgz#8a964288759f3d681e23bfc3a837a3e2c7523f8e" - integrity sha512-2J0ZUV5tEzkPiawdkgPz6bmex7NXAde1VXooMwdvK+vuT8PV3U61yorTJOZVLdw7TjjI1Yo94mzsp6UwBud43Q== +"@chakra-ui/modal@2.2.12": + version "2.2.12" + resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.12.tgz#8c6dc66a6db4abdaf6f5e0dae70183ee41ce361a" + integrity sha512-F1nNmYGvyqlmxidbwaBM3y57NhZ/Qeyc8BE9tb1FL1v9nxQhkfrPvMQ9miK0O1syPN6aZ5MMj+uD3AsRFE+/tA== dependencies: "@chakra-ui/close-button" "2.0.17" - "@chakra-ui/focus-lock" "2.0.16" + "@chakra-ui/focus-lock" "2.0.17" "@chakra-ui/portal" "2.0.16" "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" @@ -665,19 +669,19 @@ "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/popover@2.1.11": - version "2.1.11" - resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.11.tgz#3f893199559b670b8acfcd1a75313469983d0ead" - integrity sha512-ntFMKojU+ZIofwSw5IJ+Ur8pN5o+5kf/Fx5r5tCjFZd0DSkrEeJw9i00/UWJ6kYZb+zlpswxriv0FmxBlAF66w== +"@chakra-ui/popover@2.1.12": + version "2.1.12" + resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.12.tgz#093bb60f7c044f829e2acc3a93f0c1077ba58cfb" + integrity sha512-Corh8trA1f3ydcMQqomgSvYNNhAlpxiBpMY2sglwYazOJcueHA8CI05cJVD0T/wwoTob7BShabhCGFZThn61Ng== dependencies: "@chakra-ui/close-button" "2.0.17" "@chakra-ui/lazy-utils" "2.0.5" "@chakra-ui/popper" "3.0.14" "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-animation-state" "2.0.8" + "@chakra-ui/react-use-animation-state" "2.0.9" "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-focus-effect" "2.0.10" + "@chakra-ui/react-use-focus-effect" "2.0.11" "@chakra-ui/react-use-focus-on-pointer-down" "2.0.6" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" @@ -706,15 +710,15 @@ dependencies: "@chakra-ui/react-context" "2.0.8" -"@chakra-ui/provider@2.2.4": - version "2.2.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.2.4.tgz#7b8a2958ed174c8b62417d932e5c637368490a1c" - integrity sha512-vz/WMEWhwoITCAkennRNYCeQHsJ6YwB/UjVaAK+61jWY42J7uCsRZ+3nB5rDjQ4m+aqPfTUPof8KLJBrtYrJbw== +"@chakra-ui/provider@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.3.0.tgz#18b3bdc3087e90569049832b2f0f4f8afd5cedf6" + integrity sha512-vKgmjoLVS3NnHW8RSYwmhhda2ZTi3fQc1egkYSVwngGky4CsN15I+XDhxJitVd66H41cjah/UNJyoeq7ACseLA== dependencies: - "@chakra-ui/css-reset" "2.1.1" + "@chakra-ui/css-reset" "2.1.2" "@chakra-ui/portal" "2.0.16" "@chakra-ui/react-env" "3.0.0" - "@chakra-ui/system" "2.5.7" + "@chakra-ui/system" "2.5.8" "@chakra-ui/utils" "2.0.15" "@chakra-ui/radio@2.0.22": @@ -751,12 +755,12 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/react-types/-/react-types-2.0.7.tgz#799c166a44882b23059c8f510eac9bd5d0869ac4" integrity sha512-12zv2qIZ8EHwiytggtGvo4iLT0APris7T0qaAWqzpUGS0cdUtR8W+V1BJ5Ocq+7tA6dzQ/7+w5hmXih61TuhWQ== -"@chakra-ui/react-use-animation-state@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.8.tgz#544ef3007498d4a0629b9d1916056ddaf59aa286" - integrity sha512-xv9zSF2Rd1mHWQ+m5DLBWeh4atF8qrNvsOs3MNrvxKYBS3f79N3pqcQGrWAEvirXWXfiCeje2VAkEggqFRIo+Q== +"@chakra-ui/react-use-animation-state@2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.9.tgz#8e6377e7583cc80c649cdc443c90ab5b48a03e78" + integrity sha512-WFoD5OG03PBmzJCoRwM8rVfU442AvKBPPgA0yGGlKioH29OGuX7W78Ml+cYdXxonTiB03YSRZzUwaUnP4wAy1Q== dependencies: - "@chakra-ui/dom-utils" "2.0.6" + "@chakra-ui/dom-utils" "2.1.0" "@chakra-ui/react-use-event-listener" "2.0.7" "@chakra-ui/react-use-callback-ref@2.0.7": @@ -785,12 +789,12 @@ dependencies: "@chakra-ui/react-use-callback-ref" "2.0.7" -"@chakra-ui/react-use-focus-effect@2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.10.tgz#0328a85e05fd6f8927359a544184494b5cb947bd" - integrity sha512-HswfpzjP8gCQM3/fbeR+8wrYqt0B3ChnVTqssnYXqp9Fa/5Y1Kx1ZADUWW93zMs5SF7hIEuNt8uKeh1/3HTcqQ== +"@chakra-ui/react-use-focus-effect@2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.11.tgz#9a5c76981677fc356308526c7d2b3dc48101ea06" + integrity sha512-/zadgjaCWD50TfuYsO1vDS2zSBs2p/l8P2DPEIA8FuaowbBubKrk9shKQDWmbfDU7KArGxPxrvo+VXvskPPjHw== dependencies: - "@chakra-ui/dom-utils" "2.0.6" + "@chakra-ui/dom-utils" "2.1.0" "@chakra-ui/react-use-event-listener" "2.0.7" "@chakra-ui/react-use-safe-layout-effect" "2.0.5" "@chakra-ui/react-use-update-effect" "2.0.7" @@ -871,14 +875,14 @@ dependencies: "@chakra-ui/utils" "2.0.15" -"@chakra-ui/react@^2.6.1": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.6.1.tgz#0fc4b9811eb675ade09c3fb0541b4412be060d83" - integrity sha512-Lt8c8pLPTz59xxdSuL2FlE7le9MXx4zgjr60UnEc3yjAMjXNTqUAoWHyT4Zn1elCGUPWOedS3rMvp4KTshT+5w== +"@chakra-ui/react@^2.7.1": + version "2.7.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.7.1.tgz#1419a4856b7dd74a558ced97f148a97d4953109e" + integrity sha512-uIYIAg+gnUoRbgdCfSEVvQnrEz0oWWXATGGSQpxmuJovNVyZKnX/Xug7NkWQfBUJPYRSG+VB69ZmsAFpyLSMtA== dependencies: - "@chakra-ui/accordion" "2.1.11" + "@chakra-ui/accordion" "2.2.0" "@chakra-ui/alert" "2.1.0" - "@chakra-ui/avatar" "2.2.10" + "@chakra-ui/avatar" "2.2.11" "@chakra-ui/breadcrumb" "2.1.5" "@chakra-ui/button" "2.0.18" "@chakra-ui/card" "2.1.6" @@ -886,45 +890,46 @@ "@chakra-ui/close-button" "2.0.17" "@chakra-ui/control-box" "2.0.13" "@chakra-ui/counter" "2.0.14" - "@chakra-ui/css-reset" "2.1.1" + "@chakra-ui/css-reset" "2.1.2" "@chakra-ui/editable" "3.0.0" - "@chakra-ui/focus-lock" "2.0.16" + "@chakra-ui/focus-lock" "2.0.17" "@chakra-ui/form-control" "2.0.18" "@chakra-ui/hooks" "2.2.0" "@chakra-ui/icon" "3.0.16" "@chakra-ui/image" "2.0.16" "@chakra-ui/input" "2.0.22" - "@chakra-ui/layout" "2.1.19" + "@chakra-ui/layout" "2.2.0" "@chakra-ui/live-region" "2.0.13" "@chakra-ui/media-query" "3.2.12" - "@chakra-ui/menu" "2.1.14" - "@chakra-ui/modal" "2.2.11" + "@chakra-ui/menu" "2.1.15" + "@chakra-ui/modal" "2.2.12" "@chakra-ui/number-input" "2.0.19" "@chakra-ui/pin-input" "2.0.20" - "@chakra-ui/popover" "2.1.11" + "@chakra-ui/popover" "2.1.12" "@chakra-ui/popper" "3.0.14" "@chakra-ui/portal" "2.0.16" "@chakra-ui/progress" "2.1.6" - "@chakra-ui/provider" "2.2.4" + "@chakra-ui/provider" "2.3.0" "@chakra-ui/radio" "2.0.22" "@chakra-ui/react-env" "3.0.0" "@chakra-ui/select" "2.0.19" "@chakra-ui/skeleton" "2.0.24" - "@chakra-ui/slider" "2.0.24" + "@chakra-ui/skip-nav" "2.0.15" + "@chakra-ui/slider" "2.0.25" "@chakra-ui/spinner" "2.0.13" "@chakra-ui/stat" "2.0.18" "@chakra-ui/stepper" "2.2.0" - "@chakra-ui/styled-system" "2.9.0" + "@chakra-ui/styled-system" "2.9.1" "@chakra-ui/switch" "2.0.27" - "@chakra-ui/system" "2.5.7" + "@chakra-ui/system" "2.5.8" "@chakra-ui/table" "2.0.17" "@chakra-ui/tabs" "2.1.9" "@chakra-ui/tag" "3.0.0" "@chakra-ui/textarea" "2.0.19" - "@chakra-ui/theme" "3.1.1" - "@chakra-ui/theme-utils" "2.0.17" - "@chakra-ui/toast" "6.1.3" - "@chakra-ui/tooltip" "2.2.8" + "@chakra-ui/theme" "3.1.2" + "@chakra-ui/theme-utils" "2.0.18" + "@chakra-ui/toast" "6.1.4" + "@chakra-ui/tooltip" "2.2.9" "@chakra-ui/transition" "2.0.16" "@chakra-ui/utils" "2.0.15" "@chakra-ui/visually-hidden" "2.0.15" @@ -937,11 +942,6 @@ "@chakra-ui/form-control" "2.0.18" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/shared-utils@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.4.tgz#8661f2b48dd93d04151b10a894a4290c9d9a080c" - integrity sha512-JGWr+BBj3PXGZQ2gxbKSD1wYjESbYsZjkCeE2nevyVk4rN3amV1wQzCnBAhsuJktMaZD6KC/lteo9ou9QUDzpA== - "@chakra-ui/shared-utils@2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz#cb2b49705e113853647f1822142619570feba081" @@ -956,10 +956,15 @@ "@chakra-ui/react-use-previous" "2.0.5" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/slider@2.0.24": - version "2.0.24" - resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.24.tgz#e40a6bd0a776ec41e037477df8cb0c580a98eacc" - integrity sha512-o3hOaIiTzPMG8yf+HYWbrTmhxABicDViVOvOajRSXDodbZSCk1rZy1nmUeahjVtfVUB1IyJoNcXdn76IqJmhdg== +"@chakra-ui/skip-nav@2.0.15": + version "2.0.15" + resolved "https://registry.yarnpkg.com/@chakra-ui/skip-nav/-/skip-nav-2.0.15.tgz#cb3b2ffb9c1bc492e66d6b0a189253aa53014257" + integrity sha512-5UtmlnV4BmIgEk6lQ0h81JEYhPX04wJEk5ZMoilQ2zEQYL6TkVVHkhRXyc1Zfq76hmHuZPXZV/yJeTecj6jIrA== + +"@chakra-ui/slider@2.0.25": + version "2.0.25" + resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.25.tgz#2d69af68f4afcc648d14603d7c3163660d35e9eb" + integrity sha512-FnWSi0AIXP+9sHMCPboOKGqm902k8dJtsJ7tu3D0AcKkE62WtYLZ2sTqvwJxCfSl4KqVI1i571SrF9WadnnJ8w== dependencies: "@chakra-ui/number-utils" "2.0.7" "@chakra-ui/react-context" "2.0.8" @@ -997,10 +1002,10 @@ "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/styled-system@2.9.0", "@chakra-ui/styled-system@^2.9.0": - version "2.9.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.0.tgz#b3bace83c78cf9c072c461cc963bf73c0e7ccd3d" - integrity sha512-rToN30eOezrTZ5qBHmWqEwsYPenHtc3WU6ODAfMUwNnmCJQiu2erRGv8JwIjmRJnKSOEnNKccI2UXe2EwI6+JA== +"@chakra-ui/styled-system@2.9.1", "@chakra-ui/styled-system@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.1.tgz#888a4901b2afa174461259a8875379adb0363934" + integrity sha512-jhYKBLxwOPi9/bQt9kqV3ELa/4CjmNNruTyXlPp5M0v0+pDMUngPp48mVLoskm9RKZGE0h1qpvj/jZ3K7c7t8w== dependencies: "@chakra-ui/shared-utils" "2.0.5" csstype "^3.0.11" @@ -1014,16 +1019,16 @@ "@chakra-ui/checkbox" "2.2.15" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/system@2.5.7", "@chakra-ui/system@^2.5.7": - version "2.5.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.5.7.tgz#f56c480af336d9f48e0ad84e2434d834017c44e2" - integrity sha512-yB6en7YdJPxKvKY2jJROVwkBE2CLFmHS4ZDx27VdYs0Fa4kGiyDFhJAfnMtLBNDVsTy1NhUHL9aqR63u56QqFg== +"@chakra-ui/system@2.5.8", "@chakra-ui/system@^2.5.8": + version "2.5.8" + resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.5.8.tgz#9026090b792320683bf1cc3a8f04af7b10c947ce" + integrity sha512-Vy8UUaCxikOzOGE54IP8tKouvU38rEYU1HCSquU9+oe7Jd70HaiLa4vmUKvHyMUmxkOzDHIkgZLbVQCubSnN5w== dependencies: "@chakra-ui/color-mode" "2.1.12" "@chakra-ui/object-utils" "2.1.0" "@chakra-ui/react-utils" "2.0.12" - "@chakra-ui/styled-system" "2.9.0" - "@chakra-ui/theme-utils" "2.0.17" + "@chakra-ui/styled-system" "2.9.1" + "@chakra-ui/theme-utils" "2.0.18" "@chakra-ui/utils" "2.0.15" react-fast-compare "3.2.1" @@ -1066,47 +1071,38 @@ "@chakra-ui/form-control" "2.0.18" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/theme-tools@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.17.tgz#9496094336c9480f950c8d7ab6e05f1c19caa955" - integrity sha512-Auu38hnihlJZQcPok6itRDBbwof3TpXGYtDPnOvrq4Xp7jnab36HLt7KEXSDPXbtOk3ZqU99pvI1en5LbDrdjg== +"@chakra-ui/theme-tools@2.0.18", "@chakra-ui/theme-tools@^2.0.18": + version "2.0.18" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.18.tgz#8160f0abe331e60b56f77426c28ff9a605c1a5c4" + integrity sha512-MbiRuXb2tb41FbnW41zhsYYAU0znlpfYZnu0mxCf8U2otCwPekJCfESUGYypjq4JnydQ7TDOk+Kz/Wi974l4mw== dependencies: "@chakra-ui/anatomy" "2.1.2" "@chakra-ui/shared-utils" "2.0.5" color2k "^2.0.0" -"@chakra-ui/theme-tools@^2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.0.16.tgz#17caae14a61f93759f072b16c7346489eb8be643" - integrity sha512-B/LD+2LNDeHYd/LVCHIJqckVZfhrycTUpNbhRVAiDRaS0AAcsPxKas7liTFkkMkM076YjiHlcla3KpVX+E9tzg== - dependencies: - "@chakra-ui/anatomy" "2.1.1" - "@chakra-ui/shared-utils" "2.0.4" - color2k "^2.0.0" - -"@chakra-ui/theme-utils@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.17.tgz#3db5780ab812a07945a5eb7565a66478d9f149c0" - integrity sha512-aUaVLFIU1Rs8m+5WVOUvqHKapOX8nSgUVGaeRWS4odxBM95dG4j15f4L88LEMw4D4+WWd0CSAS139OnRgj1rCw== +"@chakra-ui/theme-utils@2.0.18": + version "2.0.18" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.18.tgz#c240545d0f00b6cc059195a784683d1f143a44af" + integrity sha512-aSbkUUiFpc1NHC7lQdA6uYlr6EcZFXz6b4aJ7VRDpqTiywvqYnvfGzhmsB0z94vgtS9qXc6HoIwBp25jYGV2MA== dependencies: "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.9.0" - "@chakra-ui/theme" "3.1.1" + "@chakra-ui/styled-system" "2.9.1" + "@chakra-ui/theme" "3.1.2" lodash.mergewith "4.6.2" -"@chakra-ui/theme@3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-3.1.1.tgz#4ddb916cab33c132798d0f2d1a5a2c4b87381202" - integrity sha512-VHcG0CPLd9tgvWnajpAGqrAYhx4HwgfK0E9VOrdwa/3bN+AgY/0EAAXzfe0Q0W2MBWzSgaYqZcQ5cDRpYbiYPA== +"@chakra-ui/theme@3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-3.1.2.tgz#1e78a19083adecb38b884c1c2da6dee2c84c81f2" + integrity sha512-ebUXMS3LZw2OZxEQNYaFw3/XuA3jpyprhS/frjHMvZKSOaCjMW+c9z25S0jp1NnpQff08VGI8EWbyVZECXU1QA== dependencies: "@chakra-ui/anatomy" "2.1.2" "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/theme-tools" "2.0.17" + "@chakra-ui/theme-tools" "2.0.18" -"@chakra-ui/toast@6.1.3": - version "6.1.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-6.1.3.tgz#1e8b8f781c2b9e5b4dc2a9c97e6a1f91d5f167ca" - integrity sha512-dsg/Sdkuq+SCwdOeyzrnBO1ecDA7VKfLFjUtj9QBc/SFEN8r+FQrygy79TNo+QWr7zdjI8icbl8nsp59lpb8ag== +"@chakra-ui/toast@6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-6.1.4.tgz#853a844408c0e22f15c66b4f2607b8416300c649" + integrity sha512-wAcPHq/N/ar4jQxkUGhnsbp+lx2eKOpHxn1KaWdHXUkqCNUA1z09fvBsoMyzObSiiwbDuQPZG5RxsOhzfPZX4Q== dependencies: "@chakra-ui/alert" "2.1.0" "@chakra-ui/close-button" "2.0.17" @@ -1115,14 +1111,15 @@ "@chakra-ui/react-use-timeout" "2.0.5" "@chakra-ui/react-use-update-effect" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.9.0" - "@chakra-ui/theme" "3.1.1" + "@chakra-ui/styled-system" "2.9.1" + "@chakra-ui/theme" "3.1.2" -"@chakra-ui/tooltip@2.2.8": - version "2.2.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.8.tgz#994e9a597d64a25daa1322a6cf603f055a890498" - integrity sha512-AqtrCkalADrqqd1SgII4n8F0dDABxqxL3e8uj3yC3HDzT3BU/0NSwSQRA2bp9eoJHk07ZMs9kyzvkkBLc0pr2A== +"@chakra-ui/tooltip@2.2.9": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.9.tgz#a7f25f7e6d1304ea448a3420ed99f79a657537bd" + integrity sha512-ZoksllanqXRUyMDaiogvUVJ+RdFXwZrfrwx3RV22fejYZIQ602hZ3QHtHLB5ZnKFLbvXKMZKM23HxFTSb0Ytqg== dependencies: + "@chakra-ui/dom-utils" "2.1.0" "@chakra-ui/popper" "3.0.14" "@chakra-ui/portal" "2.0.16" "@chakra-ui/react-types" "2.0.7" @@ -1291,10 +1288,10 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/react@^11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02" - integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw== +"@emotion/react@^11.11.1": + version "11.11.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.1.tgz#b2c36afac95b184f73b08da8c214fdf861fa4157" + integrity sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA== dependencies: "@babel/runtime" "^7.18.3" "@emotion/babel-plugin" "^11.11.0" @@ -1380,10 +1377,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.40.0": - version "8.40.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.40.0.tgz#3ba73359e11f5a7bd3e407f70b3528abfae69cec" - integrity sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA== +"@eslint/js@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0" + integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg== "@ethereumjs/common@^2.6.4": version "2.6.5" @@ -1757,10 +1754,10 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -2658,10 +2655,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/react-dom@^18.2.4": - version "18.2.4" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.4.tgz#13f25bfbf4e404d26f62ac6e406591451acba9e0" - integrity sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw== +"@types/react-dom@^18.2.6": + version "18.2.6" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.6.tgz#ad621fa71a8db29af7c31b41b2ea3d8a6f4144d1" + integrity sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A== dependencies: "@types/react" "*" @@ -2674,10 +2671,10 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@^18.2.6": - version "18.2.6" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.6.tgz#5cd53ee0d30ffc193b159d3516c8c8ad2f19d571" - integrity sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA== +"@types/react@^18.2.14": + version "18.2.14" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.14.tgz#fa7a6fecf1ce35ca94e74874f70c56ce88f7a127" + integrity sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2724,15 +2721,15 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz#a350faef1baa1e961698240f922d8de1761a9e2b" - integrity sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw== +"@typescript-eslint/eslint-plugin@^5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz#2f4bea6a3718bed2ba52905358d0f45cd3620d31" + integrity sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg== dependencies: "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.59.6" - "@typescript-eslint/type-utils" "5.59.6" - "@typescript-eslint/utils" "5.59.6" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/type-utils" "5.60.0" + "@typescript-eslint/utils" "5.60.0" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" @@ -2740,72 +2737,72 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.6.tgz#bd36f71f5a529f828e20b627078d3ed6738dbb40" - integrity sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA== +"@typescript-eslint/parser@^5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.60.0.tgz#08f4daf5fc6548784513524f4f2f359cebb4068a" + integrity sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ== dependencies: - "@typescript-eslint/scope-manager" "5.59.6" - "@typescript-eslint/types" "5.59.6" - "@typescript-eslint/typescript-estree" "5.59.6" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/typescript-estree" "5.60.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz#d43a3687aa4433868527cfe797eb267c6be35f19" - integrity sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ== +"@typescript-eslint/scope-manager@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz#ae511967b4bd84f1d5e179bb2c82857334941c1c" + integrity sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ== dependencies: - "@typescript-eslint/types" "5.59.6" - "@typescript-eslint/visitor-keys" "5.59.6" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/visitor-keys" "5.60.0" -"@typescript-eslint/type-utils@5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz#37c51d2ae36127d8b81f32a0a4d2efae19277c48" - integrity sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ== +"@typescript-eslint/type-utils@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz#69b09087eb12d7513d5b07747e7d47f5533aa228" + integrity sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g== dependencies: - "@typescript-eslint/typescript-estree" "5.59.6" - "@typescript-eslint/utils" "5.59.6" + "@typescript-eslint/typescript-estree" "5.60.0" + "@typescript-eslint/utils" "5.60.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.6.tgz#5a6557a772af044afe890d77c6a07e8c23c2460b" - integrity sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA== +"@typescript-eslint/types@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.60.0.tgz#3179962b28b4790de70e2344465ec97582ce2558" + integrity sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA== -"@typescript-eslint/typescript-estree@5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz#2fb80522687bd3825504925ea7e1b8de7bb6251b" - integrity sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA== +"@typescript-eslint/typescript-estree@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz#4ddf1a81d32a850de66642d9b3ad1e3254fb1600" + integrity sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ== dependencies: - "@typescript-eslint/types" "5.59.6" - "@typescript-eslint/visitor-keys" "5.59.6" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/visitor-keys" "5.60.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.6.tgz#82960fe23788113fc3b1f9d4663d6773b7907839" - integrity sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg== +"@typescript-eslint/utils@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.60.0.tgz#4667c5aece82f9d4f24a667602f0f300864b554c" + integrity sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.59.6" - "@typescript-eslint/types" "5.59.6" - "@typescript-eslint/typescript-estree" "5.59.6" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/typescript-estree" "5.60.0" eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.59.6": - version "5.59.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz#673fccabf28943847d0c8e9e8d008e3ada7be6bb" - integrity sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q== +"@typescript-eslint/visitor-keys@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz#b48b29da3f5f31dd1656281727004589d2722a66" + integrity sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw== dependencies: - "@typescript-eslint/types" "5.59.6" + "@typescript-eslint/types" "5.60.0" eslint-visitor-keys "^3.3.0" "@vespaiach/axios-fetch-adapter@github:ecadlabs/axios-fetch-adapter": @@ -3307,10 +3304,10 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -boring-avatars@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/boring-avatars/-/boring-avatars-1.7.0.tgz#70ac7146bbf37d8e69a35544b24f1d75558f868a" - integrity sha512-ZNHd8J7C/V0IjQMGQowLJ5rScEFU23WxePigH6rqKcT2Esf0qhYvYxw8s9i3srmlfCnCV00ddBjaoGey1eNOfA== +boring-avatars@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/boring-avatars/-/boring-avatars-1.10.1.tgz#0e40811043cb3412bee38a0b6ca14f85fcdb0d2b" + integrity sha512-WcgHDeLrazCR03CDPEvCchLsUecZAZvs4F6FnMiGlTEjyQQf15Q5TRl4EUaAQ1dacvhPq7lC9EOTWkCojQ6few== borsh@^0.7.0: version "0.7.0" @@ -4305,16 +4302,16 @@ eslint-visitor-keys@^3.4.1: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== -eslint@^8.40.0: - version "8.40.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.40.0.tgz#a564cd0099f38542c4e9a2f630fa45bf33bc42a4" - integrity sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ== +eslint@^8.43.0: + version "8.43.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094" + integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.4.0" "@eslint/eslintrc" "^2.0.3" - "@eslint/js" "8.40.0" - "@humanwhocodes/config-array" "^0.11.8" + "@eslint/js" "8.43.0" + "@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" @@ -4333,13 +4330,12 @@ eslint@^8.40.0: find-up "^5.0.0" glob-parent "^6.0.2" globals "^13.19.0" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" - js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" @@ -4708,10 +4704,10 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -framer-motion@^10.12.12: - version "10.12.12" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.12.12.tgz#24c3620520f225e446972c42cad1c94d6ce70bbc" - integrity sha512-DDCqp60U6hR7aUrXj/BXc/t0Sd/U4ep6w/NZQkw898K+u7s+Vv/P8yxq4WTNA86kU9QCsqOgn1Qhz2DpYK0Oag== +framer-motion@^10.12.17: + version "10.12.17" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.12.17.tgz#0e891aaddbe6049267c413449945af95585cbc87" + integrity sha512-IR+aAYntsyu6ofyxqQV4QYotmOqzcuKxhqNpfc3DXJjNWOPpOeSyH0A+In3IEBu49Yx/+PNht+YMeZSdCNaYbw== dependencies: tslib "^2.4.0" optionalDependencies: @@ -4920,6 +4916,11 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -5370,11 +5371,6 @@ js-file-download@^0.4.12: resolved "https://registry.yarnpkg.com/js-file-download/-/js-file-download-0.4.12.tgz#10c70ef362559a5b23cdbdc3bd6f399c3d91d821" integrity sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg== -js-sdsl@^4.1.4: - version "4.3.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" - integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== - js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" @@ -6236,7 +6232,7 @@ react-fast-compare@3.2.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.1.tgz#53933d9e14f364281d6cba24bfed7a4afb808b5f" integrity sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg== -react-focus-lock@^2.9.2: +react-focus-lock@^2.9.4: version "2.9.4" resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.4.tgz#4753f6dcd167c39050c9d84f9c63c71b3ff8462e" integrity sha512-7pEdXyMseqm3kVjhdVH18sovparAzLg5h6WvIx7/Ck3ekjhrrDMEegHSa3swwC8wgfdd7DIdUVRGeiHT9/7Sgg== @@ -6248,10 +6244,10 @@ react-focus-lock@^2.9.2: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-icons@^4.8.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.8.0.tgz#621e900caa23b912f737e41be57f27f6b2bff445" - integrity sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg== +react-icons@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.10.1.tgz#3f3b5eec1f63c1796f6a26174a1091ca6437a500" + integrity sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw== react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" @@ -6942,10 +6938,10 @@ typeforce@^1.11.5: resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== -typescript@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" - integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +typescript@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" + integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== unbox-primitive@^1.0.2: version "1.0.2"