Enjin RPC Guide: Matrix Chain + Relay Chain Endpoints, Substrate Methods, Gaming NFT Patterns (2026)
Enjin runs two chains: the Enjin Matrix Chain (application layer, where NFTs and tokens live) and the Enjin Relay Chain (consensus and security layer). Both use Substrate’s WebSocket RPC protocol. Neither is EVM-compatible. If you are coming from Ethereum development, this guide explains what is different and how to connect to both chains.
This guide covers endpoints for both Enjin Matrix Chain and Enjin Relay Chain, Polkadot.js connection examples, Substrate method reference, Enjin’s native NFT standard, production patterns for gaming backends.
For BoltRPC’s free public Enjin endpoints and dedicated infrastructure options, see the Enjin chain page.
Enjin Matrix Chain: Why It Is Different from EVM Chains
Not EVM. Enjin Matrix Chain does not support eth_* JSON-RPC methods. You cannot use ethers.js, Web3.py, or MetaMask in their standard configurations. The chain uses Substrate’s RPC protocol, which exposes methods like system_chain, chain_getBlock, state_getStorage.
Polkadot parachain. Enjin Matrix Chain is a Polkadot parachain. It gets Polkadot’s shared security and can communicate with other parachains via XCM. Block production is tied to Polkadot’s relay chain cadence (approximately 12 seconds).
Native NFT functionality at protocol layer. Enjin’s Multi-Token standard is built into the Substrate runtime, not deployed as a smart contract. Token operations are native extrinsics. You do not deploy ERC-721 or ERC-1155 contracts. Instead, you call pallet methods directly through the Substrate RPC.
WebSocket-first protocol. Substrate’s RPC is WebSocket-first. All method calls and subscriptions use a persistent WebSocket connection. There is no HTTP polling model equivalent. The Polkadot.js API library manages this connection for you.
Two networks: Enjin Matrix Chain and Canary. Enjin runs a production chain (Matrix Chain) and a canary network (Canary). The canary network receives upgrades first. Both expose the same Substrate RPC interface.
Enjin Endpoints: Matrix Chain + Relay Chain
Enjin runs two separate chains. Both use Substrate WebSocket RPC.
Enjin Matrix Chain (application layer: NFTs, tokens, gaming assets)
| Protocol | URL | Notes |
|---|---|---|
| WSS | wss://enjin-matrix-chain.matrixed.link | BoltRPC free public, no API key |
| HTTPS | https://enjin-matrix-chain.matrixed.link | BoltRPC free public, no API key |
| WSS | wss://rpc.matrix.blockchain.enjin.io | Official public |
| WSS | wss://rpc.matrix.canary.enjin.io | Canary network (staging) |
Enjin Relay Chain (consensus and security layer)
| Protocol | URL | Notes |
|---|---|---|
| WSS | wss://enjin-relay-chain.matrixed.link | BoltRPC free public, no API key |
| HTTPS | https://enjin-relay-chain.matrixed.link | BoltRPC free public, no API key |
Most application developers connect to the Matrix Chain. Connect to the Relay Chain when you need consensus data, cross-chain messaging via XCM, or relay-level block information.
For dedicated production capacity: BoltRPC Enjin endpoint.
Connecting to Enjin Matrix Chain and Relay Chain
Polkadot.js (Matrix Chain)
import { ApiPromise, WsProvider } from "@polkadot/api";
// Connect using BoltRPC's free public endpoint
const provider = new WsProvider("wss://enjin-matrix-chain.matrixed.link");
const api = await ApiPromise.create({ provider });
// Verify connection
const chain = await api.rpc.system.chain();
const version = await api.rpc.system.version();
console.log("Connected to:", chain.toString());
console.log("Node version:", version.toString());
// Get latest block
const latestBlock = await api.rpc.chain.getBlock();
console.log("Block number:", latestBlock.block.header.number.toNumber());
// Get finalized head
const finalizedHash = await api.rpc.chain.getFinalizedHead();
console.log("Finalized hash:", finalizedHash.toHex());
Polkadot.js (Relay Chain)
import { ApiPromise, WsProvider } from "@polkadot/api";
// Connect to the Enjin Relay Chain
const provider = new WsProvider("wss://enjin-relay-chain.matrixed.link");
const api = await ApiPromise.create({ provider });
// Verify connection
const chain = await api.rpc.system.chain();
const version = await api.rpc.system.version();
console.log("Connected to:", chain.toString());
console.log("Node version:", version.toString());
// Get finalized head on Relay Chain
const finalizedHash = await api.rpc.chain.getFinalizedHead();
console.log("Relay finalized hash:", finalizedHash.toHex());
// Check connected parachains (Relay Chain specific)
const parachains = await api.query.paras.parachains();
console.log("Active parachains:", parachains.toJSON());
Polkadot.js (subscriptions)
import { ApiPromise, WsProvider } from "@polkadot/api";
const api = await ApiPromise.create({
provider: new WsProvider("wss://enjin-matrix-chain.matrixed.link")
});
// Subscribe to new blocks
const unsubscribe = await api.rpc.chain.subscribeNewHeads((header) => {
console.log("New Enjin block:", header.number.toNumber());
});
// Subscribe to finalized blocks
const unsubFin = await api.rpc.chain.subscribeFinalizedHeads((header) => {
console.log("Finalized block:", header.number.toNumber());
});
// Clean up subscriptions when done
// unsubscribe();
// unsubFin();
Enjin Platform SDK
// The Enjin Platform SDK wraps Substrate RPC
// Install: npm install @enjin/platform-sdk
import { EnjinPlatform } from "@enjin/platform-sdk";
const platform = new EnjinPlatform({
nodeUrl: "wss://enjin-matrix-chain.matrixed.link"
});
await platform.connect();
console.log("Connected to Enjin Matrix Chain");
// The SDK exposes higher-level methods for token operations
// See official Enjin docs for Platform SDK reference
Raw WebSocket (for testing)
# Substrate RPC over WebSocket (wscat or websocat)
# Install wscat: npm install -g wscat
# Test Matrix Chain
wscat -c wss://enjin-matrix-chain.matrixed.link
# Once connected, send:
{"id":1,"jsonrpc":"2.0","method":"system_chain","params":[]}
# Response: {"jsonrpc":"2.0","result":"Enjin Matrix Chain","id":1}
{"id":2,"jsonrpc":"2.0","method":"chain_getBlockHash","params":[0]}
# Returns genesis block hash
{"id":3,"jsonrpc":"2.0","method":"chain_getFinalizedHead","params":[]}
# Returns hash of latest finalized block
# Test Relay Chain
wscat -c wss://enjin-relay-chain.matrixed.link
{"id":1,"jsonrpc":"2.0","method":"system_chain","params":[]}
# Response: {"jsonrpc":"2.0","result":"Enjin Relay Chain","id":1}
curl (HTTPS for quick tests)
Both Matrix Chain and Relay Chain support HTTPS for one-shot queries:
# Matrix Chain via HTTPS
curl -X POST \
-H "Content-Type: application/json" \
--data '{"id":1,"jsonrpc":"2.0","method":"system_chain","params":[]}' \
https://enjin-matrix-chain.matrixed.link
# Relay Chain via HTTPS
curl -X POST \
-H "Content-Type: application/json" \
--data '{"id":1,"jsonrpc":"2.0","method":"system_health","params":[]}' \
https://enjin-relay-chain.matrixed.link
Substrate RPC Methods: Matrix Chain + Relay Chain
Both chains use Substrate’s JSON-RPC protocol. The system, chain, state and author method namespaces are available on both. The Matrix Chain has the multiTokens pallet for NFT and token operations. The Relay Chain has the paras pallet for parachain coordination. Code examples are for reference. Verify against official Enjin documentation before production use.
System Methods (both chains)
| Method | Purpose | Parameters |
|---|---|---|
system_chain | Get chain name | none |
system_version | Get node version | none |
system_health | Check node sync status and peer count | none |
system_peers | List connected peers | none |
Chain Methods (both chains)
| Method | Purpose | Parameters |
|---|---|---|
chain_getBlock | Get full block including extrinsics | [hash?] |
chain_getBlockHash | Get block hash by number | [blockNumber] |
chain_getFinalizedHead | Get latest finalized block hash | none |
chain_getHeader | Get block header only | [hash?] |
chain_subscribeNewHeads | Subscribe to new block headers | none |
chain_subscribeFinalizedHeads | Subscribe to finalized block headers | none |
State Methods (both chains)
| Method | Purpose | Parameters |
|---|---|---|
state_getStorage | Read raw pallet storage by key | [key, hash?] |
state_getMetadata | Get full chain metadata | [hash?] |
state_call | Call a runtime API method | [method, data, hash?] |
state_subscribeStorage | Subscribe to storage key changes | [keys] |
Author Methods (Matrix Chain)
Used to submit token transfers, NFT operations and other signed extrinsics on the Matrix Chain.
| Method | Purpose | Parameters |
|---|---|---|
author_submitExtrinsic | Submit a signed extrinsic | [extrinsic] |
author_submitAndWatchExtrinsic | Submit and subscribe to status updates | [extrinsic] |
author_pendingExtrinsics | Get pending extrinsics in mempool | none |
Relay Chain Methods (Relay Chain only)
These methods are available on the Enjin Relay Chain and expose parachain coordination data.
| Method | Purpose | Parameters |
|---|---|---|
paras_parachains | List all active parachain IDs | none |
paras_parachain | Get parachain head data by ID | [paraId] |
grandpa_roundState | Get current GRANDPA round state | none |
babe_epochAuthorship | Get BABE epoch authorship info | none |
Enjin Multi-Token Standard: NFT Queries via Substrate RPC
Enjin Matrix Chain has NFT functionality at the protocol layer through the multi-tokens pallet. Instead of calling smart contract functions like ownerOf(), you read pallet storage directly via state_getStorage or use higher-level SDK calls.
Key concepts:
- Collection: A group of tokens with a shared ID. Equivalent to an NFT contract on EVM but native to the protocol.
- Token: A token within a collection. Can be fungible (supply > 1), non-fungible (supply = 1), or semi-fungible.
- Token Account: A record linking a wallet address to a token balance within a collection.
import { ApiPromise, WsProvider } from "@polkadot/api";
const api = await ApiPromise.create({
provider: new WsProvider("wss://enjin-matrix-chain.matrixed.link")
});
// Query token details for collection ID + token ID
// The multi-tokens pallet exposes these as queryable storage entries
const collectionId = 1234;
const tokenId = 1;
// Read token info using pallet storage query
const tokenInfo = await api.query.multiTokens.tokens(collectionId, tokenId);
if (tokenInfo.isSome) {
const token = tokenInfo.unwrap();
console.log("Token supply:", token.supply.toString());
console.log("Token cap:", token.cap.toString());
}
// Check if a specific address holds a token
const walletAddress = "cZaddressHere"; // Enjin uses SS58 format
const tokenAccount = await api.query.multiTokens.tokenAccounts(
collectionId, tokenId, walletAddress
);
if (tokenAccount.isSome) {
const account = tokenAccount.unwrap();
console.log("Balance:", account.balance.toString());
}
// Query all tokens owned by an address (requires iterating token accounts)
const ownedTokens = await api.query.multiTokens.tokenAccountsOf.entries(walletAddress);
ownedTokens.forEach(([key, value]) => {
console.log("Owns:", key.args.map(k => k.toString()));
});
Submitting Extrinsics (Transactions)
On Enjin Matrix Chain, transactions are called “extrinsics.” You sign and submit them using Polkadot.js with a Substrate-compatible keypair.
import { ApiPromise, WsProvider } from "@polkadot/api";
import { Keyring } from "@polkadot/keyring";
const api = await ApiPromise.create({
provider: new WsProvider("wss://enjin-matrix-chain.matrixed.link")
});
// Create keypair (never expose private keys in production, use secure key management)
const keyring = new Keyring({ type: "sr25519" });
const sender = keyring.addFromMnemonic("your mnemonic phrase here");
// Transfer a token between wallets using multi-tokens pallet
const collectionId = 1234;
const tokenId = 1;
const recipient = "cZrecipientAddress";
const amount = 1;
const transfer = api.tx.multiTokens.transfer(
{ AccountId: recipient },
{ Simple: { collectionId, tokenId, amount, keepAlive: false } }
);
// Sign and submit
const unsub = await transfer.signAndSend(sender, ({ status, events }) => {
if (status.isInBlock) {
console.log("In block:", status.asInBlock.toHex());
}
if (status.isFinalized) {
console.log("Finalized:", status.asFinalized.toHex());
unsub();
}
});
SS58 Address Format
Enjin Matrix Chain uses Substrate’s SS58 address encoding, not Ethereum’s hex addresses. Enjin uses SS58 prefix 1110.
import { Keyring } from "@polkadot/keyring";
import { encodeAddress, decodeAddress } from "@polkadot/util-crypto";
// Convert between formats
const keyring = new Keyring();
// Encode to Enjin SS58 format (prefix 1110)
const enjinAddress = encodeAddress(publicKeyBytes, 1110);
// Most Enjin addresses start with "cZ" due to the SS58 prefix
console.log("Enjin address:", enjinAddress);
// Decode SS58 to raw public key
const publicKey = decodeAddress(enjinAddress);
Production Issues on Enjin Matrix Chain
WebSocket disconnection handling. Substrate RPC is WebSocket-only. Connection drops during indexing or block monitoring require reconnection and re-syncing from a known checkpoint. Implement reconnection logic with exponential backoff. The Polkadot.js API has built-in reconnection behavior. Configure the WsProvider with retry options.
const provider = new WsProvider(
"wss://enjin-matrix-chain.matrixed.link",
1000, // reconnect delay in ms
{}, // headers
10000 // connection timeout
);
Historical indexing requires block-by-block traversal. Unlike EVM chains where eth_getLogs lets you query events across a block range in one call, Substrate indexing requires fetching blocks one at a time with chain_getBlock. For full historical scans, implement a crawler that starts at a known block and works forward. Cache block hashes to avoid re-fetching.
Metadata versioning. Substrate runtime upgrades change the metadata (pallet structure, type definitions). When Enjin Matrix Chain upgrades, the metadata version changes and Polkadot.js may need to re-fetch and re-decode storage layouts. The ApiPromise handles this automatically in most cases, but be aware that type definitions can shift across runtime versions.
ENJ vs ENJ2. The Enjin ecosystem has gone through token migrations. Enjin Matrix Chain uses ENJ2 as its native token for parachain operations. Confirm you are using the correct token format in your application.
Canary network for testing. Use Enjin’s canary network (wss://rpc.matrix.canary.enjin.io) for development before deploying to production. The canary runs the same runtime as Matrix Chain and receives upgrades first.
Gaming Backend Architecture on Enjin
Gaming backends on Enjin Matrix Chain follow a different architecture than EVM chains:
Single persistent WebSocket connection. Maintain one ApiPromise connection per backend instance rather than creating connections per request. The Polkadot.js API is designed for long-lived connections.
Batch ownership queries. Use api.query.multiTokens.tokenAccountsOf.entries(playerAddress) to get all tokens owned by a player in one call rather than querying each token individually.
Subscribe to storage changes. For real-time inventory updates, subscribe to relevant storage keys rather than polling. state_subscribeStorage with your collection’s storage keys delivers updates as on-chain state changes.
Extrinsic status tracking. Use author_submitAndWatchExtrinsic instead of author_submitExtrinsic to receive status callbacks (ready, broadcast, inBlock, finalized) rather than polling for receipt.
Enjin RPC FAQ
What are the Enjin Matrix Chain and Relay Chain RPC endpoints?
BoltRPC provides free public endpoints for both chains. Matrix Chain: wss://enjin-matrix-chain.matrixed.link (also https://enjin-matrix-chain.matrixed.link). Relay Chain: wss://enjin-relay-chain.matrixed.link (also https://enjin-relay-chain.matrixed.link). No API key required for either. For dedicated capacity, contact BoltRPC.
What is the difference between Enjin Matrix Chain and Enjin Relay Chain? The Enjin Matrix Chain is the application layer where NFTs, fungible tokens and gaming assets live. It is a Polkadot parachain. The Enjin Relay Chain is the consensus and security layer that coordinates parachains, provides shared security and handles cross-chain messaging (XCM). Application developers connect to the Matrix Chain. Infrastructure teams needing relay-level data connect to the Relay Chain.
Is Enjin Matrix Chain EVM-compatible?
No. Enjin Matrix Chain is a Substrate chain and does not support Ethereum JSON-RPC (eth_* methods). Use Polkadot.js or the Enjin Platform SDK for development. MetaMask does not work with Enjin Matrix Chain.
What is the difference between Enjin Matrix Chain and ERC-721? Enjin Matrix Chain has NFT functionality built into the protocol through the multi-tokens pallet. You do not deploy contracts. Token operations are native extrinsics. The Enjin Multi-Token standard supports fungible, non-fungible, semi-fungible tokens in a single standard, unlike Ethereum where you need separate ERC-20 and ERC-721 contracts.
How do I check NFT ownership on Enjin Matrix Chain?
Query pallet storage using api.query.multiTokens.tokenAccounts(collectionId, tokenId, address) through the Polkadot.js API. This returns the token account for a specific address, including balance. See the code examples in this guide for implementation.
What is a Substrate extrinsic?
An extrinsic is the Substrate equivalent of a transaction. It is a signed operation submitted to the chain to change state (transfer tokens, create collections, etc.). On Enjin Matrix Chain, you build and sign extrinsics using Polkadot.js, then submit them via author_submitExtrinsic or author_submitAndWatchExtrinsic.
Does Enjin Matrix Chain use ETH or ENJ for gas? Enjin Matrix Chain uses ENJ (the Enjin token) for transaction fees, not ETH. The specific version used on the Polkadot parachain is ENJ2 following the token migration. Confirm token format with the official Enjin documentation.