Skip to main content

Overview

The BalanceService is responsible for tracking and managing token balances across different blockchain networks supported by SubWallet Extension. It provides real-time balance updates, token detection, and cross-chain transfer capabilities.

Key Features

  • Multi-chain balance tracking (Substrate, EVM, Ton, Cardano, Bitcoin)
  • Real-time balance subscriptions
  • Automatic token detection and enabling
  • Transfer balance calculations
  • XCM (Cross-Consensus Message) support
  • Token optimization and balance caching

Class: BalanceService

Constructor

constructor(state: KoniState)
state
KoniState
required
The global state object of the extension

Properties

isStarted
boolean
Indicates whether the service is currently running
status
ServiceStatus
Current status of the service (NOT_INITIALIZED, INITIALIZING, INITIALIZED, STARTING, STARTED, STOPPING, STOPPED)

Core Methods

init()

Initializes the balance service and loads cached data.
async init(): Promise<void>
Usage:
const balanceService = new BalanceService(state);
await balanceService.init();

start()

Starts the balance service and begins tracking balances.
async start(): Promise<void>

stop()

Stops the balance service and unsubscribes from all balance updates.
async stop(): Promise<void>

Balance Subscription Methods

subscribeBalance()

Subscribes to balance updates for a specific address, chain, and token.
async subscribeBalance(
  address: string,
  chain: string,
  tokenSlug: string | undefined,
  balanceType: BalanceType = BalanceType.TRANSFERABLE,
  extrinsicType?: ExtrinsicType,
  callback?: (rs: AmountData) => void
): Promise<[() => void, AmountData]>
address
string
required
The wallet address to track
chain
string
required
The chain slug (e.g., ‘polkadot’, ‘kusama’, ‘ethereum’)
tokenSlug
string
The token identifier. If undefined, uses the native token
balanceType
BalanceType
default:"BalanceType.TRANSFERABLE"
Type of balance to track (TRANSFERABLE, TOTAL, TOTAL_MINUS_RESERVED)
extrinsicType
ExtrinsicType
Optional extrinsic type for context-specific balance calculations
callback
(rs: AmountData) => void
Optional callback function called on balance updates
Returns:
[0]
() => void
Unsubscribe function to stop receiving updates
[1]
AmountData
Current balance data
Usage:
const [unsub, balance] = await balanceService.subscribeBalance(
  '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
  'polkadot',
  'polkadot-NATIVE-DOT',
  BalanceType.TRANSFERABLE,
  undefined,
  (balanceData) => {
    console.log('New balance:', balanceData.value);
  }
);

// Later, unsubscribe
unsub();

getTransferableBalance()

Fetches the transferable balance for an address on a specific chain.
async getTransferableBalance(
  address: string,
  chain: string,
  tokenSlug?: string,
  extrinsicType?: ExtrinsicType
): Promise<AmountData>
Returns:
AmountData
object
Balance information object
value
string
Balance value as string
decimals
number
Token decimals
symbol
string
Token symbol
metadata
any
Additional metadata

getTotalBalance()

Fetches the total balance (free + locked) for an address.
async getTotalBalance(
  address: string,
  chain: string,
  tokenSlug?: string,
  extrinsicType?: ExtrinsicType
): Promise<AmountData>

subscribeBalanceMap()

Subscribes to the complete balance map for all accounts and tokens.
subscribeBalanceMap(): BehaviorSubject<BalanceJson>
Returns:
BehaviorSubject<BalanceJson>
BehaviorSubject
Observable that emits balance updates for all tracked tokens
Usage:
balanceService.subscribeBalanceMap().subscribe((balanceData) => {
  console.log('Balance map updated:', balanceData.details);
});

Token Detection Methods

autoEnableChains()

Automatically detects and enables chains with non-zero balances.
async autoEnableChains(addresses: string[]): Promise<void>
addresses
string[]
required
Array of addresses to check for balances

evmDetectBalanceToken()

Detects EVM tokens with balances for given addresses.
async evmDetectBalanceToken(addresses: string[]): Promise<string[]>
Returns:
string[]
array
Array of token slugs with non-zero balances

substrateDetectBalanceToken()

Detects Substrate tokens with balances for given addresses.
async substrateDetectBalanceToken(addresses: string[]): Promise<string[]>

Transfer Methods

getOptimalTransferProcess()

Determines the optimal transfer path for cross-chain transfers.
async getOptimalTransferProcess(
  params: RequestOptimalTransferProcess
): Promise<CommonOptimalTransferPath>
params
RequestOptimalTransferProcess
required
Transfer parameters
originChain
string
required
Source chain slug
destChain
string
Destination chain slug
tokenSlug
string
required
Token to transfer
address
string
required
Sender address
amount
string
required
Amount to transfer

getTokensHasBalance()

Retrieves tokens with non-zero balances for a specific address and chain.
async getTokensHasBalance(
  address: string,
  chain: string,
  tokenSlug?: string
): Promise<Record<string, BalanceItem>>
Returns:
Record<string, BalanceItem>
object
Map of token slugs to balance items

Utility Methods

reloadBalance()

Reloads all balance data from scratch.
async reloadBalance(): Promise<void>

removeBalanceByAddresses()

Removes balance data for specific addresses.
removeBalanceByAddresses(addresses: string[]): void
addresses
string[]
required
Array of addresses to remove

optimizeEnableTokens()

Optimizes the token list by enabling tokens with balances and disabling zero-balance tokens.
async optimizeEnableTokens(): Promise<void>

Types

BalanceType

enum BalanceType {
  TRANSFERABLE = 'TRANSFERABLE',
  TOTAL = 'TOTAL',
  TOTAL_MINUS_RESERVED = 'TOTAL_MINUS_RESERVED'
}

BalanceItem

interface BalanceItem {
  address: string;
  tokenSlug: string;
  free: string;
  locked: string;
  state: APIItemState;
  chain: string;
  lockedDetails?: {
    staking?: string;
    reserved?: string;
    frozen?: string;
  };
}

Events

The BalanceService listens to and emits events through the EventService:
  • account.updateCurrent - Current account changed
  • account.add - New account added
  • account.remove - Account removed
  • chain.updateState - Chain state changed
  • asset.updateState - Asset state changed

Example: Complete Balance Tracking

import { BalanceService } from '@subwallet/extension-base';

// Initialize service
const balanceService = new BalanceService(state);
await balanceService.init();
await balanceService.start();

// Subscribe to specific token balance
const [unsub, initialBalance] = await balanceService.subscribeBalance(
  '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
  'polkadot',
  'polkadot-NATIVE-DOT',
  BalanceType.TRANSFERABLE,
  undefined,
  (balance) => {
    console.log(`DOT Balance: ${balance.value} ${balance.symbol}`);
  }
);

// Get current balance
const balance = await balanceService.getTransferableBalance(
  '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
  'polkadot'
);
console.log('Balance:', balance);

// Subscribe to all balances
balanceService.subscribeBalanceMap().subscribe((data) => {
  console.log('All balances:', data.details);
});

// Cleanup
unsub();

Build docs developers (and LLMs) love