import { useCallback, useEffect, useState } from 'react' import { create, IPFSHTTPClient, Options } from 'ipfs-http-client' import type { CIDVersion } from 'multiformats/cid' import { formatBytes } from '../utils' import { FileDropzone } from '../components/Dropzone' import { FileIpfs } from '../@types/ipfs' export interface IpfsApiValue { ipfs: IPFSHTTPClient | undefined version: string | undefined isIpfsReady: boolean ipfsError: string | undefined addFiles: (files: FileDropzone[]) => Promise } export default function useIpfsApi(config: Options): IpfsApiValue { const [ipfs, setIpfs] = useState() const [version, setVersion] = useState() const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs)) const [ipfsError, setIpfsError] = useState() const addFiles = useCallback( async (files: FileDropzone[]): Promise => { if (!ipfs || !files?.length) return const ipfsFiles = [ ...files.map((file: FileDropzone) => { return { path: file.path, content: file } }) ] const options = { wrapWithDirectory: true, cidVersion: 1 as CIDVersion, hashAlg: 'sha2-256', progress: (length: number) => formatBytes(length, 0) } const results: FileIpfs[] = [] for await (const result of ipfs.addAll(ipfsFiles, options)) { console.log(result) results.push(result) } return results }, [ipfs] ) useEffect(() => { if (ipfs) return async function initIpfs() { try { const ipfs = create(config) setIpfs(ipfs) const version = await ipfs.version() setVersion(version.version) setIpfsReady(Boolean(ipfs && (await ipfs.id()))) } catch (e) { setIpfsError(`IPFS connection error: ${(e as Error).message}`) setIpfsReady(false) return } } initIpfs() return () => { if (ipfs) { setIpfsReady(false) setIpfs(undefined) setVersion(undefined) setIpfsError(undefined) } } }, [config, ipfs]) return { ipfs, version, isIpfsReady, ipfsError, addFiles } }