DZNYE CHAIN connecting…
Developers

Build on Dznye

Plain HTTP and JSON. Every change is a transaction you sign yourself; there is no privileged endpoint, and no account needed with us.

Node address: https://api.dznye.com (also https://chain.dznye.com/api). The wallet is at wallet.dznye.com, the explorer at explorer.dznye.com, network status at status.dznye.com.

Fees paid for you: the welcome fund pays the fee for everyday actions (sending, names, devices, trading, channels, small contract calls), within limits, so newcomers never need DZY first. Name it as payer (its address is at GET /sponsor) and send the signed transaction to POST /sponsor {"tx": …}.

The chain

dznye-1

Namedznye-1 (inside every signature)
Genesis hash1085eabf51d40005d6e8ad6d70dcdd66d7cb6b4a6c4eb8eae858ff2e6a33ad77
Genesis filedznye-1.genesis.json
Fee0.001 DZY per transaction (1,000 parts; 1 DZY = 1,000,000 parts)
CoinDZY, 6 decimals, at most 12,000,000, never destroyed

Check that a node runs exactly this chain: node chain/cli.mjs genesis check dznye-1.genesis.json --node https://chain.dznye.com/api

Read

The API

RequestGives
GET /api/chain, block height, validators, the fee, the latest snapshot, this node's role, any alert
GET /api/account/<address>balances, the nonce to use next, device keys, agent keys, guardian, stake
GET /api/validatorsthe validators, each one's say, every stake
GET /api/assets, /api/offersevery token and every open offer
GET /api/supply, /api/supply/<token>limit, issued, existing, circulating; for DZY the treasury, stake and each pool
GET /api/genesis, /api/blocks?from=1&limit=100, /api/block/<n>everything needed to replay and check the chain
GET /api/snapshotthe latest kept snapshot: a block and the whole state after it
GET /api/peers, POST /api/peers {url}places known to hold this chain; announce yours (checked before it is listed)
GET /api/contracts, /api/contract/<addr>, /api/contract/<addr>/view?fn=&args=contracts: all of them, one in full, or a free question to one
GET /api/channel/<id>a payment channel
POST /api/tx { "tx": … }send a signed transaction (60 a minute per address)
Write

Signing a transaction

A transaction is { chain, from, nonce, type, data, sig }. The signature is Ed25519 over "dzy-tx:" + canon({ chain, from, nonce, type, data, signer, payer }), where canon writes JSON with keys sorted and whole numbers only. Amounts are whole numbers of the smallest part.

import { Client } from './chain/src/client.ts';
const c = new Client('https://chain.dznye.com/api');
await c.send(myKey, 'transfer', { asset: 'DZY', to: address, amount: 1_500_000 }); // 1.5 DZY

// an app paying its user's fee: the user signs naming the app, the app adds its signature
const tx = await c.prepare(userKey, 'transfer', { asset: tokenId, to, amount: 5 }, { payer: appKey.address });
await c.submit(await Client.sponsor(appKey, tx));
TypeDoes
transfersend any asset, with an optional public memo
asset.create, mint, burnmake a token (1 DZY to the treasury), issue it (its maker only), destroy your own (DZY goes to the treasury instead)
offer.create, offer.take, offer.cancelswap any asset for any other, both sides at once
key.add, key.removedevices on one account
agent.allow, agent.revokea limited key for software: one asset, a total, a fee budget, an end time
guardian.set, recover.start / .cancel / .finishrecovery through a guardian, with a 3-day wait
stake.bond, stake.unbond, stake.withdraw, validator.unjailvalidators locking DZY
evidenceproof that a validator signed two different votes
treasury.spendthe treasury paying out (the issuing key only, with a public reason)
name.set, name.releasechoose a name (3 to 20 small letters, digits or dashes; 0.1 DZY to the treasury), so people can send to @name. Look one up: GET /api/name/<name>
account.multisigseveral keys must agree: every transaction from the account then needs need of keys to sign (extra signatures go in cosigs; Client.cosign)
contract.deploy, contract.callput a program on the chain; call one of its functions, optionally sending it coins
channel.open, .fund, .close, .start, .update, .settlepayment channels (the second layer)
Command line

No installs: Node 24 is enough

node chain/cli.mjs key new me.json
node chain/cli.mjs info      --node https://chain.dznye.com/api
node chain/cli.mjs balance <address> --node https://chain.dznye.com/api
node chain/cli.mjs send --key me.json --to <address> --amount 1.5 --node https://chain.dznye.com/api
node chain/cli.mjs token create --key me.json --symbol GOLD --name "Game gold" --node https://chain.dznye.com/api
node chain/cli.mjs validators --node https://chain.dznye.com/api
Contracts

Programs on the chain

A contract is a set of functions written as JSON: no compiler, and every node reads it the same way. It has its own address, can hold DZY and tokens, and keeps its own storage. Everything is whole numbers, nothing random, nothing outside the chain, so every node gets the same result. Every step costs gas; a call that fails (a require, too little gas) changes nothing at all, including coins sent with it.

{ "functions": {
    "lock": { "args": ["until"], "body": ["seq",
        ["require", [">", ["paid", "DZY"], 0], "send the DZY to lock with this call"],
        ["set", "owner", ["caller"]], ["set", "until", ["arg", "until"]]] },
    "withdraw": { "body": ["seq",
        ["require", ["=", ["caller"], ["get", "owner"]], "only the owner"],
        ["require", [">=", ["now"], ["get", "until"]], "still locked"],
        ["transfer", "DZY", ["get", "owner"], ["balance", "DZY"]]] },
    "unlocks": { "view": true, "body": ["get", "until"] } } }
Valueswhole numbers, text, true, false, null
Operations+ - * / % min max, = != < <= > >= and or not, if seq for let var arg, str len, require fail, get has set del, caller self now height paid balance isaddress, transfer
Limitsprogram 12,000 characters; 200,000 gas a call; loops of at most 1,000 rounds; 10,000 stored values
Costsdeploying: 1 DZY to the treasury. Gas: the chain's fee, once, plus once per 1,000 gas; unused gas is paid back
Not in version 1contracts calling contracts (so re-entrancy attacks cannot exist), making tokens, deleting contracts
node chain/cli.mjs contract deploy --key me.json --file chain/contracts/vault.json --node https://chain.dznye.com/api
node chain/cli.mjs contract call --key me.json --contract <address> --fn lock --args '[1800000000000]' --pay 5 --node …
node chain/cli.mjs contract view --contract <address> --fn unlocks --node …

Examples to copy: escrow, crowdfund and vault, in chain/contracts/. Ask a contract something for free: GET /api/contract/<address>/view?fn=unlocks&args=[].

Second layer

Payment channels: instant and free

Two people lock coins in a channel once (channel.open, channel.fund). From then on they pay each other off the chain, instantly and for free, by both signing each new state: { nonce, a, b }, the amounts each side would get. They settle on the chain once:

Together

channel.close with the newest state both signed: paid out at once.

Alone

channel.start with the newest state (or the deposits). The other side has a day to show a newer one with channel.update; then anyone sends channel.settle.

Cheating fails

Closing on an old state only works if the other side never shows up within the day. Keep the newest state, and check in.

node chain/cli.mjs channel open --key alice.json --to <bob> --amount 10 --node …
node chain/cli.mjs channel sign --key alice.json --id <id> --nonce 7 --a 6 --b 4    # both sign; swap signatures
node chain/cli.mjs channel close --key bob.json --id <id> --nonce 7 --a 6 --b 4 --sig-a … --sig-b … --node …
Copies everywhere

Keep a copy of the chain

No single place should hold the only copy. Every copy can be checked against the chain's own fingerprints, so a copy from anywhere is safe to use.

The archive: the whole chain as plain files, at /archive/index.json. Make your own and keep it anywhere (a folder, a USB stick, a git repository, a web server, IPFS):

node chain/archive.mjs update --node https://chain.dznye.com/api --out ./dznye-archive

The swarm: /api/peers lists the nodes known to hold this chain. A follower can copy from several sources at once (nodes and archives), finds more through them, and raises an alert if any of them shows a different history:

node chain/node/server.mjs --follow https://chain.dznye.com/archive/index.json,https://chain.dznye.com/api --data ./dznye-data
# with a public address, others learn of your node too:
PUBLIC_URL=https://my-node.example.org node chain/node/server.mjs --follow https://chain.dznye.com/api --host 0.0.0.0
Run a node

Check it yourself, or help run it

A follower holds no key: it copies every block, checks every rule and signature, and raises an alert if anything is wrong.

node chain/node/server.mjs --follow https://chain.dznye.com/api --data ./dznye-data

A validator stakes at least 1,000 DZY and runs a node with its key and the other validators as peers. The whole process, from keys to upgrades, is in the runbook (chain/launch/RUNBOOK.md).

Watching any set of nodes: node chain/launch/check.mjs https://chain.dznye.com/api --genesis dznye-1.genesis.json