Интеграция с Pinata (IPFS pinning)
IPFS — контент-адресуемая файловая система: хеш файла и есть его адрес. Но если никто не "пинит" (хранит) файл — он исчезнет из сети. Pinata — managed pinning service: вы загружаете файлы, они гарантируют доступность. Используется в NFT-проектах, dApp'ах с on-chain метаданными, децентрализованных хранилищах.
Загрузка файлов через Pinata API
const PINATA_JWT = process.env.PINATA_JWT!; // из dashboard.pinata.cloud
// Загрузка файла
async function uploadFile(fileBuffer: Buffer, filename: string): Promise<string> {
const formData = new FormData();
formData.append('file', new Blob([fileBuffer]), filename);
formData.append('pinataMetadata', JSON.stringify({ name: filename }));
formData.append('pinataOptions', JSON.stringify({ cidVersion: 1 }));
const response = await fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', {
method: 'POST',
headers: { Authorization: `Bearer ${PINATA_JWT}` },
body: formData,
});
const data = await response.json();
return data.IpfsHash; // CIDv1 хеш
}
// Загрузка JSON (для NFT metadata)
async function uploadJson(metadata: object, name: string): Promise<string> {
const response = await fetch('https://api.pinata.cloud/pinning/pinJSONToIPFS', {
method: 'POST',
headers: {
Authorization: `Bearer ${PINATA_JWT}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
pinataContent: metadata,
pinataMetadata: { name },
pinataOptions: { cidVersion: 1 },
}),
});
const data = await response.json();
return data.IpfsHash;
}
NFT metadata workflow
Стандартный ERC-721/ERC-1155 workflow:
// 1. Загружаем изображение
const imageCid = await uploadFile(imageBuffer, 'nft-image.png');
// 2. Формируем metadata по ERC-721 Metadata Standard
const metadata = {
name: 'My NFT #1',
description: 'Description here',
image: `ipfs://${imageCid}`, // ipfs:// URI, не https://
attributes: [
{ trait_type: 'Background', value: 'Blue' },
{ trait_type: 'Rarity', value: 'Rare' },
],
};
// 3. Загружаем metadata
const metadataCid = await uploadJson(metadata, 'nft-1-metadata.json');
// 4. tokenURI = ipfs://{metadataCid}
// В контракте: tokenURI(tokenId) возвращает ipfs://{metadataCid}
Используйте ipfs:// URI в контракте, не https://gateway.pinata.cloud/ipfs/. Gateway может меняться или быть недоступен — ipfs:// URI работает с любым gateway.
Pinata SDK (v2)
import { PinataSDK } from 'pinata';
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: process.env.PINATA_GATEWAY!, // yourname.mypinata.cloud
});
// Загрузка из URL
const upload = await pinata.upload.url('https://example.com/image.png');
console.log(upload.cid);
// Получение файла через dedicated gateway
const url = await pinata.gateways.convert(`ipfs://${cid}`);
// → https://yourname.mypinata.cloud/ipfs/{cid}
Dedicated gateway (платная опция) значительно быстрее публичного gateway.pinata.cloud — важно для NFT маркетплейсов, где изображения грузятся пользователями.
Групповой пин и управление коллекциями
// Список запиненных файлов с фильтрацией
async function listPins(keyValues?: Record<string, string>) {
const params = new URLSearchParams({
status: 'pinned',
pageLimit: '100',
...(keyValues ? { 'metadata[keyvalues]': JSON.stringify(keyValues) } : {}),
});
const response = await fetch(
`https://api.pinata.cloud/data/pinList?${params}`,
{ headers: { Authorization: `Bearer ${PINATA_JWT}` } }
);
return response.json();
}
// Анпин файла (освобождает хранилище)
async function unpinFile(cid: string) {
await fetch(`https://api.pinata.cloud/pinning/unpin/${cid}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${PINATA_JWT}` },
});
}
Используйте pinataMetadata.keyvalues для тегирования файлов по проекту или коллекции — потом удобно фильтровать и управлять хранением.
Локальное резервирование
Pinata — централизованный сервис. Для долгосрочной надёжности: дублируйте критичные CID в Filecoin через NFT.Storage или web3.storage, или держите собственную IPFS ноду с ipfs pin add {cid}.
# Собственная IPFS нода как дополнительное хранилище
ipfs pin add bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
CID одинаков везде — если файл есть хотя бы у одной ноды в сети, он достижим. Два pinning-провайдера = двойная надёжность.







