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

Aleph Zero Snap: онбординг пользователей Web3 в сеть Aleph Zero

Snap для MetaMask, подключающий пользователей к сети Aleph Zero

7 мин чтения
Aleph Zero Snap: онбординг пользователей Web3 в сеть Aleph Zero

MetaMask Snaps — это дорожная карта, которая сделает MetaMask самым расширяемым кошельком в мире. Как разработчик, вы можете добавлять свои функции и API в MetaMask совершенно новыми способами. Web3-разработчики — основа этого роста, и данная серия материалов призвана продемонстрировать новаторские MetaMask Snaps, создаваемые сегодня.

Aleph Zero Snap с Пётром и Майклом

Мы беседуем с Web3-разработчиками Пётром и Майклом, которые создали Aleph Zero Snap на хакатоне ETHWarsaw.

Репозиторий Snap: https://github.com/piotr-roslaniec/ethwarsaw-2022/tree/main/azero-snap/packages/snap-adapter

Почему вы его создали?

На наш взгляд, работа с кошельком в экосистеме Polkadot по-прежнему оставляет желать лучшего. С другой стороны, интеграция с MetaMask Snaps могла бы помочь привлечь уже существующую аудиторию web3-пользователей в сеть Aleph Zero.

Расскажите о технической реализации.

Адаптер

Наш snap состоит из двух частей. Первая — это веб-сайт, с которым взаимодействуют пользователи. Вторая — сам Snap. Эти два элемента работают по принципу, схожему с архитектурой клиент-сервер, где snap выступает сервером, а веб-сайт — клиентом. Чтобы отразить эту естественную границу, мы вынесли API snap в отдельный пакет под названием adapter. Он предоставляет все возможные методы, которые веб-сайт может использовать для взаимодействия со snap. Такой уровень абстракции упрощает использование Snap другими клиентами (веб-сайтами). Наш API можно описать четырьмя методами с говорящими названиями. Если хотите погрузиться глубже, вот полный код.

export const getAccountFromSeed = async (seed: string): Promise<PublicAccount> => {
  return await requestSnap("getAccountFromSeed", [seed]);
}

export const generateNewAccount = async (): Promise<PublicAccount> => {
  return await requestSnap("generateNewAccount", []);
}

export const signTransaction = async (transaction: SignerPayloadJSON): Promise<{ signature: string }> => {
  return await requestSnap("signTransaction", [transaction as unknown as string]);
}

export const getAccounts = async (): Promise<string[]> => {
  return await requestSnap("getAccounts", []);
}
Копировать

Приложение

Итак, мы объяснили связующее звено между нашими слоями — перейдём к первому из них: веб-сайту. Мы сделали форк официального браузерного приложения Polkadot. Затем нам потребовалось заменить ключевые функции — такие как подписание транзакций, создание и восстановление аккаунтов — с браузерного кошелька на кошелёк на основе Snap. Например, для подписания транзакций внутри MetaMask мы изменили реализацию QrSigner, чтобы использовать signTransaction из Snap.

Интеграция MetaMask Snap с приложением Polkadot принесла два улучшения:

  • Во-первых, появилась возможность унаследовать модель безопасности расширения MetaMask вместо использования кошелька приложения Polkadot, основанного на локальном хранилище.

  • Во-вторых, мы смогли использовать seed MetaMask для детерминированного создания аккаунта в приложении Polkadot — таким образом, при экспорте seed ключ Aleph Zero также экспортируется.

MetaMask API

MetaMask предоставляет API-вызовы, которые MetaMask Snaps может использовать при наличии разрешения пользователя. В данном случае мы задействовали два из них:

snap_manageState — позволяет хранить зашифрованные данные внутри MetaMask. Например, мы используем его для хранения созданных аккаунтов. Взаимодействие с состоянием очень простое и сводится к следующему:

const request = async (method: 'clear' | 'get' | 'update', newState?: unknown): Promise<any> => {
if (['get', 'clear'].includes(method) && newState) {
    throw new Error(`Cannot ${method} with newState`);
}
if (method == 'update' && !newState) {
    throw new Error('Cannot call update without newState');
}

const params = newState ? [method, newState] : [method];
return await wallet.request({
    method: `snap_manageState`,
    params,
  });
}
Копировать

snap_getBip44Entropy_ — для получения энтропии из seed MetaMask. Документация

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

SDK

Подведём итог: мы модифицировали приложение Polkadot, внедрив фрагменты JavaScript, обеспечивающие использование Snap. Snap может получать энтропию из seed внутри MetaMask и управлять зашифрованным состоянием. Последним шагом стала интеграция с SDK для Aleph Zero — polkadotjs.

Казалось бы, простая задача: выполни npm install @polkadot/api и импортируй. Однако импорт зависимостей в Snap может быть непростым делом. Сложности возникают потому, что Snap выполняется не напрямую на виртуальной машине JavaScript — сначала он должен быть изолирован в Secure ECMAScript (SES). Если коротко: код, который в обычных условиях компилируется без проблем, может не загрузиться в SES.

Код

При работе с большинством библиотек проблем не возникает, но в нашем случае всё оказалось иначе. У нас было две проблемы с выполнением polkadotjs SDK внутри SES; для их устранения мы написали два скрипта, которые запускались на собранном исходном коде.

Первая была вызвана некорректно отформатированным wasm-кодом, встроенным в JavaScript-файл. Вот исправляющий скрипт:

const fs = require('fs').promises;
const path = require('path');

const dirPath =
  '../../../../node_modules/@substrate/smoldot-light/dist/cjs/instance/autogen';

// SES doesn't like double slashes in strings so we need to replace them with single slashes
// and string concatenation.
async function fixDoubleSlash() {
  const files = ['wasm0.js', 'wasm1.js', 'wasm2.js'];
  for (const file of files) {
    console.log('Fixing ${file}');
    const filePath = path.join(__dirname, dirPath, file);
    const contents = await fs.readFile(filePath, 'utf8');
    let fixedContents = contents;
    while (fixedContents.includes('//')) {
      fixedContents = fixedContents.split('//').join('/"+"/');
    }
    await fs.writeFile(filePath, fixedContents);
  }
}

fixDoubleSlash();
Копировать

Вторая проблема также была вызвана расширением Polkadot, которое пыталось обратиться к методу window.addEventListener, запрещённому в SES. Она также была тривиально решена с помощью простого

const fs = require('fs').promises;
const path = require('path');

const bundlePath = path.join(__dirname, '../dist/bundle.js');

async function fix() {
  console.log(`Fixing ${bundlePath}`);
  const contents = await fs.readFile(bundlePath, 'utf8');
  const replaceMissingTypes = '\n\nwindow.addEventListener = function(){};\n\n';

  // Looking for a first breakline after the first line of the file
  // This is where we can safely inject our code
  const fixed = contents.replace('\n\n', replaceMissingTypes);
  await fs.writeFile(bundlePath, fixed);
}

fix();
Копировать

Каковы следующие шаги, если бы вы продолжали разработку?

Мы хотели бы сделать наш snap полностью совместимым с polkadot.js и пригодным для использования в качестве веб-кошелька в экосистеме Polkadot.

Расскажите немного о себе и своей команде.

Майкл — программист в польском банке, ежедневно работающий с технологией блокчейн. Он увлечён программированием и любит осваивать новое.

Пётр — инженер-программист в NuCypher. Его интересуют приватность, данные и распределённые системы.

Когда вы впервые узнали о MetaMask Snaps и каким было ваше первое впечатление?

Пётр — Впервые узнал о MetaMask Snaps на Devcon в Осаке. Тема снова всплыла в начале этого года, незадолго до хакатона EthDenver.

Майкл — Пётр познакомил меня с MetaMask Snaps вскоре после EthDenver.

Чем MetaMask Snaps отличается от других кошельков?

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

Расскажите, каково это — создавать MetaMask Snaps вместе с MetaMask для вас и вашей команды?

Основа есть, но создание более сложных MetaMask Snaps, особенно тех, которые требуют нестандартных элементов UI, — непростая задача. Мы потратили немало времени, пытаясь вписать нашу модель опыта веб-разработчика в Snaps — такие вещи, как деплой, тестирование и прочее.

Что для вас значит MetaMask Snaps?

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

Какие возможности вы видите в MetaMask Snaps и что это открывает для пространства Web3?

Доступ к большему числу сетей (особенно не-EVM); возможность встраиваться в жизненный цикл транзакций и добавлять пользовательскую логику (например, проверки безопасности) или настраивать UX; зашифрованное хранилище в браузере для конфиденциального контента, специфичного для dapp, а также возможность «принести свою криптографию» пользователям с помощью MetaMask Snaps.

Какой совет вы хотели бы дать разработчикам, желающим попробовать MetaMask Snaps?

Компиляция JS-библиотек в SES может быть непростой, но, по нашему опыту, это не невозможно. Цикл обратной связи при разработке MetaMask довольно длинный, поэтому обязательно пишите юнит-тесты.

Вокруг MetaMask Snaps сложилось небольшое, но активное сообщество разработчиков — посещение Discord, обсуждений на GitHub и других площадок может быть очень полезным, особенно учитывая, что продукт ещё новый и за пределами этого круга образовательных материалов пока немного.

Создание с MetaMask Snaps

Чтобы начать работу с MetaMask Snaps:

  1. Ознакомьтесь с документацией для разработчиков

  2. Установите MetaMask Flask

  3. Изучите руководство по MetaMask Snaps

  4. Оставайтесь на связи с нами в Twitter, обсуждениях на GitHub и Discord

Следите за нашей командой на следующем хакатоне рядом с вами! Удачного BUIDLing'а ⚒️

Отказ от ответственности: MetaMask Snaps, как правило, разрабатываются третьими сторонами, а не Consensys Software. Использование MetaMask Snaps, разработанных третьими сторонами, осуществляется по вашему собственному усмотрению и на ваш риск, и вы соглашаетесь с тем, что несёте единоличную ответственность за любые убытки или ущерб, возникшие в результате такой деятельности. Consensys не даёт никаких явных или подразумеваемых гарантий, устных или письменных, в отношении MetaMask Snaps, разработанных третьими сторонами, и отказывается от какой-либо ответственности за них. Использование программного обеспечения, связанного с блокчейном, сопряжено с рисками, которые вы принимаете в полной мере при использовании MetaMask Snaps.

Переведено ИИ. Может содержать ошибки. Пожалуйста, всегда проверяйте информацию.

Оцените перевод

Автор статьи:

  • MetaMask

    MetaMask, ранее известная как Consensys Software Inc, — крупнейшая в мире самостоятельная финансовая платформа, предоставляющая людям единое место для хранения, расходования, накопления и приумножения средств как в криптовалюте, так и в традиционных активах. Компания создаёт потребительскую платформу, объединяющую платежи, сбережения, инвестиции и цифровые активы в едином бесшовном опыте. Вырастая из самого широко используемого в мире self-custodial кошелька, MetaMask предоставляет пользователям прямой контроль над их деньгами и активами, охватывая около 190 стран. MetaMask сыграл основополагающую роль в развитии Ethereum с 2016 года. Сегодня MetaMask занимает центральное место в экономике блокчейна, создавая операционную систему для Open Money и предоставляя людям полный контроль над их финансовой жизнью.

    Читать все статьи