import { useCallback, useEffect, useState } from 'react' import { create } from 'ipfs-http-client' import type { IPFSHTTPClient } from 'ipfs-http-client' import type { CIDVersion } from 'multiformats/cid' import { ipfsNodeUri } from '../../site.config' import { formatBytes } from '../utils' import type { FileIpfs } from '../@types/ipfs' import { FileWithPath } from 'react-dropzone' export interface IpfsApiValue { ipfs: IPFSHTTPClient | undefined version: string | undefined isIpfsReady: boolean ipfsError: string | undefined addFiles: (files: FileWithPath[]) => Promise } const { hostname, port, protocol } = new URL(ipfsNodeUri) const ipfsConfig = { protocol: protocol.replace(':', ''), host: hostname, port: Number(port) || 443 } export default function useIpfsApi(): IpfsApiValue { const [ipfs, setIpfs] = useState() const [version, setVersion] = useState() const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs)) const [ipfsError, setIpfsError] = useState() const addFiles = useCallback( async (files: FileWithPath[]): Promise => { if (!ipfs || !files?.length) return const ipfsFiles = [ ...files.map((file: FileWithPath) => { 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(ipfsConfig) setIpfs(ipfs) const version = await ipfs.version() setVersion(version.version) setIpfsReady(ipfs?.isOnline()) } 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) } } }, [ipfs]) return { ipfs, version, isIpfsReady, ipfsError, addFiles } }