Skip to main content

Setup

This walks you through the process of creating a simple ReactiveDOT application.

🚧Work-in-progress

This project is under active development, and the API may change at any time.

Installation​

First add ReactiveDOT, along with required packages as dependencies to your React project.

npm install @reactive-dot/react polkadot-api

Download & sync metadata​

Next, download the latest metadata from the chain you want to connect to and generate the types.

# `papi add` is the command
# `dot` is the name we're giving to this chain (can be any JS variable name)
# `-n polkadot` specifies to download the metadata from the well-known chain polkadot
npx papi add dot -n polkadot
# Wait for the latest metadata to download, then generate the types:
npx papi
info

For more information on metadata syncing and type generation, please refer to this documentation provided by Polkadot-API.

Create config​

config.ts
// `dot` is the name we gave to `npx papi add`
import { dot } from "@polkadot-api/descriptors";
import { defineConfig } from "@reactive-dot/core";
import { InjectedWalletProvider } from "@reactive-dot/core/wallets.js";
import { chainSpec } from "polkadot-api/chains/polkadot";
import { getSmProvider } from "polkadot-api/sm-provider";
import { startFromWorker } from "polkadot-api/smoldot/from-worker";

const smoldot = startFromWorker(
new Worker(new URL("polkadot-api/smoldot/worker", import.meta.url), {
type: "module",
}),
);

export const config = defineConfig({
chains: {
// "polkadot" here can be any unique string value
polkadot: {
descriptor: dot,
provider: getSmProvider(smoldot.addChain({ chainSpec })),
},
},
wallets: [new InjectedWalletProvider()],
});

Add type information​

The type declarations extension here will be used to provide you with the right type definitions when using hooks.

reactive-dot.d.ts
import type { config } from "./config.js";

declare module "@reactive-dot/core" {
export interface Register {
config: typeof config;
}
}

Wrap app in context providers​

app.tsx
import { config } from "./config";
import { ChainProvider, ReactiveDotProvider } from "@reactive-dot/react";
import { Suspense } from "react";

export function App() {
return (
<ReactiveDotProvider config={config}>
<ChainProvider chainId="polkadot">
{/* Make sure there is at least one Suspense boundary wrapping the app */}
<Suspense>{/* ... */}</Suspense>
</ChainProvider>
</ReactiveDotProvider>
);
}

Use ReactiveDOT​

my-component.tsx
import { config } from "./config";
import { useAccounts, useLazyLoadQuery } from "@reactive-dot/react";

export function MyComponent() {
const accounts = useAccounts();
const [timestamp, totalIssuance] = useLazyLoadQuery((builder) =>
builder
.readStorage("Timestamp", "Now", [])
.readStorage("Balances", "TotalIssuance", []),
);

return (
<div>
<ul>
{accounts.map((account, index) => (
<li key={index}>
<div>Address: {account.address}</div>
{account.name && <div>Name: {account.name}</div>}
</li>
))}
</ul>
<section>
<div>
Latest block timestamp: {new Date(Number(timestamp)).toLocaleString()}
</div>
<div>Total issuance: {totalIssuance.toString()}</div>
</section>
</div>
);
}