import { backOff } from '@insertish/exponential-backoff'; import { IPFS } from 'ipfs-core-types'; import { CID, IPFSHTTPClient } from 'ipfs-http-client'; import { HTTPError as IPFSHTTPError } from 'ipfs-utils/src/http/error.js'; const IPFS_PIN_REMOTE_RETRIES = 10; const IPFS_PIN_REMOTE_RETRY_DELAY = 5_000; export async function pinToRemoteService( ipfsClient: IPFSHTTPClient, cid: CID, service: string, name: string, options?: Parameters[1], ): Promise { async function run() { try { await ipfsClient.pin.remote.add(cid, { ...options, service, name }); return; } catch (err) { if ( err instanceof IPFSHTTPError && err.message.includes('DUPLICATE_OBJECT') ) { return; } else { throw err; } } } await backOff(run, { numOfAttempts: IPFS_PIN_REMOTE_RETRIES, startingDelay: IPFS_PIN_REMOTE_RETRY_DELAY, jitter: 'full', retry: (err, attempt) => { // eslint-disable-next-line no-console console.warn( 'Error while trying to pin', cid.toString(), 'as', name, err.toString(), ); // eslint-disable-next-line no-console console.log('Pinning', cid.toString(), 'as', name, 'attempt', attempt); return true; }, }); // eslint-disable-next-line no-console console.log('Successfully pinned', cid.toString(), 'as', name); } export function makePinName( prefix: string, suffix: string, maxPrefixLength: number = 50 - suffix.length, ): string { return `${prefix.slice(0, maxPrefixLength)}/${suffix}`; }