PWA with Privy and Account Abstraction

Objectives

The goal of this tutorial is to:

  • Implement Privy's template to create a PWA that runs a Next.js application using their embedded wallets.

  • Adjust the application to sign and submit transactions for an Account Abstraction Wallet.

Prerequisites

Before starting this tutorial, you should have a good understanding of the following:

  • React: You need to know how to code with React as this tutorial involves creating a PWA using Next.js, which is based on React.

  • Hardhat: You should be familiar with deploying smart contracts using Hardhat.

  • Fee Delegation: Understanding fee delegation, especially in the context of VeChain, is crucial for implementing Account Abstraction Wallets.

Privy

Introduction

Privy is a service that provides authentication services, which most users use daily, to access web3 wallets.

Privy handles wallet generation, security aspects, and interfaces that manage the signing of transactions or messages.

Setup

Privy offers a setup guide in a template project on GitHub: https://github.com/privy-io/create-privy-pwa

The steps to be done are:

Clone Template

Install Dependencies

Run npm install to install the project required dependencies:

Configure Privy

Visit https://privy.io to create a new App.

Create the file .env and add your created App Id:

Start App

You can start the app with npm run dev, and you will be able to sign into the app.

For testing development, its recommend to use ngrok (guide), since privy makes use of crypto.subtle which requires a secure context (https).

Login Methods

To adjust the desired login methods, toggle them on or off in the Privy dashboard for the app at: https://dashboard.privy.io

Account Abstraction

Introduction

Account Abstraction is a standard that allows smart contracts to initiate transactions, providing an on-chain wallet that can replace an externally owned account (EOA).

Example projects using this standard are available on GitHub at:

Setup

For the purpose of this tutorial, the account abstraction contracts from the SimpleAccount example by eth-infinitism are used.

The contracts to be deployed are:

To simplify the process, a modified project is available on GitHub at: https://github.com/vechain-energy/example-pwa-privy-account-abstraction/tree/main/account-abstraction-contracts

Clone Contracts

Install Dependencies

Run npm install --legacy-peer-deps to install the project required dependencies:

Configure Network

Generate a new private key and create the file .env, to configure it as deployer:

A simple way to generate a private key can be openssl:

Optionally adjust more network related options in the hardhat.config.ts file.

Deploy Contracts

The deploy scripts are in the deploy/ folder. Inspect for further understanding.

Use the hardhat deploy plugin to deploy the example contracts:

The output of the command shows the addresses of the deployed contracts:

The deployment addresses and ABIs are archived in the deployments/vechain_testnet folder.

Please document the address of the deployed SimpleAccountFactory for future use. In the above example output, it is 0x41Ea0cDa1471d70961bdc81bB9203a09cbf9B65e.

Background: Accept Signed Executions

The SimpleAccount restricts access to its owner or the endpoint contract.

Because Privy does not support the VeChain network, the interaction will be based on signed messages. A new function executeWithAuthorization verifies a signature for an execution to be from the owner.

You can add yourself a signature verification to SimpleAccount.sol with these changes:

Call the EIP721 with the constructor by adjusting its definition:

And add a new function that verifies signatures and does the same as execute:

Implement Account Abstraction into Privy PWA

Configure Account Abstraction and VeChain

Extend the .env file with the following lines:

  • NEXT_PUBLIC_AA_FACTORY is the address of the previously deployed SimpleAccountFactory

  • NEXT_PUBLIC_NODE_URL is the link to the VeChain network to use.

  • NEXT_PUBLIC_DELEGATOR_URL is a fee delegation service, that will pay the VTHO gas fees. Visit vechain.energy to create one or build one yourself.

Install VeChain Dependencies

Install the VeChain SDK to simplify interaction with the VeChain network:

useVeChainAccount.tsx

A prepared hook will provide connectivity to the Account Abtractions deployment.

Copy useVeChainAccount.tsx into the components/lib folder.

Background: How the Hook Works

The hook internally performs the following steps:

  1. Generates a random wallet for blockchain interaction, providing an entry point into the network from which transactions can be accepted.

  2. Requests the user to sign a typed message with the Privy embedded wallet.

  3. If the SimpleAccount does not exist yet, it injects a clause to deploy a new SimpleAccount first.

  4. Builds a transaction to interact with the Account Abstraction Wallet.

  5. Requests the Gas Fee Payment from a Fee Delegator to avoid funding the random wallet with VTHO.

  6. Sends the transaction to the VeChain Network.

  7. Returns the transaction ID.

The visualized process is:

Add VeChainAccountProvider

Add the VeChainAccountProvider into the pages/_app.tsx to wrap the application components.

VeChainAccountProvider is a React Context provider that does the following:

  1. Creates a new ThorClient to connect to the VeChain Network.

  2. Identifies the address of the embedded Privy wallet.

  3. Loads the SimpleAccount address from the SimpleAccountFactory identified by the user's embedded Privy address.

  4. Exports the address, a function to send transactions, and some generic network/connectivity information.

The file after modification looks like this:

Use useVeChainAccount

Import the useVeChainAccount hook into pages/embedded-wallet.tsx and call it within the component:

Display Address

The address exported from the useVeChainAccount hook is the address from which future transactions will originate.

Add the following snippet to display the account address in the embedded-wallet.tsx:

Configure Test Call

To test an interaction, replace the existing test transfer with a call to vechain.sendTransaction.

Replace the onTransfer function in embedded-wallet.tsx with the following code:

Test the PWA

Open two terminals to run the application and create a public https endpoint:

  • Run npm run dev to start the PWA application.

  • Run ngrok http 3004 to start an ngrok proxy and get a public secure address.

Switch to your browser:

  • Open the forwarding address shown by ngrok.

  • Log in with your social account.

  • Switch to the Embedded Wallet menu.

Fund VeChain Wallet

Visit faucet.vecha.in to claim VET on the TestNet and send 1 VET to the VeChain address shown in your PWA.

Test Transactions

In your PWA, enter a valid address for the transfer and test the Transfer function. A dialog will open and request to sign a transaction. Once signed, the SimpleAccount will transfer 0.004 VET to the entered address.

Interact with Smart Contracts

To interact with other smart contracts, sendTransaction accepts to, data, and value parameters like other similar functions.

Either pass in the data for the smart contract call encoded or pass the data as an object, which will then be used to call encodeFunctionData within the useVeChainAccount hook.

For example:

Hide Transaction Signing

Signing messages or transactions can be complex and a hurdle for regular users. To reduce friction, you can disable the signing dialog in the Privy Dashboard under Embedded Wallets > Add confirmation modals.

Disabling this option allows the application to instantly interact with the blockchain, improving the user experience. Pending transactions can be managed with loading animations.

Conclusion

In this article, we've created a way of adding VeChain support within the Privy demo project by creating an Account Abstraction Factory that serves as the interaction source.

By using Fee Delegation, the gas fees are covered for the user, eliminating the need to ask the user to fund it with VTHO first.

An example application for further exploration of Account Abstractions and a Privy PWA is available on GitHub at docs-pwa-privy-account-abstraction-my-pwa-project.

You can use the information to either build on top of the example project and hook or derive your own process.

Last updated

Was this helpful?