Docs

system_properties - Kusama RPC Method

Get chain properties on Kusama including token symbol, decimals, and the address-format prefix when the chain exposes one. Essential for token formatting, wallet configuration, and address handling.

Returns the chain-specific properties for Kusama, including the native token symbol, token decimals, and the address-format prefix when the chain exposes one. This information is critical for correctly formatting balances, validating addresses, and configuring wallets.

Why Kusama? Build on Polkadot's canary network for real-world testing with live economic conditions with 7-day governance cycles (vs 1 month on Polkadot), lower bonding requirements, live KSM token economy, and first-to-market feature testing.

When to Use This Method

system_properties is essential for experimental dApp developers, parachain teams, and early adopters validating new features:

  • Token Formatting -- Get the correct decimals and symbol to display human-readable balances on Kusama
  • Address Validation -- Retrieve the SS58 prefix to encode and validate addresses for parachain experimentation, early feature deployment, and production-grade testing with real value
  • Wallet and dApp Configuration -- Dynamically configure your UI with the correct token symbol, decimals, and address format
  • Multi-Chain Support -- Automatically adapt your application to different Substrate chains without hardcoding properties

Code Examples

Common Use Cases

1. Human-Readable Balance Formatting

Format raw on-chain balances into human-readable token amounts:

JavaScript
import { ApiPromise, WsProvider } from '@polkadot/api';
import { BN } from '@polkadot/util';

async function formatBalance(api, rawBalance) {
  const properties = await api.rpc.system.properties();
  const raw = properties.toJSON();
  const decimalsRaw = raw.tokenDecimals;
  const symbolRaw = raw.tokenSymbol;
  const decimals = Array.isArray(decimalsRaw) ? decimalsRaw[0] : decimalsRaw;
  const symbol = Array.isArray(symbolRaw) ? symbolRaw[0] : symbolRaw;

  const divisor = new BN(10).pow(new BN(decimals));
  const whole = new BN(rawBalance).div(divisor);
  const fractional = new BN(rawBalance).mod(divisor).toString().padStart(decimals, '0');

  return `${whole}.${fractional.slice(0, 4)} ${symbol}`;
}

// Example output depends on the chain's live token symbol and decimals.

2. Dynamic Wallet Configuration

Auto-configure your wallet or dApp based on chain properties:

JavaScript
async function configureWallet(endpoint) {
  const provider = new WsProvider(endpoint);
  const api = await ApiPromise.create({ provider });

  const [chain, properties] = await Promise.all([
    api.rpc.system.chain(),
    api.rpc.system.properties()
  ]);

  const raw = properties.toJSON();
  const symbolsRaw = raw.tokenSymbol;
  const decimalsRaw = raw.tokenDecimals;
  const symbols = Array.isArray(symbolsRaw) ? symbolsRaw : [symbolsRaw];
  const decimals = Array.isArray(decimalsRaw) ? decimalsRaw : [decimalsRaw];
  const ss58Format = raw.ss58Format ?? raw.SS58Prefix ?? null;

  const config = {
    chainName: chain.toString(),
    ss58Format,
    tokens: symbols.map((symbol, idx) => ({
      symbol,
      decimals: decimals[idx] ?? decimals[0],
    }))
  };

  console.log('Wallet configured for:', config.chainName);
  console.log('Native token:', config.tokens[0].symbol, `(${config.tokens[0].decimals} decimals)`);
  console.log('Address format SS58:', config.ss58Format ?? 'not exposed');

  await api.disconnect();
  return config;
}

3. SS58 Address Encoding and Validation

Use the SS58 prefix to properly encode addresses for the target chain:

JavaScript
import { encodeAddress, decodeAddress } from '@polkadot/util-crypto';

async function formatAddressForChain(api, genericAddress) {
  const properties = await api.rpc.system.properties();
  const raw = properties.toJSON();
  const ss58Format = raw.ss58Format ?? raw.SS58Prefix;

  if (ss58Format == null) {
    throw new Error('This chain does not expose an SS58 prefix through system_properties.');
  }

  // Convert any SS58 address to this chain's format
  const publicKey = decodeAddress(genericAddress);
  const chainAddress = encodeAddress(publicKey, ss58Format);

  console.log(`Address on ${ss58Format}: ${chainAddress}`);
  return chainAddress;
}

Error Handling

Common errors and solutions:

Error CodeDescriptionSolution
-32603Internal errorNode may be starting up -- retry after delay
-32005Rate limit exceededReduce request frequency or implement client-side rate limiting
Connection refusedNode unreachableVerify the RPC endpoint URL and that the node is running
Empty or alternate result fieldsChain spec missing properties or using SS58PrefixNormalize scalar vs array values and fall back to SS58Prefix when ss58Format is absent