Programmatic transactions (demos.run)
Every DEMOS transaction has historically been a three-step dance:
confirm → broadcast for you,
auto-broadcasting within a configurable fee ceiling (default 5 DEM).
demos.run.*. The classic
demos.pay / demos.confirm / demos.broadcast methods are unchanged —
demos.run is an additive facade, so nothing breaks.
Prefer this API for scripts and automation where you want one call per action.
The step-by-step flow documented in Creating,
Signing and
Broadcasting remains fully
supported and is the right choice when you need to inspect or gate each stage
yourself.
Setup
Demos.start(rpc, wallet?, walletOptions?) returns the connected instance;
omit wallet to connect read-only.
The uniform result
Everydemos.run.* method (except attest.dahr, see below) resolves to a
ProgrammaticTxResult:
The fee ceiling (maxFee)
In the default "auto" mode the runner broadcasts only if the confirmed fee is
within maxFee (DEM, default 5). If it is exceeded, the tx is signed and
confirmed but NOT broadcast, and the runner throws FeeCapExceededError
carrying the fee details — a loud safety net against surprise fees.
Confirmation strategies (confirm)
Waiting for inclusion (wait)
Namespaces
demos.run.pay / demos.run.transfer
Native value transfers. Amount is a DEM number (legacy) or OS bigint
(preferred). See Amounts & Denominations
for how the two formats are handled.
demos.run.attest.*
Identity attestations. Each returns a ProgrammaticTxResult.
demos.run.attest.dahr — the exception
DAHR (Demos Attestation Hash Response) is a web2 proxy attestation: the
node performs the HTTP request and its confirm/broadcast lifecycle happens
server-side. So dahr does not go through the fee-cap runner and returns
the web2 result directly (not a ProgrammaticTxResult); maxFee / confirm
options do not apply.
demos.run.tokens.*
Token creation and execution.
Coverage & caveats
demos.run.* namespaces: pay / transfer, attest.* (web2 + web3/xm + pqc +
ud + nomis + humanpassport + ethos + tlsn + dahr), tokens.*, storage.*
(store, program), escrow.*, validator.*, governance.*, xm.submit,
bridge.submit, demoswork.submit, ipfs.*, d402.pay.
- Live-verified against a node:
pay/transfer,storage.store,storage.program, plus the fee-cap / confirm-mode behaviour. ipfs.*,d402.payandcontracts.*are wired and type-checked but the underlying operations are not enabled on production nodes yet — they cannot be exercised end-to-end until the network turns them on.contracts.*(deploy/call/deployTemplate/ …) is RPC-native and NOT fee-capped: it bypasses theconfirm → broadcastrunner and returns the contract’s own result types (ContractInstance,ContractCallResult, gasbigint), not aProgrammaticTxResult. It lives underdemos.run.contractsfor a uniform surface, butmaxFee/confirm/waitdo not apply there.xm.submittakes an already-assembledXMScript; building that script (per-chain signed payloads) stays with the caller.
Design note
Under the hood a single runner (runProgrammaticTx) is the only place that
calls confirm / broadcast. Each typed method just builds and signs its
transaction and hands it to the runner, which normalises the three historical
builder shapes (returns-signed-tx, returns-validityData, server-internal
lifecycle) into one confirmation policy and one result type. This is the
“common element” that makes demos.run.pay(addr) and
demos.run.attest.dahr(params) feel the same despite very different underlying
operations.