🌳
pt0/ipfsF/ipfsClientAI.mts
1import { create } from 'kubo-rpc-client'
8const filebaseApiUrl = 'https://api.filebase.io/v1/ipfs'
9const ocWebIpfsApiUrl = 'http://ipfs:5001'
11const getIpfsApiUrl = () => getEnvConf().ipfsApiUrl || (isOcWeb && ocWebIpfsApiUrl) || primaryIpfsApiUrl
12const getIpfsGatewayUrl = () => getEnvConf().ipfsGatewayUrl || primaryIpfsGatewayUrl
14export const getIpfsClient = () => create({url: getIpfsApiUrl()})
16export type PinTarget = {host: string, client: ReturnType<typeof create>}
18export const getFilebaseClient = () => {
19 return null // filebase down 2026-04-03 — re-enable when stable
20 const token = getPlainSecOpt('ipfs-filebase' as any)
21 if (!token) return null
22 return create({url: filebaseApiUrl, headers: {Authorization: `Bearer ${token}`}})
25export const getPinTargets = async (): Promise<PinTarget[]> => {
26 const targets: PinTarget[] = [{host: new URL(getIpfsApiUrl()).hostname, client: getIpfsClient()}]
27 const fbClient = getFilebaseClient()
28 if (fbClient) targets.push({host: new URL(filebaseApiUrl).hostname, client: fbClient})
29 for (const {apiUrl} of await getActiveIpfsHostsForLan()) {
30 const host = new URL(apiUrl).hostname
31 if (!targets.some(t => t.host === host)) targets.push({host, client: create({url: apiUrl})})
32 }
33 return targets
36export const uploadToIpfs = async (content: Buffer | Uint8Array): Promise<string> => {
37 const [primary, ...secondaries] = await getPinTargets()
38 const result = await primary.client.add(content, {chunker: 'size-1048576', pin: true})
39 const cid = result.cid.toString()
41 for (const {host, client} of secondaries) {
42 try { await client.pin.add(cid) }
43 catch (err) { betLog('pinFail', {host, cid, errMsg: (err as Error).message}) }
44 }
46 return cid
49export const pinCid = async (cid: string) => {
50 for (const {host, client} of await getPinTargets()) {
51 try { await client.pin.add(cid) }
52 catch (err) { betLog('pinFail', {host, cid, errMsg: (err as Error).message}) }
53 }
56export const unpinCid = async (cid: string) => {
57 for (const {host, client} of await getPinTargets()) {
58 try { await client.pin.rm(cid).catch(() => {}) }
59 catch {} // catch:userapproved
60 }
63export const ipfsGatewayLink = (cid: string) => `${getIpfsGatewayUrl()}/${cid}`
65export const ipfsGatewayFetchUrl = (cid: string) => `${getIpfsGatewayUrl()}/${cid}`