Public Testnet · Docs v0.1
Technical Documentation
How WCAHT Chain works end to end — the consensus and execution architecture, the
core account/staking/fee model, pure EVM support, and the developer tools (SDK and EVM tracing).
Testnet notice. WCAHT is a public testnet. Parameters, economics, and some features
(governance, slashing, cross-shard) are still hardening — each section flags what is live vs. in development.
Testnet tokens have no monetary value.
Introduction
WCAHT is a high-throughput Layer 1 with stake-weighted BFT consensus and a
parallel execution engine. It is not a fork of an existing chain — it is a purpose-built stack
of named subsystems that each own one stage of the block lifecycle. The design goal is Solana-class throughput
on commodity hardware, with an institutional compliance layer built into the node.
Wallet installation
Use the browser extension for quick testnet access, or install the standalone Windows wallet for a dedicated desktop experience. Both wallets are non-custodial: keep recovery material private and use testnet funds only.
Browser extension · Chrome, Edge, Brave, Opera
Install the unpacked extension from the WCAHT testnet ZIP.
- Download the WCAHT extension ZIP.
- Extract the ZIP to a folder that will not be deleted.
- Open your browser’s extensions page (Chrome:
chrome://extensions).
- Enable Developer mode, choose Load unpacked, and select the extracted folder.
- Pin WCAHT Wallet, open it, and connect to the public testnet.
Open web wallet →
Desktop wallet · Windows
Install the native wallet without running a node.
- Download the Windows installer.
- Verify the download before running it. In PowerShell run
Get-FileHash .\WCAHT-Wallet-Setup-1.0.4.exe -Algorithm SHA256 and compare the result
with the SHA-256 published on the download section. If it differs, delete the file.
- This build is not yet code-signed, so Windows SmartScreen will warn about it. We do not
recommend clicking past that warning for a wallet. If you would rather not, use the
web wallet or the browser extension instead — signed builds and
store distribution are in progress.
- Launch WCAHT Wallet and create a new test wallet. Do not import a wallet you use on another network.
- Back up your recovery phrase offline. Never share it with support or type it into a website — anyone
who has it controls the wallet.
Wallet security
Read this before you create a wallet. It is short on purpose.
WCAHT will never ask for your Secret Recovery Phrase or private key.
Not by email, not in Telegram or Discord, not through a support form, not through a "verification"
step, and never on this website. Anyone who has that phrase controls the wallet completely and
permanently. If someone asks for it while claiming to be WCAHT staff, they are stealing from you.
Where your keys live
The web wallet generates keys in your browser. The secret key is shown to you once, at
creation, so you can back it up — it is not uploaded to our servers, and we cannot recover or recreate it
for you. Saved wallets in the dashboard hold public metadata only; when a signature is needed, you supply
the key locally for that one operation and it is discarded from memory immediately afterwards.
Public-testnet validator operators may select an encrypted v2
<name>-validator-keypair.json. The browser derives its AES key with the same Argon2id parameters
used by wcaht-keygen, authenticates and decrypts with AES-256-GCM, verifies the embedded public
identity, and discards the decrypted key after the one operation. The encrypted file and passphrase are not
uploaded or saved. On-host signing remains the recommended hardened validator path.
What leaves your device
Signed transactions and public addresses, because a blockchain cannot work otherwise. Balance and history
lookups send your public address to a WCAHT node. Private keys, secret phrases and key files never leave
the browser. Key files you select for import are read locally and are not uploaded.
Which network this is
Everything on this site is the public testnet, chain ID 7789. Test WCAHT has no monetary
value, cannot be exchanged for money, and is not an investment. Do not send assets from another network to
a WCAHT testnet address — they will not arrive and cannot be returned. Mainnet is targeted for 2027 and is
conditional on the security and economics milestones on the roadmap, not on a date.
What has and has not been audited
No independent third-party security audit has been completed yet. It is scheduled ahead of mainnet, after
outside validators are running, so that the audit covers the real network rather than a snapshot. Treat
this software as testnet software: use a fresh test wallet, and do not import a wallet you use anywhere
else. Desktop builds are not yet code-signed — verify the published SHA-256 before running an installer,
and do not get in the habit of clicking past operating-system warnings for wallet software.
Claiming test tokens is always free
The faucet never requires a payment, a deposit, a "verification" transfer, a social
media task, or contact through a private message. If you are asked for any of those in order to receive
test WCAHT, it is a scam and it is not us.
Reporting a vulnerability
Report security issues privately to the maintainers through the official
Telegram or
Discord channels linked in the
site footer, with reproduction steps. Consensus, fork-handling and sync edge cases are the most valuable
reports. Please give us a chance to fix an issue before disclosing it publicly. A paid public bug bounty is
planned alongside the incentivized testnet phase. Never include a private key or recovery phrase in a
report — we do not need it, and no legitimate report requires one.
Transaction pipeline
A transaction flows through five subsystems from submission to finality:
01 · INGRESS
TxFabric
Validates, prioritizes and lanes incoming transactions in a sharded mempool.
02 · EXECUTE
Prism
Runs non-conflicting transactions in parallel (MVCC) and computes the state root.
03 · ORDER
Skyfall
The scheduled leader proposes a block; validators vote to finalize at ≥⅔ stake.
04 · PROPAGATE
Cascade
Erasure-codes the block into shreds and fans them out across the validator mesh.
05 · PERSIST
Hyperion
Commits to a fork-aware ledger and serves the canonical chain to explorers & RPC.
Network parameters
| Parameter | Value | Notes |
| Slot duration | 400 ms | SLOT_DURATION_MS |
| Leader schedule | Round-robin, 12 slots/leader | WCAHT_RR_SLOTS_PER_LEADER |
| Finality threshold | ≥ ⌈2N/3⌉ stake | BFT supermajority |
| Min validator stake | Query getMinimumValidatorStake immediately before registration | The RPC value is in kak; the onboarding UI converts it using 1 WCAHT = 10⁹ kak and does not hardcode a different floor |
| Max txs / block | 50,000 (soft cap 2,000) | drain-budget tunable |
| Native unit | 1 WCAHT = 10⁹ kak | EVM layer uses 18 decimals |
| EVM chain ID | 7789 (0x1e6d) | RPC at /eth |
Skyfall — Consensus
Skyfall is the stake-weighted Byzantine-fault-tolerant consensus layer. Validators stake WCAHT and take turns
producing blocks on a deterministic round-robin schedule (12 consecutive slots per leader),
then vote on every block. A block is final once votes representing at least a two-thirds
supermajority of active stake (⌈2N/3⌉) are collected. Because the schedule is deterministic, every node can
independently verify who the leader for a slot should be.
- Leader selection is unified in a single module — fork tie-breaks read the canonical schedule, not stale caches.
- Finality certificates are verifiable: the aggregate of votes for a finalized block can be checked by any peer.
- Liveness improves with validator count — more validators keep finalizing through node churn.
Public-testnet status: validator onboarding is open and the active
set is dynamic. Canonical finality uses Ed25519 Skyfall certificates. Production does not emit the experimental
seed-derived BLS vote fields; independent BLS key registration and rotation are required before that path can be
activated. Operators must test upgrades on a non-voting replica before activation.
Skyreach — Accounts & State
Skyreach owns the account model and state storage. Every account is keyed by its Base58 public key and stored
in a dedicated RocksDB column family. Balances are denominated in kak (1 WCAHT = 10⁹ kak), and
each account tracks a nonce for replay protection. Account writes are committed per slot with commit markers so
state can be recovered deterministically after a restart. Reads are lazy (loaded from the store on demand),
which keeps memory bounded regardless of chain size.
Prism — Parallel execution
Prism executes a block's transactions concurrently using multi-version concurrency control
(MVCC). Non-conflicting transactions run on separate cores; conflicting ones are ordered deterministically so
every validator computes an identical state root. Duplicate-transaction detection is
ancestry-based — a pure function of the block and its parent chain — so consensus execution never
consults node-local state and can never fork on multi-transaction blocks.
Live & validated: parallel execution scales with cores and is
the source of the chain's throughput. Zero state-root mismatches across load tests.
TxFabric — Mempool
TxFabric is the ingress layer. Incoming transactions are validated (signature, nonce, fee, balance), assigned
to priority lanes, and partitioned across shards so the block builder can drain them in
parallel. This intra-node sharding is what feeds Prism enough independent work to saturate all cores.
Cascade — Block propagation
Cascade distributes finalized blocks across the validator mesh using erasure-coded shreds
(Turbine-style fan-out) over QUIC. A receiver can reconstruct a block from a subset of shreds, so propagation is
resilient to packet loss and does not depend on any single peer. Broadcast streams are explicitly finished so
receivers never truncate a block mid-stream.
Hyperion — Ledger
Hyperion is the fork-aware ledger. It tracks competing chain tips, applies fork choice against the canonical
leader schedule, and exposes the finalized chain to explorers, wallets, and the JSON-RPC / EVM endpoints.
Accounts & units
| Concept | Detail |
| Address | Base58-encoded Ed25519 public key (native) / 20-byte hex (EVM) |
| Smallest unit | 1 kak; 1 WCAHT = 1,000,000,000 kak |
| Replay protection | Per-account nonce, enforced at ingress |
| Per-tx cap | 10¹⁵ kak |
Staking & validators
Validators register with a RegisterValidator transaction and provide the self-stake required by the
connected network. Operators must obtain the quorum-backed live minimum from getMinimumValidatorStake
immediately before signing; the returned value is in kak and the website displays its exact WCAHT conversion.
Stake, validators, and vote accounts are persisted to
RocksDB and reloaded on startup, so the active set survives restarts. See the
validator guide or start validator onboarding.
Choose a setup method · Guided terminal ·
QR wallet pairing · Security checklist
Validator-capable onboarding: a new validator host starts in the same
NODE_TYPE=validator runtime as an active validator, but with zero on-chain consensus weight. It can
synchronize, serve RPC and verify finality, but it cannot propose or sign. Registering stake does not require a
service-role change or a restart: after the exact identity has non-zero activated consensus weight, the ordinary
canonical-chain, trust, catch-up and Tower gates decide whether it may vote. The emergency
WCAHT_DISABLE_VOTING=1 hold remains available for maintenance or recovery. Stake enters a one-epoch
activation queue and becomes active automatically at the next epoch boundary. The current epoch is 172,800 slots
(about 19.2 hours at 400 ms/slot).
Current public topology: N5, N6, N7, N8, and N9 are the active voting set. A dedicated
service at rpc1 follows the chain as a zero-weight rpc_validator_observer and is the intended
public read/RPC tier. N1 is retired and is not part of the active topology.
In development: validator rewards, fee splits and slashing
parameters are finalized during the incentivized-testnet phase. On the current testnet, tokens are for testing only.
Node types & startup
All roles run the same checksum-verified WCAHT binary and canonical genesis. The practical architecture has four node types;
fullnode remains a legacy/general role and rpc_validator_observer is a compatibility hybrid.
Choose one source of truth for the role. If both are supplied, the service environment's NODE_TYPE
overrides node_role in JSON.
| Node type | Role value | Purpose | Can become voting? |
| RPC | rpc | Wallet, explorer, REST/EVM RPC and finalized-chain replay. | No; first move it to a validator-capable runtime. |
| Observer | observer | Verifies, follows and monitors the chain without proposing or voting. | Yes, after promotion to validator. |
| Archive | archive | Observer/RPC services plus long-history retention. | Not while archival/non-voting; use a dedicated validator host for consensus. |
| Validator-capable | validator | Loads consensus services in standby and follows finality even with zero stake. | Yes; voting activates only after registration and stake activation. |
Common installation
- Provision the host, install only a checksum/signature-verified release, and use the canonical genesis bundle.
- Generate a unique identity on that host; keep its private files permission-restricted and backed up offline.
- Configure at least two trusted bootstrap/snapshot peers and an externally reachable endpoint where required.
- Set the role-specific fields below, install the service, then verify identity, peer count, tip and finalized slot.
# RPC node
"node_role": "rpc", "is_validator": false, "disable_consensus": true
# Observer / monitoring node
"node_role": "observer", "is_validator": false, "disable_consensus": true
# Archive node — omit ledger_keep_blocks or set it to null
"node_role": "archive", "is_validator": false, "disable_consensus": true,
"archival_mode": true, "ledger_keep_blocks": null
# Validator-capable node; zero stake remains safe and non-voting
"node_role": "validator", "is_validator": true, "disable_consensus": false
Use the matching service environment when the launcher requires it:
sudo systemctl edit wcaht-NODE
# Add exactly one role:
[Service]
Environment="NODE_TYPE=observer" # rpc | observer | archive | validator
sudo systemctl daemon-reload
sudo systemctl enable --now wcaht-NODE
RPC/REST uses 8901/tcp; gossip uses 8001/udp; QUIC block/vote transport uses
9001/udp. Validator-capable nodes must also make the dedicated signed consensus relay
8902/tcp reachable by active validators. Restrict SSH and any operator-control endpoint to a private
management network.
curl -fsS http://127.0.0.1:8901/status | jq '{
status, height:.block_height, slot, finalized:.finalized_slot,
role:.node.effective_node_role, weight:.node.registered_consensus_weight,
can_vote:.node.can_attempt_vote, voting:.node.is_voting_validator,
behind:.sync.blocks_behind, peers:.peers.connected
}'
Running a node · discovery, joining & becoming a validator
Every participant runs the same binary. The service role controls which subsystems are available; activated
consensus weight controls whether a validator-capable node may actually propose and vote. A UI toggle alone can
never grant voting power. This section covers discovery, joining and the complete voting lifecycle.
1 · Peer discovery & gossip
A node builds its peer set in layers: it first attempts local UDP discovery, then falls back to
the configured seed / bootstrap nodes, and finally a DHT walk. Discovered peers are
tracked by the PeerManager. Blocks, transactions and consensus votes travel over a binary QUIC
transport (port 9001) plus a gossip layer; the JSON-RPC / REST control plane is a separate HTTP port
(8901), with signed HTTP consensus fallback on 8902. A node behind NAT can still reach the
mesh by dialling out to public seeds, but a validator must provide working return paths for its advertised QUIC,
gossip and consensus-relay endpoints. A home/NAT machine without those forwards is best run as an observer.
Discovery does not grant trust. Connected peers are never
auto-registered into the validator set. Only the on-chain / genesis registry defines who can vote — a peer you
gossip with has zero consensus weight until it is a registered, activated, staked validator.
2 · Joining as a new node (observer)
A fresh node points at one or more seed nodes, restores the latest snapshot (fast-sync), then
replays blocks forward until it reaches the live tip. Until it is caught up and holds
activated stake it should run as either an explicit observer or a validator-capable
validator in zero-weight standby. It verifies and stores blocks, serves RPC and gossips, but cannot
propose or vote. This is the normal, safe state for a new machine.
3 · Becoming a validator
Two things must both be true before a node votes:
- Validator-capable runtime — role
validator, trusted state, near-zero sync lag, visible
to peers, and reachable on the consensus transports.
- Activated consensus weight — its identity is in the validator registry with a self-stake of at
least the minimum shown by the connected network and wallet. A
RegisterValidator transaction records the stake; stake,
validators and vote accounts persist to RocksDB and survive restarts.
Permissionless & consensus-safe. Admission is open — dynamic
validators are enabled (allow_dynamic_validators) and stake activation is deterministic.
The network runs atomic-delta staking (active from slot 0): a stake's activation and deactivation
are applied in-block at the epoch boundary and bound into the state root, so every node
agrees on exactly when a stake becomes active — no wall-clock race, no fork risk. In practice: provision a node,
sync it in validator-capable zero-weight standby, submit a RegisterValidator transaction with at least the minimum self-stake
(query getMinimumValidatorStake), and it is automatically activated into the voting set at the
next epoch boundary — no permissioned genesis inclusion required. The public bundle already runs
NODE_TYPE=validator with zero weight, so do not change role or restart at that boundary; verify the
active weight and every ordinary vote-safety gate. N5, N6, N7 and N8 are simply the current
active set; anyone meeting the live stake minimum can join it. Query getEpochInfo rather than copying an
old constant; the live network currently reports 172,800 slots (~19.2 h at 400 ms/slot).
4 · What happens with zero stake / zero voting power
The runtime asks one question — is my consensus weight > 0? If not, the node cannot attempt to
vote and behaves as an observer no matter how it was launched. A zero-stake node:
- fully syncs, stores and serves the chain, and relays transactions;
- has any votes counted as zero weight — it can neither help nor block quorum;
- is explicitly excluded from consensus totals, so it cannot alter consensus state or inflate
voting power through gossip.
The dashboard labels this state validator-ready. Voting power appears only once the node holds
activated stake in the registry.
5 · What the dashboard can and cannot change
The current public dashboard publishes the checksum-verified bundle and validator-capable zero-weight standby
instructions. It does not
connect to the host over SSH, fund an identity, rewrite a running service role, or enable voting. The recommended
registration path signs on the validator host. For public-testnet testing, the wallet can also read the selected
encrypted v2 <name>-validator-keypair.json in local browser memory, verify its declared identity and
sign one operation; the file, passphrase and decrypted key are not uploaded or saved.
The public bundle needs no promotion control: it starts as the validator-capable runtime with zero consensus weight.
That still cannot create voting weight: the operator must explicitly fund and register the identity, and the network
activates stake deterministically.
6 · Onboarding commands
The full guided flow lives at validator onboarding. In short:
provision an Ubuntu host (8+ cores, 16+ GiB RAM, NVMe SSD, public IPv4), obtain the checksum-verified release and canonical
genesis bundle, generate the encrypted five-role validator key set on the server and back it up offline, start the node and let it
sync in zero-weight validator standby, fund its public identity, then sign registration on that host:
# Use the exact command in the downloaded bundle README.
sudo -u wcaht-validator env \
WCAHT_KEY_PASSPHRASE_FILE=/run/wcaht-key-passphrase \
/opt/wcaht-validator/wcaht-submit-tx \
--node http://127.0.0.1:8901 --rpc \
--genesis-keypair-path /var/lib/wcaht-validator-secrets/keys/NODE-validator-keypair.json \
--tx-type register-validator --to VALIDATOR_IDENTITY \
--amount LIVE_MINIMUM_IN_KAK --commission-bps REVIEWED_BPS
The encrypted identity stays on the validator host with this recommended method. After registration, keep the
zero-weight validator standby online through the activation epoch, without a role change or restart, then verify
non-zero voting weight, convergence and finality. The complete five-key role map, secure PowerShell copy/passphrase procedure, four-way
identity check, optional dashboard import, registration and activation sequence is in the
validator key operator flow.
Key safety. Never export a raw validator key. The optional testnet
dashboard path accepts only the encrypted identity envelope; never import vote, stake, withdraw, fee-payer or TLS
key files. Never paste a key or passphrase into a screenshot, log, support request or chat.
Validator troubleshooting
Symptoms below are all real failures seen while onboarding a validator. Work top to bottom:
each step eliminates a whole class of cause, so you are never guessing.
Golden rule — do not restart a newly onboarded node for ~3.6 hours
Snapshot bootstrap writes a completed-snapshot witness. The node refuses to start
again until its own rooted_slot has advanced 32,768 slots past the restore point,
and that counter only advances while the node is running. Restart it inside that
window and it will not come back until the window has passed.
curl -fsS http://127.0.0.1:8901/health | jq '{rooted_slot}'
# safe to restart once rooted_slot is 32768 past its value at restore time
“Decryption failed: wrong passphrase or corrupted key file”
That error names two causes and is usually neither. Prove both halves on the validator first
— this decrypts and validates without printing secret material:
PASS=$(sudo systemd-creds decrypt --name=wcaht-key-passphrase /etc/credstore.encrypted/wcaht-key-passphrase -)
sudo env WCAHT_KEY_PASSPHRASE="$PASS" /opt/wcaht-validator/wcaht-keygen verify \
--path /var/lib/wcaht-validator-secrets/keys/<name>-validator-keypair.json
unset PASS
If it prints Encrypted keypair verified (pubkey: ...), your key file and
passphrase are both correct and the problem is in what reached the browser field.
Check the passphrase actually reached your clipboard
On the validator, print a fingerprint (safe to compare, reveals almost nothing):
P=$(sudo systemd-creds decrypt --name=wcaht-key-passphrase /etc/credstore.encrypted/wcaht-key-passphrase -)
printf "%s" "$P" | python3 -c "
import sys,hashlib
p=sys.stdin.read()
print('length:',len(p),'first3:',p[:3],'last3:',p[-3:],'sha256[:12]:',hashlib.sha256(p.encode()).hexdigest()[:12])"
unset P
Then compare your clipboard in Windows PowerShell. The length must be 64 and
the hash must match:
$c = Get-Clipboard
$sha = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash([Text.Encoding]::UTF8.GetBytes($c))).Replace('-','').ToLower()
Write-Host "length:" $c.Length " first3:" $c.Substring(0,3) " last3:" $c.Substring($c.Length-3) " sha:" $sha.Substring(0,12)
If they differ, some shells append a newline when copying. Transfer via a file with no
trailing byte instead, then open it, select all and copy:
$p = (ssh <user>@<validator-ip> 'sudo systemd-creds decrypt --name=wcaht-key-passphrase /etc/credstore.encrypted/wcaht-key-passphrase -').Trim()
[IO.File]::WriteAllText("$env:USERPROFILE\Desktop\pass.txt", $p)
Remove-Variable p
Delete that file and clear the clipboard as soon as the import succeeds. The passphrase is the
one generated during key generation — it is not your SSH password, not your SSH key, not the
recovery-archive password, and not the validator public address. It is exactly 64 characters.
The node will not start after onboarding
sudo journalctl -u wcaht-validator -n 80 --no-pager | grep -i "undischarged\|witness\|panic"
If you see production startup refuses an undischarged completed network-snapshot
witness, the node was stopped inside its witness window. Do not wipe the ledger and
do not generate new keys — that destroys the identity your node already gossiped and
any stake bound to it. Re-run the snapshot bootstrap, then leave the node running uninterrupted.
Bootstrap cannot find a snapshot quorum
no two active voters advertise an identical snapshot is a timing race, not a
misconfiguration. Snapshots are cut independently every 50 blocks so the agreeing set drifts.
Confirm every voter is reachable, then simply run the bootstrap again:
for a in $(sudo jq -r '.bootstrap_nodes[].ip' /var/lib/wcaht-validator/config/validator.json); do
printf "%-16s " "$a"; curl -s -o /dev/null -w "%{http_code}\n" -m 8 "http://$a:8901/snapshot/info"
done
# each line is one of your first-contact nodes and should read 200
Confirm you have genuinely joined
You are a real cluster member only when peers list you by validator identity, not
merely when your own health endpoint responds:
curl -fsS http://127.0.0.1:8901/health | jq '{
block_height, finalized_slot, rooted_slot,
role:.node.effective_node_role, voting:.node.is_voting_validator,
weight:.node.registered_consensus_weight,
trusted:(.state_verification.account_state_untrusted|not),
behind:.sync.production_gate_blocks_behind, peers:.peers.connected }'
A healthy standby reports trusted: true, behind: 0, peers
above zero, weight: 0 and voting: false. Zero weight and non-voting are
correct — that is the intended state until you deliberately register stake.
Fees
Transactions pay a fee in kak that is deducted atomically with the transfer. Fee parameters are logged at
node startup and are governable in the target design. All balance arithmetic on the canonical execution path is
saturating and guarded, so a transaction can never underflow an account.
EVM and MetaMask compatibility
WCAHT exposes an Ethereum JSON-RPC endpoint for signed legacy, EIP-2930, and EIP-1559 transactions, balances,
receipts, contract execution, logs, and common wallet tooling. This public testnet is still closing less-common
execution-client edge cases; applications should test the exact RPC methods they depend on before production use.
# Add the network to MetaMask
Network name: WCAHT Testnet
RPC URL: https://denvion.com/eth
Chain ID: 7789 (0x1e6d)
Currency: WCAHT (18 decimals on the EVM layer)
Signed fee and receipt rules. The validator recovers the sender from
the raw transaction and binds chain ID, nonce, recipient, value, gas limit, gas-price cap, fee, and canonical
Ethereum transaction hash at consensus verification. Transfers currently require at least 21,000 gas and 1 gwei;
the receipt reports the signed gas-price cap. Values must be exactly representable in the native 9-decimal kak unit.
Wallet-key safety. The web wallet stores public wallet metadata only.
Imported secret keys remain in current-session memory and are requested again after refresh. Use the bundled on-host
signer for the hardened validator-registration path. The optional public-testnet path reads an encrypted validator
identity locally for one operation; it never accepts the vote, stake, withdraw, fee-payer or TLS key files.
See the Developer Hub for one-click network add and code examples.
Faucet & airdrop
On testnet, anyone can claim free WCAHT from the faucet (the "airdrop") so they can deploy
contracts, run validators, and test transfers without buying anything.
Where do the free coins come from?
They are not newly minted. The faucet pays from a dedicated faucet account
that the operator funds with a fixed amount from the treasury. Each claim is an ordinary signed transfer from
that account to your address, and it goes through consensus like any other transaction. Total supply never
increases. The faucet's signing key is used only for the faucet: it is never the treasury key, and the node
refuses to start the faucet with the treasury key.
Limits
| Rule | Value |
| Amount per claim | 101 WCAHT (the 100 WCAHT validator minimum plus fees) |
| Claims per address and per connection | 2 per day, at least 5 hours apart |
| Budget | Whatever the faucet account holds; the live figure is shown in the wallet and at
GET /api/faucet/status |
| Availability | Testnet only |
When does it end?
The faucet stops dispensing in any of these cases:
- Faucet account empty: claims stop until the operator funds it again.
- Mainnet launch: the faucet is testnet-only. After that, WCAHT comes only from transfers,
validator rewards or exchanges.
- Per-user limit: a third claim within a day, or a second within 5 hours, is refused with
faucet_rate_limited and the time to wait.
Testnet tokens have no monetary value. The faucet exists purely so
developers can test. Do not treat faucet WCAHT as an investment.
POST/api/wallet/airdropBody { "address": "<your_address>" } → 101 WCAHT. Also available as the "Request test tokens" button in the web wallet.
Integrating — exchanges, wallets & apps
Everything you need to read balances, send transfers, and decide when a transfer is final. The endpoints
below are public HTTPS. They need no key.
Public testnet: WCAHT balances are test tokens, and the parameters
on this page may change before mainnet. Do not accept WCAHT in exchange for anything of real value.
| Item | Value | Notes |
| EVM chain ID | 7789 (0x1e6d) | eth_chainId / net_version |
| EVM JSON-RPC | https://denvion.com/eth | Standard eth_*; works with ethers.js, web3.js and MetaMask |
| Native JSON-RPC | https://denvion.com/node/rpc | getBalance, getSlot, getBlock, getSignatureStatuses, sendTransaction |
| Units | 1 WCAHT = 10⁹ kak (native) | The EVM layer shows 18 decimals. Every EVM value must be a whole number of kak (a multiple of 10⁹ wei). |
| Gas (EVM) | ≥ 21,000 gas, ≥ 1 gwei | eth_gasPrice returns 0x3b9aca00 |
| Batches | Up to 50 read requests per batch | A native sendTransaction goes alone. A batch containing one is refused. |
When is a transfer final?
Every transaction moves through three levels. Credit a deposit only at finalized.
| Level | Native confirmationStatus | EVM block tag | Meaning |
| Processed | "processed" | latest | The node has seen it, or its block is not yet confirmed. It can still be dropped. |
| Confirmed | "confirmed" | safe | Validators holding ≥ ⅔ of stake voted for its block. A rollback is rare but possible. |
| Finalized | "finalized" | finalized | Rooted: irreversible. Safe to credit. |
On the live testnet, finalized usually trails the newest block by 2–10 seconds. Under heavy
load, allow about 30 seconds.
Crediting a deposit
- EVM: fetch the receipt with
eth_getTransactionReceipt. Credit only when
status is 0x1 and the receipt's blockNumber is at or below the number
of eth_getBlockByNumber("finalized", false).
- Native: call
getSignatureStatuses. Credit only when
confirmationStatus is "finalized" and err is null. A failed
transfer stays in its block with err set. It moved no funds: at most its fee was charged.
- Do not credit on a send response, a websocket notification,
processed or confirmed.
- EVM state reads (
eth_getBalance, eth_call) are answered only at the current head
(latest). Asking for safe or finalized returns an error. Use receipts
plus the finalized block number for deposits. Native getBalance accepts
{"commitment":"finalized"}.
Sending
- EVM:
eth_sendRawTransaction takes signed legacy, EIP-2930 and EIP-1559
transactions. Track each sender's nonce yourself, or read it with
eth_getTransactionCount(address, "pending").
- Native:
sendTransaction on /node/rpc takes a signed WCAHT
transaction object, one per request. Transfers of 1,000 WCAHT or more must carry Travel Rule data.
- If a send times out, resend the identical signed bytes. The chain includes a transaction at most once.
A re-signed native transfer (new blockhash) is a different transaction. Send one only after the first has expired
or failed, or both may land. An EVM replacement must reuse the same nonce.
Limits and running your own node
The public endpoints are shared and rate-limited per client. On HTTP 429, back off and retry. For
production volume, run your own node from the validator bundle (it can run without
stake as an observer), and point your app at its local RPC.
Example — check finality
# EVM: the newest irreversible block
curl -X POST https://denvion.com/eth \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}'
# Native: the status of a transaction signature
curl -X POST https://denvion.com/node/rpc \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["<signature>"],{"searchTransactionHistory":true}]}'
Developer API reference
Every node exposes a public HTTP API (default port 8901). Reads are open; transaction submission
requires an x-api-key. There is also an Ethereum JSON-RPC endpoint at /eth.
Chain & blocks
GET/api/chain_infoChain id, height, finalized slot, validator count.
GET/recent_blockhashReplay-protection token required when building a transaction.
GET/recent_blocks GET/api/blocks_by_height?start&endRecent blocks / a height range.
GET/total_supplyTotal & circulating supply in kak.
Accounts & balances
GET/balance/{address} GET/api/account/{address}Balance (kak) / full account record.
GET/transaction/history/{address}Transaction history for an address.
Transactions
POST/transactions/submitSubmit a signed transaction. Requires header x-api-key. Transfers ≥ 1000 WCAHT require Travel Rule data.
POSThttps://denvion.com/node/rpcPublic HTTPS native JSON-RPC proxy: read methods such as getBalance, getLatestBlockhash and getSignatureStatuses, plus single sendTransaction requests. A node operator's local endpoint remains http://127.0.0.1:8901/rpc.
GET/transactions?hash={tx_hash}Look up a transaction / confirmation status.
Staking & validators
GET/api/stake/info GET/api/stake/validators GET/api/stake/epochStake summary, validator set, epoch info.
POST/api/validator/registerRegister a validator (signed
CreateValidatorRequest). See the
validator guide.
POST/api/stake/delegate POST/api/stake/deactivate POST/api/stake/withdrawSigned delegation lifecycle.
Contracts
POST/contract GET/contractsDeploy / call / query a contract; list deployed contracts.
Exchanges, multisig wallets and other DeFi run as ordinary Solidity contracts on the EVM (chain ID
7789), deployed with the usual tools (Hardhat, Foundry, Remix). The node has no separate DeFi,
bridge, multisig or exchange APIs.
Network & performance
GET/network/stats GET/peers GET/performance/stats GET/prism/stats GET/fabric/metricsLive mesh, throughput, parallel-execution and mempool metrics.
EVM (Ethereum JSON-RPC)
POST/ethStandard eth_* methods (eth_chainId, eth_getBalance, eth_sendRawTransaction, …). Chain ID 7789. Works with MetaMask / ethers.js / web3.js.
POST/ethTracing:
debug_traceCall,
debug_traceTransaction and
trace_transaction (see
EVM tracing).
Example — read a balance
# Native JSON-RPC (balance in kak, at finalized)
curl -X POST https://denvion.com/node/rpc \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["<address>",{"commitment":"finalized"}]}'
# EVM JSON-RPC
curl -X POST https://denvion.com/eth \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
JavaScript SDK
@wcaht/sdk builds, signs and sends native WCAHT transactions (transfers, staking, validator
registration) and reads balances and transaction status. Keys never leave your process: transactions are signed
locally with ed25519. For EVM contracts use ethers or viem with chain ID 7789; the SDK exports the
chain description as wcahtEvmChain.
# Node.js 18+ (until the package is on the npm registry, install it from this site)
npm install https://denvion.com/static/downloads/wcaht-sdk-0.2.0.tgz
import { Keypair, WcahtClient, toBaseUnits, fromBaseUnits } from "@wcaht/sdk";
const client = WcahtClient.publicGateway();
const keypair = Keypair.fromSecretKey(process.env.WCAHT_SECRET); // base58, 64 bytes
console.log(fromBaseUnits(await client.getBalance(keypair.publicKey)), "WCAHT");
const { signature } = await client.transfer(keypair, "<recipient>", toBaseUnits("1.5"));
console.log(await client.waitForTransaction(signature));
Staking: client.delegate, client.withdrawStake and
client.registerValidator(keypair, toBaseUnits(100), 500) (100 WCAHT minimum, commission in basis
points). Amounts are bigint base units (1 WCAHT = 1,000,000,000). waitForTransaction
returns once the transaction is recorded; credit deposits only after it is final (see
Integrating). Package SHA-256:
50dcf2ec136c21e4fde1c27bb2289767d9d33aae8151339e9ded971c138e867b.
Verify a transaction without trusting the node
const proof = await client.verifyTransaction(signature);
// { height, slot, blockHash, contentVerified, merkleProof, finalityEpoch, signedStake, totalStake }
verifyTransaction checks everything itself instead of believing the server: it rebuilds the block's
transaction root and block hash, verifies the validators' finality signatures and that they hold at least 2/3 of
the stake, and checks the validator set against the trust anchor pinned in the SDK. It throws if any check fails
or the block is not final yet. The building blocks (verifyFinality,
transactionMerkleProof, computeBlockHash, …) are exported too.
EVM tracing
The EVM endpoint supports Geth's callTracer and the Parity-style trace_transaction:
debug_traceCall(call, block, {"tracer":"callTracer"}) simulates a call against current state and
returns the call tree: type, from, to, value, gas, input, output, error and nested calls.
debug_traceTransaction(hash, {"tracer":"callTracer"}) returns the same tree for a mined
transaction.
trace_transaction(hash) returns the flattened list with traceAddress.
Traces are recorded by the network's RPC nodes while blocks execute and kept for 7 days. A transaction older
than that, or executed before tracing was enabled (17 Oct 2026), returns
trace not available. Other tracers (prestateTracer, struct logs) are not supported.
curl -X POST https://denvion.com/eth -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"debug_traceTransaction","params":["0x<tx hash>",{"tracer":"callTracer"}]}'