konopek1
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    > Why did you build it? In our views the wallet experience in Polkadot ecosystem is still lacking. On the other hand, integrating with MetaMask Snaps could help onboard an existing population of web3 users to Alpeh Zero network. > Put your walkthrough video https://www.youtube.com/watch?v=lS5-YwOy9gE > Can you walk us through the technical implementation? ## The adapter Our snap is composed from two parts. First is a website that users interact with. The second one is the actual Snap. Those two elements work in a way similar to client-server architecture, where the snap is a server and the website is the client. To reflect this natural boundary we have extracted snap API to a separate package named `adapter`. It exposes all possible methods the website may use to interact with the snap. Such a layer of abstraction, ease usage of the Snap by other clients (websites). Our API can be described by four methods, which names are pretty self-explanatory. If u want to deep dive, here is the full [code](https://github.com/piotr-roslaniec/ethwarsaw-2022/tree/main/azero-snap/packages/snap-adapter). ```javascript= 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", []); } ``` ## The App So, we explained the glue between our layers, let’s move on to the first layer - website. We have forked the official browser based [polkadot app](https://github.com/Cardinal-Cryptography/apps). Then we had to replace core functionalites like signing transactions, creating accounts or recovering them, from browser based wallet to the Snap based. For example to sign transactions inside MetaMask we changed implementation of [QrSigner](https://github.com/piotr-roslaniec/ethwarsaw-2022/blob/ed9f12e54c9c721685692f75b78e2f3e1d8b546b/polkadot-apps/packages/react-signer/src/signers/QrSigner.ts#L20) to use Snap `signTransaction` instead. Integrating MetaMask Snap with the polkadot app introduced two improvments. Firstly, it allowed to inherit the security model from the MetaMask extension instead of using the polkadot app wallet, which is based on local storage. Secondly, we could use MetaMask seed to create a polkadot app in a deterministic way, so whenever we export our seed, the Aleph Zero key will be also exported. ## The MetaMask API MetaMask provides [API calls](https://docs.metamask.io/guide/snaps-rpc-api.html#restricted-methods), which can be used by snaps if permitted by user. In this case we have levarged two of them: `snap_manageState` - which allow as two store encrypted data inside MeteMask. For instance we use it to store created accounts. Interacting with state is very easy and can be simplified to: ```typescript 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_` - to get entropy from MetaMask seed. [docs](https://docs.metamask.io/guide/snaps-rpc-api.html#snap-getbip44entropy) It is worth to mention that there exists very cool MetaMask library [passworder](https://www.npmjs.com/package/@metamask/browser-passworder), which allow us to easly encrypt and decrypt state. In our case as a symetric key to encrypt state we have used entropy from MetaMask seed once again. ## The SDK So let's recap, we have hacked polkadot app by injecting some javascript here and there enabling usage of the Snap. The Snap can get entropy from the seed inside MetaMask and manage encrypted state. So the last step would be to integrate with the SDK for the Aleph Zero - [polkadotjs](https://polkadot.js.org/docs/api/). That seems like a easy task, just run `npm install @polkadot/api` and import it. However importing dependencies to Snap can be challening. This difficulties appears, because Snap is not evaluated directly on javascript virtual machine, it first has to be sandboxed in Secure Ecma Script (SES). In short, code which normally compile without any problems could fail when loading in [SES](https://docs.metamask.io/guide/snaps-development-guide.html#fixing-build-eval-issues). When working with most of the librariers we wont have any problems, but it wasn't case for us. We had two issues with evaluating `polkadotjs SDK` inside SES, to mitigate them we have written two scripts which were run on bundled source code. First of them was caused by incorrectly formatted wasm code embedded inside javascript file. Here is the fixing script: ```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(); ``` Second issue was also caused, by polkadot extension, which was trying to access `window.addEventListener` method, which is forbidden in SES. It was also trivally solved with simple ```javascript= 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(); ``` > What are the next steps if you would implement this? We'd love to make make our snap fully compatible with polkadot.js and viable as a web wallet in Polkadot ecosystem. > Your Story > Can you tell us a little bit about yourself and your team? Micheal is a programmer in a Polish bank working on a daily basis with blockchain technology. He loves programming and learning new stuff. Piotr is a software engineer working in NuCypher. He’s interested in privacy, data, and distributed systems. > When were you first introduced to MetaMask Snaps and what was your experience like? Piotr - Initially learned about snaps during Devcon in Osaka. The topic resurfaced earlier this year, shortly before EthDenver hackathon. Michał - Piotr introduced me to Snaps, shortly after EthDenver. > What makes MetaMask Snaps different from other wallets? An ability to access application-specific cryptography/private keys in your dapp - It enables building new user flows on top of a familiar browser-wallet experience. > Tell us about what building Snaps with MetaMask is like for you and your team? The basics are there, but building more sophisticated snaps, especially ones that require custom UI elements, is tricky. We spent a lot of time figuring out how to fit our mental model of web developer experience into snaps - things like deployment, testing, etc. > What does Snaps mean to you? It is a tool which gives real power to the community, everyone for themself decides, what features should their MetaMask have. Plugins allows to democratize development and enable faster growth. > What opportunities do you see with MetaMask Snaps and the possibilities it unlocks for the Web3 space? Access to more network (especially non-EVM ones); An ability to tap into transaction lifecycle and add custom logic (like safety checks) or customize the UX; Encrypted storage in the browser for dapp-specific sensitive content, and also an ability to "bring your own cryptography" to your users with snaps. > Any advice you would like to share with developers keen to try MetaMask Snaps? Compiling JS libraries in SES could be difficult, but from our experience it's not impossible. Feedback loop in developing metamask is pretty long, so we be sure to write unit tests. There is a small but active developers community in MetaMask snaps - visiting Discord, GitHub discussions etc. can be very rewarding, especially that the product is still new and there is little education avalible outside this bubble. >Article Structure: Video Intro the team and what was your roles Technical walkthrough The mission of the snap Future builds and next steps in the development > Notes to deliver a better blog post: Add a lot of screenshots of the demo Add the walkthrough video - https://www.youtube.com/watch?v=lS5-YwOy9gE Screenshots of the code, main parts with an explanation Add tons of links referring to the snaps documentation or talks CTA where devs can check your repos etc >Deliverables to Snaps Team: Team picture Pictures from the event Link to Snap repo - https://github.com/piotr-roslaniec/ethwarsaw-2022 Link to personal/team website - https://devpost.com/software/aleph-zero-snap Team members Twitter handles - https://twitter.com/piotrroslaniec, https://twitter.com/konopek68 Sample posts: https://consensys.net/blog/metamask/metamasks-community-at-the-core-of-its-growth/

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully