Repository navigation
Expand file tree
/
Copy pathapi.html
More file actions
207 lines (206 loc) · 19.7 KB
/
Copy pathapi.html
File metadata and controls
207 lines (206 loc) · 19.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<!doctype html>
<!-- Generated by src/build.py from src/pages/api.html. Edit those, not this file. -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Public API | LapseCoin</title>
<meta name="description" content="Public read-only HTTP API served by every LapseCoin node: chain info, blocks, transactions, addresses, fees and broadcast.">
<link rel="icon" type="image/svg+xml" href="lapsecoin.svg">
<link rel="canonical" href="https://lapsecoin.github.io/api.html">
<meta property="og:site_name" content="LapseCoin">
<meta property="og:type" content="website">
<meta property="og:title" content="Public API">
<meta property="og:description" content="Public read-only HTTP API served by every LapseCoin node: chain info, blocks, transactions, addresses, fees and broadcast.">
<meta property="og:url" content="https://lapsecoin.github.io/api.html">
<meta property="og:image" content="https://lapsecoin.github.io/logo-512.png">
<meta property="og:image:width" content="512">
<meta property="og:image:height" content="512">
<meta name="twitter:card" content="summary">
<meta name="theme-color" content="#f4f1ea">
<link rel="preload" href="css/fonts/Geist-Variable.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="css/site.css">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-2XWCJKT8GJ"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-2XWCJKT8GJ');
</script>
</head>
<body>
<header class="bar"><div class="bar-in">
<a class="brand" href="index.html"><img src="lapsecoin.svg" alt="" width="22" height="22">LapseCoin</a>
<nav class="nav" aria-label="Site"><a href="downloads.html">Download</a><a href="index.html#start">Get started</a><div class="menu"><button class="menu-btn on" type="button" aria-expanded="false" aria-controls="menu-docs">Documentation<svg class="chev" viewBox="0 0 12 12" aria-hidden="true"><path d="M2.5 4.5 6 8l3.5-3.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button><div class="menu-list" id="menu-docs"><a href="api.html" aria-current="page">API reference</a><a href="tx.html">Transactions</a><a href="exchange.html">Exchange integration</a><a href="wallets.html">Wallet integration</a><a href="https://lapsecoin.github.io/core/whitepaper.html">Whitepaper</a></div></div><a href="index.html#community">Community</a><a href="index.html#support">Support</a></nav>
<div class="ext"><a href="https://discord.gg/FP2d8JmK6r"><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M13.545 2.907a13.2 13.2 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.2 12.2 0 0 0-3.658 0 8 8 0 0 0-.412-.833.05.05 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.04.04 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032q.003.022.021.037a13.3 13.3 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019q.463-.63.818-1.329a.05.05 0 0 0-.01-.059.05.05 0 0 0-.018-.011 8.9 8.9 0 0 1-1.248-.595.05.05 0 0 1-.02-.066.05.05 0 0 1 .015-.019q.127-.095.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.05.05 0 0 1 .053.007q.121.1.248.195a.05.05 0 0 1-.004.085 8 8 0 0 1-1.249.594.05.05 0 0 0-.03.03.05.05 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.2 13.2 0 0 0 4.001-2.02.05.05 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.03.03 0 0 0-.02-.019m-8.198 7.307c-.789 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612m5.316 0c-.788 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612"/></svg><span>Discord</span></a><a href="https://github.com/Lapsecoin/core"><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.6 7.6 0 0 1 4 0c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg><span>GitHub</span></a></div>
</div></header>
<main><div class="wrap">
<div class="page-head"><h1>Public API</h1><p>Read-only JSON over HTTP. Broadcasting an already signed transaction is the one write.</p></div>
<div class="doc"><div class="prose">
<section id="basics">
<h2>Basics</h2>
<p>Every node serves a public, read-only HTTP API on its public port (default <code>8333</code>). Example base URL: <code>https://lapsenode.vicnas.me</code>, or your own node at <code>http://host:8333</code>.</p>
<ul>
<li>All amounts are integers in <strong>ticks</strong>. 1 LAPSE = 100,000,000 ticks.</li>
<li>Responses are JSON. Errors return a non-2xx status with an <code>error</code> field.</li>
<li>Requests are rate limited per client IP (default 60 per minute; <code>POST /api/tx/send</code> allows 20 per second).</li>
<li>The API sends no CORS headers, so call it from a server rather than from browser JavaScript on another origin.</li>
<li>No authentication. The wallet's Send feature is only on the private local port, but broadcasting an already-signed transaction is public.</li>
</ul>
</section>
<section id="chain">
<h2>Chain</h2>
<div class="endpoint" id="api-info">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/info</span></div>
<div class="endpoint-desc">Chain and node status.</div>
<div class="tbl"><table>
<tr><th>Field</th><th>Description</th></tr>
<tr><td>height</td><td>Current chain height</td></tr>
<tr><td>sync_percent, sync_target</td><td>Sync progress (capped at 99 until within 3 blocks of the observed tip) and the height being synced toward</td></tr>
<tr><td>tip_hash, genesis_hash</td><td>Hash of the newest block and of block 0</td></tr>
<tr><td>mempool_size</td><td>Pending transactions</td></tr>
<tr><td>peer_count</td><td>Known peers</td></tr>
<tr><td>address</td><td>The node's own address, or <code>null</code> when the operator hides it publicly (the default)</td></tr>
<tr><td>total_minted</td><td>Ticks minted so far (cap: 21,000,000 LAPSE)</td></tr>
<tr><td>burned</td><td>Ticks held by the burn address</td></tr>
<tr><td>circulating</td><td>total_minted minus burned</td></tr>
<tr><td>can_mint</td><td>Ticks still mintable before the cap</td></tr>
<tr><td>block_reward</td><td>Reward in ticks for the next block</td></tr>
<tr><td>block_time_ratio</td><td>This node's median VDF build time relative to the chain's recent median block time, or <code>null</code></td></tr>
<tr><td>network_age_seconds</td><td>Seconds since the genesis block's timestamp</td></tr>
<tr><td>status</td><td>Human-readable node status</td></tr>
<tr><td>oblivious_key</td><td>Base64 X25519 public key a client seals a request to when asking this node something through another node (see <code>/api/oblivious</code>), or <code>null</code> if the node does not take them (<code>--no-relay</code>)</td></tr>
<tr><td>public_url</td><td>The <code>https://</code> address the operator says the node can also be reached at, or <code>null</code> (see <code>--public-url</code>)</td></tr>
<tr><td>recent_txs</td><td>Recent confirmed transactions: <code>{height, hash, from, amount}</code></td></tr>
</table></div>
<pre>curl https://lapsenode.vicnas.me/api/info</pre>
</div>
<div class="endpoint" id="api-block-height">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/block/{height}</span></div>
<div class="endpoint-desc">The block at that height, as stored on chain (including its <code>transactions</code> list). Returns 404 with <code>{"error": "not found"}</code> for an unknown height.</div>
</div>
<div class="endpoint" id="api-tx-hash">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/tx/{hash}</span></div>
<div class="endpoint-desc">A transaction by hash, from the mempool or a block, with a <code>confirmations</code> field added. Mempool transactions have <code>confirmations: 0</code>. Returns 404 if unknown.</div>
</div>
<div class="endpoint" id="api-mempool">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/mempool</span></div>
<div class="endpoint-desc">Returns <code>{"size": n, "transactions": [...]}</code>. Each entry is <code>{hash, from, outputs, fee}</code>.</div>
</div>
<div class="endpoint" id="api-fees">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/fees</span></div>
<div class="endpoint-desc">Current fee-per-byte picture of the mempool. All rates are ticks per byte, where size is the transaction's canonical JSON excluding the signature.</div>
<div class="tbl"><table>
<tr><th>Field</th><th>Description</th></tr>
<tr><td>pending</td><td>Number of pending transactions</td></tr>
<tr><td>min, median, max</td><td>Fee rates across pending transactions (0 when the mempool is empty)</td></tr>
<tr><td>next_block</td><td>Suggested rate to be included in the next block. It is the lowest rate that still fit when the block is full, otherwise the relay floor of 1 tick per byte.</td></tr>
</table></div>
</div>
</section>
<section id="addresses">
<h2>Addresses</h2>
<div class="endpoint" id="api-address-addr-valid">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/address/{addr}/valid</span></div>
<div class="endpoint-desc">Returns <code>{"address": "...", "valid": true|false}</code>. This checks format only: exactly twelve dot-separated words from the BIP39 English list. It cannot tell whether anyone holds the key.</div>
</div>
<div class="endpoint" id="api-address-addr-balance">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/address/{addr}/balance</span></div>
<div class="endpoint-desc">Balance from the node's chain state. Returns 400 for a malformed address.</div>
<div class="tbl"><table>
<tr><th>Field</th><th>Description</th></tr>
<tr><td>address</td><td>The address queried</td></tr>
<tr><td>balance_ticks</td><td>Integer balance in ticks</td></tr>
<tr><td>balance_lapse</td><td>The same balance divided by 100,000,000 (a float, for display only)</td></tr>
</table></div>
</div>
<div class="endpoint" id="api-address-addr-history">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/address/{addr}/history</span></div>
<div class="endpoint-desc">Confirmed transactions touching the address, newest first, as a bare JSON array. Pending mempool transactions are not included.</div>
<div class="tbl"><table>
<tr><th>Element field</th><th>Description</th></tr>
<tr><td>height</td><td>Block height containing the transaction</td></tr>
<tr><td>tx_hash</td><td>Transaction hash</td></tr>
<tr><td>direction</td><td><code>"sent"</code> if the address is the sender, otherwise <code>"received"</code></td></tr>
<tr><td>tx</td><td>The full transaction object</td></tr>
</table></div>
<p>Optional query parameters: <code>limit</code> and <code>offset</code> select a slice. With no <code>limit</code> the full history is returned. The total count is in the <code>X-Total-Count</code> response header.</p>
</div>
</section>
<section id="broadcast">
<h2>Broadcast</h2>
<div class="endpoint" id="api-tx-send">
<div class="endpoint-title"><span class="endpoint-method post">POST</span> <span class="endpoint-path">/api/tx/send</span></div>
<div class="endpoint-desc">Broadcast a fully signed transaction. The JSON body is the transaction object itself; see <a href="tx.html">Transactions</a> for the format and how to sign it.</div>
<pre>{
"from": "word.word. ... (12 words)",
"pubkey": "hex FALCON-512 public key",
"outputs": [{"to": "word.word. ... (12 words)", "amount": 100000000}],
"nonce": 1,
"fee": 500,
"memo": "optional, up to 200 bytes",
"signature": "hex FALCON-512 signature"
}</pre>
<p>Success: <code>{"ok": true, "tx_hash": "..."}</code>. Failure (HTTP 400): <code>{"ok": false, "error": "reason"}</code>, for example a bad nonce, insufficient balance or an invalid signature. The node may also answer "node busy" if its inbound queue is full.</p>
</div>
</section>
<section id="wallet-and-light-clients">
<h2>Wallet and light clients</h2>
<div class="endpoint" id="api-state">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/state</span></div>
<div class="endpoint-desc">What a wallet needs about one address, in a single answer. Query parameters: <code>addr</code>, <code>fees=1</code>.</div>
<div class="tbl"><table>
<tr><th>Field</th><th>Description</th></tr>
<tr><td>board_floor</td><td>Always present: the minimum fee a board post must pay right now</td></tr>
<tr><td>balance</td><td>With <code>addr</code>: the address's balance in ticks</td></tr>
<tr><td>nonce</td><td>With <code>addr</code>: the highest nonce the address has used, confirmed or pending. The next transaction uses this plus one.</td></tr>
<tr><td>fees</td><td>With <code>fees=1</code>: the same object as <code>/api/fees</code></td></tr>
</table></div>
</div>
<div class="endpoint" id="api-address-addr-page">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/address/{addr}/page</span></div>
<div class="endpoint-desc">One page of the address's history as the Balance page shows it, with its totals. Optional <code>page</code> parameter. Returns <code>balance</code>, <code>tx_count</code>, <code>page</code>, <code>total_pages</code> and <code>rows</code>, each row <code>[height, hash, direction, amount, kind]</code> where kind is <code>"tx"</code> or <code>"block"</code> (a block the address built). Much smaller than <code>/history</code>, which carries whole transactions.</div>
</div>
<div class="endpoint" id="api-board-page">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/board/page</span></div>
<div class="endpoint-desc">The board with threads, profiles, votes and reply targets resolved, as the Board page shows it. The <code>chunks</code> parameter is how many chunks of threads to include. The response carries an <code>ETag</code>: send it back as <code>If-None-Match</code> and an unchanged board costs a 304 with no body. Gzipped when the client sends <code>Accept-Encoding: gzip</code>.</div>
</div>
</section>
<section id="peers-and-relay">
<h2>Peers and relay</h2>
<div class="endpoint" id="api-peers">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/peers</span></div>
<div class="endpoint-desc">The node's peer graph: <code>self</code>, <code>peer_count</code>, <code>graph_peers</code>, <code>claims</code> and <code>attempting</code>. For a plain list of <code>ip:port</code> strings that can seed a new node, use <code>GET /api/peers/download</code>, which returns a <code>lapsecoin_peers.json</code> file.</div>
</div>
<div class="endpoint" id="api-peers-http">
<div class="endpoint-title"><span class="endpoint-method">GET</span> <span class="endpoint-path">/api/peers/http</span></div>
<div class="endpoint-desc">Returns <code>{"nodes": ["ip:port", ...], "https": ["https://name", ...], "keys": {"ip:port": key}, "self_key": key}</code>: this node and the peers it has found answering HTTP on its own chain, best-connected first, and the HTTPS addresses this node and those peers advertise (see <code>--public-url</code>), and the <code>oblivious_key</code> of those that take sealed requests. A short list for light clients, which cannot afford <code>/api/peers</code> and send a wallet address only to nodes reached over https.</div>
</div>
<div class="endpoint" id="api-oblivious">
<div class="endpoint-title"><span class="endpoint-method post">POST</span> <span class="endpoint-path">/api/oblivious</span></div>
<div class="endpoint-desc">A request sealed to this node (a NaCl sealed box to its <code>oblivious_key</code>, padded to 1, 2, 4 or 8 KiB), answered sealed to the one-time key the request carries. The plaintext is <code>{"m": method, "p": path, "b": body, "k": one-time public key}</code>, and only <code>/api/state</code>, <code>/api/fees</code>, <code>/api/address/{addr}/page</code> and <code>POST /api/tx/send</code> are answered, by the same code as the open endpoints. It exists so a light client can name its wallet address to this node without the node that carried the request seeing the client's IP: see <code>/api/relay</code> and the README.</div>
</div>
<div class="endpoint" id="api-relay">
<div class="endpoint-title"><span class="endpoint-method post">POST</span> <span class="endpoint-path">/api/relay</span></div>
<div class="endpoint-desc">Body <code>{"to": "ip:port", "blob": base64}</code>. Passes a sealed request to <code>/api/oblivious</code> on <code>to</code>, which must be a peer this node already knows answers HTTP, and returns the sealed answer. The node cannot open what it passes on. Rate limited, at most 8 KiB each way.</div>
</div>
</section>
<section id="finding-the-next-nonce">
<h2>Finding the next nonce</h2>
<p>A transaction's nonce must be exactly one more than the sender's last used nonce, starting from 0, so the first transaction uses nonce 1. Ask <code>/api/state?addr=...</code>: its <code>nonce</code> is the highest the address has used, confirmed or pending, so the next transaction uses that plus one.</p>
</section>
</div><aside class="toc" aria-label="On this page"><b>On this page</b><a href="#basics">Basics</a><a href="#chain">Chain</a><a class="sub" href="#api-info">/info</a><a class="sub" href="#api-block-height">/block/{height}</a><a class="sub" href="#api-tx-hash">/tx/{hash}</a><a class="sub" href="#api-mempool">/mempool</a><a class="sub" href="#api-fees">/fees</a><a href="#addresses">Addresses</a><a class="sub" href="#api-address-addr-valid">/address/{addr}/valid</a><a class="sub" href="#api-address-addr-balance">/address/{addr}/balance</a><a class="sub" href="#api-address-addr-history">/address/{addr}/history</a><a href="#broadcast">Broadcast</a><a class="sub" href="#api-tx-send">/tx/send</a><a href="#wallet-and-light-clients">Wallet and light clients</a><a class="sub" href="#api-state">/state</a><a class="sub" href="#api-address-addr-page">/address/{addr}/page</a><a class="sub" href="#api-board-page">/board/page</a><a href="#peers-and-relay">Peers and relay</a><a class="sub" href="#api-peers">/peers</a><a class="sub" href="#api-peers-http">/peers/http</a><a class="sub" href="#api-oblivious">/oblivious</a><a class="sub" href="#api-relay">/relay</a><a href="#finding-the-next-nonce">Finding the next nonce</a></aside></div>
</div></main>
<footer><div class="wrap">
<div class="foot">
<div class="foot-brand"><a class="brand" href="index.html"><img src="lapsecoin.svg" alt="" width="22" height="22">LapseCoin</a><p>Peer-to-peer electronic cash.</p></div>
<div class="foot-col"><b>Start</b><a href="downloads.html">Download a release</a><a href="index.html#run">Run a node</a><a href="index.html#how">How it works</a></div>
<div class="foot-col"><b>Documentation</b><a href="api.html">API reference</a><a href="tx.html">Transactions</a><a href="exchange.html">Exchange integration</a><a href="wallets.html">Wallet integration</a><a href="https://lapsecoin.github.io/core/whitepaper.html">Whitepaper</a></div>
<div class="foot-col"><b>Community</b><a href="https://discord.gg/FP2d8JmK6r">Discord</a><a href="https://github.com/Lapsecoin/core">GitHub</a><a href="https://lapsenode.vicnas.me/">Live node</a><a href="index.html#support">Support LapseCoin</a></div>
</div>
<p class="legal">LapseCoin is open source, released under the MIT license.</p>
</div></footer>
<script src="js/site.js" defer></script>
</body>
</html>