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
- yarn
- pnpm
npm add @reactive-dot/react polkadot-api
yarn add @reactive-dot/react polkadot-api
pnpm add @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β
- Light client
- WebSocket
config.ts
// `dot` is the name we gave to `npx papi add`
import { dot } from "@polkadot-api/descriptors";
import type { Config } from "@reactive-dot/core";
import { InjectedWalletAggregator } 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 = {
chains: {
// "polkadot" here can be any unique string value
polkadot: {
descriptor: dot,
provider: getSmProvider(smoldot.addChain({ chainSpec })),
},
},
wallets: [new InjectedWalletAggregator()],
} as const satisfies Config;
config.ts
import { dot } from "@polkadot-api/descriptors";
import { WebSocketProvider } from "@polkadot-api/ws-provider/web";
import type { Config } from "@reactive-dot/core";
import { InjectedWalletAggregator } from "@reactive-dot/core/wallets.js";
export const config = {
chains: {
polkadot: {
descriptor: dot,
provider: WebSocketProvider("wss://polkadot-rpc.publicnode.com"),
},
},
wallets: [new InjectedWalletAggregator()],
} as const satisfies Config;
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";
import type { InferChains } from "@reactive-dot/core";
declare module "@reactive-dot/core" {
export interface Chains extends InferChains<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}>
{/* `chainId` match the ID previously specified via `polkadot: typeof dot` */}
<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>
);
}