Kontoabstraktion är konceptet som gör det möjligt för oss att förbättra användarupplevelsen på Web3 när vi interagerar med decentraliserade applikationer (dApps). Vi definierar det som möjligheten att lägga till godtycklig logik i processen att validera en transaktion. Kontoabstraktion i blockkedjesystem gör det möjligt att inneha tillgångar av smarta konton (smarta kontraktsplånböcker), snarare än att hanteras av externt ägda konton (EOAs). ERC-4337-standarden är den tokenstandard för kontoabstraktioner som gör det möjligt för konton på Ethereum att bete sig mer som smarta kontrakt.
EOA:er har begränsade funktioner eftersom regler för användning av EOA-plånböcker är hårdkodade i protokollet och inte kan ändras. Smarta konton, å andra sidan, är lättprogrammerbara, vilket gör det möjligt för utvecklare att lägga till godtycklig logik för att tillhandahålla nya funktioner.
Den största utmaningen med den nuvarande webb3-användarupplevelsen är de många friktionspunkter som användare stöter på innan de faktiskt kan använda vår decentraliserade applikation (dApp). De måste:

Tänk nu på komplexiteten i dessa steg om vi var tvungna att utföra dem för varje dApp vi använder dagligen.
Account Abstraction (AA) medför två viktiga framsteg: Smart Accounts och UserOps. Vi kommer att förklara ERC-4337-transaktionsflödet med hjälp av smarta konton, med fokus på fyra viktiga komponenter: Användaroperationer, Mempool för användaroperationer, Bundler-tjänst och Paymaster-tjänst.

När en användare interagerar med blockkedjan via sitt smarta konto, inkapslas deras avsedda handlingar i UserOps. En UserOp är inte en traditionell blockkedjetransaktion, utan fungerar snarare som en anpassningsbar transaktion. Följaktligen är det möjligt att programmatiskt ställa in anpassade regler och villkor för dessa transaktioner.
Till skillnad från traditionella transaktioner som går in i den publika mempoolen, dirigeras UserOperations till den alternativa mempoolen – en specialiserad mempool på högre nivå som är specifikt utformad för att hantera UserOps.
Bundler-tjänsten lyssnar på UserOperation mempoolen, bundlar flera UserOps och skickar dem till Entry Point Contract som så småningom hjälper till att hantera UserOps och skapa en enda transaktion att skicka in på blockkedjan.
Paymaster-tjänsten möjliggör gasuttag, vilket gör det möjligt för en tredje part (dApp eller plånbok) att betala gasavgifterna för användarens räkning. Dessutom ger den användare möjlighet att betala gasavgifter med ERC-20-tokens.
Baserat på den information som tillhandahållits är det tydligt hur Account Abstraction förbättrar användarupplevelsen på Web3 och hanterar de utmaningar som nya användare står inför. Förbättrad UX möjliggjord av AA omfattar:
Account Abstraction är den revolutionerande bryggan som för den sömlösa användarupplevelsen hos Web2 till den blockchain-drivna världen hos Web3.
För att förenkla användningen av smarta konton och bygga dApps har utvecklare tillgång till olika verktyg som integrerar AA i sina projekt. AA API:er och programvaruutvecklingspaket (SDK:er) överbryggar klyftan mellan de komplexiteter som utvecklare stöter på när de implementerar AA-koncept och den smidiga, intuitiva användarupplevelse som förväntas av vanliga användare. De flesta av dessa SDK:er är utformade för att vara "plug & play" – vilket gör att utvecklare snabbt och enkelt kan integrera avancerade AA-funktioner i sina dApps med minimal ansträngning. Av de många tillgängliga SDK:erna är här tre som gör ett bra jobb med att integrera AA i våra projekt:



Låt oss integrera Biconomys SDK i vårt NextJS-projekt för att visa upp hur man skickar gaslösa transaktioner med deras Paymaster-tjänst.
Starta projektets skapande och välj följande alternativ:yarn create next-app
✔ What is your project named? … biconomy-gasless-transactions-demo ✔ Would you like to use TypeScript? … Yes ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like to use `src/` directory? … No ✔ Would you like to use App Router? (recommended) … Yes ✔ Would you like to customize the default import alias (@/*)? … NoVi ansluter till en plånbok med hjälp av RegnbågssatsInstallera RainbowKit och dess peer-beroenden, wagmi, viem, och @tanstack/react-query:yarn add @rainbow-me/rainbowkit wagmi viem@2.x @tanstack/react-query
Välj dina önskade kedjor och konfigurera en wagmi-konfiguration:
import { getDefaultConfig } from "@rainbow-me/rainbowkit";
import { sepolia } from "wagmi/chains";
export const config = getDefaultConfig({
appName: "biconomy-gasless-transactions-demo",
projectId: process.env.NEXT_PUBLIC_PROJECT_ID ?? "",
chains: [sepolia],
ssr: true,
});
Du kan få ditt projekt-ID från WalletConnect genom att logga in och skapa ett nytt projekt.


Nu ska vi skapa en Providers-komponent som vi ska använda i vår layout.js för att koppla in vår applikation med RainbowKitProvider, WagmiProvider, QueryClientProvider och, senare, BiconomyProvider.
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
import { config } from "app/wagmiConfig";
import "@rainbow-me/rainbowkit/styles.css";
const queryClient = new QueryClient();
export const Providers = ({ children }: { children: React.ReactNode }) => {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider theme={darkTheme()}>{children}</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
};Genom att använda ConnectButton-komponenten förlitar vi oss på RaibowKit för att hantera våra användares plånboksval, visa plånboksinformation och hantera nätverksväxling.
import { ConnectButton } from "@rainbow-me/rainbowkit";
const Home = () => {
return <ConnectButton />;
};
export default Home;Nu ska vi integrera Biconomy i vårt projekt. Nyligen släppte de sitt useAA-paket, specifikt utformat för React-projekt. Detta paket förenklar implementeringen genom att tillhandahålla hooks för transaktionssponsring, sessionshantering och mycket mer. Vi behöver också installera det centrala SDK-paketet, som används internt av useAA för att utföra AA-operationer.yarn add @biconomy/konto @biconomy/use-aa
Låt oss lägga till BiconomyProvider-komponenten i vår Providers.tsx-fil så att vi kan använda useAA-hooks.
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { BiconomyProvider } from "@biconomy/use-aa";
import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
import { config } from "app/wagmiConfig";
import { BUNDELER_URL } from "./constants";
import "@rainbow-me/rainbowkit/styles.css";
const queryClient = new QueryClient();
export const Providers = ({ children }: { children: React.ReactNode }) => {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider theme={darkTheme()}>
<BiconomyProvider
config={{
biconomyPaymasterApiKey:
process.env.NEXT_PUBLIC_BICONOMY_PAYMASTER_API_KEY ?? "",
bundlerUrl: BUNDELER_URL,
}}
queryClient={queryClient}
>
{children}
</BiconomyProvider>
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
};Vi kan hämta information om betalningsansvarig och paketleverantör från Biconomys instrumentpanel . Logga in med e-post, Github eller Gitlab och hämta din bundlerUrl .

För att hämta biconomyPaymasterApiKey måste du registrera en ny Paymaster hos valt nätverk, vilket i vårt fall är Sepolias testnätverk. Då kommer du att kunna se din Paymaster-URL och API-nyckeln.

Det är möjligt att betala bensinavgifter med ERC-20-tokens direkt. För att skapa ett bensinsponsorskap måste vi ansluta en plånbok och konfigurera en bensintank, där vi sätter in pengar som kommer att användas för att betala våra användares bensinavgifter.

Låt bygga en TransactionForm-komponent som ansvarar för att skicka våra användares transaktioner.
"use client";
import { useAccount } from "wagmi";
import { useSendTransaction, useSmartAccount } from "@biconomy/use-aa";
import { PaymasterMode } from "@biconomy/account";
import { Address, parseEther } from "viem";
import Input from "app/components/Input";
import Button from "app/components/Button";
const TransactionForm = ({ isGasless }: { isGasless: boolean }) => {
const { address } = useAccount();
const { mutate, isPending } = useSendTransaction();
const smartAccount = useSmartAccount();
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const formData = new FormData(event.target as HTMLFormElement);
const to = formData.get("address") as Address;
const value = formData.get("value") as string;
const etherValue = parseEther(value);
mutate({
transactions: {
to,
value: etherValue,
},
...(isGasless && {
options: { paymasterServiceData: { mode: PaymasterMode.SPONSORED } },
}),
});
};
return (
<div className="flex flex-col items-center justify-evenly">
<form
onSubmit={handleSubmit}
className="flex flex-col items-end gap-4 justify-center"
>
<Input
label="Smart Account Address"
name="smartAddress"
placeholder="Please connect wallet"
disabled
value={smartAccount.smartAccountAddress}
/>
<Input
label="Address"
name="address"
placeholder="0xA0Cf…251e"
required
disabled={!address}
/>
<Input
label="Value"
name="value"
placeholder="0.05"
required
disabled={!address}
/>
{address ? (
<Button isActive type="submit" className="mt-2" disabled={isPending}>
{isPending ? "Waiting..." : "Send"}
</Button>
) : (
<Button className="mt-2" disabled={true}>
Connect Wallet
</Button>
)}
</form>
</div>
);
};
export default TransactionForm;För närvarande kan vi inte visa den slutliga transaktionshashen för att kontrollera transaktionsinformationen på Etherscan . För att lägga till den här funktionen använder vi useUserOpWait- hooken, som returnerar UserOp-kvittot som innehåller transaktionshashen.
"use client";
import { useAccount } from "wagmi";
import {
useSendTransaction,
useSmartAccount,
useUserOpWait,
} from "@biconomy/use-aa";
import { PaymasterMode } from "@biconomy/account";
import { Address, parseEther } from "viem";
import Link from "next/link";
import Input from "app/components/Input";
import Button from "app/components/Button";
import { formatHash } from "app/helpers";
const TransactionForm = ({ isGasless }: { isGasless: boolean }) => {
const { address, chain } = useAccount();
const {
mutate,
isPending,
data: userOpResponse,
error: errorSendTransaction,
} = useSendTransaction();
const smartAccount = useSmartAccount();
const {
isLoading: waitIsPending,
error: waitError,
data: waitData,
} = useUserOpWait(userOpResponse);
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const formData = new FormData(event.target as HTMLFormElement);
const to = formData.get("address") as Address;
const value = formData.get("value") as string;
const etherValue = parseEther(value);
mutate({
transactions: {
to,
value: etherValue,
},
...(isGasless && {
options: { paymasterServiceData: { mode: PaymasterMode.SPONSORED } },
}),
});
};
return (
<div className="flex flex-col items-center justify-evenly">
<form
onSubmit={handleSubmit}
className="flex flex-col items-end gap-4 justify-center"
>
<Input
label="Smart Account Address"
name="smartAddress"
placeholder="Please connect wallet"
disabled
value={smartAccount.smartAccountAddress}
/>
<Input
label="Address"
name="address"
placeholder="0xA0Cf…251e"
required
disabled={!address}
/>
<Input
label="Value"
name="value"
placeholder="0.05"
required
disabled={!address}
/>
{address ? (
<Button
isActive
type="submit"
className="mt-2"
disabled={isPending || waitIsPending}
>
{isPending || waitIsPending ? "Waiting..." : "Send"}
</Button>
) : (
<Button className="mt-2" disabled={true}>
Connect Wallet
</Button>
)}
</form>
<div className="w-80 min-h-40">
{waitData?.receipt?.transactionHash && (
<div className="flex justify-between">
Transaction Hash:
<Link
href={`${chain?.blockExplorers?.default?.url}/tx/${waitData.receipt.transactionHash}`}
rel="noopener noreferrer"
target="_blank"
className="text-indigo-500"
>
{formatHash(waitData.receipt.transactionHash)}
</Link>
</div>
)}
<div className="flex flex-col gap-2">
{isPending && <div>Waiting for confirmation...</div>}
{waitIsPending && (
<div>Transaction confirmed, waiting to process...</div>
)}
{errorSendTransaction && (
<div className="text-rose-500">{`Error message: ${errorSendTransaction}`}</div>
)}
{waitError && (
<div className="text-rose-500">{`Error message: ${waitError}`}</div>
)}
</div>
</div>
</div>
);
};
export default TransactionForm;

Och där har du det – du har framgångsrikt börjat dra av bensinavgifter från dina användare! Genom att hantera dessa avgifter åt användarna blir din dApp mer tillgänglig och användarvänlig, vilket sannolikt kommer att öka användarengagemang och trafik.
Visa hela kodlösningen: github/web3-transaction-manager
Besök webbappen: vercel/web3-transaction-manager – Observera att för närvarande endast Polygon Amoy-nätverket stöds av den distribuerade appen.