Децентрализованная идентификация – создайте профиль с помощью Next.js, Ethereum и сети Ceramic

Древние централизованные посредники, например правительство или крупные компании, создают и сохраняют вашу идентификационную информацию в традиционных системах, управляющих вашим лицом.

Но это означает, что вы не можете контролировать информацию, связанную с вашей идентификацией, кто имеет доступ к информации, позволяющей идентифицировать личность (PII) и в каком объеме.

В результате децентрализованная идентификация предоставляет связанную с идентификацией информацию, которая самоконтролируемой, частной и переносимой. Децентрализованные идентификаторы и аттестации служат основными составляющими.

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

В этой статье вы узнаете о децентрализованной идентификации, децентрализованных идентификаторов, сети Ceramic и о том, как создать децентрализованный профиль идентификации с помощью Ethereum в сетях Ceramic.

Вот что мы рассмотрим:

  • Что такое децентрализованная идентификация?
  • Что такое децентрализованные идентификаторы?
  • Что такое керамическая сеть данных?
  • Почему Ceramic Network?
  • Как создать децентрализованный профиль идентификации с помощью Next.js
  • предпосылки
  • Настройка и установка проекта
  • Установите TailwindCSS в Next.js
  • Аутентификация пользователей
  • Создать/обновить профиль пользователя
  • Как протестировать программу
  • Вывод
  • Список литературы

Что такое децентрализованная идентификация?

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

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

Децентрализованная идентификация – это самостоятельная, независимая идентификация, которая обеспечивает доверенный обмен данными.

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

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

Что такое децентрализованные идентификаторы?

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

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

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

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

В последние годы платформы смарт-контрактов, такие как Ethereum продемонстрировали полезность децентрализованных программ (dApps), которые можно собрать как блоки для создания новых программ. Это особенно очевидно в строящихся друг на друге токенах, в протоколах DeFi, которые используют друг друга, и так далее.

Благодаря Ceramic данные в Интернете теперь могут иметь такую ​​же возможность компоновки. Можно включить любой тип данных, включая профили, социальные связи, публикации в блогах, идентификационные данные, репутацию и т.д. Вы узнаете больше о Ceramic Network в разделе ниже.

Что такое керамическая сеть?

Ceramic — это общедоступный протокол с открытым исходным кодом без разрешения, предлагающий вычисление, изменение состояний и консенсус для всех структур данных в децентрализованном Интернете.

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

Ceramic сохраняет все содержимое в смарт-документах, которые являются журналами IPFS только для добавления. Прежде чем закрепляться в блокчейне для консенсуса, каждый коммит проверяется посредством децентрализованной идентификации (DID).

Все документы в Ceramic открыто доступны, и на них можно ссылаться в других документах или запрашивать любой другой пользователь сети, поскольку система полностью одноранговая.

Почему Ceramic Network?

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

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

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

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

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

Как создать децентрализованный профиль идентификации с помощью Next.js

предпосылки

Чтобы пройти это руководство, вам понадобится определенный опыт работы с JavaScript и React.js. Опыт работы с Next.js не обязателен, но его приятно иметь.

Убедитесь, что на компьютере установлен Node.js или npm. Если нет, нажмите здесь.

Кроме того, будет очень полезно обладать базовым пониманием технологии блокчейн и концепций Web3.

Настройка и установка проекта

Перейдите к терминалу и cd в любой каталог по вашему выбору. Затем выполните следующие команды:

mkdir decentralized-identity-project
cd decentralized-identity-project
npx create-next-app@latest .

Примите следующие варианты:

0b46fd0f-d47a-4533-9450-a79007205efe

Установите @self.id/react и @self.id/web пакеты, используя приведенный ниже фрагмент кода:

npm install @self.id/web @self.id/react

Далее запустите программу с помощью такой команды:

npm run dev

У вас должно быть что-то вроде того, что показано ниже: шаблонный макет по умолчанию для Next.js 13.

799cfc73-78b3-49f9-8b72-a407813f7d9c

Установите TailwindCSS в Next.js

В этом разделе вы настроите CSS Tailwind в проекте Next.js. установить tailwindcss и его одноранговые зависимости через npm, а затем запустите команду init, чтобы сгенерировать оба tailwind.config.js и postcss.config.js.

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Перейдите к tailwind.config.js и добавьте пути к файлам шаблона с помощью следующего фрагмента кода.

/** @type {import('tailwindcss').Config} */

module.exports = {
  content: [
    "./app/**/*.{js,ts,jsx,tsx}",
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
 
    // Or if using `src` directory:
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Удалите все стили CSS внутри globals.css . Добавьте @tailwind директивы для каждого из слоев Tailwind globals.css файл.

@tailwind base;
@tailwind components;
@tailwind utilities;

Настройте компонент поставщика

The Provider компонент должен быть размещен в верхней части дерева приложения, чтобы использовать хуки, описанные ниже. Вы можете использовать его для предоставления исходного состояния, а также определенной конфигурации для клиентов и запросов Self.ID.

Обновить _app.js файл в папке pages с таким фрагментом кода:

// Import the Provider component from the "@self.id/react" library.
import { Provider } from "@self.id/react";

// Import the "globals.css" file from the "@/styles" directory.
import "@/styles/globals.css";

// Define the App component as a default export.
export default function App({ Component, pageProps }) {
    
  // Render the Provider component, which provides authentication and authorization functionality to the application.
  // Pass a client prop to the Provider component, which configures the Ceramic testnet with the "testnet-clay" value.
  // Render the Component with its props inside the Provider component, which allows the application to access the authentication and authorization context.
    
  return (
    <Provider client={{ ceramic: "testnet-clay" }}>
      <Component {...pageProps} />
    </Provider>
  );
}
Настроить поставщика

В приведенном выше фрагменте кода мы:

  • Импортирован компонент поставщика контекста и глобальные стили CSS, а затем определены App компонент, который оборачивает всю программу поставщиком контекста.
  • Настроил поставщика контекста с помощью клиента тестовой сети Ceramic, позволяющего программе получать доступ к функциям аутентификации и авторизации.
  • Наконец, Component отображается со своими свойствами внутри поставщика контекста, что позволяет программе получать доступ к контексту аутентификации и авторизации.

Создайте макет

Далее перейдите к index.js файл под pages папку и обновите ее с помощью следующего кода:

// Import the Head component from the "next/head" module.
import Head from "next/head";

// Import the useViewerConnection and useViewerRecord hooks from the "@self.id/react" library.
import { useViewerConnection, useViewerRecord } from "@self.id/react";

// Import the EthereumAuthProvider component from the "@self.id/web" library.
import { EthereumAuthProvider } from "@self.id/web";

// Import the useState hook from the "react" module.
import { useEffect, useState } from "react";


export default function Home() {

  return (
    <>
      <Head>
        <title>
          Decentralized Identity: Build a Profile with NextJs, Ethereum & Ceramic Network
        </title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href=" />
      </Head>
      <main className="min-h-screen bg-gray-200">
        <div className="bg-gray-600 py-4 px-4 sm:px-6 lg:px-8 lg:py-6 shadow-lg text-white">
          <div className="container mx-auto px-6 md:px-0">
            <h1 className="text-2xl font-bold text-white text-center">
              Decentralized Identity: Build a Profile with NextJs, Ethereum & Ceramic Network
            </h1>
          </div>
        </div>

        <div className="flex items-center justify-center pt-20 font-sans overflow-hidden">
          <div className="max-w-md w-full mx-auto">
            <div className="bg-white p-10 rounded-lg shadow-lg">
              <form>
                <div className="mb-6">
                  <label
                    className="block text-gray-700 font-bold mb-2"
                    htmlFor="name"
                  >
                    Name
                  </label>
                  <input
                    className="border border-gray-300 p-2 w-full rounded-lg"
                    type="text"
                    name="name"
                    id="name"
                    placeholder="Your name"
                  />
                </div>
                <div className="mb-6">
                  <label
                    className="block text-gray-700 font-bold mb-2"
                    htmlFor="bio"
                  >
                    Bio
                  </label>
                  <textarea
                    className="border border-gray-300 p-2 w-full rounded-lg"
                    name="bio"
                    id="bio"
                    rows="5"
                    placeholder="Write something about yourself"
                  ></textarea>
                </div>
                <div className="mb-6">
                  <label
                    className="block text-gray-700 font-bold mb-2"
                    htmlFor="username"
                  >
                    Username
                  </label>
                  <input
                    className="border border-gray-300 p-2 w-full rounded-lg"
                    type="text"
                    name="username"
                    id="username"
                    placeholder="Your username"
                  />
                </div>
                <div className="flex items-center justify-between">
                  <button
                    className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
                    type="submit"
                  >
                    Update Profile
                  </button>
                  <button
                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
                    type="button"
                  >
                    Connect Wallet
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      </main>
    </>
  );
}

Для запуска программы выполните следующую команду и перейдите к localhost:3000 в вашем браузере; у вас должно быть что-то похожее на то, что показано ниже:

bc0620d9-d7bb-4297-bdb1-6021d08d8d6c

Как аутентифицировать пользователей

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

Обновить index.js с таким кодом:

//..

export default function Home() {

  // State variables for connection, connect function, and disconnect function
  const [connection, connect, disconnect] = useViewerConnection();
    
  
  const [isWindow, setIsWindow] = useState(null);
    

  // State variable for viewer's basic profile data
  const record = useViewerRecord("basicProfile");

  // Function to create EthereumAuthProvider using window.ethereum provider
  async function createAuthProvider() {
    const addresses = await window.ethereum.request({
      method: "eth_requestAccounts",
    });
    return new EthereumAuthProvider(window.ethereum, addresses[0]);
  }

  // Function to connect to viewer's account using created authProvider
  async function connectAccount() {
    const authProvider = await createAuthProvider();
    await connect(authProvider);
  }

  // Rendered JSX code
  return (
    <>
      {/* ... */}
      <div className="flex items-center justify-between">
        {/* ... */}

        {/* Conditionally render a button to connect/disconnect user */}
        {connection.status === "connected" ? (
          <button
            className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
            type="button"
            onClick={() => disconnect()}
          >
            Disconnect
          </button>
        ) : isWindow && "ethereum" in window ? (
          <button
            className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
            type="button"
            disabled={connection.status === "connecting" || !record}
            onClick={() => {
              connectAccount();
            }}
          >
            Connect Wallet
          </button>
        ) : (
          <p className="text-red-500 text-sm italic mt-2 text-center w-full">
            An injected Ethereum provider such as{" "}
            <a href=" is needed to
            authenticate.
          </p>
        )}
      </div>
    </>
  )
}

В приведенном выше фрагменте кода

  • The useViewerConnection hook используется для установки переменного состояния для статуса пользовательского подключения, подключения и отключения.
  • isWindow чтобы установить исходное состояние окна, чтобы избежать ошибки гидратации React
  • The useViewerRecord хук используется для получения основных данных пользователя.
  • The createAuthProvider функция создает EthereumAuthProvider объект с помощью window.ethereum провайдер.
  • The connectAccount вызовы функций createAuthProvider и подключается к аккаунту пользователя с помощью connect(authProvider).
  • Код JSX условно рендерит кнопку на основе статуса подключения пользователя и доступности ethereum провайдер в window объект.
  • Если пользователь уже подключен, кнопка позволит отключиться. Если пользователь еще не подключен и an ethereum поставщик доступен, кнопка позволит им подключиться. Но если пользователь не подключен и нет ethereum поставщик доступен, появится сообщение, чтобы сообщить пользователю о том, что для проверки подлинности требуется инъецированный поставщик Ethereum, например MetaMask.

Испытывая функцию аутентификации, вы должны иметь что-то вроде того, что показано ниже:

bc91509c-cd69-479a-80e5-7bc9b680150d

Как создать или обновить профиль пользователя

В предыдущем разделе вы узнали, как успешно аутентифицировать пользователей. Далее вы введете функциональность для создания и обновления аутентифицированного пользователя с помощью следующего фрагмента кода:

pages/index.js

//...


export default function Home() {
// Use the useState hook to create state variables and functions to update them
  const [name, setName] = useState("");
  const [bio, setBio] = useState("");
  const [username, setUsername] = useState("");

  //...

// Define an asynchronous function called updateProfile to update the profile information
  async function updateProfile() {
    // If any of the required fields are empty, return early and do not update
     if (!name || !bio || !username) {
       return;
     }
    
     // Use the merge method to update the record with the new information
     await record.merge({
       name,
       bio,
       username,
     });
   }

  // Render the component's UI
  return (
    <>

    {/* ... */}

    <div className="flex items-center justify-center pt-20 font-sans overflow-hidden">
          <div className="max-w-md w-full mx-auto">
            <div className="bg-white p-10 rounded-lg shadow-lg">
              <form>
               {/* ... */}
              </form>
            </div>
			{connection.status === "connected" && record && record.content ? (
              <div className="flex flex-col items-center mt-8">
                <h2 className="text-3xl font-bold mb-6 text-gray-900">
                  Profile Information
                </h2>
                <div className="w-full max-w-md bg-white p-8 rounded-lg shadow-lg">
                  <p className="mb-4">
                    <span className="font-bold text-gray-700 mr-2 text-lg">
                      Name:
                    </span>{" "}
                    <span id="nameOutput" className="text-lg">
                      {record.content.name || "No name set"}
                    </span>
                  </p>

                  <p className="mb-4">
                    <span className="font-bold text-gray-700 mr-2 text-lg">
                      Bio:
                    </span>{" "}
                    <span id="bioOutput" className="text-lg">
                      {record.content.bio || "No bio set"}
                    </span>
                  </p>
                  <p>
                    <span className="font-bold text-gray-700 mr-2 text-lg">
                      Username:
                    </span>{" "}
                    <span id="usernameOutput" className="text-lg">
                      {record.content.username || "No username set"}
                    </span>
                  </p>
                </div>
              </div>
            ) : (
              <div className="mt-8">
                <div className="bg-white p-8 rounded-lg shadow-lg">
                  <p>No profile found.</p>
                </div>
              </div>
            )}
           
          </div>
        </div>
    </>
  ) 
}

В приведенном выше коде

  • Компонент использует useState хук для управления состоянием трех переменных: name, bioи username.
  • Вызывается асинхронная функция updateProfile отвечающий за объединение текущего состояния переменных в запись.
  • Если любая из переменных пуста, updateProfile функция возвращается без обновления записи.
  • Есть три условных оператора, которые отображают другой пользовательский интерфейс в зависимости от того, найдена запись или нет.
  • Первый условный оператор проверяет, загружается ли запись, и если загружается, отображается a Loading... сообщения.
  • Второй условный оператор проверяет, нет ли содержимого записи и статус подключения подключен. Если это правда, отображается a No profile found. сообщения.

Третий условный оператор проверяет, существует ли содержимое записи. Если да, то отображается информация о профиле, включающая данные пользователя name, bioи username.

Вы почти там. В теге формы обновите name, bio и username поле ввода с следующим кодом:

<div className="mb-6">
  <label
    className="block text-gray-700 font-bold mb-2"
    htmlFor="name"
  >
    Name
  </label>
  <input
    //...
    onChange={(e) => {
      setName(e.target.value);
    }}
  />
</div>
<div className="mb-6">
  <label
    className="block text-gray-700 font-bold mb-2"
    htmlFor="bio"
  >
    Bio
  </label>
  <textarea
    //...
    onChange={(e) => {
      setBio(e.target.value);
    }}
  ></textarea>
</div>
<div className="mb-6">
  <label
    className="block text-gray-700 font-bold mb-2"
    htmlFor="username"
  >
    Username
  </label>
  <input
    //...
    onChange={(e) => {
      setUsername(e.target.value);
    }}
  />
</div>

В приведенном выше фрагменте кода setName, setBioи setUsername это функции, которые предоставляет useState крючок, обновляющий состояние name, bioили username.

Далее, Update Profile кнопку.

//...

 <button
     className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
     type="submit"
     disabled={!record.isMutable || record.isMutating}
     onClick={() => updateProfile()}
 >
    {record.isMutating ? "Updating..." : "Update Profile"}
</button>

//..

В приведенном выше фрагменте кода кнопка выключена, если запись не меняется или меняется.

Когда кнопка нажата, она вызывает updateProfile функция, отвечающая за обновление информации в пользовательском профиле. Если запись изменится, отобразится кнопка Updating.... В противном случае он отобразится Update Profile.

Вы можете протестировать программу, подобную ниже.

Пожалуйста, найдите полный код в репозитории GitHub здесь.

Вывод

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

Список литературы

Я хотел бы связаться с вами по адресу Twitter | LinkedIn | GitHub | Портфолио

До встречи в моей следующей статье. Заботиться!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *