Skip to main content

Dynamic Gasless Starter

Want to see smart wallets in action? Check out our Dynamic Gasless Starter - a Next.js demo that showcases gasless transactions with email-based wallet creation and token minting, all without users paying gas fees.

Quickstart

Prerequisites

  • Create a Zerodev account and projects for each network you want to support, as well as a gas policy for each one. Make sure you use the V1 dashboard to configure your project.
  • Visit the Sponsor Gas section of the dashboard, toggle on Zerodev and add your project IDs.

Configure Your SDK

The @dynamic-labs/zerodev-extension depends on the Viem Extension, so before going through this setup, make sure to have the Viem Extension set up and working. Viem Extension Setup

Setup

Install ZeroDevExtension

Install the @dynamic-labs/zerodev-extension package:
Shell
npx expo install @dynamic-labs/zerodev-extension
When running the ZeroDevExtension in your React Native application, you might encounter an error where Metro cannot resolve the paymasterClient.js file. This issue occurs because Metro tries to load paymasterClient.js, but the actual file is named paymasterClient.ts.To fix this, you need to customize Metro’s resolver in your metro.config.js file to handle TypeScript file extensions properly.

Generate metro.config.js for Expo Projects

If you don’t have a metro.config.js file in your project, you can generate one using the following command:
Shell
npx expo customize metro.config.js

Customize Metro Resolver

Add the following code to your metro.config.js file to instruct Metro to resolve .ts files when it cannot find the corresponding .js files:
metro.config.js
const { getDefaultConfig } = require('expo/metro-config')

const config = getDefaultConfig(__dirname)

/**
* Custom resolver to handle ZeroDev imports
*/
config.resolver.resolveRequest = (context, moduleName, platform) => {
    try {
        return context.resolveRequest(context, moduleName, platform)
    } catch (error) {
        if (moduleName.endsWith('.js')) {
            const tsModuleName = moduleName.replace(/\.js$/, '.ts')
            return context.resolveRequest(context, tsModuleName, platform)
        }
        throw error
    }
}

module.exports = config
This modification allows Metro to attempt to resolve .ts files when it fails to find .js files, which fixes the resolution error for the paymasterClient file.

Events Polyfill

ZeroDevExtension requires a polyfill for the Node.js events module. You can install the events polyfill using one of the following commands:
Shell
npx expo install events
Extend the client with the extension, get the kernel client, and then use it to send sponsored transactions. Here is an example:
import { createClient } from '@dynamic-labs/client'
import { ReactNativeExtension } from '@dynamic-labs/react-native-extension'
import { ViemExtension } from '@dynamic-labs/viem-extension'
import { ZeroDevExtension } from '@dynamic-labs/zerodev-extension'
import 'fast-text-encoding'

const environmentId = process.env.EXPO_PUBLIC_ENVIRONMENT_ID as string

if (!environmentId) {
    throw new Error('EXPO_PUBLIC_ENVIRONMENT_ID is required')
}

export const client = createClient({
    environmentId,
    appLogoUrl: 'https://demo.dynamic.xyz/favicon-32x32.png',
    appName: 'React Native Stablecoin App',
})
.extend(ReactNativeExtension())
.extend(ViemExtension())
.extend(ZeroDevExtension())
You can also use the ZerodevBundlerProvider.Alchemy or ZerodevBundlerProvider.Gelato provider to use the Alchemy or Gelato bundler services.You can either use PaymasterTypeEnum.SPONSOR to sponsor all transactions or PaymasterTypeEnum.NONE to send a non-sponsored transaction.

Advanced Usage

You can find more advanced usage examples in our advanced usage guide.
Using server wallets? See Sponsor Gas for Server Wallets (EVM).

Note on 7702

EIP-7702 is the default for enabling gas sponsorship using Dynamic & Zerodev, but you can switch back to 4337 if you want using the dashboard settings.

Why use 7702?

EIP-7702 introduces a new transaction type that allows a wallet to delegate execution to an address with a deployed smart account. This means:
  • No need to switch or manage multiple accounts and wallets.
  • Users retain their existing EOA and gain smart account functionality.
  • The transition is smooth and invisible to the end user.

Common questions

  • Do all chains/networks support 7702? No, not all chains/networks support 7702. You can see a list of chains/networks that support 7702 here.
  • When does the delegation (authorization) signing happen? The delegation authorization is signed automatically behind the scenes on the first transaction. If a paymaster is used, the paymaster will pay for the transaction.
  • How long does the delegation remain active? The delegation stays active until the user delegates to a new address.
  • How does this work for existing EOAs (e.g. MetaMask)? At the moment, delegation is a feature exclusive to embedded wallets. That’s because we need to sign the authorization in a very specific way that requires access to the private key. From what we’ve heard, external wallets like MetaMask are unlikely to expose the signAuthorization method, making it unclear how (or if) this flow will work with them.

Resources

Using Other Providers

Dynamic supports a large number of providers and we have guides for each one: