Introduction
A Radix dApp consists of two layers: on-ledger blueprints deployed as Scrypto packages, and an off-ledger frontend that connects to the user's Radix Wallet to sign and submit transactions. The Radix dApp Toolkit (RDT) is the official TypeScript library that handles wallet connection, session management, data requests, and transaction submission. This guide covers integrating RDT into a web application.
Project Setup
The fastest way to start is the official scaffolding tool:
npx create-radix-app@latestThis generates a project with RDT pre-configured, the Connect Button wired up, and example transaction code. Alternatively, add RDT to an existing project:
npm install @radixdlt/radix-dapp-toolkitInitialising the Toolkit
Create an RDT instance with your dApp's configuration:
import { RadixDappToolkit, RadixNetwork } from '@radixdlt/radix-dapp-toolkit'
const rdt = RadixDappToolkit({
dAppDefinitionAddress: 'account_rdx...', // your dApp definition account
networkId: RadixNetwork.Stokenet, // or RadixNetwork.Mainnet
applicationName: 'My dApp',
applicationVersion: '1.0.0',
})The dAppDefinitionAddress is a Radix account that you own, registered as your dApp's identity through the Developer Console metadata settings. This is how the wallet identifies your application to the user.
Wallet Connection & Authentication
RDT provides the ā Connect Button, a framework-agnostic web component that handles the full wallet connection flow:
<!-- Add to your HTML -->
<radix-connect-button />When a user clicks the button, RDT coordinates with the Radix Wallet Connector browser extension to establish a connection to the user's mobile wallet. The user authenticates using a Persona ā a reusable identity that can share selected accounts and personal data with your dApp.
Requesting Account Data
Configure what data your dApp needs at connection time:
import { DataRequestBuilder } from '@radixdlt/radix-dapp-toolkit'
rdt.walletApi.setRequestData(
DataRequestBuilder.accounts().atLeast(1),
DataRequestBuilder.persona().withProof(),
)This asks the user to share at least one account address and a cryptographic proof of Persona ownership. For ROLA (Radix Off-Ledger Authentication), provide a challenge generator that fetches a 32-byte hex challenge from your backend:
rdt.walletApi.provideChallengeGenerator(async () => {
const res = await fetch('/api/auth/challenge')
return (await res.json()).challenge
})Submitting Transactions
Radix transactions are built using transaction manifests ā a declarative syntax that describes what the transaction should do. Your dApp sends a manifest stub to the wallet; the wallet completes it by adding fee payment and any user-specified assertions.
const result = await rdt.walletApi.sendTransaction({
transactionManifest: `
CALL_METHOD
Address("component_rdx...")
"buy_token"
Decimal("100")
;
CALL_METHOD
Address("${accountAddress}")
"deposit_batch"
Expression("ENTIRE_WORKTOP")
;
`,
})The user reviews the transaction in their wallet ā seeing exactly which assets move where ā signs it, and the wallet submits it to the network. Your dApp receives a transaction hash that you can track via the Gateway API.
Reacting to Wallet Data
Subscribe to wallet state changes to update your UI in real time:
rdt.walletApi.walletData$.subscribe((walletData) => {
const accounts = walletData.accounts
// Update UI with connected accounts
})