Инновации зовут

Используя удивительный новый чат GPT от открытого ИИ, голову, полную идей и знаний, чтобы связать все это воедино, я смог подготовить это руководство в рекордно короткие сроки.

Если вы еще не проверили это, поиграйте здесь.

Создайте React-приложение

В этом руководстве предполагается, что у вас настроен узел, если нет, вы можете установить его здесь.

Создайте новый каталог для нашего внешнего приложения на рабочем столе, откройте новое окно терминала и перейдите в этот каталог.

Оказавшись в этом новом каталоге, введите в терминал следующее, чтобы создать новое реагирующее приложение:

npx create-react-app FileCompressor

После установки ваша новая структура каталогов будет построена.

Добавить форму загрузки внешнего интерфейса

Перейдите к src/app.js и перейдите к функции App, чтобы поместить внутрь эту логику:

import React from "react";

function App(props) {
  const handleChange = e => {
    const fileReader = new FileReader();
    fileReader.readAsText(e.target.files[0], "UTF-8");
    fileReader.onload = e => {
      if(e.target !== null) {
        console.log("e.target.result", e.target.result);
      }
    };
  };

  return (
    <>
      <h1>Upload file</h1>

      <input type="file" onChange={handleChange} />
    </>
  );
}

export default App;

Это создаст новую функцию с именем handleChange, которая вызывается каждый раз, когда файл загружается во внешний интерфейс.

Base64

Наши файлы в настоящее время не имеют формата, который может понять цепочка, затем нам нужно преобразовать их в строку base64, которую можно хранить в цепочке.

Вернитесь к вашему файлу app.js, где мы добавим логику base64 в метод handleChange:

import React from "react";

function App(props) {
  const handleChange = e => {
    const fileReader = new FileReader();
    fileReader.readAsDataURL(file)
    fileReader.onload = () => {
      console.log(fileReader.result);
    }
    fileReader.onerror = (error) => {
      console.log(error);
    }
  };

  return (
    <>
      <h1>Upload file</h1>

      <input type="file" onChange={handleChange} />
    </>
  );
}

export default App;

На данный момент у нас есть форма загрузки файла, которая принимает входные данные, преобразует файл в строку base64 и выводит консоль. Как бы то ни было, это нормально, но гораздо лучше использовать сжатие, чтобы уменьшить количество байтов.

Сжатие строк LZ

Сначала установите библиотеку для сжатия lz:

npm i lzma-js

После установки измените app.js, чтобы он напоминал приведенный ниже пример, после чего на терминал будет записана сжатая строка base64:

import React from "react";
import LZMA from "lzma-js";

function App(props) {
  const handleChange = e => {
    const fileReader = new FileReader();
    fileReader.readAsDataURL(file)
    fileReader.onload = () => {
      // Convert the base64 encoded string to a Uint8Array
      const uint8Array = Uint8Array.from(atob(fileReader.result), c => c.charCodeAt(0));
      
      // Compress the Uint8Array using LZMA-JS
      LZMA.compress(uint8Array, 9, (result, error) => {
        if (error) {
          // Handle error
        } else {
          // The compressed data is a Uint8Array, so you need to convert it to a base64 encoded string
          const compressedBase64String = btoa(String.fromCharCode(...result));
          console.log(compressedBase64String); // Outputs the compressed base64 encoded string
        }
      });
    }
    fileReader.onerror = (error) => {
      console.log(error);
    }
  };

  return (
    <>
      <h1>Upload file</h1>

      <input type="file" onChange={handleChange} />
    </>
  );
}

export default App;

Смарт-контракт

Это простой смарт-контракт, в котором хранится массив строк bytes32, в данном случае наши строки bytes32 являются файлами.

// SPDX-License-Identifier: MIT 

pragma solidity ^0.8.10;

contract FileStorage { 
  mapping (address => bytes32[]) userFiles;

  function addFile(string calldata _file) public { 
    userFiles[msg.sender].push(_file);
  }

  function deleteFile(uint arrayIndex) public {
    delete userFiles[msg.sender][arrayIndex];
  }

  function getFiles() public view returns (bytes32[] memory) {
    return userFiles[msg.sender];
  }
}

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

Подключение децентрализованного приложения

Сначала возьмите abi для вашего развернутого контракта и сохраните в новом файле с именем abi.json.

[
 {
  "inputs": [
   {
    "internalType": "string",
    "name": "_file",
    "type": "string"
   }
  ],
  "name": "addFile",
  "outputs": [],
  "stateMutability": "nonpayable",
  "type": "function"
 },
 {
  "inputs": [
   {
    "internalType": "uint256",
    "name": "arrayIndex",
    "type": "uint256"
   }
  ],
  "name": "deleteFile",
  "outputs": [],
  "stateMutability": "nonpayable",
  "type": "function"
 },
 {
  "inputs": [],
  "name": "getFiles",
  "outputs": [
   {
    "internalType": "string[]",
    "name": "",
    "type": "string[]"
   }
  ],
  "stateMutability": "view",
  "type": "function"
 }
]

Если вы вернетесь к файлу app.js, последним этапом будет замена нашего консольного журнала строки файла вызовом смарт-контракта. Сначала мы вводим abi контракта, заполняем адрес контракта, подключаемся к MetaMask через интерфейс, а затем разрешаем сохранение файла пользователя после установления соединения.

import React from "react";
import LZMA from "lzma-js";

function App(props) {
  const abi = require('./abi.json');
  const handleChange = e => {
    const fileReader = new FileReader();
    const CONTRACT_ADDRESS = "0xof";
    fileReader.readAsDataURL(file)
    fileReader.onload = () => {
      // Convert the base64 encoded string to a Uint8Array
      const uint8Array = Uint8Array.from(atob(fileReader.result), c => c.charCodeAt(0));
      
      // Compress the Uint8Array using LZMA-JS
      LZMA.compress(uint8Array, 9, (result, error) => {
        if (error) {
          console.log(error);
        } else {
            // The compressed data is a Uint8Array, so you need to convert it to a base64 encoded string
            const compressedBase64String = btoa(String.fromCharCode(...result));
            const { ethereum } = window;
            const provider = new ethers.providers.Web3Provider(ethereum);
            const signer = provider.getSigner()
            const connectedContract = new ethers.Contract(CONTRACT_ADDRESS, abi, signer);

            let tx = async() => await connectedContract.addFile(compressedBase64String);

            console.log(tx); // Outputs the result of the smart contract call
        }
      });
    }
    fileReader.onerror = (error) => {
      console.log(error);
    }
  };

  return (
    <>
      <h1>Upload file</h1>

      <input type="file" onChange={handleChange} />
    </>
  );
}

export default App;

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

Чтобы вернуть ваши файлы и распаковать, вам нужно будет создать новый метод для запроса функции getFiles смарт-контрактов и прокрутить каждый из них, внутри каждой итерации вы просто вызовете метод ниже и сохраните распакованные данные любым способом, который подходит для вашего варианта использования. :

LZMA.decompress(properties, inStream, outStream, outSize);

У этого подхода так много возможностей, но, как всегда, это просто руководство, которое приведет вас к прочной основе и пониманию, но ни в коем случае не готово к производству.

Иди твори!

Новичок в трейдинге? Попробуйте криптотрейдинговых ботов или копи-трейдинг