@radiant-core/sdk is the clean TypeScript SDK most web and app developers reach for first. It lets you build Radiant (RXD) dapps — wallets, marketplaces, games, payment flows — without reading internal wallet or library source. It wraps radiantjs (the low-level tx/script library) and adds the ecosystem-specific pieces app devs actually need.
alice.rxd → address.m/44'/512'/0'/0/k (SLIP-0044 coin type 512).BigInt throughout.@radiant-core/sdk is the application layer built on top of it (networking, token-safe funding, Glyph, WAVE, units). You install only the SDK — radiantjs comes along as a dependency and you never touch its API directly.
npm install @radiant-core/sdk
# Node < 22 has no global WebSocket — also install the optional peer:
npm install ws
Requires Node 20.19+ or 22+ (radiantjs pulls in an ESM-only dependency that needs require(ESM) support). Ships dual ESM + CJS with bundled types.
BigInt — 1 RXD = 100,000,000 photons. Convert only at your UI edge with rxdToPhotons() / photonsToRxd(). Never do balance math in floating point.
The ElectrumClient speaks JSON-RPC over a single reconnecting WebSocket. Scripthash methods accept a plain address (the scripthash is computed for you).
import { ElectrumClient, photonsToRxd } from '@radiant-core/sdk';
const client = new ElectrumClient({ network: 'mainnet' });
await client.connect();
const address = '1Yourradiantaddress...';
const { confirmed, unconfirmed } = await client.getBalance(address);
console.log(`Confirmed: ${photonsToRxd(confirmed)} RXD`);
const utxos = await client.listUnspent(address); // Utxo[] (photons as BigInt)
// React to incoming payments:
await client.subscribe(address, (status) => {
console.log('address changed:', status); // re-fetch balance/UTXOs here
});
The default mainnet endpoint is wss://electrumx.radiantcore.org:443; pass endpoint to point at your own ElectrumX/RXinDexer.
Create or restore a BIP39 HD wallet. Derivation defaults to the Radiant path m/44'/512'/account'/0/index.
import { HDWallet } from '@radiant-core/sdk';
// New wallet
const mnemonic = HDWallet.generateMnemonic();
const wallet = HDWallet.fromMnemonic(mnemonic, { network: 'mainnet' });
const me = wallet.deriveKey(0); // m/44'/512'/0'/0/0
console.log(me.path, me.address, me.scriptHash);
// Batch derive a gap of receive addresses
const receive = wallet.deriveRange(0, 20); // DerivedKey[]
The single most important safety property of the SDK: funding is never gathered by a value heuristic. A UTXO that carries a token ref (FT/NFT/dMint) looks like plain value to a naive selector, but spending it as funding burns the token. selectRxdFunding screens every candidate two ways — indexer-reported refs and a local script scan — and silently excludes token UTXOs.
import { ElectrumClient, HDWallet, buildRxdTransfer, rxdToPhotons } from '@radiant-core/sdk';
const client = new ElectrumClient({ network: 'mainnet' });
const wallet = HDWallet.fromMnemonic(mnemonic);
const me = wallet.deriveKey(0);
const utxos = await client.listUnspent(me.address);
const { hex, txid } = buildRxdTransfer({
address: me.address,
wif: me.wif,
to: '1Recipient...',
amount: rxdToPhotons('1.25'), // 1.25 RXD -> photons
utxos, // token-bearing UTXOs are auto-excluded
feeRate: 10_000n, // photons/byte (mainnet min-relay)
});
await client.broadcastTx(hex);
console.log('sent', txid);
filterFundingCandidates(utxos) or guard with assertFundingSafe(utxos) first.
Mint and move Glyph tokens with the commit/reveal pattern handled for you. Fund from token-free UTXOs.
import { mintFT, mintNFT, transferToken, filterFundingCandidates } from '@radiant-core/sdk';
const funding = filterFundingCandidates(await client.listUnspent(me.address));
// Fungible token (FT amount == output photons)
const ft = await mintFT({
client, address: me.address, wif: me.wif,
ticker: 'DEMO',
supply: 1_000_000n,
metadata: { name: 'Demo Token', desc: 'Minted with @radiant-core/sdk' },
fundingUtxos: funding,
});
console.log('FT ref:', ft.refDisplay, ft.commitTxid, ft.revealTxid);
// Non-fungible token (singleton)
const nft = await mintNFT({
client, address: me.address, wif: me.wif,
metadata: { name: 'My NFT', attrs: { rarity: 'rare' } },
fundingUtxos: funding,
});
// Transfer a token (FT or NFT) to a new owner
await transferToken({
client, address: me.address, wif: me.wif,
tokenUtxo, // the FT/NFT UTXO (must include its on-chain script)
toAddress: '1Recipient...',
fundingUtxos: funding, // covers the fee; token value is conserved
});
scriptHash(zeroRefs(tokenScript)), not the owner's plain address. To list a held token, query client.listUnspent(scriptHash(zeroRefs(ftScript(owner, ref)))) — the entries come back with refs:[{ ref, type }] (type is "normal" for FT, "single" for an NFT singleton).
mintFT / mintNFT / transferToken broadcast real, irreversible transactions. They reproduce the proven Photonic-Wallet on-chain templates and are regtest-validated, but you should smoke-test your own flow on regtest/testnet before mainnet.
Resolve WAVE names to addresses through the public indexer.
import { waveResolve, waveResolveAddress } from '@radiant-core/sdk';
const rec = await waveResolve('alice'); // "alice.rxd" works too
if (rec.registered) console.log(rec.address, rec.owner, rec.expires);
const addr = await waveResolveAddress('alice'); // string | null
| Area | Exports |
|---|---|
| Client | ElectrumClient |
| Wallet | HDWallet, Keys |
| Funding | selectRxdFunding, filterFundingCandidates, isFundingSafe, assertFundingSafe, estimateFee, sumValue |
| Transactions | buildRxdTransfer, buildTx |
| Tokens | mintFT, mintNFT, transferToken, encodeGlyph, ftScript, nftScript, parseTokenRef |
| WAVE | waveResolve, waveResolveAddress, waveLabel |
| Script | scriptHash, addressToScriptHash, p2pkhScript, isTokenBearing, zeroRefs, packRef, unpackRef |
| Units | rxdToPhotons, photonsToRxd |
| Errors | RadiantSdkError, InsufficientFundsError, TokenBurnGuardError, ElectrumError, ValidationError |
Full reference (every export, options, and return types) is in docs/API.md.
Validated end-to-end. The SDK ships with unit tests (CI on Node 20/22/24), on-chain consensus validation against a radiantd regtest node (FT/NFT mint + transfer accepted), and indexer validation against RXinDexer/ElectrumX (tokens surfaced via listUnspent with their refs).
Fee policy. Mainnet min-relay is 10,000 photons/byte; testnet/regtest is 1,000. The SDK sets the fee from the measured signed transaction size, so token transactions reliably clear the floor.
| Resource | Link |
|---|---|
| npm package | @radiant-core/sdk |
| Source & issues | github.com/Radiant-Core/radiant-sdk |
| API reference | docs/API.md |
| Low-level library | radiantjs |
| Related guides | Developer Guide · Token Creation · WAVE Names |