Rivellum

Rivellum Portal

Download Wallet (Chrome)
Checking...
testnet

Core TypeScript SDK (`@rivellum/sdk`)

The official TypeScript/JavaScript SDK for interacting with the Rivellum network. Covers account queries, encrypted envelope submission, smart contracts, NFTs, the native ledger, randomness, prefabs, governance, bridge, XCM, tokenomics, and the constraint engine.

Installation

npm install @rivellum/sdk
# or
pnpm add @rivellum/sdk
# or
yarn add @rivellum/sdk

Quick Start

import { RivellumClient } from '@rivellum/sdk';

const client = new RivellumClient({
  nodeUrl: 'https://rpc.rivellum.network',
  timeout: 30_000,
});

// Check health
const ok = await client.isHealthy();

// Get balance
const balance = await client.getBalance('a1b2c3...64hexchars');
console.log(balance.balance); // e.g. "1000000000"

RivellumClient

Constructor

new RivellumClient(config: ClientConfig)
ParameterTypeRequiredDescription
config.nodeUrlstringNode RPC URL. Must be https:// — localhost/loopback throws ValidationError.
config.timeoutnumberRequest timeout in milliseconds. Default: 30000.

Properties:

  • .prefabsPrefabClient instance (prefab discovery)
  • .randomRandomnessClient instance (VRF randomness)
const client = new RivellumClient({
  nodeUrl: 'https://rpc.rivellum.network',
  timeout: 60_000,
});

Account Methods

getBalance(address)

async getBalance(address: string): Promise<Balance>

Returns the native balance, nonce, and all asset sub-balances for an address.

Parameters:

NameTypeDescription
addressstring32-byte hex address. 0x prefix optional. Must be 64 hex chars.

Returns: Balance

interface Balance {
  address: string;
  balance: string;                      // Native balance as decimal string
  nonce: number;                        // Replay-protection nonce
  balances?: Record<string, string>;    // Asset sub-balances keyed by asset ID (hex)
}

Throws: ValidationError if address is not 64 hex characters.

const bal = await client.getBalance('a1b2...c3d4');
console.log(`Native: ${bal.balance}, Nonce: ${bal.nonce}`);
if (bal.balances) {
  for (const [assetId, amount] of Object.entries(bal.balances)) {
    console.log(`Asset ${assetId}: ${amount}`);
  }
}

getSessionKeys(address)

async getSessionKeys(address: string): Promise<SessionKey[]>

Returns all session keys associated with an account.

Parameters:

NameTypeDescription
addressstring32-byte hex address (64 chars, 0x prefix optional).

Returns: SessionKey[]

interface SessionKey {
  public_key: { key: string };
  policy: {
    allowed_contracts: string[];
    max_gas_per_intent: number;
    expiration_ms: number;
    max_calls: number;
  };
  calls_used: number;
  revoked: boolean;
  created_at_ms: number;
}
const keys = await client.getSessionKeys('a1b2...c3d4');
for (const sk of keys) {
  if (!sk.revoked) {
    console.log(`Key: ${sk.public_key.key}`);
    console.log(`Calls: ${sk.calls_used} / ${sk.policy.max_calls}`);
  }
}

createSessionKey(params)

async createSessionKey(params): Promise<string>

Creates an account-scoped session key using the auth endpoints. The SDK attempts these routes in order:

  • /v1/session-keys/create
  • /v1/account/session-keys/create
  • /v1/auth/session-keys/create

Returns the transaction/intent identifier reported by the node.


revokeSessionKey(params)

async revokeSessionKey(params): Promise<string>

Revokes an account-scoped session key. The SDK attempts these routes in order:

  • /v1/session-keys/revoke
  • /v1/account/session-keys/revoke
  • /v1/auth/session-keys/revoke

Returns the transaction/intent identifier reported by the node.


getAccountAuth(address)

async getAccountAuth(address: string): Promise<AccountAuth | null>

Returns the account's authentication configuration, or null if using the default Dilithium3 key scheme.


Envelope Submission

Rivellum uses encrypted envelopes as the canonical way to submit intents. Plaintext intent submission is permanently disabled. Envelopes flow through the lifecycle:

received → admitted → batched → sealed → decrypted → ordered → executed → finalized

submitEnvelope(envelope)

async submitEnvelope(envelope: EncryptedEnvelope): Promise<EnvelopeSubmitResult>

Submits a single encrypted envelope. This is the canonical submission method.

Parameters:

NameTypeDescription
envelopeEncryptedEnvelopePre-built encrypted envelope (see Envelope Builder).

Returns: EnvelopeSubmitResult

interface EnvelopeSubmitResult {
  status: 'accepted' | 'rejected';
  envelope_id: string;         // 64-hex identifier for status polling
  batch_window_id?: string;    // Assigned batch window (present on accepted)
  rejection_reason?: string;   // Error code (present on rejected)
}
const result = await client.submitEnvelope(myEnvelope);
if (result.status === 'accepted') {
  console.log(`Envelope ${result.envelope_id} in batch ${result.batch_window_id}`);
  // Poll until finalized
  let status = await client.getEnvelopeStatus(result.envelope_id);
  while (status && status.status !== 'finalized' && status.status !== 'rejected') {
    await new Promise(r => setTimeout(r, 2000));
    status = await client.getEnvelopeStatus(result.envelope_id);
  }
}

submitEnvelopeBatch(envelopes)

async submitEnvelopeBatch(envelopes: EncryptedEnvelope[]): Promise<EnvelopeBatchSubmitResult>

Submits up to 10,000 envelopes in a single HTTP request. Each envelope is validated independently.

Parameters:

NameTypeDescription
envelopesEncryptedEnvelope[]Array of encrypted envelopes. Max 10,000.

Returns: EnvelopeBatchSubmitResult

interface EnvelopeBatchSubmitResult {
  accepted: number;
  rejected: number;
}

getEnvelopeStatus(envelopeId)

async getEnvelopeStatus(envelopeId: string): Promise<EnvelopeStatusResponse | null>

Returns the current lifecycle stage of an envelope, or null if not found.

Returns: EnvelopeStatusResponse | null

interface EnvelopeStatusResponse {
  envelope_id: string;
  status: EnvelopeStatusValue;
  sender: string;
  nonce: number;
  lane_id: string;
  epoch_id: number;
  max_fee: string;
  batch_id?: string;           // Set once batched
  rejection_reason?: string;   // Set if rejected
  admitted_at_ms?: number;
  sealed_at_ms?: number;
  intent_id?: string;          // Set once decrypted/ordered
}

type EnvelopeStatusValue =
  | 'received'   // Received by node, not yet validated
  | 'admitted'   // Passed admission checks, in a batch window
  | 'batched'    // Added to a batch
  | 'sealed'     // Batch sealed, contents still encrypted
  | 'decrypted'  // Epoch key released, contents revealed
  | 'ordered'    // Intent placed in execution order
  | 'executed'   // Intent executed by Mist VM
  | 'finalized'  // State root committed
  | 'rejected';  // Rejected (see rejection_reason)

getBatchInfo(batchId)

async getBatchInfo(batchId: string): Promise<BatchInfoResponse | null>

Returns metadata about a sealed batch, or null if not found.

Returns: BatchInfoResponse | null

interface BatchInfoResponse {
  batch_id: string;
  lane_id: string;
  epoch_id: number;
  state: BatchLifecycleState;
  envelope_count: number;
  total_bytes: number;
  seal_hash?: string;          // Commitment hash (after sealing)
  envelope_ids: string[];
  sealed_at_ms?: number;
}

type BatchLifecycleState =
  | 'filling'    // Accepting new envelopes
  | 'sealed'     // Closed, contents encrypted
  | 'decrypted'  // Epoch key applied
  | 'ordered'    // Intents ordered for execution
  | 'dispatched' // Sent to execution engine

getAdmissionTicket(intentId)

async getAdmissionTicket(intentId: string): Promise<AdmissionTicket | null>

Returns the admission ticket tracking an intent's pipeline lifecycle, or null if not found.

Returns: AdmissionTicket | null

interface AdmissionTicket {
  admission_id: string;
  sender: string;
  validated_nonce: number;
  intent_id: string;
  idempotency_key?: string;
  accepted_at_ms: number;
  status: 'admitted' | 'dispatched' | 'committed' | 'finalized';
}

sendIntent() 🚫 Permanently Disabled

async sendIntent(intent: Intent): Promise<SendIntentResult>

Status: PERMANENTLY DISABLED. The plaintext intent endpoint returns 410 Gone. Calling this method throws immediately with an error explaining to use submitEnvelope().


submitTransparentIntent() 🚫 Permanently Disabled

Status: PERMANENTLY DISABLED. Same as above — throws immediately.


Contract Methods

contract(contractId)

contract(contractId: string): ContractHandle

Returns a ContractHandle bound to a deployed Mist contract.

interface ContractHandle {
  call(functionName: string, args?: Record<string, unknown>): Promise<ContractCallResult>;
}

interface ContractCallResult {
  receipt_id: string;
  contract_id: string;
  function: string;
  status: string;
  intent_id?: string;
}
const counter = client.contract('0xdeadbeef...64hex');
const result = await counter.call('increment', { by: 5 });
console.log(result.receipt_id);

simulateIntent(intent, options?)

async simulateIntent(intent: Intent, options?: SimulateIntentOptions): Promise<SimulationResult>

Dry-run an intent to predict gas usage, fees, and state changes without committing.

Parameters:

NameTypeDefaultDescription
intentIntentIntent to simulate (signed or unsigned).
options.atHeightnumberSimulate at a specific ledger height.
options.maxGasOverridenumberOverride max gas limit.
options.validateSignaturebooleanfalseCheck signature validity.

Returns: SimulationResult

interface SimulationResult {
  status: 'success' | 'failed';
  gas_used: number;
  fee_estimate: string;   // In native token units
  state_diff?: {
    touched_accounts: string[];
    balance_changes: [string, string, string][];  // [address, assetId, delta]
  };
  failure_reason?: string;
}
const sim = await client.simulateIntent(intent, { validateSignature: true });
if (sim.status === 'success') {
  console.log(`Costs ${sim.fee_estimate} — proceeds`);
  for (const [addr, asset, delta] of sim.state_diff?.balance_changes ?? []) {
    console.log(`  ${addr}: ${asset} ${delta}`);
  }
}

Ledger Methods

getLedgerTip()

async getLedgerTip(): Promise<LedgerTip>

Returns the latest committed ledger state.

Returns:

interface LedgerTip {
  height: number;      // Global ledger height
  root: string;        // Meta-root hash (hex)
  timestamp_ms: number;
}

getLedgerEntries(from?, to?)

async getLedgerEntries(from?: number, to?: number): Promise<LedgerEntriesResponse>

Query ledger events in a height range.

ParameterTypeDescription
fromnumber?Start height (inclusive).
tonumber?End height (inclusive).

getRecentIntents(n?)

async getRecentIntents(n?: number): Promise<RecentIntentsResponse>

Returns up to n (default 50, max 1000) recently executed intents, deduplicated and sorted by batch height descending.

Returns:

interface RecentIntentsResponse {
  intents: IntentSummary[];
  total: number;
}
interface IntentSummary {
  intent_id: string;
  sender: string;
  height: number;
  status: 'committed' | 'failed';
  gas_used: number;
  fee_charged: number;
  timestamp_ms: number;
}

getAccountTimeline(address, options?)

async getAccountTimeline(
  address: string,
  options?: { limit?: number; beforeHeight?: number }
): Promise<AccountTimelineResponse>

Returns all events touching an account. Performs a parallel fan-out over 5 event query filters:

  • Events by address
  • Events by contract
  • native.mint events
  • native.transfer events
  • native.asset_transfer events

Results are deduplicated, filtered to match the address, and sorted by batch height descending.

Parameters:

NameTypeDefaultDescription
addressstring32-byte hex address (64 chars).
options.limitnumber50Max entries. Capped at 1000.
options.beforeHeightnumberOnly return events before this height.

Note: Internally fetches up to max(limit × 20, 2000) events per query (paginated, max 50 pages each) to ensure coverage.


getIntent(intentId)

async getIntent(intentId: string): Promise<IntentDetailsResponse>

Returns all events associated with a specific intent ID. Paginates /v1/events/query?intent_id= until exhausted.


getTopAccounts(n?) 🚫 Unsupported

async getTopAccounts(n?: number): Promise<TopAccountsResponse>

Status: 501 Intentionally Unsupported. Throws NodeError. Not part of production-critical distributed network APIs.


PoUW Methods

getProvers()

async getProvers(): Promise<ProverStats[]>

Returns statistics for all registered PoUW provers.

Returns: ProverStats[]

interface ProverStats {
  prover_id: string;
  jobs_completed: number;
  jobs_failed: number;
  total_fee_earned: string;
  avg_completion_time_ms: number;
  last_seen_ms: number;
}

getProverStats(proverId)

async getProverStats(proverId: string): Promise<ProverStats>

Returns stats for one specific prover. Internally calls getProvers() and filters. Throws NodeError with 404 status if not found.


getPendingJobs()

async getPendingJobs(): Promise<JobSummary[]>

Returns the list of pending proof jobs.

Returns: JobSummary[]

interface JobSummary {
  job_id: string;
  tier: 'Low' | 'Medium' | 'High';
  trace_hash: number[];
  fee_budget: string;
  created_at_ms: number;
  deadline_ms: number;
}

Health Methods

health()

async health(): Promise<HealthResponse>

Returns:

interface HealthResponse {
  status: string;    // 'ok' when healthy
  service: string;
}

isHealthy()

async isHealthy(): Promise<boolean>

Returns true if health().status === 'ok', false on any error.


getNodeUrl()

getNodeUrl(): string

Returns the configured node URL string.


Epoch Methods

getCurrentEpoch()

async getCurrentEpoch(): Promise<CurrentEpochResponse>

Derives the current epoch from governance params (epoch length in slots) and the current ledger height.

Returns:

interface CurrentEpochResponse {
  epoch_id: number;
  start_height: number;
  end_height: number;
  current_height: number;
  progress: number;   // 0.0 – 1.0
}

getEpochInfo(epochId)

async getEpochInfo(epochId: number): Promise<EpochInfoResponse>

Returns start/end height range for a historical epoch.

Returns:

interface EpochInfoResponse {
  epoch_id: number;
  start_height: number;
  end_height: number;
  status: string;
}

Bridge Methods

lockAsset(from, asset, amount, destinationChain, foreignRecipient)

async lockAsset(
  from: string,
  asset: string,
  amount: string,
  destinationChain: string,
  foreignRecipient: string
): Promise<BridgeOperationResponse>

Locks an asset on Rivellum to initiate a bridge transfer to a foreign chain.

ParameterTypeDescription
fromstringSender address on Rivellum (hex).
assetstringAsset ID to lock (hex).
amountstringAmount as decimal string (avoids precision loss).
destinationChainstringTarget chain ID, e.g. 'ethereum-mainnet'.
foreignRecipientstringRecipient address on the foreign chain (hex).

mintBridgedAsset(proof, asset, amount, recipient)

async mintBridgedAsset(
  proof: BridgeProofData,
  asset: string,
  amount: string,
  recipient: string
): Promise<BridgeOperationResponse>

Mints bridged assets on Rivellum after presenting a proof from the foreign chain.


getBridgeMessages(query?)

async getBridgeMessages(query?: BridgeMessagesQuery): Promise<BridgeMessage[]>

Lists bridge messages with optional filters.

interface BridgeMessagesQuery {
  status?: string;
  chain?: string;
  direction?: string;   // 'inbound' | 'outbound'
}

sendCrossChainMessage(params)

Submits a cross-chain message through the XCM/bridge send surface. The SDK attempts these routes in order:

  • /xcm/send
  • /v1/xcm/send
  • /bridge/send
  • /v1/bridge/send

Returns a normalized response with msg_id, nonce, and status.


getCrossChainMessages(query?)

async getCrossChainMessages(query?: XcmMessagesQuery): Promise<XcmMessagesResponse>
interface XcmMessagesQuery {
  source_chain?: string;
  dest_chain?: string;
  src_address?: string;
  dest_address?: string;
  status?: string;
  limit?: number;
  cursor?: string;
}
interface XcmMessagesResponse {
  messages: CrossChainMessage[];
  total: number;
  next_cursor?: string;
}

getCrossChainMessage(msgId)

async getCrossChainMessage(msgId: string): Promise<CrossChainMessage>

Get full details for a specific XCM message by ID.


watchCrossChainMessage(msgId, callback, pollingIntervalMs?)

watchCrossChainMessage(
  msgId: string,
  callback: (message: CrossChainMessage) => void,
  pollingIntervalMs?: number   // Default: 5000
): () => void

Polls for status changes on a cross-chain message and calls callback whenever the status changes. Returns a cleanup function.

const stop = client.watchCrossChainMessage('0x1234...', (msg) => {
  console.log('Status:', msg.status);
  if (msg.status === 'Executed') stop();
});

Governance Methods

createProposal(request)

async createProposal(request: CreateProposalRequest): Promise<GovernanceOperationResponse>
interface CreateProposalRequest {
  governanceAddress: string;
  paramKey: string;
  newValue: unknown;
  votingPeriodMs?: number;  // Default: 86400000 (24h)
  from: string;
}

vote(request)

async vote(request: VoteRequest): Promise<GovernanceOperationResponse>
interface VoteRequest {
  governanceAddress: string;
  proposalId: number;
  support: boolean;
  from: string;
}

executeProposal(governanceAddress, proposalId, from?)

async executeProposal(
  governanceAddress: string,
  proposalId: number,
  from?: string
): Promise<GovernanceOperationResponse>

Executes a passed governance proposal.


listProposals(governanceAddress)

async listProposals(governanceAddress: string): Promise<Proposal[]>

Lists governance history from /governance/history.


getProposal(governanceAddress, proposalId)

async getProposal(governanceAddress: string, proposalId: number): Promise<Proposal>

Fee Tiers

getFeeTiers()

getFeeTiers(): FeeTierInfo[]

Returns the three fee tier definitions. Synchronous.

type IntentTier = 'Premium' | 'Medium' | 'Micro';

interface FeeTierInfo {
  tier: IntentTier;
  range: { min_usd_micros: number; max_usd_micros: number };
  description: string;
  use_cases: string[];
}
TierFee RangeUse Cases
Premium$0.10 – $0.50Contract calls, ZK proofs, bridge, DeFi
Medium$0.01 – $0.05NFTs, hooks, marketplace, contract game actions
Micro$0.001 – $0.005Wallet transfers, game loops, AI agent updates

isValidFeeForTier(tier, feeUsdMicros)

isValidFeeForTier(tier: IntentTier, feeUsdMicros: number): boolean

Returns true if feeUsdMicros falls within the tier's range. Synchronous.


getRecommendedFee(tier)

getRecommendedFee(tier: IntentTier): number

Returns the midpoint of the tier's range. Synchronous.


getOperationTier(operationType)

getOperationTier(operationType: OperationType): IntentTier

Classifies an operation type into its fee tier. Synchronous.


getOperationInfo(operationType)

getOperationInfo(operationType: OperationType): OperationInfo

Returns full fee info (typical, min, max, description) for an operation. Synchronous.

interface OperationInfo {
  type: OperationType;
  tier: IntentTier;
  typical_fee_usd_micros: number;
  min_fee_usd_micros: number;
  max_fee_usd_micros: number;
  description: string;
}

Operation type fees (usd micros):

OperationTypicalMinMax
BasicContractCall200,000200,000200,000
StatefulContractUpdate250,000250,000250,000
AmmSwapSingle250,000250,000250,000
AmmSwapMulti350,000300,000400,000
LendingOperation275,000250,000300,000
Liquidation450,000400,000500,000
OraclePublish250,000200,000300,000
ZkProofVerification400,000300,000500,000
BridgeTransfer425,000350,000500,000
BridgeMessage300,000250,000350,000
BridgeProofVerification350,000300,000400,000
NftTransfer20,00020,00020,000
NftMintBurn35,00030,00040,000
MarketplaceSale45,00040,00050,000
TokenTransferWithHook25,00020,00030,000
GameActionContract20,00020,00020,000
WalletTransfer1,0001,0001,000
GameTick1,5001,0002,000
GameResourceUpdate1,5001,0002,000
AiAgentUpdate2,5002,0003,000
AgentMessaging2,0001,0003,000

getOperationsForTier(tier)

getOperationsForTier(tier: IntentTier): OperationType[]

Returns all operation types in a given tier. Synchronous.


getOperationFee(operationType)

getOperationFee(operationType: OperationType): number

Returns the typical fee for one operation type. Synchronous.


Tokenomics Methods

All tokenomics methods accept an optional indexerUrl parameter. If omitted, they use the default public indexer: https://api.rivellum.network.

getTokenomicsStats(indexerUrl?)

async getTokenomicsStats(indexerUrl?: string): Promise<TokenomicsStats>

Returns top-level tokenomics statistics (total supply, circulating supply, burned, etc.).


getPoolSnapshots(params?, indexerUrl?)

async getPoolSnapshots(
  params?: { start_height?: number; end_height?: number; limit?: number },
  indexerUrl?: string
): Promise<MiningPoolSnapshot[]>

Returns historical Mining Pool balance snapshots.


getLatestPoolSnapshot(indexerUrl?)

async getLatestPoolSnapshot(indexerUrl?: string): Promise<MiningPoolSnapshot>

Returns the most recent Mining Pool snapshot.


getAllocations(indexerUrl?)

async getAllocations(indexerUrl?: string): Promise<AllocationRecord[]>

Returns all genesis allocation records.


getVestingUnlocks(allocationType?, limit?, indexerUrl?)

async getVestingUnlocks(
  allocationType?: string,
  limit?: number,          // Default 100, max 1000
  indexerUrl?: string
): Promise<VestingUnlock[]>

Returns vesting unlock events for a specific allocation type, or aggregates all types if allocationType is omitted.


getFeeFlows(params?, indexerUrl?)

async getFeeFlows(
  params?: { start_height?: number; end_height?: number; limit?: number },
  indexerUrl?: string
): Promise<TokenomicsFeeFlow[]>

Returns fee flow history. Fee split: 65% validator/proving pool, 25% Rivellum treasury, 10% burn.


getOperatorRewards(params?, indexerUrl?)

async getOperatorRewards(
  params?: { start_height?: number; end_height?: number; limit?: number },
  indexerUrl?: string
): Promise<OperatorRewardDistribution[]>

getCpiAdjustments(params?, indexerUrl?)

async getCpiAdjustments(
  params?: { start_height?: number; end_height?: number; limit?: number },
  indexerUrl?: string
): Promise<CpiAdjustment[]>

Returns CPI adjustment history.


getProverRewards(proverId, indexerUrl?)

async getProverRewards(proverId: string, indexerUrl?: string): Promise<ProverRewardsSummary>

Returns accumulated reward data for a specific prover.


getFeeSummary(options?, indexerUrl?)

async getFeeSummary(
  options?: { from_height?: number; to_height?: number; limit?: number },
  indexerUrl?: string
): Promise<FeeSummary>

getSupplySnapshots(limit?, indexerUrl?)

async getSupplySnapshots(limit?: number, indexerUrl?: string): Promise<SupplySnapshotsResponse>

Analytics Methods

Analytics methods use https://api.rivellum.network as the default base URL. Override with analyticsUrl.

getAnalyticsEvents(params?, analyticsUrl?)

async getAnalyticsEvents(
  params?: EventsQueryParams,
  analyticsUrl?: string
): Promise<EventsResponse>
interface EventsQueryParams {
  topic?: string;
  contract?: string;
  limit?: number;
  cursor?: string;
}

getAccountActivity(address, params?, analyticsUrl?)

async getAccountActivity(
  address: string,
  params?: AnalyticsQueryParams,
  analyticsUrl?: string
): Promise<AccountActivityResponse>

Returns the activity timeline for an account via the analytics indexer.


getContractEvents(params?, analyticsUrl?)

async getContractEvents(
  params?: EventsQueryParams,
  analyticsUrl?: string
): Promise<EventsResponse>

getContractCalls(address, params?, analyticsUrl?)

async getContractCalls(
  address: string,
  params?: ContractCallsQueryParams,
  analyticsUrl?: string
): Promise<ContractCallsResponse>
interface ContractCallsQueryParams {
  entrypoint?: string;
  limit?: number;
  cursor?: string;
}

Protocol Methods

getProtocolVersion()

async getProtocolVersion(): Promise<ProtocolVersionInfo>

Returns chain version, chain ID, genesis hash, and active feature flags from /v1/chain.


getProtocolUpgrades()

async getProtocolUpgrades(): Promise<UpgradesListResponse>

Returns all past and scheduled protocol upgrades with activation heights.


NFT Methods

getNftMetadata(nftId)

async getNftMetadata(nftId: string): Promise<NftMetadata>

Returns NFT metadata for a given NFT ID (hex-encoded).


getNftsOwnedBy(address, page?, limit?)

async getNftsOwnedBy(
  address: string,
  page?: number,    // Default: 1
  limit?: number    // Default: 50
): Promise<NftListResponse>

getNftTransferHistory(nftId, page?, limit?)

async getNftTransferHistory(
  nftId: string,
  page?: number,    // Default: 1
  limit?: number    // Default: 50
): Promise<NftTransferHistoryResponse>

listCollections(page?, limit?)

async listCollections(page?: number, limit?: number): Promise<CollectionListResponse>

getCollection(collectionId)

async getCollection(collectionId: string): Promise<NftCollection>

getCollectionNfts(collectionId, page?, limit?)

async getCollectionNfts(
  collectionId: string,
  page?: number,
  limit?: number
): Promise<NftListResponse>

Native Ledger Methods

The Native Ledger handles fungible tokens and NFTs on-chain. Asset IDs are derived using BLAKE3 — see NativeLedger Helpers.

getNativeLedgerBalance(address, assetId)

async getNativeLedgerBalance(
  address: string,
  assetId: string
): Promise<NativeLedgerBalance>

Returns the balance of a specific asset for an account.

Both address and assetId must be 64 hex characters.

interface NativeLedgerBalance {
  address: string;
  asset_id: string;
  balance: string;
}

getNativeLedgerBalances(address)

async getNativeLedgerBalances(address: string): Promise<NativeLedgerBalance[]>

Returns all asset balances for an account.


nativeLedgerTransfer(params)

async nativeLedgerTransfer(params: NativeLedgerTransferParams): Promise<NativeLedgerOperationResult>
interface NativeLedgerTransferParams {
  from: string;
  to: string;
  assetId: string;
  amount: string;
  privacy?: boolean;    // Default: true
  maxGas?: number;
}
interface NativeLedgerOperationResult {
  txHash: string;
  status: string;
  gas_used?: number;
}

nativeLedgerMint(params)

async nativeLedgerMint(params: NativeLedgerMintParams): Promise<NativeLedgerOperationResult>
interface NativeLedgerMintParams {
  account: string;
  assetId: string;
  amount: string;
  privacy?: boolean;
  maxGas?: number;
}

nativeLedgerBurn(params)

async nativeLedgerBurn(params: NativeLedgerBurnParams): Promise<NativeLedgerOperationResult>
interface NativeLedgerBurnParams {
  account: string;
  assetId: string;
  amount: string;
  privacy?: boolean;
  maxGas?: number;
}

getNativeLedgerEvents(query)

async getNativeLedgerEvents(query: NativeLedgerEventsQuery): Promise<NativeLedgerEventsResponse>
interface NativeLedgerEventsQuery {
  asset_id?: string;
  account?: string;
  from_height?: number;
  to_height?: number;
  cursor?: string;
  limit?: number;
}

estimateNativeLedgerTransferGas(params)

async estimateNativeLedgerTransferGas(params: NativeLedgerTransferParams): Promise<NativeLedgerGasEstimate>
interface NativeLedgerGasEstimate {
  base_gas: number;
  privacy_overhead: number;
  total_gas: number;
  fee_estimate: string;
}

Gas constants:

OperationGas Units
Transfer (base)500
Mint (base)1,000
Burn (base)500
Privacy overhead2,000
Balance query100

estimateNativeLedgerMintGas(params) / estimateNativeLedgerBurnGas(params)

Same signature as estimateNativeLedgerTransferGas but for mint/burn params respectively.


Constraint Engine Methods

The constraint engine enforces per-asset compliance rules (transfer limits, freeze lists, KYC requirements).

getAssetConstraints(assetId)

async getAssetConstraints(assetId: string): Promise<AssetConstraintInfo>

Returns the full constraint binding, policies, capability flags, and pause state for an asset. If the asset has no constraint binding, constrained will be false.

assetId must be 64 hex characters.

interface AssetConstraintInfo {
  asset_id: string;
  constrained: boolean;
  policy_id?: string;
  paused?: boolean;
  capabilities?: string[];
}

preflightConstraint(assetId, sender, receiver, amount)

async preflightConstraint(
  assetId: string,
  sender: string,
  receiver: string,
  amount: string
): Promise<ConstraintPreflightResult>

Dry-run a constraint check: tests whether a transfer would pass without actually submitting.

interface ConstraintPreflightResult {
  allowed: boolean;
  denial_reason?: string;
}

getConstraintPolicy(policyId)

async getConstraintPolicy(policyId: string): Promise<ConstraintPolicyDefinition>

Returns the policy definition for a given policy ID (64 hex chars).


getAccountFreezeStatus(assetId, account)

async getAccountFreezeStatus(assetId: string, account: string): Promise<AccountFreezeStatus>

Checks whether an account is frozen for a specific asset.

interface AccountFreezeStatus {
  frozen: boolean;
  reason?: string;
  frozen_at_ms?: number;
}

RandomnessClient (client.random)

VRF-based randomness backed by the Rivellum beacon chain. All values are derived from BLAKE3 with domain separation.

getBeacon()

async getBeacon(): Promise<BeaconOutput>

Returns the latest VRF beacon output.

interface BeaconOutput {
  height: number;
  output: string;        // Hex-encoded VRF output
  proof: string;         // Hex-encoded VRF proof
  producer: string;      // Producer address
  timestamp_ms: number;
  verified: boolean;
}

u64(seed?)

async u64(seed?: string): Promise<number>

Returns a random u64 as a JS number (safe up to 2^53). Derived from 8 random beacon bytes.

ParameterTypeDescription
seedstring?Optional domain seed for deterministic derivation.

bytes(len, seed?)

async bytes(len: number, seed?: string): Promise<Uint8Array>

Returns len random bytes (max 65,536).


pickIndex(len, seed?)

async pickIndex(len: number, seed?: string): Promise<number>

Returns a uniformly random integer in [0, len).


shuffleSmall(items, seed?)

async shuffleSmall<T>(items: T[], seed?: string): Promise<T[]>

Fisher-Yates shuffle. Maximum 256 items.


raffleWinner(addresses, seed?)

async raffleWinner(addresses: string[], seed?: string): Promise<string>

Selects a random winner from an array of addresses.


enableReplayMode(config) / disableReplayMode()

enableReplayMode(config: ReplayConfig): void
disableReplayMode(): void

Testing only. Blocked on mainnet. Replay mode uses a fixed beacon output for deterministic tests.


PrefabsClient (client.prefabs)

Prefabs are pre-built contract templates discoverable via the Rivellum manifest.

Categories

CategoryDescription
'CASUAL'Casual gaming & social contracts
'WORLD'Open-world / MMO game contracts
'UNIVERSAL'Chain-agnostic utility contracts

getAvailable(category?)

async getAvailable(category?: 'CASUAL' | 'WORLD' | 'UNIVERSAL'): Promise<PrefabDefinition[]>

Lists available prefabs, optionally filtered by category.


getManifest()

async getManifest(): Promise<PrefabManifest>

Returns the full prefab manifest. Cached for 5 minutes.


findById(prefabId)

async findById(prefabId: string): Promise<PrefabDefinition | undefined>

Searches the manifest for a prefab by exact ID.


search(query)

async search(query: string): Promise<PrefabDefinition[]>

Case-insensitive search across prefab name, description, and tags.


getCasual() / getWorld() / getUniversal()

async getCasual(): Promise<PrefabDefinition[]>
async getWorld(): Promise<PrefabDefinition[]>
async getUniversal(): Promise<PrefabDefinition[]>

Convenience wrappers for each prefab category.


LightClientVerifier

Standalone class for verifying sealed-batch ZK proofs. Import separately.

import { LightClientVerifier } from '@rivellum/sdk/lightclient';

const verifier = new LightClientVerifier({ nodeUrl: 'https://rpc.rivellum.network' });

fetchProofBundle(batchId)

async fetchProofBundle(batchId: string): Promise<LightClientProofBundle>

Fetches the proof bundle for a sealed batch from /batches/{batchId}/proof-bundle.

interface LightClientProofBundle {
  batch: ExecutionBatchSummary;
  traceProofs: TraceProof[];
  batchProof?: unknown;
}

verifyBundle(bundle, mode)

async verifyBundle(
  bundle: LightClientProofBundle,
  mode: 'mock' | 'real'
): Promise<VerificationResult>
ModeStatusDescription
'mock'✅ WorkingRe-hashes traces and compares proof hashes.
'real'⚠️ StubbedZK proof verification (TODO, not yet implemented).
interface VerificationResult {
  verified: boolean;
  mode: 'mock' | 'real';
  error?: string;
  details?: {
    batchId: string;
    height: number;
    intentCount: number;
    traceProofsVerified: number;
    batchProofVerified: boolean;
  };
}

NativeLedger Helpers

Standalone utility functions for asset ID derivation. Import directly.

import { deriveFungibleAssetId, deriveNftAssetId } from '@rivellum/sdk/nativeLedger';

deriveFungibleAssetId(params)

function deriveFungibleAssetId(params: {
  creator: string;    // 64 hex chars (32 bytes)
  symbol: string;     // 1–32 characters
  decimals: number;   // 0–18
}): string            // 64-hex AssetId

Derives a deterministic asset ID using BLAKE3(creator || symbol || decimals).

const assetId = deriveFungibleAssetId({
  creator: 'a1b2...c3d4',
  symbol: 'GOLD',
  decimals: 8,
});

deriveNftAssetId(params)

function deriveNftAssetId(params: {
  creator: string;    // 64 hex chars
  symbol: string;     // Collection name
  tokenId: string;    // Token identifier
}): string            // 64-hex AssetId

Derives a deterministic NFT asset ID using BLAKE3(creator || symbol || tokenId).


PrivacyClient

Standalone class for shielded private balances and transfers using view keys.

import { PrivacyClient } from '@rivellum/sdk/privacy';

const privacy = new PrivacyClient({
  nodeUrl: 'https://rpc.rivellum.network',
  viewKeyHex: 'abcdef...64hex',   // 32-byte view key
  timeoutMs: 30_000,
});

Constructor Parameters

NameTypeRequiredDescription
nodeUrlstringNode URL (https only).
viewKeyHexstring64 hex chars (32 bytes) view key for decrypting private balances.
timeoutMsnumberRequest timeout in ms.

getPrivateBalance()

async getPrivateBalance(): Promise<PrivateBalance>

Decrypts and returns the private balance visible to the configured view key.

submitPrivateTransfer(builder)

async submitPrivateTransfer(builder: PrivateTransferBuilder): Promise<PrivateTransferResult>

Types:

interface PrivacyRoutingHint {
  circuit_class: string;
  input_count: number;
  output_count: number;
  max_fee: string;
  domain_hint?: string;
}
interface AntiSpamProof {
  pow_nonce: string;
  fee_commitment?: string;
  sender_pk: string;
  nonce: number;
}

Envelope Builder

Low-level utilities for constructing encrypted envelopes. Requires Dilithium3 WASM initialization.

import {
  initDilithium,
  generateKeypair,
  addressFromPublicKey,
  computeLaneHint,
  serializeTransferPayload,
  buildEncryptedEnvelope,
} from '@rivellum/sdk/envelope';

initDilithium()

async function initDilithium(): Promise<void>

Must be called once before using any key generation or signing functions. Initializes the Dilithium3 WASM module.


generateKeypair()

function generateKeypair(): { publicKey: Uint8Array; secretKey: Uint8Array }

Generates a Dilithium3 post-quantum keypair. Requires initDilithium() to have been called.


addressFromPublicKey(publicKey)

function addressFromPublicKey(publicKey: Uint8Array): Uint8Array   // 32 bytes

Derives a Rivellum address from a Dilithium3 public key using BLAKE3(0x03 || pk).


computeLaneHint(sender, laneCount)

function computeLaneHint(sender: Uint8Array, laneCount: number): number

Computes the preferred lane for a sender: BLAKE3(sender)[0] & (laneCount - 1).


serializeTransferPayload(to, amount)

function serializeTransferPayload(to: Uint8Array, amount: bigint): Uint8Array  // 52 bytes

Serializes a transfer intent payload in bincode layout (variant 0 = Transfer, 32-byte recipient, 16-byte amount).


buildEncryptedEnvelope(params)

async function buildEncryptedEnvelope(params: EnvelopeBuilderParams): Promise<EncryptedEnvelope>

Constructs a complete encrypted envelope using:

  • Signing: Dilithium3 (post-quantum)
  • Encryption: ChaCha20-Poly1305
interface EncryptedEnvelope {
  sender: string;          // Hex-encoded sender address
  nonce: number;
  lane_hint: number;
  epoch_id: number;
  max_fee: string;
  encrypted_payload: string;   // Hex-encoded ciphertext
  signature: string;           // Dilithium3 signature
}

Error Types

import { NetworkError, NodeError, ValidationError } from '@rivellum/sdk/errors';

NetworkError

Thrown when the HTTP request fails (no response received, timeout, DNS failure).

class NetworkError extends Error {
  code?: number;
}

NodeError

Thrown when the node returns an error response (4xx/5xx).

class NodeError extends Error {
  data: unknown;   // Raw response body
}

Check error.data for structured error details. The status field in data maps to HTTP status codes (404, 501, etc.).

ValidationError

Thrown for invalid client-side input before any request is made (e.g., address length ≠ 64 hex chars, localhost URL).

class ValidationError extends Error {}

Common Patterns

Poll Until Finalized

async function waitForFinalization(client: RivellumClient, envelopeId: string): Promise<void> {
  const terminal = new Set(['finalized', 'rejected']);
  while (true) {
    const status = await client.getEnvelopeStatus(envelopeId);
    if (!status || terminal.has(status.status)) break;
    await new Promise(r => setTimeout(r, 2_000));
  }
}

Derive and Mint a Custom Token

import { deriveFungibleAssetId } from '@rivellum/sdk/nativeLedger';

const assetId = deriveFungibleAssetId({
  creator: myAddress,
  symbol: 'GEMS',
  decimals: 6,
});

const result = await client.nativeLedgerMint({
  account: playerAddress,
  assetId,
  amount: '1000000',
});

Check if a Transfer Would Pass Constraints

const check = await client.preflightConstraint(assetId, sender, receiver, '500000');
if (!check.allowed) {
  console.error('Transfer blocked:', check.denial_reason);
}

Pick a Random Raffle Winner

const winner = await client.random.raffleWinner([
  'addr1...', 'addr2...', 'addr3...'
]);
console.log('Winner:', winner);

Build and Submit an Encrypted Envelope

import { initDilithium, generateKeypair, addressFromPublicKey,
         computeLaneHint, serializeTransferPayload, buildEncryptedEnvelope } from '@rivellum/sdk/envelope';

await initDilithium();
const { publicKey, secretKey } = generateKeypair();
const senderAddr = addressFromPublicKey(publicKey);

const payload = serializeTransferPayload(
  Buffer.from(recipientAddress, 'hex'),
  BigInt(1_000_000)
);

const epoch = await client.getCurrentEpoch();
const laneHint = computeLaneHint(senderAddr, 8);

const envelope = await buildEncryptedEnvelope({
  sender: senderAddr,
  secretKey,
  payload,
  nonce: 1,
  laneHint,
  epochId: epoch.epoch_id,
  maxFee: '5000',
});

const result = await client.submitEnvelope(envelope);