Skip to main content

Subsocial Utils

This section covers the utilities that are provided by the @subsocial/utils package. It contains a set of helper functions to help you develop in the Subsocial Ecosystem.

There are several sections which are divided by their functionality. The table below contains links to each section:

AccountsParse a Substrate address to a Subsocial address.
BalancesFormat balances to readable formats.
MarkdownProcess markdown texts to different formats.
SummarizeSummarize text and markdown to display properly in post previews.
TwitterUtilities to help you integrate posts from Twitter to your app.
SlugCreate a slug from a content body to improve SEO.
Social LinksManages links from other social media platforms.


Each substrate account has a different address depending on the chain. This is because each chain has an address prefix, which may be the same or different from each other. For example, the Subsocial parachain and Soonsocial testnet have the same address prefix, which is 28. But Polkadot has a different prefix, which is 0. This makes the same account have a different address format for Subsocial and Polkadot. You can manually convert addresses to any format that you want by using the Subscan Address Converter.


A simple function to convert any substrate address format into Subsocial's address format.

toSubsocialAddress(address?: string): string


import { toSubsocialAddress } from '@subsocial/utils'
const subsocialAddress = toSubsocialAddress(anySubstrateAddress)


Most blockchains doesn't support decimals, so BigInt is used to store token balances. This BigInt numbers are paired with a constant usually named decimals which parses the balance into its real value. For example, if user A has 1 token Z, where the decimals of token Z is 10, then the value stored in the blockchain for that user's token balance is 10000000000 (with 10 zeros).

However, this is not the value that user wants to see, so we need to format it first to its decimal version. To do so, there are several formatting functions in @subsocial/utils that can be used. To simplify things, the value stored on the blockchain will be named blockchain value, and the decimal version will be named real value.


Formats blockchain value into a human readable real value based on the decimals given.

simpleFormatBalance(balance: BN | string | number, decimals?: number, currency?: string, withUnit: boolean = true): string
import { simpleFormatBalance } from '@subsocial/utils'
const balance = '100000000000000000000' // 1_000_000_000_000_000_000 (18 zeros)
simpleFormatBalance(balance, 10) // 100,000,000.0000 Unit
simpleFormatBalance(balance, 10, 'SUB', 'SUB') // 100,000,000.0000 SUB
simpleFormatBalance(balance, 10, 'SUB', false) // 100,000,000.0000


Parses real value into blockchain value based on the decimals given.

balanceWithDecimal(balance: string | number, decimal: number): BigNumber
import { balanceWithDecimal } from '@subsocial/utils'
const balance = '1'
balanceWithDecimal(balance, 10).toString() // 10_000_000_000 (10 zeros)


Formats blockchain value into real value based on the decimals given.

convertToBalanceWithDecimal(balance: string | number, decimal: number): BigNumber
import { convertToBalanceWithDecimal } from '@subsocial/utils'
const balance = '10000000000' // 10_000_000_000 (10 zeros)
convertToBalanceWithDecimal(balance, 10).toString() // 1


Formats real value to have a number separator and token symbol

formatBalanceWithoutDecimals(balance: BigNumber, symbol: string): string
import { formatBalanceWithoutDecimals } from '@subsocial/utils'
import BigNumber from 'bignumber.js'

const balance = new BigNumber(100_000)
formatBalanceWithoutDecimals(balance, 'SUB') // 100,000 SUB


Formats real value to a short format. For example, 1_000_000 will be shortened to 1M

type ShortMoneyProps = {
num: number
prefix?: string // Any string placed before the amount
suffix?: string // Any string placed after the amount
fractions?: number // Number of digits after the decimal point
toShortMoney(arg: ShortMoneyProps): string
import { toShortMoney } from '@subsocial/utils'
toShortMoney({ num: 100_000_000 }) // 100.0M
toShortMoney({ num: 1_000_000_000 }) // 1.0B


Subsocial supports any format of content, but for apps built by the Subsocial team, such as Grill, we use markdown (md) for content. Because of this, we have several utils function related to processing md text.


Converts markdown text into plain text. One example use case for this is displaying previews, where you don't want to have any formatting.

mdToText(md: string | undefined): string | undefined
import { mdToText } from '@subsocial/utils'
const mdText = '# title [link to subsocial]('
console.log(mdToText(mdText)) // title link to subsocial


Converts markdown text into html.

mdToHtml(md: string | undefined): string | undefined
import { mdToHtml } from '@subsocial/utils'
const mdText = '# title [link to subsocial]('
console.log(mdToHtml(mdText)) // <h1>title <a href="">link to subsocial</a></h1>


This section contains simple helper functions to summarize long texts. One example is to show a summary instead of a full post in the post list section.


Truncates plain text so it doesn't exceed the limit given. The truncation process will not truncate a word if possible.

type SummarizeOpt = {
limit?: number // the max length of text
omission?: string // the suffix that's added if the text is longer than the limit
summarize(text: string, opts: SummarizeOpt): string | undefined
import { summarize } from '@subsocial/utils'
const text = 'Lorem ipsum dolor sit amet'
summarize(mdText, { limit: 7 }) // Lore...
summarize(mdText, { limit: 10 }) // Lorem... - this doesn't include second word entirely as it will exceed the limit.
summarize(mdText, { limit: 10, suffix: '' }) // Lorem ipsum - removes the suffix


The same as summarize, but it converts md text into plain text first before going to the summarize function. The return of this function is an object, with a summary field, which is the same as the summarized text, and isShowMore which indicates if that text is truncated or not.

type SummarizeOpt = {
limit?: number // the max length of text
omission?: string // the suffix that's added if the text is longer than the limit
summarize(mdText: string, opts: SummarizeOpt): { summary: string; isShowMore: boolean; }
import { summarizeMd } from '@subsocial/utils'
const text = '# Lorem ipsum dolor sit amet'
summarizeMd(mdText, { limit: 7 }) // { summary: 'Lore...', isShowMore: true }
summarizeMd(mdText, { limit: 10 }) // { summary: 'Lorem...', isShowMore: true } - this doesn't include second word entirely as it will exceed the limit.
summarizeMd('Lorem', { limit: 10 }) // { summary: 'Lorem', isShowMore: false } - text is not truncated


Helpers to integrate Subsocial posts that originated from Twitter.


Parses plain text to markdown that add links to Twitter for several formats (e.g. tags and mentions)

parseTwitterTextToMarkdown(text: string): string
import { parseTwitterTextToMarkdown } from '@subsocial/utils'
parseTwitterTextToMarkdown('Hi from @SubsocialChain') // Hi from [@SubsocialChain](


Generates a Twitter url from the id and username that are given.

createTwitterURL(tweet: { username: string; id: string }): string
import { createTwitterURL } from '@subsocial/utils'
createTwitterURL({ username: 'SubsocialChain', id: '1622592114419724290' }) //


These utility functions will help you to create a content slug for your app. A content slug is where you use, for example, a post title as part of the url of your page, which can help your app gain better SEO (Search Engine Optimization).


Converts content that has the title or body attribute and its id to a url content slug. It primarily uses title, but if that doesn't exist, it will use body. If the title or body is too long (the limit is 60), then it will go through the summarize function first to truncate any excess text.

type HasTitleOrBody = {
title?: string,
body: string
createPostSlug(postId: string, content?: HasTitleOrBody): string
import { createPostSlug } from '@subsocial/utils'
createPostSlug('1', { title: 'My First Subsocial App' }) // my-first-subsocial-app-1
createPostSlug('1', { body: 'My body text' }) // my-body-text-1


Gets the id from the slug generated by createPostSlug.

getPostIdFromSlug(slug: string): string | undefined
import { getPostIdFromSlug } from '@subsocial/utils'
getPostIdFromSlug('my-first-subsocial-app-1') // 1

Manage links from other social media platforms.


Extracts the video id of YouTube videos.

extractVideoId(url: string): string | false
import { extractVideoId } from '@subsocial/utils'
extractVideoId('') // vC9VAylxuJY
extractVideoId('') // vC9VAylxuJY


Generates an embed url for a supported video platform url. Currently supported platforms: vimeo, youtube,, soundcloud The list of supported platforms is also available in the variable allowEmbedList exported in the utils package.

getEmbedUrl(url: string, embed: string | undefined): string | undefined
import { getEmbedUrl } from '@subsocial/utils'
getEmbedUrl('', 'youtube') //
getEmbedUrl('', '') //

Checks whether the link is from the specified social platform brand.

isSocialBrandLink(brand: SocialBrand, link: string): boolean
import { isSocialBrandLink } from '@subsocial/utils'
isSocialBrandLink('twitter', '') // true
) // true
isSocialBrandLink('gitHub', '') // false


Gets the platform where the link is originated. If link's platform is not supported, it will return website as the default.

getLinkBrand(link: string): SocialBrand
import { getLinkBrand } from '@subsocial/utils'
getLinkBrand('') // twitter
getLinkBrand('') // linkedIn