UNPKG

four-flap-meme-sdk

Version:

SDK for Flap bonding curve and four.meme TokenManager

107 lines (106 loc) 3.94 kB
export class PinataClient { constructor(cfg) { this.ready = (async () => { const mod = await import('pinata'); this.client = new mod.PinataSDK({ pinataJwt: cfg.jwt, pinataGateway: cfg.gateway }); })(); } async uploadFile(file) { await this.ready; const r = await this.client.upload.file(file); return { cid: r.cid, id: r.id }; } async uploadJSON(obj, name = 'meta.json') { const blob = new Blob([JSON.stringify(obj)], { type: 'application/json' }); const file = new File([blob], name, { type: 'application/json' }); return await this.uploadFile(file); } async get(cid) { await this.ready; const data = await this.client.gateways.public.get(cid); return data; } async url(cid) { await this.ready; return await this.client.gateways.convert(cid); } } /** * 使用 Pinata JWT 直接上传文件(Node 环境) * @param jwt Pinata JWT(以 Bearer 形式传入) * @param filePath 本地文件绝对/相对路径(优先) * @param data 可选:内存 Buffer(当未提供 filePath 时使用) * @param fileName 可选:内存数据的文件名 */ export async function pinFileToIPFSWithJWT(jwt, filePath, data, fileName) { const axiosMod = await import('axios'); const FormDataMod = await import('form-data'); const fsMod = await import('fs'); const form = new FormDataMod.default ? new FormDataMod.default() : new FormDataMod(); if (filePath && filePath.length > 0) { form.append('file', fsMod.createReadStream(filePath)); } else if (data) { form.append('file', data, { filename: fileName || 'upload.bin' }); } else { throw new Error('pinFileToIPFSWithJWT: either filePath or data must be provided'); } const resp = await axiosMod.default.post('https://api.pinata.cloud/pinning/pinFileToIPFS', form, { headers: { Authorization: `Bearer ${jwt}`, ...(form.getHeaders ? form.getHeaders() : {}) }, maxContentLength: Infinity, maxBodyLength: Infinity }); const d = resp.data || {}; return { cid: d.IpfsHash || d.cid, size: d.PinSize, timestamp: d.Timestamp, raw: d }; } /** * 便捷方法:上传本地图片路径(返回 CID) */ export async function pinImageByPath(jwt, filePath) { const r = await pinFileToIPFSWithJWT(jwt, filePath); return r.cid; } // ============ 浏览器端(前端)便捷方法 =========== // 说明:使用浏览器自带 FormData + fetch;参数为 File/Blob 或 dataURL export async function pinFileToIPFSWithJWTWeb(jwt, file, fileName) { const form = new FormData(); const name = fileName || file.name || 'upload.bin'; form.append('file', file, name); const resp = await fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', { method: 'POST', headers: { Authorization: `Bearer ${jwt}` }, body: form }); if (!resp.ok) { const txt = await resp.text(); throw new Error(`Pinata upload failed: ${resp.status} ${txt}`); } const d = await resp.json(); return { cid: d.IpfsHash || d.cid, size: d.PinSize, timestamp: d.Timestamp, raw: d }; } export function dataURLToBlob(dataUrl) { const [header, base64] = dataUrl.split(','); const mimeMatch = /data:(.*?);base64/.exec(header || ''); const mime = mimeMatch ? mimeMatch[1] : 'application/octet-stream'; const bin = atob(base64); const len = bin.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i); return new Blob([bytes], { type: mime }); } export async function pinDataURLWithJWTWeb(jwt, dataUrl, fileName = 'image.png') { const blob = dataURLToBlob(dataUrl); return await pinFileToIPFSWithJWTWeb(jwt, blob, fileName); }