This guide is currently React only.
Setup Instructions
Create Dynamic Environment
- Visit the Dynamic Dashboard
- Create a new app or select an existing one
- Enable the
Embedded Wallets feature
- Copy your Environment ID from the dashboard
Get Gelato API Key
- Visit the Gelato App
- Navigate to
Paymaster & Bundler > API Keys
- Create a new API Key and select your required networks
- Copy the generated API Key
Create App with create-dynamic-app
Use the CLI to scaffold a Next.js app pre-configured with Dynamic, Wagmi and viem (non-interactive via flags):npx create-dynamic-app@latest gelato-smart-wallet --framework nextjs --library viem --wagmi true --chains ethereum --pm npm
Install Gelato Smart Wallet SDK
Install the Gelato Smart Wallet SDK in the generated project:cd gelato-smart-wallet && npm install @gelatonetwork/smartwallet
Set Environment Variables
In the scaffolded project, create a .env.local file in the project root:NEXT_PUBLIC_DYNAMIC_APP_ID=your_dynamic_environment_id
NEXT_PUBLIC_GELATO_API_KEY=your_gelato_api_key
Implementation
Configure providers (lib/providers.tsx)
In the scaffolded app, update your providers to include Dynamic, Wagmi, and React Query. If your project already has a lib/providers.tsx, edit it; otherwise create it and use it in your root layout.// lib/providers.tsx
import React from "react";
import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";
import { EthereumWalletConnectors, isEthereumWallet } from "@dynamic-labs/ethereum";
import { DynamicWagmiConnector } from "@dynamic-labs/wagmi-connector";
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
import { WagmiProvider, createConfig, http } from "wagmi";
import { baseSepolia } from "viem/chains";
const queryClient = new QueryClient();
export default function Providers({ children }: { children: React.ReactNode }) {
return (
<DynamicContextProvider
settings={{
environmentId: process.env.NEXT_PUBLIC_DYNAMIC_APP_ID!,
walletConnectors: [EthereumWalletConnectors],
}}
>
<WagmiProvider
config={createConfig({
chains: [baseSepolia],
transports: {
[baseSepolia.id]: http(),
},
})}
>
<QueryClientProvider client={queryClient}>
<DynamicWagmiConnector>{children}</DynamicWagmiConnector>
</QueryClientProvider>
</WagmiProvider>
</DynamicContextProvider>
);
}
Create Smart Wallet Client (components/SendTransactionButton.tsx)
// components/SendTransactionButton.tsx
import React from "react";
import { useDynamicContext } from "@dynamic-labs/sdk-react-core";
import { isEthereumWallet } from "@dynamic-labs/ethereum";
import { isDynamicWaasConnector } from "@dynamic-labs/wallet-connector-core";
import {
createGelatoSmartWalletClient,
} from "@gelatonetwork/smartwallet";
import {
prepareAuthorization,
SignAuthorizationReturnType,
} from "viem/actions";
export function SendTransactionButton() {
const { primaryWallet } = useDynamicContext();
const sendTransaction = async () => {
if (!primaryWallet || !isEthereumWallet(primaryWallet)) return;
const connector = primaryWallet.connector;
if (!connector || !isDynamicWaasConnector(connector)) return;
const client = await primaryWallet.getWalletClient();
client.account.signAuthorization = async (parameters) => {
const preparedAuthorization = await prepareAuthorization(client, parameters);
const signedAuthorization = await connector.signAuthorization(preparedAuthorization);
return {
address: preparedAuthorization.address,
chainId: preparedAuthorization.chainId,
nonce: preparedAuthorization.nonce,
r: signedAuthorization.r,
s: signedAuthorization.s,
v: signedAuthorization.v,
yParity: signedAuthorization.yParity,
} as SignAuthorizationReturnType;
};
const smartWalletClient = await createGelatoSmartWalletClient(client, {
apiKey: process.env.NEXT_PUBLIC_GELATO_API_KEY,
scw: { type: "gelato" }, // use gelato, kernel, safe, or custom
});
// Example: call execute later (see next step)
console.log("Gelato Smart Wallet client ready", smartWalletClient);
};
return <button onClick={sendTransaction}>Send Transaction</button>;
}
Use the button (e.g., app/page.tsx)
// app/page.tsx
import { SendTransactionButton } from "@/components/SendTransactionButton";
export default function Page() {
return (
<main>
<SendTransactionButton />
</main>
);
}
Execute Transactions
Execute transactions using different payment methods:
Additional Resources