BlockchainAppMaker

Blockchain

Polkadot dApp Development: From Contract to Front End

A Polkadot dApp is a front end plus logic that lives somewhere in the Polkadot network: a smart contract on Polkadot Hub, a contract on a parachain such as Moonbeam or Astar, or a pallet in a runtime you control. The first decision is where that logic runs; the rest of the stack (client library, wallet connection, indexing) follows from it.

Step one: decide where your logic lives

OptionLanguage and toolingGood forTrade-off
Smart contracts on Polkadot HubSolidity via the Revive toolchain and Ethereum-style RPC; ink! (Rust) also targets the same contracts palletApps that want Polkadot's native assets and users without running a chainNewer environment; verify tooling maturity and limits for your use case
EVM parachain (e.g. Moonbeam)Standard Solidity with Hardhat or Foundry, MetaMaskPorting an existing Ethereum dApp with minimal changesUsers need the parachain's gas token; less native to the Polkadot account model
Wasm or multi-VM parachain (e.g. Astar)ink! or Solidity depending on the chainTeams already in that parachain's ecosystemTied to one parachain's roadmap and liquidity
Your own runtime palletRust with FRAME in the Polkadot SDKProducts that need custom fees, governance or performanceYou run a chain and buy coretime; covered in the wider Polkadot development guide

For most new dApps, deploying contracts rather than launching a chain is the sensible default. Only build a pallet when a contract genuinely cannot express what you need or when the economics of your own chain make sense.

The front end: talking to Substrate-based chains

If your logic is an EVM contract, your front end looks like any Ethereum dApp: viem or ethers, and an EVM wallet. If it touches native Polkadot functionality (balances on Polkadot Hub, staking, governance, XCM, or your own pallet), you need a Substrate client.

The long-standing library is @polkadot/api (polkadot.js). Newer projects increasingly use polkadot-api (PAPI), which generates TypeScript types from chain metadata, is designed around a light client, and keeps bundles smaller; Dedot is another modern alternative. Whatever you choose, a few Polkadot specifics shape the code:

  • Metadata-driven types. Calls and storage are described by runtime metadata. When a chain upgrades, types can change. Generating descriptors and testing against upcoming runtimes prevents surprise breakage.
  • Light clients. smoldot can run in the browser and verify chain data without trusting an RPC provider, at the cost of a short sync on first load.
  • Multiple chains. A user's DOT, stablecoins and identity may sit on different system chains. Your app may need connections to several at once.
  • Planck units. DOT uses 10 decimals; never hardcode 18.

Connecting wallets

Polkadot browser wallets (Polkadot.js extension, Talisman, SubWallet) inject accounts into the page through a shared extension interface; mobile wallets like Nova support WalletConnect and in-app browsers. Your connect flow should list available extensions, let the user pick accounts, and pass a signer to your client library. Display SS58 addresses with the correct network prefix. If your dApp mixes EVM contracts with native Substrate calls, decide early whether users will have one account type or two, because that decision ripples through the whole UX. For the wallet side of the stack, see Polkadot wallet development.

Cross-chain features with XCM

XCM (Cross-Consensus Messaging) lets your dApp move assets between parachains or trigger actions on another chain. In practice dApps use it for deposits ("bring USDT from Polkadot Hub to our chain"), withdrawals, and occasionally remote execution. Fee estimation on the destination chain and handling failed messages are the hard parts; test with tools that replay XCM on forked networks before shipping.

Indexing and data

Chain storage is not designed for queries such as "all trades by this user". Most Polkadot dApps add an indexer: SubQuery and Subsquid are the established options, both able to index events from Substrate pallets and EVM contracts. Plan for the indexer as a production service with its own monitoring, not an afterthought.

A realistic build sequence

  1. Pick the execution environment and confirm the token standards, wallets and liquidity you need exist there.
  2. Write and test contracts (Foundry or Hardhat for Solidity; the ink! tooling for Rust) on a local node or public testnet.
  3. Build the front end with PAPI or an EVM library, plus wallet connection and network switching.
  4. Add an indexer and any backend services such as notifications.
  5. Audit the contracts, then launch with conservative limits.

A focused dApp (a few contracts, one front end, an indexer) is commonly a two-to-four person team for three to five months, plus an external audit. Cross-chain features and a custom pallet each add months. For general dApp architecture beyond Polkadot, see dApp development, and for token sales in the ecosystem, IDO launchpads on Polkadot.

Frequently asked questions

Can I deploy my existing Solidity contracts on Polkadot?

Yes, either on an EVM parachain like Moonbeam with no changes, or on Polkadot Hub through its Ethereum-compatible contract environment. On Polkadot Hub, test carefully: gas accounting and some low-level behaviors can differ from Ethereum.

Is ink! still relevant?

ink! remains the Rust option for contracts on Polkadot, and recent versions target the same contracts infrastructure as Solidity on Polkadot Hub. Choose it if your team prefers Rust; choose Solidity if you want the larger tooling and auditor pool.

Should I use polkadot.js or PAPI?

For new projects PAPI is usually the better starting point thanks to generated types and light-client support. polkadot.js remains widely used and well documented, so it is a reasonable choice when you depend on existing examples.