React Hooks Reference
React bindings for Selendra TypeScript SDK v1.0.4
React Hooks Reference
React bindings for @selendrajs/sdk v1.0.4. Provides hooks for connecting to Selendra, querying balances, and managing transactions.
Installation
npm install @selendrajs/sdk
Exports
import {
// Provider
SelendraProvider,
SelendraContext,
// Hooks
useSelendra,
useBalance,
useTransaction,
useTransactions,
// Types
type SelendraProviderProps,
type SelendraContextValue,
type UseSelendraResult,
type UseBalanceResult,
type BalanceState,
type UseTransactionResult,
type TransactionState,
type TransactionStatus,
} from "@selendrajs/sdk/react";
SelendraProvider
Context provider that makes the SDK available to all child components.
Props
| Prop | Type | Required | Description |
|---|---|---|---|
config | SDKConfig | Yes | SDK configuration |
children | ReactNode | Yes | Child components |
autoConnect | boolean | No | Auto-connect on mount |
onConnected | (sdk: SelendraSDK) => void | No | Called when connected |
onDisconnected | () => void | No | Called when disconnected |
onError | (error: Error) => void | No | Called on error |
Example
import { SelendraProvider } from "@selendrajs/sdk/react";
function App() {
return (
<SelendraProvider
config={{ endpoint: "wss://rpc.selendra.org" }}
autoConnect
onConnected={(sdk) =>
console.log("Connected to", sdk.getConnectionInfo()?.chainName)
}
onError={(error) => console.error("Connection error:", error)}
>
<MyApp />
</SelendraProvider>
);
}
useSelendra
Core hook for accessing the SDK instance and connection state.
Returns
interface UseSelendraResult {
sdk: SelendraSDK | null; // SDK instance (null if not connected)
isConnected: boolean; // Whether SDK is connected
isConnecting: boolean; // Whether SDK is connecting
error: Error | null; // Connection error if any
connectionInfo: ConnectionInfo | null; // Chain info (name, token, decimals)
connect: () => Promise<void>; // Connect to chain
disconnect: () => Promise<void>; // Disconnect from chain
reconnect: () => Promise<void>; // Reconnect to chain
}
Example
import { useSelendra } from "@selendrajs/sdk/react";
function ChainInfo() {
const { sdk, isConnected, isConnecting, connectionInfo, error } =
useSelendra();
if (error) return <div>Error: {error.message}</div>;
if (isConnecting) return <div>Connecting...</div>;
if (!isConnected) return <div>Not connected</div>;
return (
<div>
<p>Chain: {connectionInfo?.chainName}</p>
<p>Token: {connectionInfo?.tokenSymbol}</p>
<p>Decimals: {connectionInfo?.tokenDecimals}</p>
</div>
);
}
Querying with SDK
function AccountInfo({ address }: { address: string }) {
const { sdk, isConnected } = useSelendra();
const [account, setAccount] = useState(null);
useEffect(() => {
if (sdk && isConnected) {
sdk.pallets.balances.queries.account(address).then(setAccount);
}
}, [sdk, isConnected, address]);
return account ? <div>Free: {account.free.toString()}</div> : null;
}
useBalance
Hook for querying and subscribing to account balances.
Parameters
useBalance(address: string, options?: {
subscribe?: boolean; // Subscribe to balance changes (default: false)
})
Returns
interface UseBalanceResult {
balance: BalanceState | null; // Balance data
loading: boolean; // Whether loading
error: Error | null; // Error if any
refresh: () => Promise<void>; // Refresh balance
subscribe: () => () => void; // Subscribe to changes
}
interface BalanceState {
raw: AccountData | null; // Raw chain data
free: string; // Free balance (formatted)
reserved: string; // Reserved balance
total: string; // Total balance
frozen: string; // Frozen balance
transferable: string; // Transferable (free - frozen)
locks: BalanceLock[]; // Balance locks
reserves: ReserveData[]; // Balance reserves
existentialDeposit: string; // Existential deposit
symbol: string; // Token symbol (SEL)
decimals: number; // Token decimals (18)
}
Example
import { useBalance } from "@selendrajs/sdk/react";
function BalanceDisplay({ address }: { address: string }) {
const { balance, loading, error, refresh } = useBalance(address);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!balance) return null;
return (
<div>
<p>
Free: {balance.free} {balance.symbol}
</p>
<p>
Reserved: {balance.reserved} {balance.symbol}
</p>
<p>
Total: {balance.total} {balance.symbol}
</p>
<p>
Transferable: {balance.transferable} {balance.symbol}
</p>
<button onClick={refresh}>Refresh</button>
</div>
);
}
With Subscription
function LiveBalance({ address }: { address: string }) {
const { balance, subscribe } = useBalance(address, { subscribe: true });
useEffect(() => {
const unsubscribe = subscribe();
return () => unsubscribe();
}, [subscribe]);
return balance ? (
<div>
Balance: {balance.free} {balance.symbol} (live)
</div>
) : null;
}
useTransaction
Hook for executing single transactions with status tracking.
Returns
interface UseTransactionResult {
status: TransactionStatus; // 'idle' | 'pending' | 'success' | 'error'
txHash: string | null; // Transaction hash
blockHash: string | null; // Block hash (when finalized)
error: Error | null; // Error if failed
events: unknown[]; // Transaction events
isPending: boolean; // status === 'pending'
isSuccess: boolean; // status === 'success'
isError: boolean; // status === 'error'
execute: <T>(tx: (sdk: SelendraSDK) => Promise<T>) => Promise<T | null>;
reset: () => void; // Reset state for next tx
}
Example
import { useTransaction, useSelendra } from "@selendrajs/sdk/react";
function TransferForm() {
const { sdk } = useSelendra();
const { status, txHash, error, execute, reset, isPending, isSuccess } =
useTransaction();
const [recipient, setRecipient] = useState("");
const [amount, setAmount] = useState("");
const handleTransfer = async () => {
if (!sdk) return;
await execute(async (sdk) => {
const tx = sdk.pallets.balances.manager.transfer({
dest: recipient,
value: amount,
});
return new Promise((resolve, reject) => {
tx.signAndSend(signer, {}, (result) => {
if (result.status.isFinalized) {
resolve({
txHash: result.txHash.toHex(),
blockHash: result.status.asFinalized.toHex(),
events: result.events,
});
}
if (result.isError) {
reject(new Error("Transaction failed"));
}
});
});
});
};
return (
<div>
<input
placeholder="Recipient address"
value={recipient}
onChange={(e) => setRecipient(e.target.value)}
disabled={isPending}
/>
<input
type="text"
placeholder="Amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
disabled={isPending}
/>
<button onClick={handleTransfer} disabled={isPending}>
{isPending ? "Sending..." : "Send"}
</button>
{isSuccess && (
<div>
✅ Transaction successful!
<br />
Hash: {txHash}
</div>
)}
{error && <div>❌ Error: {error.message}</div>}
{isSuccess && <button onClick={reset}>Reset</button>}
</div>
);
}
useTransactions
Hook for managing batch/multiple transactions.
Returns
interface UseTransactionsResult {
transactions: TransactionState[]; // Array of transaction states
isAnyPending: boolean; // Any transaction pending
isAllSuccess: boolean; // All transactions succeeded
hasAnyError: boolean; // Any transaction failed
executeBatch: <T>(
txs: Array<(sdk: SelendraSDK) => Promise<T>>
) => Promise<(T | null)[]>;
reset: () => void; // Reset all states
}
Example
import { useTransactions } from "@selendrajs/sdk/react";
function BatchTransfer() {
const { transactions, isAnyPending, isAllSuccess, executeBatch, reset } =
useTransactions();
const handleBatch = async () => {
await executeBatch([
async (sdk) => {
// First transfer
const tx = sdk.pallets.balances.manager.transfer({
dest: "addr1",
value: "1000000000000000000",
});
return await signAndWait(tx, signer);
},
async (sdk) => {
// Second transfer
const tx = sdk.pallets.balances.manager.transfer({
dest: "addr2",
value: "2000000000000000000",
});
return await signAndWait(tx, signer);
},
]);
};
return (
<div>
<button onClick={handleBatch} disabled={isAnyPending}>
{isAnyPending ? "Processing..." : "Execute Batch"}
</button>
{transactions.map((tx, i) => (
<div key={i}>
Transaction {i + 1}: {tx.status}
{tx.txHash && <span> - {tx.txHash}</span>}
</div>
))}
{isAllSuccess && <div>✅ All transactions completed!</div>}
<button onClick={reset}>Reset</button>
</div>
);
}
Complete Example App
import {
SelendraProvider,
useSelendra,
useBalance,
useTransaction,
} from "@selendrajs/sdk/react";
// Main App with Provider
function App() {
return (
<SelendraProvider
config={{ endpoint: "wss://rpc.selendra.org" }}
autoConnect
>
<Wallet />
</SelendraProvider>
);
}
// Wallet Component
function Wallet() {
const { isConnected, isConnecting, connectionInfo, error } = useSelendra();
const [address, setAddress] = useState("");
if (isConnecting) return <div>Connecting to Selendra...</div>;
if (error) return <div>Connection Error: {error.message}</div>;
if (!isConnected) return <div>Not connected</div>;
return (
<div>
<h1>{connectionInfo?.chainName}</h1>
<input
placeholder="Enter address"
value={address}
onChange={(e) => setAddress(e.target.value)}
/>
{address && <BalanceCard address={address} />}
</div>
);
}
// Balance Card
function BalanceCard({ address }: { address: string }) {
const { balance, loading, error, refresh } = useBalance(address);
if (loading) return <div>Loading balance...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!balance) return null;
return (
<div className="balance-card">
<h3>Balance</h3>
<p>
Free: {balance.free} {balance.symbol}
</p>
<p>
Reserved: {balance.reserved} {balance.symbol}
</p>
<p>
Transferable: {balance.transferable} {balance.symbol}
</p>
<button onClick={refresh}>🔄 Refresh</button>
</div>
);
}
export default App;
TypeScript Types
// SDK Config
interface SDKConfig {
endpoint?: string;
network?: string;
chainType?: ChainType;
autoReconnect?: boolean;
debug?: boolean;
}
// Connection Info
interface ConnectionInfo {
chainName: string;
tokenSymbol: string;
tokenDecimals: number;
ss58Prefix: number;
}
// Transaction Status
type TransactionStatus = "idle" | "pending" | "success" | "error";
// Balance Lock
interface BalanceLock {
id: string;
amount: bigint;
reasons: string;
}
// Reserve Data
interface ReserveData {
id: string;
amount: bigint;
}
Upcoming Hooks
The following hooks are implemented but temporarily disabled pending API updates:
| Hook | Purpose | Status |
|---|---|---|
useStaking | Staking operations | Coming soon |
useGovernance | Democracy & voting | Coming soon |
useNominationPools | Pool staking | Coming soon |
These will be re-enabled in a future SDK release.
See Also
- TypeScript API - Core SDK documentation
- Pallets Reference - Complete pallet documentation
- CLI Reference - Command-line tools
Contribute
Found an issue or want to contribute?
Help us improve this documentation by editing this page on GitHub.