Wallet API Reference
Every DAI miner exposes an HTTP API on walletApiPort (default 3456).
Balance responses are in μDAI (raw) — 1 DAI = 1 000 000 000 μDAI.
Input amounts for /api/wallet/send and staking endpoints are in DAI (the server converts internally).
Public miners (e.g. miner.iamai.kg) expose the same routes over HTTPS. CORS is open for browser clients.
Generate Wallet
A DAI wallet is an ed25519 keypair. The address is derived from the signing public key — no seed phrases, no custodians. Follow these four steps to create a wallet and start submitting jobs.
Run this Node.js script (requires tweetnacl — npm i tweetnacl).
It deterministically derives an ed25519 signing keypair from 32 random bytes, then
computes the canonical DAI address as 'dai' + sha256(signingPublicKey).slice(0,40).
Keep dai-wallet.json secret.
The signingSecretKeyB64 is the private signing key — never share or commit it.
Post your address, signingPublicKey, and the proof from Step 1 to any miner.
The proof is an ed25519 signature over your address — it proves you hold the private key.
This binds your key to your address so the network can verify your job payment signatures.
Missing the proof returns 400 { "error": "address, signingPublicKey, and proof required" }.
An invalid proof returns 403 { "error": "invalid proof" }. To rotate to a new key later,
include a rotationProof signed by your existing key.
Registration is free and only needs to happen once per keypair. It does not require any DAI balance.
Compute and skill jobs require a signed paymentTx with sufficient budget. Fund your address
via the P2P exchange, a transfer from another wallet, or a faucet.
Check your balance at any time:
Sign a payment proof and post to /job. The snippet below uses the wallet file from Step 1.
Chain & Wallet
Fourteen regional stablecoins ride on the DAI chain alongside DAI: KGST (Kyrgyzstan som, bridged across DAI/BSC/Tron) plus αιETB, αιBTN, αιVES, αιPYG, αιBDT, αιPKR, αιEGP, αιIQD, αιAOA, αιCUP, αιLYD, αιSDG, αιIRR (wire tickers aiETB, aiBTN, aiVES, aiPYG, aiBDT, aiPKR, aiEGP, aiIQD, aiAOA, aiCUP, aiLYD, aiSDG, aiIRR). All use 2 decimals (1 unit = 100 raw); DAI keeps 9 (1 DAI = 1e9 μDAI). Off-chain on-ramps: USDT (USDT-ERC20, USDT-TRC20, USDT-TON, USDT-SOL, USDT-BEP20), USDC, and bank transfer.
GET /api/assets lists every asset with decimals, display names and per-currency gas prices. GET /api/wallet/balance returns an additional assets map with each stablecoin's raw and display balance.
Transfers: POST /api/wallet/send (and /api/tx/submit) accept a currency field — omit it for DAI. A transaction's signed hash includes currency ONLY when non-DAI, so existing DAI transactions and signatures remain valid unchanged.
/statusNode status — chain height, sync state, reputation.
/api/miner/infoVersion, uptime, peer count, wallet address.
/api/wallet/balance?address=<addr>Balance in μDAI for a DAI wallet address.
/api/wallet/nonce?address=<addr>Current nonce for transaction / payment signing.
/api/wallet/transactions?address=<addr>&limit=<n>DAI transfer history, read from the chain — every node returns the same result for an address, and both sender and recipient see a transfer once it is mined. Mempool entries appear first with status: "pending".
/api/tx/<id>One transaction by hash. Falls back to the mempool before returning 404, so a just-submitted transfer resolves immediately. Mining rewards have no hash of their own and carry a synthetic id of the form coinbase-<height>-<kind>-<address>.
/api/wallet/history?address=<addr>Full history with block confirmations.
/api/wallet/jobs?address=<addr>&limit=20Public job history — joins job-submitted transitions with mined scanResults. Returns { jobs, latestSkillMemory, chatTurns }.
/api/wallet/register-keyRegister an ed25519 signing key for an address. Required before signed job payments. See Generate Wallet for how to produce the proof. proof = ed25519 signature over the address string.
/api/wallet/sendTransfer DAI between wallets. The sender wallet must be stored on this node (loaded via walletManager). Amount is in DAI (not μDAI). Optional fee and memo fields.
/api/tx/submitSubmit a pre-signed DAITransaction to the mempool.
/api/tx/pendingInspect pending mempool transactions.
/api/chain/supply-auditChain supply audit — total issued vs. accounted balances.
Jobs
Submit compute work to the network. Types: verdict (identity scan, free), skill, compute.
skill and compute jobs require a signed payment proof (maxBudget in μDAI).
Paid jobs are metered per AI compute token at 1 μDAI per token (the default gasPrice; μDAI is the smallest unit, so this is the floor). Since 1 DAI = 1 000 000 000 μDAI, one DAI buys up to 1 billion tokens.
The fee is tokensUsed × gasPrice and is never less than the tokens actually used (1 000 tokens ⇒ ≥ 1 000 μDAI). Unused budget is refunded. A maxBudget too small to cover the job's token cost is rejected with 402 FEE_TOO_LOW.
Block reward. On top of the fee, each block's ~1 DAI subsidy is split among the workers who completed jobs, weighted by delivered compute (a deterministic token estimate — splitting into many nodes earns nothing extra), minus a small (~10%) proposer cut. Blocks with no real work mint only a small keepalive, so emission tracks demand.
DAI has no fixed price — the market defines it via the best open P2P order (see GET /api/p2p/price).
Job fees can be paid in DAI or any stablecoin: set currency on the job payload. The fee floor is priced per currency, and the miner receives exactly the currency paid — no conversion.
/jobSubmit a job. Returns { jobId, statusUrl, resultUrl }. id is generated by the client and signed into the payment proof: paymentTx.txHash is a SHA-256 of JSON.stringify({ jobId, requesterAddress, minerAddress, amount, nonce }) — not a blockchain transaction hash. minerAddress comes from GET /api/miner/info; nonce is the wallet's current /api/wallet/nonce value; the signature is over the hex hash string. When paying in a stablecoin, append currency to the hashed object.
/api/estimate · GET /api/estimate?prompt=…Estimate a job's fee before you sign it — the eth_estimateGas of DAI. Send the same fields you would submit; the node sizes the whole pipeline (attachment text, skill and MCP output, dataset rows, planner and synthesis calls) and returns the AI tokens it will use, the minimum fee it accepts and a recommended budget. Read-only — nothing runs and nothing is paid. Amounts are raw units of the fee currency (μDAI for DAI; 1 DAI = 1e9 μDAI).
Each contributor is tagged measured (counted exactly — prompt, attachment text, dataset rows), bounded (what a skill fetched or an MCP tool returned is capped by the executing code, so it is a {min,max} range) or assumed. fees.minimum is what the node rejects below; fees.recommended covers the worst case. A currency nobody quotes on the P2P book is reported unavailable rather than priced. Errors: 422 dataset_not_installed, 404 skill_not_found, 400 for bad input. Available on nodes newer than 0.4.36.
A public job can set payload.requesterEncryptionPublicKey (the requester's X25519 key). The chain then stores the prompt as promptCipher and the reply as profile.replyCipher, with computeOutput null. The job is still listed — encryption does not remove it. Only that key opens the text. Poll GET /job/:id/status (this miner, then the board, then the chain) or GET /api/wallet/jobs?address=. GET /jobboard/status?jobId= is the live queue: it keeps a finished job until a block includes it, then for 10 minutes.
/jobboard/submitSame body as POST /job, sent to a bootnode so any miner can pull the work. The payment hash is sha256 of JSON.stringify({ jobId, requesterAddress, amount, nonce }) — no minerAddress, because the worker is not known yet. Poll GET /jobboard/status?jobId= while it is queued. After inclusion the same job is on GET /job/:id/status and in the wallet job list.
/job/:id/statusPoll job state: queued, computing, done, error. A miss in this process's memory is looked up on the job board and then on chain, so a board job stays visible after the queue drops it.
/job/:id/resultFull result when the job is done. Cleartext replies are in profile.computeOutput. Sealed replies are in profile.replyCipher (computeOutput is null) — open that envelope with the requester's X25519 key.
/jobsList active jobs on this node.
/gossipReceive P2P gossip envelopes from peer miners.
Chat & Routing
/chat/routeRoute a message to the best matching skill.
/chat/askFull AI reply — routes to a skill or free chat. Accepts optional attachments (text files or images, ≤1 MB total). Images force a vision-capable model. May return { fromChainHistory: true } for cached on-chain replies.
Attachments are an optional array of { type: 'text'|'image', data: '<base64>', filename?: '...' }. Text is inlined into the prompt; images select a vision model automatically. Max 1 MB per request.
Private chat uses in-memory session history. Public (paid) jobs also pull on-chain history via
/api/wallet/jobs so follow-ups work across devices.
Model Context Protocol (MCP)
Every node ships a builtin pack (22 public-data tools + onion search). Chat picks from that address book instead of dumping every schema into the prompt. Extra servers overlay via Electron Settings or config.json. HTTP connectors accept arbitrary custom headers, not only Authorization: Bearer.
/api/mcp/statusList connected MCP servers and their available tools, plus the builtin pack. Returns { servers, tools, builtin }.
/api/mcp/catalog?q=Search the address-book cards (builtin + overlay). Cards are names and one-liners, not full schemas.
/api/mcp/executeRun a tool. Peers may call this for builtin tools so picked MCPs disperse across nodes.
When you ask a question in
/chat/ask or /chat/route, the miner picks 0–few tools from the catalog (never the whole pack), may run each on a different peer, then synthesizes. Tool names are namespaced: <server>__<tool>.
Configuration
Add servers to config.json under mcpServers (standard Claude Desktop / Cursor format):
Electron users: paste server config into Settings → MCP Servers instead of editing config.json manually.
Chat History Search
Meilisearch runs locally on each miner (port 7700). Remote clients call these wallet API routes — not Meilisearch directly.
/api/search/suggest?q=<prefix>&wallet=<addr>&limit=8Autocomplete from indexed blockchain job history — past prompts and reply snippets.
/api/search/history-match?q=<message>&wallet=<addr>Return a full cached reply when the prompt closely matches prior on-chain history (similarity ≥ 0.86).
Blockchain Explorer
/api/explorer/blocks?page=0&limit=20Recent blocks (newest first). Each entry includes jobCount when the block contains mined results.
/api/explorer/block/:heightFull block JSON — scanResults, stateTransitions, hash, miner, reward.
/api/explorer/search?q=<query>Lookup by block height, tx/block hash, or wallet address. Address search returns balance, transfers, and completed jobs.
Skills
On-demand agent modules. Deploy a public skill for 1 DAI; community staking reaches 10 DAI to graduate a skill network-wide.
/api/skillsList skills with staking totals and economics: { proposeFeeDai, graduationThresholdDai }.
/api/skills/prefs?address=<addr>Skill enable/disable and staking preferences for a wallet.
/api/skills/proposePropose a new skill. Public proposals cost 1 DAI (escrowed for code_audit).
/api/skills/:id/stakeStake DAI toward skill graduation. Amount is in DAI (not μDAI). Uses the node's own wallet.
/api/skills/:id/unstakeWithdraw staked DAI from a proposed skill.
/api/skills/:id/enable | /disableToggle whether this node runs a skill.
HF Datasets
Hugging Face datasets installed on this node. Compute jobs can reference them by ID. Chat will suggest installs when a dataset is missing.
Datasets are stored under ~/.dai-miner/brain-data/hf-datasets/.
/api/hf-datasetList installed datasets. Returns { datasets: [{ id, files, rowCount, source }] }.
/api/hf-dataset/:id/downloadInstall a dataset by Hugging Face ID. Falls back to pulling from a peer miner if HF is unreachable. Returns { ok: true, manifest } on success.
/api/hf-dataset/:idRemove an installed dataset from this node.
LLM & Brain
Inference runs in-process via QVAC. Brain state stores human feedback and signal weights.
/api/chatStreaming chat via local QVAC (Ollama-compatible body).
/api/generateQVAC generate endpoint (Ollama-compatible body).
/api/modelsModels available on this node (built-in + loaded + registry).
/api/network-modelsAggregated model list from connected peers.
/api/brain/stateWeights count, feedback count, model info.
/api/brain/weightsFull weights.json for the identity brain.
/api/brain/feedbackSubmit a human correction to improve signal weights.
/api/brain/voteVote on signal weight adjustments.
P2P Exchange
On-chain DAI assets (DAI, aiETB, aiBTN, aiBDT, aiPKR, …) + bridged KGST (DAI/BSC/Tron) trade as base. When both legs settle on DAI (e.g. KGST/aiBDT or DAI/aiETB) the trade settles atomically in one step — no payment-sent/confirm phase; proceeds go directly to the taker's dai address. Off-chain legs (USDT, USDC, bank transfer) keep the manual escrow flow.
Peer-to-peer DAI trading with on-chain escrow.
/api/p2p/currenciesSupported quotes and on-chain bases. Includes KGST and USDT wires.
/api/p2p/marketsPair list with last price (mid from the open book) and 24h change. change24h is null until history exists. Optional ?pair=BASE-QUOTE (e.g. KGST-USDT-TRC20).
/api/p2p/price?quoteCurrency=<cur>Reference DAI price — the market price derived only from the best open P2P order(s): { price (mid), bestBid, bestAsk, source }. Omit quoteCurrency for a per-currency map. DAI has no oracle/fixed price.
/api/p2p/ordersOpen order book. Filters: side, quoteCurrency, baseAsset, pair.
/api/p2p/orders/my?address=<addr>Orders created by this address.
/api/p2p/ordersCreate a buy or sell order.
/api/p2p/orders/:id/cancelCancel an open order.
/api/p2p/orders/:id/selectTaker selects an order to begin a trade. Optional takerPayoutAddress is the taker's off-chain receive address when taking a buy.
/api/p2p/trades/my?address=<addr>Active and completed trades for an address.
/api/p2p/trades/:id/:actionAdvance trade: payment-sent, release, cancel, dispute.
Push Notifications
/api/push/registerRegister an Expo push token for a wallet address.
/api/push/sendSend a push notification. Optional address filter.
Errors & Auth
Responses are JSON. Errors return { "error": "message" } with an appropriate HTTP status (400, 401, 402, 404, 500).
Payment-required (402): skill/compute jobs without a valid signed paymentTx are rejected before execution.
Signing: register your ed25519 key via /api/wallet/register-key, then sign payment proofs binding jobId + minerWallet + maxBudget + nonce.
SDKs: use runCompute() / submitJob() in dai-miner SDK to handle signing automatically, and estimate() to price a job first.