Radiant Developer Guide

Version 1.2 Last Updated: February 2026

1. Getting Started

Prerequisites

Quick Start

# Create new project
mkdir my-radiant-app
cd my-radiant-app
npm init -y

# Install core dependencies
npm install @radiantblockchain/radiantjs
npm install @radiantblockchain/constants

# Optional: ElectrumX client
npm install ws-electrumx-client

Hello World: Send RXD

const radiant = require('@radiantblockchain/radiantjs');

// Create a new private key
const privateKey = new radiant.PrivateKey();
console.log('Address:', privateKey.toAddress().toString());
console.log('WIF:', privateKey.toWIF());

// To send RXD, you'll need:
// 1. Fund the address
// 2. Get UTXOs from ElectrumX
// 3. Build and sign transaction
// 4. Broadcast to network

2. Development Environment

Recommended Setup

# Install global tools
npm install -g typescript ts-node

# Project structure
my-radiant-app/
├── src/
│   ├── index.ts
│   ├── wallet.ts
│   ├── transactions.ts
│   └── electrum.ts
├── tests/
├── package.json
└── tsconfig.json

TypeScript Configuration

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Environment Variables

# .env
ELECTRUMX_HOST=electrumx.radiantexplorer.com
ELECTRUMX_PORT=50012
ELECTRUMX_PROTOCOL=ssl
NETWORK=mainnet

3. radiantjs SDK

Core Modules

const radiant = require('@radiantblockchain/radiantjs');

const {
  PrivateKey,      // Key management
  PublicKey,       // Public key operations
  Address,         // Address handling
  Transaction,     // Transaction building
  Script,          // Script construction
  Opcode,          // Opcode constants
  crypto,          // Cryptographic functions
  encoding,        // Data encoding utilities
  Mnemonic,        // BIP39 seed phrases
  HDPrivateKey,    // Hierarchical deterministic keys
  Block,           // Block parsing
  Message,         // Message signing
  ECIES            // Encryption
} = radiant;

Key Management

// Generate new key
const privateKey = new radiant.PrivateKey();

// From WIF
const keyFromWIF = radiant.PrivateKey.fromWIF('your_wif_here');

// From seed phrase (BIP39)
const mnemonic = radiant.Mnemonic.fromRandom();
console.log('Seed phrase:', mnemonic.toString());

const hdKey = mnemonic.toHDPrivateKey();
const derived = hdKey.deriveChild("m/44'/0'/0'/0/0");
const address = derived.publicKey.toAddress();

Address Operations

// Create address from public key
const address = privateKey.toAddress();
console.log('Address:', address.toString());

// Validate address
const isValid = radiant.Address.isValid('1...');

// Parse address
const parsed = new radiant.Address('1A1zP1...');
console.log('Type:', parsed.type); // 'pubkeyhash' or 'scripthash'

Glyph v2 Module

const { Glyph } = require('@radiantblockchain/radiantjs');

// Constants
console.log(Glyph.GLYPH_MAGIC);              // 'gly'
console.log(Glyph.GlyphVersion.V2);          // 0x02
console.log(Glyph.GlyphProtocol.GLYPH_NFT);  // 2

// Encode metadata
const metadata = {
  v: 2, type: 'nft', p: [2],
  name: 'My NFT', desc: 'A unique token'
};
const encoded = Glyph.encodeMetadata(metadata);

// Validate protocols
const validation = Glyph.validateProtocols([1, 4]); // FT + dMint
console.log(validation.valid); // true

4. Working with Transactions

UTXO Model Basics

UTXO (Unspent Transaction Output):
┌─────────────────────────────────────┐
│ txid: abc123...                     │
│ vout: 0                             │
│ value: 100000000 (1 RXD in photons) │
│ script: <locking script>           │
└─────────────────────────────────────┘

To spend a UTXO:
1. Reference it by txid:vout
2. Provide unlocking script (signature)
3. Create new outputs

Building Transactions

const tx = new radiant.Transaction()
  .from({
    txId: 'previous_txid_here',
    outputIndex: 0,
    script: 'previous_locking_script',
    satoshis: 100000000
  })
  .to('recipient_address', 50000000)  // 0.5 RXD
  .change('change_address')
  .fee(1000)  // Fee in photons
  .sign(privateKey);

const txHex = tx.serialize();

Fee Estimation

// Radiant uses photons (1 RXD = 100,000,000 photons)
const FEE_RATE = 0.5; // photons per byte

function estimateFee(inputCount, outputCount) {
  const size = inputCount * 148 + outputCount * 34 + 10;
  return Math.ceil(size * FEE_RATE);
}

const fee = estimateFee(2, 2);  // ~165 photons

Multi-Signature

// 2-of-3 multisig
const redeemScript = radiant.Script.buildMultisigOut([
  pubKey1, pubKey2, pubKey3
], 2);

tx.from({
  txId: 'txid', outputIndex: 0,
  script: redeemScript.toScriptHashOut(),
  satoshis: amount
}, [pubKey1, pubKey2, pubKey3], 2);

tx.sign([privateKey1, privateKey2]);

5. Glyph Tokens

Token Types

TypeProtocol IDReference Type
Fungible (FT)1OP_PUSHINPUTREF
Non-Fungible (NFT)2OP_PUSHINPUTREFSINGLETON
Data (DAT)3None

Creating an NFT Script

function createNFTScript(tokenRef, ownerPkh) {
  return new Script()
    .add(Buffer.from(tokenRef, 'hex'))
    .add(Opcode.OP_PUSHINPUTREFSINGLETON)
    .add(Opcode.OP_DROP)
    .add(Opcode.OP_DUP)
    .add(Opcode.OP_HASH160)
    .add(Buffer.from(ownerPkh, 'hex'))
    .add(Opcode.OP_EQUALVERIFY)
    .add(Opcode.OP_CHECKSIG);
}

Glyph Metadata (CBOR)

const CBOR = require('cbor');

const metadata = {
  v: 2, type: 'nft', p: [2],
  name: 'My Artwork',
  desc: 'A beautiful digital creation',
  content: {
    primary: {
      path: 'artwork.png', mime: 'image/png',
      size: 102400,
      hash: { algo: 'sha256', hex: '...' },
      storage: 'inline'
    }
  }
};

const encodedMetadata = CBOR.encode(metadata);
const commitHash = crypto.createHash('sha256').update(encodedMetadata).digest();

Commit-Reveal Pattern

// Phase 1: Commit Transaction
function buildCommitTx(privateKey, utxo, commitHash) {
  const commitScript = new Script()
    .add(Opcode.OP_RETURN)
    .add(Buffer.from('gly'))       // Magic bytes
    .add(Buffer.from([0x02]))      // Version 2
    .add(Buffer.from([0x00]))      // Flags
    .add(commitHash);              // 32-byte hash

  return new Transaction()
    .from(utxo)
    .addOutput(new Transaction.Output({
      script: commitScript, satoshis: 0
    }))
    .addOutput(new Transaction.Output({
      script: Script.buildPublicKeyHashOut(privateKey.toAddress()),
      satoshis: utxo.satoshis - 1000
    }))
    .sign(privateKey);
}

// Phase 2: Reveal Transaction (creates the token)

6. Smart Contracts with RadiantScript

Overview

RadiantScript is a high-level language for writing Radiant smart contracts, compiled to Bitcoin Script with Radiant opcodes.

Installation

git clone https://github.com/Radiant-Core/RadiantScript
cd RadiantScript
yarn install

# Compile contract
npx rxdc MyContract.rxd -o MyContract.json

Basic Contract

// SimpleToken.rxd
contract SimpleToken(bytes36 REF, bytes20 PKH)
function (sig s, pubkey pk) {
    require(hash160(pk) == PKH);
    require(checkSig(s, pk));

    stateSeparator;

    bytes36 ref = pushInputRef(REF);
    bytes32 csh = hash256(tx.inputs[this.activeInputIndex].codeScript);
    require(tx.inputs.codeScriptValueSum(csh) >=
            tx.outputs.codeScriptValueSum(csh));
}

Introspection Features

// Transaction introspection
int inputCount = tx.inputCount;
int outputCount = tx.outputCount;
int myIndex = this.activeInputIndex;
int myValue = tx.inputs[myIndex].value;

// Reference tracking
int refCount = tx.outputs.refOutputCount(ref);
int refSum = tx.outputs.refValueSum(ref);

// Transaction state (OP_PUSH_TX_STATE)
bytes32 myTxId = tx.state.txId;       // Current transaction's txid
int totalIn = tx.state.inputSum;       // Total input value
int totalOut = tx.state.outputSum;     // Total output value

Induction Proof Patterns

Radiant supports two methods for mathematical induction proofs:

// Code-continuity induction: verify parent had same contract code
bytes myCodeScript = tx.inputs[this.activeInputIndex].codeScript;
bytes32 myCodeHash = hash256(myCodeScript);
require(tx.outputs.codeScriptCount(myCodeHash) >= 1);

// Fee-bounded transfer using tx.state
int fee = tx.state.inputSum - tx.state.outputSum;
require(fee >= 0);
require(fee <= maxFee);

NFT with Royalties

contract NFT(
    bytes36 REF, bytes20 OWNER_PKH,
    bytes20 CREATOR_PKH, int ROYALTY_BPS
)
function (sig s, pubkey pk) {
    require(hash160(pk) == OWNER_PKH);
    require(checkSig(s, pk));

    stateSeparator;
    bytes36 ref = pushInputRefSingleton(REF);

    if (tx.outputs[1].value > 0) {
        int salePrice = tx.outputs[1].value;
        int royalty = salePrice * ROYALTY_BPS / 10000;
        require(tx.outputs[2].value >= royalty);
        bytes20 royaltyRecipient = hash160(tx.outputs[2].lockingBytecode[3:23]);
        require(royaltyRecipient == CREATOR_PKH);
    }
}

Compile and Deploy

# Compile with debug info
npx rxdc NFT.rxd -o NFT.json --debug

# Use in JavaScript
const artifact = require('./NFT.json');
const contract = new Contract(artifact, [
  tokenRef, ownerPkh, creatorPkh, 500  // 5% royalty
]);
const lockingScript = contract.lockingScript;

7. Debugging with rxdeb

Installation

git clone --recursive https://github.com/Radiant-Core/rxdeb
cd rxdeb
./autogen.sh
./configure --enable-rxd
make
sudo make install

Basic Usage

# Debug a simple script
rxdeb '[OP_1 OP_2 OP_ADD OP_3 OP_EQUAL]'

# Debug with transaction context
rxdeb --tx=<spending_tx_hex> --txin=<input_tx_hex>

# Debug RadiantScript artifact
rxdeb --artifact=MyContract.json --function=transfer --args='["<sig>", "<pk>"]'

REPL Commands

CommandDescription
step / sExecute one instruction
continue / cRun to completion
rewind / rGo back one step
stackShow main stack
altstackShow alt stack
printShow script with position
sourceShow RadiantScript source
refsShow reference state
contextShow transaction context

8. ElectrumX Integration

WebSocket Connection

class ElectrumClient {
  constructor(host, port) {
    this.url = `wss://${host}:${port}`;
    this.requestId = 0;
    this.pending = new Map();
  }

  async connect() {
    return new Promise((resolve, reject) => {
      this.ws = new WebSocket(this.url);
      this.ws.on('open', () => resolve());
      this.ws.on('error', reject);
      this.ws.on('message', (data) => this.handleMessage(data));
    });
  }

  async request(method, params = []) {
    const id = ++this.requestId;
    return new Promise((resolve, reject) => {
      this.pending.set(id, { resolve, reject });
      this.ws.send(JSON.stringify({ id, method, params }));
    });
  }
}

Common API Methods

// Get server version
await client.request('server.version', ['myapp', '1.4']);

// Get address balance
await client.request('blockchain.scripthash.get_balance', [scriptHash]);

// Get address UTXOs
await client.request('blockchain.scripthash.listunspent', [scriptHash]);

// Get transaction
await client.request('blockchain.transaction.get', [txid, true]);

// Broadcast transaction
await client.request('blockchain.transaction.broadcast', [txHex]);

// Subscribe to address
await client.request('blockchain.scripthash.subscribe', [scriptHash]);

Script Hash Calculation

function addressToScriptHash(address) {
  const script = radiant.Script.buildPublicKeyHashOut(
    new radiant.Address(address)
  );
  const hash = crypto.createHash('sha256')
    .update(script.toBuffer()).digest();
  return hash.reverse().toString('hex');  // Reverse for Electrum
}

9. Running a Node

Docker (Recommended)

docker run -d --name radiant-node \
  -p 7332:7332 -p 7333:7333 \
  -v radiant-data:/root/.radiant \
  radiant-core:latest \
  -rpcuser=myuser -rpcpassword=mypassword

docker exec radiant-node radiant-cli getblockchaininfo

Node Profiles

radiantd -nodeprofile=archive   # Full history
radiantd -nodeprofile=agent     # Minimal footprint
radiantd -nodeprofile=mining    # Optimized for mining

RPC Integration

class RadiantRPC {
  constructor(user, pass, host = '127.0.0.1', port = 7332) {
    this.url = `http://${host}:${port}`;
    this.auth = { username: user, password: pass };
  }

  async call(method, params = []) {
    const response = await axios.post(this.url, {
      jsonrpc: '2.0', id: Date.now(), method, params
    }, { auth: this.auth });
    if (response.data.error) throw new Error(response.data.error.message);
    return response.data.result;
  }
}

const rpc = new RadiantRPC('user', 'pass');
const info = await rpc.call('getblockchaininfo');

Useful RPC Commands

radiant-cli getblockchaininfo       # Chain status
radiant-cli getblock <hash>          # Block details
radiant-cli getrawtransaction <txid> true  # TX details
radiant-cli getmempoolinfo          # Mempool stats
radiant-cli getmininginfo           # Mining stats
radiant-cli getnetworkinfo          # Network info

10. V2 Hard Fork (Radiant Core 2.1)

Overview

Radiant Core 2.1 introduces a hard fork at block 410,000 (mainnet & testnet3) that activates 6 new and re-enabled opcodes, gated behind the SCRIPT_ENHANCED_REFERENCES flag.

New Opcodes

OpcodeHexStack EffectDescription
OP_BLAKE30xeedata → hashBlake3 hash (32-byte output)
OP_K120xefdata → hashKangarooTwelve hash (32-byte output)
OP_LSHIFT0x98a b → (a << b)Bitwise left shift
OP_RSHIFT0x99a b → (a >> b)Bitwise right shift
OP_2MUL0x8da → (a * 2)Multiply by 2
OP_2DIV0x8ea → (a / 2)Divide by 2

Why These Opcodes

Using V2 Opcodes

const { Script, Opcode } = radiant;

// Blake3 hash verification
const script = new Script()
  .add(Opcode.OP_BLAKE3)
  .add(Opcode.OP_SIZE)
  .add(Script.buildNumber(32))
  .add(Opcode.OP_EQUALVERIFY);

// DAA bit-shift
const daaScript = new Script()
  .add(Script.buildNumber(1000))  // target
  .add(Script.buildNumber(2))     // shift amount
  .add(Opcode.OP_LSHIFT);        // target << 2 = 4000

Activation Heights

NetworkHeightStatus
Mainnet410,000Pending
Testnet3410,000Pending
Scalenet1,000Active
Regtest200Active

Fee Policy Change

Ecosystem Compatibility

ToolV2 Support
radiantjsOP_BLAKE3/K12 (pure JS), OP_LSHIFT/RSHIFT, OP_2MUL/2DIV in interpreter
radiantblockchain-constantsV2 opcode values and names
RadiantScriptblake3(), k12() compiler globals, tx.state.* induction proof operators
rxdebFull VM execution of all V2 opcodes
Glyph-minerBlake3/K12 GPU shaders for multi-algo mining
Photonic WalletPer-algorithm contract bytecodes
RXinDexerAnalytics-only (on-chain PoW eliminates indexer validation)

11. AI Integration (MCP Server)

The radiant-mcp-server package makes Radiant natively accessible to AI coding assistants and any HTTP client via a REST API.

Quick Setup (MCP)

{
  "mcpServers": {
    "radiant": {
      "command": "npx",
      "args": ["radiant-mcp-server"],
      "env": {
        "ELECTRUMX_HOST": "electrumx.radiant4people.com",
        "ELECTRUMX_PORT": "50012",
        "ELECTRUMX_SSL": "true"
      }
    }
  }
}

This gives AI agents access to 56 MCP tools across 9 categories, plus 10 MCP resources.

REST API

ELECTRUMX_HOST=electrumx.radiant4people.com \
ELECTRUMX_PORT=50012 ELECTRUMX_SSL=true \
node dist/rest.js

curl http://localhost:3080/api/chain
curl http://localhost:3080/api/address/1ADDRESS.../balance
curl http://localhost:3080/api/token/REF/metadata

See AI Integration Strategy for the full implementation reference.


12. Best Practices

Security

// ✅ Validate all inputs
function validateAddress(addr) {
  if (!radiant.Address.isValid(addr)) throw new Error('Invalid address');
}

// ✅ Use secure random for keys
const privateKey = radiant.PrivateKey.fromRandom();

// ❌ DON'T: Hardcode private keys
const key = new radiant.PrivateKey('WIF_HERE'); // NEVER in code!

// ✅ Use environment variables
const key = new radiant.PrivateKey(process.env.PRIVATE_KEY_WIF);

Error Handling

async function sendTransaction(txHex) {
  try {
    const result = await electrum.request(
      'blockchain.transaction.broadcast', [txHex]
    );
    return { success: true, txid: result };
  } catch (error) {
    if (error.message.includes('insufficient fee'))
      return { success: false, error: 'FEE_TOO_LOW' };
    if (error.message.includes('missing inputs'))
      return { success: false, error: 'UTXO_SPENT' };
    return { success: false, error: 'UNKNOWN', details: error.message };
  }
}

UTXO Management

// Consolidate small UTXOs
function shouldConsolidate(utxos) {
  const smallUtxos = utxos.filter(u => u.value < 10000);
  return smallUtxos.length > 10;
}

// Coin selection
function selectCoins(utxos, target) {
  const sorted = [...utxos].sort((a, b) => b.value - a.value);
  let sum = 0;
  const selected = [];
  for (const utxo of sorted) {
    selected.push(utxo);
    sum += utxo.value;
    if (sum >= target) break;
  }
  return { selected, sum };
}

13. Resources

Official Documentation

ResourceLink
Whitepaperradiantblockchain.org/radiant.pdf
System Designradiant4people.com
REP Proposalsgithub.com/Radiant-Core/REP

GitHub Repositories

RepositoryDescription
Radiant-CoreFull node
radiantjsJavaScript SDK
RadiantScriptContract compiler
rxdebScript debugger
ElectrumXElectrum server
Photonic-WalletReference wallet
constantsShared constants

Community

PlatformLink
Discorddiscord.gg/radiantblockchain
Telegramt.me/RadiantBlockchain
Twitter@RXD_Community

Tools

ToolPurposeLink
Block ExplorerView transactionsradiantexplorer.com
Glyph ExplorerBrowse tokensglyph-explorer
Server StatusElectrumX healthelectrumx-check
FaucetTestnet RXDfaucet