TypeScript SDK: Wallet Adapter (React)
Purpose
Guide wallet connection and frontend transaction submission in React using @aptos-labs/wallet-adapter-react . End users sign transactions via their browser wallet (Petra, Nightly, etc.) — never via raw private keys.
ALWAYS
-
Use @aptos-labs/wallet-adapter-react for frontend wallet integration — this is the standard React adapter.
-
Wrap your app root with AptosWalletAdapterProvider — all useWallet() calls require this context.
-
Use useWallet() hook to access wallet functions in React components.
-
Use the wallet adapter's signAndSubmitTransaction (from useWallet() ) in frontend — NOT the SDK's direct aptos.signAndSubmitTransaction .
-
Always call aptos.waitForTransaction({ transactionHash }) after submit — the wallet returns when the tx is accepted, not committed.
NEVER
-
Do not use Account.generate() or raw private keys in browser/frontend — use wallet adapter for end users.
-
Do not use the SDK's aptos.signAndSubmitTransaction in React components — use the wallet adapter's version from useWallet() .
-
Do not hardcode wallet names — use the wallets array from useWallet() for a dynamic list.
Installation
npm install @aptos-labs/wallet-adapter-react
Modern AIP-62 standard wallets (Petra, Nightly, etc.) are autodetected and do NOT require additional packages. Legacy wallets need their plugin package installed separately.
Provider setup
Wrap your app root with AptosWalletAdapterProvider :
// main.tsx or App.tsx import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react"; import { Network } from "@aptos-labs/ts-sdk";
function App() { return ( <AptosWalletAdapterProvider autoConnect={true} dappConfig={{ network: Network.TESTNET }} onError={(error) => console.error("Wallet error:", error)} > <YourApp /> </AptosWalletAdapterProvider> ); }
useWallet() hook
import { useWallet } from "@aptos-labs/wallet-adapter-react";
function MyComponent() { const { account, // Current connected account { address, publicKey } connected, // Boolean: is wallet connected? wallet, // Current wallet info { name, icon, url } wallets, // Array of available wallets connect, // (walletName) => Promise<void> disconnect, // () => Promise<void> signAndSubmitTransaction, // Submit entry function calls (use THIS in frontend) signTransaction, // Sign without submitting submitTransaction, // Submit a signed transaction signMessage, // Sign an arbitrary message signMessageAndVerify, // Sign and verify a message changeNetwork, // Switch networks (not all wallets support this) network // Current network info } = useWallet(); }
Frontend transaction pattern
Use typed payloads with InputTransactionData :
// entry-functions/increment.ts import { InputTransactionData } from "@aptos-labs/wallet-adapter-react"; import { MODULE_ADDRESS } from "../lib/aptos";
export function buildIncrementPayload(): InputTransactionData {
return {
data: {
function: ${MODULE_ADDRESS}::counter::increment,
functionArguments: []
}
};
}
// components/IncrementButton.tsx import { useWallet } from "@aptos-labs/wallet-adapter-react"; import { aptos } from "../lib/aptos"; import { buildIncrementPayload } from "../entry-functions/increment";
function IncrementButton() { const { signAndSubmitTransaction } = useWallet();
const handleClick = async () => { try { const response = await signAndSubmitTransaction(buildIncrementPayload()); await aptos.waitForTransaction({ transactionHash: response.hash }); } catch (error) { console.error("Transaction failed:", error); } };
return <button onClick={handleClick}>Increment</button>; }
Wallet connection UI
import { useWallet } from "@aptos-labs/wallet-adapter-react";
function WalletInfo() { const { account, connected, connect, disconnect, wallet, wallets } = useWallet();
if (!connected) { return ( <div> {wallets.map((w) => ( <button key={w.name} onClick={() => connect(w.name)}> Connect {w.name} </button> ))} </div> ); }
return ( <div> <p>Connected: {account?.address}</p> <p>Wallet: {wallet?.name}</p> <button onClick={disconnect}>Disconnect</button> </div> ); }
Common mistakes
Mistake Correct approach
Missing AptosWalletAdapterProvider wrapper Wrap app root with the provider
Not waiting for transaction after submit Always call aptos.waitForTransaction()
Using SDK aptos.signAndSubmitTransaction in React Use the wallet adapter's signAndSubmitTransaction from useWallet()
Using Account.generate() in frontend Use wallet adapter; generate only in server/scripts
Not handling user rejection Catch and check for rejection-related error messages
Hardcoding wallet names Use wallets array from useWallet() for dynamic list
References
-
Wallet Adapter: https://aptos.dev/build/sdks/wallet-adapter/dapp
-
Pattern: TYPESCRIPT_SDK.md
-
Related: ts-sdk-transactions, ts-sdk-client, use-ts-sdk