@ton/appkit-react
React components and hooks for AppKit.
Overview
Installation
npm install @ton/appkit-react @tanstack/react-query @tonconnect/ui-react @ton/core @ton/crypto
Dependencies
@ton/appkit-react requires the following peer dependencies:
react (>= 18.0.0)
react-dom (>= 18.0.0)
@tanstack/react-query (>= 5.0.0)
@tonconnect/ui-react (>= 2.4.1)
Initialization
Initialize QueryClient and AppKit, then wrap your application in QueryClientProvider and AppKitProvider.
[!NOTE]
Don't forget to import styles from @ton/appkit-react/styles.css.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { AppKit, Network, createTonConnectConnector } from '@ton/appkit';
import { AppKitProvider } from '@ton/appkit-react';
import type { FC } from 'react';
import '@ton/appkit-react/styles.css';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
},
},
});
const appKit = new AppKit({
networks: {
[Network.mainnet().chainId]: {
apiClient: {
url: 'https://toncenter.com',
key: 'your-key',
},
},
},
connectors: [
createTonConnectConnector({
tonConnectOptions: {
manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',
},
}),
],
});
export const App: FC = () => {
return (
<QueryClientProvider client={queryClient}>
<AppKitProvider appKit={appKit}>{/* <AppContent /> */}</AppKitProvider>
</QueryClientProvider>
);
};
Read more about TanStack Query
TonConnect Configuration
When using TonConnectConnector, you can pass tonConnectOptions which accepts standard TonConnectUI options, including manifestUrl, uiOptions, etc.
Basic Usage
Connect Wallet
Use TonConnectButton to allow users to connect their wallets. It handles the connection flow and UI.
import { TonConnectButton } from '@ton/appkit-react';
export const Header = () => {
return (
<header>
<TonConnectButton />
</header>
);
};
Get Wallet Address
Use useAddress to get the currently connected wallet address.
import { useAddress } from '@ton/appkit-react';
export const AddressBlock = () => {
const address = useAddress();
if (!address) {
return <div>Wallet not connected</div>;
}
return <div>Address: {address}</div>;
};
Get Balance
Use useBalance to fetch the TON balance of the connected wallet.
import { useBalance } from '@ton/appkit-react';
export const Balance = () => {
const { data: balance, isLoading } = useBalance();
if (isLoading) {
return <div>Loading...</div>;
}
return <div>Balance: {balance?.toString()} TON</div>;
};
See Hooks Documentation for all available hooks and Components Documentation for UI components.
Send Transaction
Use the Send component to trigger a transaction from a button. It handles the entire send flow.
return (
<Send
request={{
messages: [
{
address: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c', // Recipient address
amount: '100000000', // 0.1 TON in nanotons (raw format)
payload: beginCell()
.storeUint(0, 32)
.storeStringTail('Hello')
.endCell()
.toBoc()
.toString('base64') as Base64String,
},
],
}}
text="Send Transaction"
onSuccess={(result: SendTransactionReturnType) => {
console.log('Transaction sent:', result);
}}
onError={(error: Error) => {
console.error('Transaction failed:', error);
}}
/>
);
For a custom UI, use SendProvider with useSendContext — see Components Documentation.
Swap
AppKit uses a provider-based architecture for swaps. Any DEX or protocol can implement a swap provider by extending the SwapProvider class — AppKit handles routing, hooks, and transaction building through a unified interface.
OmnistonSwapProvider is an available provider. You can use it, replace it, or run multiple providers side by side. To implement your own, see Creating a Swap Provider.
Installation
npm install @ston-fi/omniston-sdk
Setup
Initialize AppKit with OmnistonSwapProvider:
const appKit = new AppKit({
networks: {
[Network.mainnet().chainId]: {
apiClient: {
url: 'https://toncenter.com',
key: 'your-key',
},
},
},
providers: [
createOmnistonProvider({
apiUrl: 'https://api.ston.fi',
defaultSlippageBps: 100,
}),
createDeDustProvider({
defaultSlippageBps: 100,
referralAddress: 'EQ...',
}),
],
});
Hooks
Use useSwapQuote to get a quote and useBuildSwapTransaction to build the transaction.
See Swap Hooks for usage examples.
Staking
AppKit supports staking through various providers (e.g., Tonstakers). The staking functionality is integrated into the core action and hook system.
Hooks
Use useStakingQuote to get a staking/unstaking quote and useBuildStakeTransaction to build the transaction.
Read more about Staking
const {
data: quote,
isLoading,
error,
} = useStakingQuote({
amount: '10',
direction: 'stake',
});
if (isLoading) return <div>Loading quote...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>Expected Output: {quote?.amountOut}</div>;
const { data: quote } = useStakingQuote({
amount: '10',
direction: 'stake',
});
const { mutateAsync: buildTx, isPending: isBuilding } = useBuildStakeTransaction();
const { mutateAsync: sendTx, isPending: isSending } = useSendTransaction();
const handleStake = async () => {
if (!quote) return;
try {
const transaction = await buildTx({
quote,
userAddress: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
});
await sendTx(transaction);
} catch (e) {
console.error(e);
}
};
const isPending = isBuilding || isSending;
return (
<div>
<button onClick={handleStake} disabled={!quote || isPending}>
{isPending ? 'Processing...' : 'Stake'}
</button>
</div>
);
Migration from TonConnect UI
AppKitProvider automatically bridges TonConnect if a TonConnectConnector is configured, so @tonconnect/ui-react hooks (like useTonAddress, useTonWallet, etc.) work out of the box inside AppKitProvider.
You can use standard TonConnect hooks in your components:
import { useTonAddress } from '@tonconnect/ui-react';
export const AppContent: FC = () => {
const address = useTonAddress();
return <p>Address: {address}</p>;
};
License
MIT