
Security News
The Changelog Podcast: Practical Steps to Stay Safe on npm
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.
@substrate/light-client-extension-helpers
Advanced tools
restart method for the smoldot clientThe module exposes a register function that is meant to be called in your background
script. It does all the heavy lifting to manage your extension's connection to smoldot.
import { register } from "@substrate/light-client-extension-helpers/background"
const { lightClientPageHelper, addOnAddChainByUserListener } = register({
smoldotClient: start({ maxLogLevel: 4 }),
getWellKnownChainSpecs: () =>
// these well known chains will be connected to when the extension is
// started and their connection will always be maintained. The location
// of these chainspecs is relative to your `assets` directory.
Promise.all(
[
"./chainspecs/polkadot.json",
"./chainspecs/ksmcc3.json",
"./chainspecs/westend2.json",
].map((path) =>
fetch(chrome.runtime.getURL(path)).then((response) => response.text()),
),
),
})
addOnAddChainByUserListener(async (inputChain) => {
// listen for chain updates
})
This module exposes a register function that should be called in your content
script. Once registered you can access the light client provider in your inpage
script.
This is useful if you are implementing the @substrate/discovery protocol
// constants.ts
export const CHANNEL_ID = "substrate-wallet-template"
// content/index.ts
import { register } from "@substrate/light-client-extension-helpers/content-script"
import { CHANNEL_ID } from "../constants"
register(CHANNEL_ID)
// inpage/index.ts
import { getLightClientProvider } from "@substrate/light-client-extension-helpers/web-page"
const provider = getLightClientProvider(CHANNEL_ID)
The webpage helper allows any dapp to discover the light client provider that
was registered using the contentScriptHelper. However this functionality
has been superseded by the discovery protocol.
// use-provider.ts
import {
type LightClientProvider,
getLightClientProvider,
} from "@substrate/light-client-extension-helpers/web-page"
import { useEffect, useState } from "react"
import { useIsMounted } from "./useIsMounted"
const providers = new Map<string, Promise<LightClientProvider>>()
export const useLightClientProvider = (channelId: string) => {
const [provider, setProvider] = useState<LightClientProvider>()
const isMounted = useIsMounted()
useEffect(() => {
if (!providers.has(channelId))
providers.set(channelId, getLightClientProvider(channelId))
providers.get(channelId)?.then((provider) => {
if (!isMounted()) return
setProvider(provider)
})
}, [channelId, isMounted])
return { provider }
}
The extension page helper is conceptually the same as the web page helper,
except it is used in the user interface of your extension. By importing helper,
you can access light client functionality.
Get and set the bootnodes
const getBootNodes = async (chainId: string) =>
(await helper.getChains()).find(
({ genesisHash }) => genesisHash === wellKnownGenesisHashByChainId[chainId],
)?.bootNodes ?? []
const setBootNodes = async (chainId: string, bootNodes: string[]) =>
helper.setBootNodes(wellKnownGenesisHashByChainId[chainId], bootNodes)
Decode call data
import { getObservableClient } from "@polkadot-api/observable-client"
import { getViewBuilder } from "@polkadot-api/view-builder"
import { createClient } from "@polkadot-api/substrate-client"
import { helper } from "@substrate/light-client-extension-helpers/extension-page"
import { filter, firstValueFrom } from "rxjs"
export const decodeCallData = async (chainId: string, callData: string) => {
const chains = await helper.getChains()
const chain = chains.find(({ genesisHash }) => genesisHash === chainId)
if (!chain) throw new Error("unknown chain")
const client = getObservableClient(createClient(chain.provider))
const { metadata$, unfollow } = client.chainHead$()
try {
const metadata = await firstValueFrom(metadata$.pipe(filter(Boolean)))
return getViewBuilder(metadata).callDecoder(callData)
} finally {
unfollow()
client.destroy()
}
}
The smoldot package is a streamlined version of the original
smoldot package. Here are the key
differences:
Restarts
The smoldot client now includes a restart method. This is useful for
restarting smoldot if it unexpectedly crashes, allowing you to quickly
fire up a new instance.
Modified Add Chain Options
When smoldot restarts, all prior connections made with client.addChain
are lost. To address this, the AddChainOptions has been modified. The
potentialRelayChains parameter is now a recursive AddChainOptions array
instead of a Chain array. This ensures that when smoldot restarts and
you need to call addChain to reconnect a parachain, the associated
relaychain is always reconnected first.
Supervision
This module also provides a supervise method, which checks the health of
smoldot and automatically invokes the restart method if it detects an
issue. It does this by repeatedly calling addChain with an empty string as
the chainspec parameter. If addChain throws an error that isn't an
AddChainError, it assumes smoldot is unhealthy and restarts it.
import { start } from "@substrate/light-client-extension-helpers/smoldot"
// Initialize the smoldot client
const client = start()
// Add a chain
client.addChain({
chainSpec: "...",
potentialRelayChains: [
{
chainSpec: "...",
potentialRelayChains: [], // Recursive AddChainOptions array
},
],
})
supervise(client, { onError: console.error })
// Supervise the client
client.supervise()
The tx-helper package allows you to easily sign transactions. You just need the calldata and an implementation of the
@polkadot-api/signer interface.
import { getLightClientProvider } from "@substrate/light-client-extension-helpers/web-page"
import { connectInjectedExtension } from "@polkadot-api/pjs-signer"
import { fromHex, toHex } from "@polkadot-api/utils"
import { createTx } from "@substrate/light-client-extension-helpers/tx-helper" // 👈 create-tx import
const CHANNEL_ID = "..."
const lightClientProvider = await getLightClientProvider(CHANNEL_ID)
const createTx = async (chainId: string, from: string, callData: string) => {
const chains = Object.values(lightClientProvider.getChains())
const chain = chains.find(({ genesisHash }) => genesisHash === chainId)
if (!chain) {
throw new Error("unknown chain")
}
const injectedExt = await connectInjectedExtension("polkadot-js")
const account = injectedExt
.getAccounts()
.find((account) => toHex(account.polkadotSigner.publicKey) === from)
if (!account) {
throw new Error("no account")
}
const signer = account.polkadotSigner // 👈 @polkadot-api/signer implementation
const tx = await createTx(chain.connect)({
callData: fromHex(callData),
signer,
})
return toHex(tx)
}
FAQs
Unknown package
We found that @substrate/light-client-extension-helpers demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 15 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.

Security News
Experts push back on new claims about AI-driven ransomware, warning that hype and sponsored research are distorting how the threat is understood.

Security News
Ruby's creator Matz assumes control of RubyGems and Bundler repositories while former maintainers agree to step back and transfer all rights to end the dispute.