For machines
A read is a plain GET. There is no key to obtain, no account to register, and no rate-limit tier to negotiate. The node reflects the request Origin header, so browser code on any domain reaches it directly without a proxy in between.
// No key, no account, no SDK. The node reflects the request Origin,// so this same call works from a browser, a server, or a sandbox.const res = await fetch('https://mainnet-node.decentralchain.io/blocks/height',);const { height } = await res.json();
Two other endpoints are verified and safe to depend on: /blocks/headers/last for a full block header, and /node/version for the running node build.
The same reads, plus the compiler below, are wrapped as an MCP server. Point any MCP client at it and a model can inspect mainnet and check that a contract compiles, with no key to configure — because there is no key. The configuration is the whole setup:
{"mcpServers": {"decentralchain": {"command": "npx","args": ["-y", "@decentralchain/mcp-node"]}}}
Six tools: get_chain_height, get_last_block, get_node_version, compile_ride, script_info_ride and decompile_ride. Reads go over plain HTTP; compilation happens inside the server's own process, so nothing leaves the machine. Set DECENTRALCHAIN_NODE to point it somewhere other than mainnet.
No tool holds a seed, signs a transaction, or broadcasts one, and none is planned. That boundary is what makes the server safe to hand to an autonomous agent: it can learn everything and still move nothing.
@decentralchain/ride-lang is the RIDE compiler cross-built from Scala with Scala.js and published to npm. It runs inside your process — no toolchain to provision, no compiler service to call, and nothing to keep running between invocations.
import { blake2b, keccak, sha256 } from '@decentralchain/ts-lib-crypto';// ride-lang is a Scala.js build. It reaches for three hash functions as// bare globals and does not bundle them, so install them first.globalThis.blake2b256 = (b) => blake2b(new Uint8Array(b));globalThis.keccak256 = (b) => keccak(new Uint8Array(b));globalThis.sha256 = (b) => sha256(new Uint8Array(b));const { compile } = await import('@decentralchain/ride-lang');const source = `{-# STDLIB_VERSION 6 #-}{-# CONTENT_TYPE DAPP #-}{-# SCRIPT_TYPE ACCOUNT #-}@Callable(i)func ping() = [ IntegerEntry("pong", height) ]`;// Second argument is the estimator version. 3 is the maximum.const out = compile(source, 3);out.complexity; // 3out.result; // ArrayBuffer — the serialized script
The same package exports decompile, parseAndCompile, scriptInfo and contractLimits. @decentralchain/ride-repl ships the evaluator alongside it if you want to run a contract rather than only build one.
This is the part that matters for autonomous software. A program can build a complete, well-formed transaction and still have no authority to send it, because signing is a separate step performed by whoever holds the key. The composing process never needs custody of anything.
// An invoke nobody has authorised: proofs is empty and no seed was// involved in building it. This object is a proposal, not a transaction.const unsigned = {type: 16, // INVOKE_SCRIPTversion: 2,chainId: 63, // 0x3f — DecentralChain mainnetdApp: '3DcZHm89byJjfdkHTJ9m89pyeMk8vChDGtD',call: { function: 'swap', args: [] },payment: [],senderPublicKey: OPERATOR_PUBLIC_KEY,timestamp: Date.now(),proofs: [],};
The chain id is 63, not 76. A DecentralChain address carries its chain byte at index 1, and decoding either live AMM contract address from base58 yields 0x3f — decimal 63, the character ?. The @decentralchain/transactions README shows chainId: 'L', and L is 76. That value is inherited from a different network, and it builds transactions DecentralChain mainnet rejects.
An unsigned transaction is inert until something with a key adds a proof. Which signer you choose decides what your program can do on its own and what it must ask a person for — the trade-offs, the packages, and the patterns that are safe to automate are covered separately.
@decentralchain/ledger — a person approves each call.Anything you automate should be designed against these, not discovered by them in production.
max-rollback-depth of 100 blocks — that is the bound to plan against.burnToken yet, so a hardware-signed agent cannot withdraw across the Solana bridge today.types, protobuf-schemas, node-api, data-service-client and @dcc-amm/sdk. Published near-equivalents exist for some — the type package on npm is @decentralchain/ts-types, not @decentralchain/types.Next
Signing for autonomous callers
How a program that should not hold keys gets a transaction authorised anyway, and what each custody pattern costs you.