Перейти к основному содержимому

Uploading to IPFS with NFT.storage

В этом руководстве мы выбираем IPFS, децентрализованный поставщик хранилища, чтобы разместить выбранное фото и объект метаданных.

Мы также будем использовать NFT.storage для загрузки напрямую в IPFS через их HTTP API. Вы можете зарегистрироваться и получить бесплатный API-ключ на их сайте.

Выбор фотографии

Вам нужно выбрать существующее фото из нашей галереи. Чтобы представить интерфейс выбора и получить путь к файлу, используйте launchImageLibrary из библиотеки react-native-image-picker.

к сведению

В примере приложения это делается в компоненте NftMinter, где handleSelectImage вызывается при нажатии кнопки.
Мы сохраняем путь к изображению как состояние, чтобы использовать его на следующем шаге.

import {launchImageLibrary} from 'react-native-image-picker';

const photo = await launchImageLibrary({
selectionLimit: 1,
mediaType: 'photo',
});
const selectedPhoto = photo?.assets?.[0];
if (!selectedPhoto?.uri) {
console.warn('Selected photo not found');
return;
}
const imagePath = selectedPhoto.uri;

Загрузка фото

Теперь, когда у нас есть путь к изображению, нам нужно загрузить сырые байты файла в IPFS, используя конечную точку NFT.storage /upload.

Шаги:

  1. Используйте библиотеку rn-fetch-blob, чтобы прочитать изображение в строку Base 64.
  2. Преобразуйте в сырые байты, декодируя строку Base64 с помощью Buffer.
  3. Используйте fetch, чтобы отправить запрос, содержащий байты изображения, на конечную точку загрузки.
предупреждение

На этом шаге вам потребуется предоставить свой собственный API-ключ от NFT.storage. В примере приложения значение NFT_STORAGE_API_KEY устанавливается через конфигурацию переменных окружения с использованием библиотеки react-native-config.

// Read the image file and get the base64 string.
const imageBytesInBase64: string = await RNFetchBlob.fs.readFile(
imagePath,
'base64',
);

// Convert base64 into raw bytes.
const bytes = Buffer.from(imageBytesInBase64, 'base64');

// Upload the image to IPFS by sending a POST request to the NFT.storage upload endpoint.
const headers = {
Accept: 'application/json',
Authorization: `Bearer ${Config.NFT_STORAGE_API_KEY}`,
};
const imageUpload = await fetch('https://api.nft.storage/upload', {
method: 'POST',
headers: {
...headers,
'Content-Type': 'image/jpg',
},
body: bytes,
});

const imageData = await imageUpload.json();
console.log(imageData.value.cid);

Если успешно, imageData.value.cid будет содержать действующий CID (Content Identifier). Это строка, которая уникально идентифицирует ваш загруженный ресурс.

Вы можете просмотреть свой загруженный ресурс на IPFS gateway, передав CID в URL (например, https://ipfs.io/ipfs/<cid>).

Загрузка метаданных

Далее нам нужно составить объект метаданных, соответствующий стандарту Metaplex NFT, затем загрузить его на ту же конечную точку /upload.

к сведению

В примере приложения шаг загрузки метаданных также обрабатывается в функции uploadToIPFS, которая вызывается позже в рамках более крупной mintNft функции.
Следует отметить небольшое отличие. Поле изображения использует предварительно вычисленный CID для фотографии, а не ожидает завершения загрузки фотографии. Это оптимизация, которая объясняется в следующем разделе.

// Construct the metadata fields.
const metadata = JSON.stringify({
name,
description,
image: `https://ipfs.io/ipfs/${imageData.value.cid}`,
});
// Upload to IPFS
const metadataUpload = await fetch('https://api.nft.storage/upload', {
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json',
},
body: metadata,
});

const metadataData = await metadataUpload.json();
console.log(metadataData.value.cid);

Если успешно, metadataData.value.cid теперь будет содержать CID, указывающий на JSON-объект, представляющий метаданные NFT.

Подытожив, у нас теперь есть два CID, которые можно просмотреть в IPFS. Первый — CID нашей загруженной фотографии, и второй — CID JSON Metadata (который имеет ссылку на CID фотографии в поле image).

Предварительное вычисление CID

Вы можете заметить в примере приложения, что во время шага загрузки в uploadToIPFS мы можем предварительно вычислить CID актива фотографии до его фактической загрузки в IPFS. Это оптимизация, позволяющая нам создавать и загружать объект метаданных без ожидания завершения загрузки фотографии и возврата CID.

// Fire off both uploads aysnc
return Promise.all([
imageUpload.then(response => response.json()),
metadataUpload.then(response => response.json()),
]);

Мы используем это преимущество, загружая как фотографию, так и метаданные асинхронно.

подсказка

Это стало возможным, потому что CID генерируются детерминированно из двоичных данных любого данного актива. Это означает, что мы можем вычислить CID актива до его загрузки в IPFS.

Чтобы вычислить CID из байтов данного актива, см. функцию getCid.

import {CID, hasher} from 'multiformats';
const crypto = require('crypto-browserify');

const SHA_256_CODE = 0x12;
const IPLD_RAW_BINARY_CODE = 0x55;

const getCid = async (bytes: Buffer) => {
const sha256 = hasher.from({
// As per multiformats table
// https://github.com/multiformats/multicodec/blob/master/table.csv#L9
name: 'sha2-256',
code: SHA_256_CODE,
encode: input =>
new Uint8Array(crypto.createHash('sha256').update(input).digest()),
});
const hash = await sha256.digest(bytes);
const cid = await CID.create(1, IPLD_RAW_BINARY_CODE, hash);

return cid;
};

ДимкаРеактнативный

🖋

katsuhira02

📝

Go!

EnglishMoji!