6const isPinnedOn = async (client: PinTarget['client'], cid: string): Promise<boolean> => { 8 // @ts-expect-error kubo-rpc-client returns AsyncIterable with .next() 9 await client.pin.ls({paths: [cid]}).next() 11 } catch { return false } 14export const verifyIpfsPins = async ({rootCids}: {rootCids: MfsRootCidEntry[]}) => { 17 totalRoots: rootCids.length, 18 hosts: targets.map(t => t.host), 22 perRoot: {} as Record<string, {cid: string, pinnedOn: string[], missingOn: string[], healed: string[]}>, 25 for (const {label, cid} of rootCids) { 26 const entry = {cid, pinnedOn: [] as string[], missingOn: [] as string[], healed: [] as string[]} 27 result.perRoot[label] = entry 29 for (const t of targets) { 30 if (await isPinnedOn(t.client, cid)) { entry.pinnedOn.push(t.host); continue } 31 entry.missingOn.push(t.host) 33 await t.client.pin.add(cid) 34 entry.healed.push(t.host) 36 betLog('pinHeal', {label, cid, host: t.host}) 38 betLog('pinHealFail', {label, cid, host: t.host, errMsg: (err as Error).message}) 42 if (entry.missingOn.length === 0) result.pinnedOnAll++ 43 else if (entry.pinnedOn.length === 0) result.missing++ 46 const failedHeals = Object.values(result.perRoot).filter(e => 47 e.missingOn.length > 0 && e.healed.length < e.missingOn.length 50 betLog('ipfsPinVerifyResult', result)