Dedot
Introduction
Section titled “Introduction”Dedot is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains.
Key Features
Section titled “Key Features”- Lightweight and tree-shakable: No more bn.js or WebAssembly blobs, optimized for dapps bundle size.
- Fully typed API: Comprehensive TypeScript support for seamless on-chain interaction.
- Multi-version JSON-RPC support: Compatible with both legacy and new JSON-RPC APIs for broad ecosystem interoperability.
- Light client support: Designed to work with light clients such as Smoldot.
- Native TypeScript for scale codec: Implements scale codec parsing directly in TypeScript without relying on custom wrappers.
- Wallet integration: Works out-of-the-box with @polkadot/extension-based wallets.
- Familiar API design: Similar API style to Polkadot.js for easy and fast migration.
Installation
Section titled “Installation”To add Dedot to your project, use the following command:
npm i dedotpnpm add dedotyarn add dedotTo enable auto-completion/IntelliSense for individual chains, install the @dedot/chaintypes package as a development dependency:
npm i -D @dedot/chaintypespnpm add -D @dedot/chaintypesyarn add -D @dedot/chaintypesGet Started
Section titled “Get Started”Initialize a Client Instance
Section titled “Initialize a Client Instance”To connect to and interact with different networks, Dedot provides two client options depending on your needs:
DedotClient: Interacts with chains via the new JSON-RPC APIs.LegacyClient: Interacts with chains via the legacy JSON-RPC APIs.
Use the following snippets to connect to Polkadot using DedotClient:
import { DedotClient, WsProvider } from 'dedot';import type { PolkadotApi } from '@dedot/chaintypes';
// Initialize providers & clientsconst provider = new WsProvider('wss://rpc.polkadot.io');const client = await DedotClient.new<PolkadotApi>(provider);import { DedotClient, SmoldotProvider } from 'dedot';import type { PolkadotApi } from '@dedot/chaintypes';import * as smoldot from 'smoldot';
// import `polkadot` chain spec to connect to Polkadotimport { polkadot } from '@substrate/connect-known-chains';
// Start smoldot instance & initialize a chainconst client = smoldot.start();const chain = await client.addChain({ chainSpec: polkadot });
// Initialize providers & clientsconst provider = new SmoldotProvider(chain);const client = await DedotClient.new<PolkadotApi>(provider);If the node doesn't support new JSON-RPC APIs yet, you can connect to the network using the LegacyClient, which is built on top of the legacy JSON-RPC APIs.
import { LegacyClient, WsProvider } from 'dedot';import type { PolkadotApi } from '@dedot/chaintypes';
const provider = new WsProvider('wss://rpc.polkadot.io');const client = await LegacyClient.new<PolkadotApi>(provider);Enable Type and API Suggestions
Section titled “Enable Type and API Suggestions”It is recommended to specify the ChainApi interface (e.g., PolkadotApi in the example in the previous section) of the chain you want to interact with. This enables type and API suggestions/autocompletion for that particular chain (via IntelliSense). If you don't specify a ChainApi interface, a default SubstrateApi interface will be used.
import { DedotClient, WsProvider } from 'dedot';import type { PolkadotApi, KusamaApi } from '@dedot/chaintypes';
const polkadotClient = await DedotClient.new<PolkadotApi>( new WsProvider('wss://rpc.polkadot.io'));const kusamaClient = await DedotClient.new<KusamaApi>( new WsProvider('wss://kusama-rpc.polkadot.io'));const genericClient = await DedotClient.new( new WsProvider('ws://localhost:9944'));If you don't find the ChainApi for the network you're working with in the list, you can generate the ChainApi (types and APIs) using the built-in dedot cli.
# Generate ChainApi interface for Polkadot network via rpc endpoint: wss://rpc.polkadot.ionpx dedot chaintypes -w wss://rpc.polkadot.ioOr open a pull request to add your favorite network to the @dedot/chaintypes repo.
Read On-Chain Data
Section titled “Read On-Chain Data”Dedot provides several ways to read data from the chain:
-
Access runtime constants: Use the syntax
client.consts.<pallet>.<constantName>to inspect runtime constants (parameter types).const ss58Prefix = client.consts.system.ss58Prefix;console.log('Polkadot ss58Prefix:', ss58Prefix); -
Storage queries: Use the syntax
client.query.<pallet>.<storgeEntry>to query on-chain storage.const balance = await client.query.system.account('INSERT_ADDRESS');console.log('Balance:', balance.data.free); -
Subscribe to storage changes:
const unsub = await client.query.system.number((blockNumber) => {console.log(`Current block number: ${blockNumber}`);}); -
Call Runtime APIs: Use the syntax
client.call.<runtimeApi>.<methodName>to execute Runtime APIs.const metadata = await client.call.metadata.metadataAtVersion(15);console.log('Metadata V15', metadata); -
Watch on-chain events: Use the syntax
client.events.<pallet>.<eventName>to access pallet events.const unsub = await client.events.system.NewAccount.watch((events) => {console.log('New Account Created', events);});
Sign and Send Transactions
Section titled “Sign and Send Transactions”Sign the transaction using IKeyringPair from Keyring (@polkadot/keyring) and send the transaction.
import { cryptoWaitReady } from '@polkadot/util-crypto';import { Keyring } from '@polkadot/keyring';// Setup keyringawait cryptoWaitReady();const keyring = new Keyring({ type: 'sr25519' });const alice = keyring.addFromUri('//Alice');// Send transactionconst unsub = await client.tx.balances .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) .signAndSend(alice, async ({ status }) => { console.log('Transaction status', status.type); if (status.type === 'BestChainBlockIncluded') { console.log(`Transaction is included in best block`); } if (status.type === 'Finalized') { console.log( `Transaction completed at block hash ${status.value.blockHash}` ); await unsub(); } });You can also use Signer from wallet extensions:
const injected = await window.injectedWeb3['polkadot-js'].enable('My dApp');const account = (await injected.accounts.get())[0];const signer = injected.signer;const unsub = await client.tx.balances .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) .signAndSend(account.address, { signer }, async ({ status }) => { console.log('Transaction status', status.type); if (status.type === 'BestChainBlockIncluded') { console.log(`Transaction is included in best block`); } if (status.type === 'Finalized') { console.log( `Transaction completed at block hash ${status.value.blockHash}` ); await unsub(); } });Where to Go Next
Section titled “Where to Go Next”For more detailed information about Dedot, check the official documentation.