Skip to content

Latest commit

 

History

History
192 lines (151 loc) · 6.31 KB

File metadata and controls

192 lines (151 loc) · 6.31 KB

Component Reference

This documentation covers the input components used in the Relaycode extrinsic builder. Each component handles a specific Substrate type and provides appropriate UI controls for user input.

Architecture Overview

Input Component System

All input components live in components/params/inputs/ and share a common interface:

components/params/
├── types.ts              # ParamInputProps interface
└── inputs/
    ├── account.tsx       # SS58 address input
    ├── amount.tsx        # Integer numeric input
    ├── balance.tsx       # Token amount with denominations
    ├── boolean.tsx       # Boolean toggle
    ├── btree-map.tsx     # BTreeMap key-value pairs
    ├── btree-set.tsx     # BTreeSet unique values
    ├── bytes.tsx         # Hex byte array
    ├── call.tsx          # Nested extrinsic builder
    ├── enum.tsx          # Variant selector
    ├── hash.tsx          # H160/H256/H512 input
    ├── key-value.tsx     # Key-value pair
    ├── moment.tsx        # Timestamp input
    ├── option.tsx        # Optional value wrapper
    ├── struct.tsx        # Composite type container
    ├── text.tsx          # String/fallback input
    ├── tuple.tsx         # Positional collection
    ├── vector.tsx        # Dynamic array
    ├── vector-fixed.tsx  # Fixed-length array
    ├── vote.tsx          # Vote input
    └── vote-threshold.tsx # Vote threshold input

ParamInputProps Interface

All input components implement this common interface:

interface ParamInputProps {
  name: string;                    // Field identifier
  label?: string;                  // Display label
  description?: string;            // Help text
  typeName?: string;               // Substrate type name (e.g., "Balance", "AccountId")
  isDisabled?: boolean;            // Disable input
  isRequired?: boolean;            // Show required indicator
  error?: string;                  // Error message to display
  client: DedotClient<PolkadotApi>; // Dedot client for type resolution
  typeId?: number;                 // Type ID for complex type resolution
  onChange?: (value: unknown) => void;  // Value change callback
}

Component Schema Pattern

Each component exports a Zod validation schema:

// Example from amount.tsx
import { z } from "zod";

const schema = z.string().refine(
  (val) => !isNaN(Number(val)) && Number(val) >= 0,
  { message: "Must be a non-negative number" }
);

export function Amount({ ... }) { ... }

Amount.schema = schema;

Component Categories

Primitive Types

Binary Types

Collection Types

Composite Types

Special Types

Type Resolution

Components are resolved from type names using the Input Map API:

import { findComponent } from "@/lib/input-map";

// Find component for a Balance type
const { component: BalanceComponent } = findComponent("Balance");

// Find component with typeId for nested resolution
const { component: VecComponent } = findComponent("Vec<AccountId>", typeId);

Value Flow

User Input → Component onChange() → Parent Form State → Encoding
                                         ↓
Decoding → Parent Form State → Component value prop → Display

onChange Callback

Components call onChange with the appropriate value type:

Component onChange Value Type
Account string (SS58 address)
Amount string (integer as string)
Balance string (planck value as string)
Boolean boolean
BTreeMap [unknown, unknown][] (array of key-value tuples)
BTreeSet unknown[] (array of unique values)
Bytes string (hex with 0x)
Hash string (hex with 0x)
Text string
Option undefined or inner value
Vector unknown[]
VectorFixed unknown[] (fixed-length array)
Struct Record<string, unknown>
Tuple unknown[]
Enum { type: string; value?: unknown }
Call { type: string; value: { type: string; ...args } }

UI Components

Input components are built on shadcn/ui primitives:

  • Input - Text fields
  • Select - Dropdowns
  • Switch - Toggles
  • Button - Actions
  • Card - Containers
  • Label - Field labels
  • FormDescription - Help text

Custom Hooks

Components use several custom hooks:

useSS58

Address formatting with chain-specific prefix:

const { ss58Prefix, formatAddress, isValidAddress, truncateAddress } = useSS58(client);

useChainToken

Token symbol and denominations:

const { symbol, decimals, denominations, existentialDeposit } = useChainToken(client);

useRecentAddresses

Recently used address history:

const { recentAddresses, addRecent } = useRecentAddresses();

useSafeAccounts / useSafeBalance

Wallet integration (safe fallbacks when wallet not connected):

const { accounts } = useSafeAccounts();
const { transferable, formattedTransferable } = useSafeBalance({ address });

See Also