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 | <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>bursa — the serverless p2p currency exchange</title>
<style>
:root {
--bg: #05060f; --panel: #0b0e1f; --panel-2: #10142a; --border: #1a2140;
--text: #d8e6ff; --muted: #6b7aa8; --accent: #00f0ff;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg); color: var(--text);
font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
padding: 40px 20px 80px;
}
main { max-width: 780px; margin: 0 auto; }
h1 { font-size: 34px; letter-spacing: 4px; color: var(--accent); text-shadow: 0 0 18px var(--accent); }
.tag { color: var(--muted); margin: 6px 0 30px; font-size: 17px; }
h2 { margin: 44px 0 12px; font-size: 22px; color: var(--accent); }
h3 { margin: 24px 0 8px; font-size: 17px; }
p, li { color: #b9c6dd; }
ul { padding-left: 22px; margin: 10px 0; }
li { margin: 5px 0; }
a { color: var(--accent); }
pre {
background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
padding: 14px 16px; overflow-x: auto; margin: 12px 0;
font: 13.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
}
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px;
background: var(--panel-2); border-radius: 5px; padding: 1px 6px; }
pre code { background: none; padding: 0; }
.card {
background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
padding: 18px 20px; margin: 14px 0;
}
.btns { display: flex; gap: 10px; flex-wrap: wrap; margin: 18px 0 6px; }
.btn {
display: inline-block; padding: 10px 18px; border-radius: 8px; text-decoration: none;
background: #0a1428; border: 1px solid #14406a; color: var(--accent);
letter-spacing: 1px; font-size: 14px;
}
.btn:hover { background: #10305a; box-shadow: 0 0 14px #00f0ff44; }
footer { margin-top: 60px; color: var(--muted); font-size: 13px; }
</style>
</head>
<body>
<!-- TODO: once the copy below is real, add ro/hu blocks + the language nav
in the pattern of game1/site/index.html (data-lang-block + localStorage). -->
<main>
<h1>bursa</h1>
<p class="tag">orderbooks for the suite's bank currencies, settled atomically — this page is also the git repo.</p>
<div class="btns">
<a class="btn" href="https://bursa.ardegazu.ro/">open the app</a>
<a class="btn" href="browse/index.html">browse the code</a>
<a class="btn" href="#clone">clone the repo</a>
</div>
<h2 id="clone">Clone</h2>
<p>This site serves the repository over git's dumb-HTTP protocol as plain static
files (plain files — there is no git server here, or any server at all):</p>
<pre><code>git clone https://git.ardegazu.ro/bursa.git
cd bursa</code></pre>
<h2>What it is</h2>
<p>bursa is a currency exchange with no exchange in it: one encrypted log
holds the book, every member's replica runs the same matching fold, and a
trade settles as two bank-held escrow locks under one hashlock — either both
sides are paid or neither is. Banks come from banca; a match obliges nobody
until the money locks. Installable PWA — works saved to an
iOS home screen, safe-area aware.</p>
<h2>How it works</h2>
<ul>
<li><strong>No server.</strong> Browsers are
<a href="https://libp2p.io">libp2p</a> peers: they meet through a
circuit-relay-v2 node, discover each other via gossipsub, and upgrade to
direct WebRTC. The room secret lives in the URL fragment (<code>#…</code>)
and never leaves the browser.</li>
<li><strong>Everything is end-to-end encrypted.</strong> Every peer pair is
noise-encrypted end-to-end (even while frames still cross the relay), and
room membership is proved with an AES-256-GCM sealed hello derived from
the room secret — an undecryptable hello means you're not in the room.
TURN with ephemeral credentials covers the stubborn NATs.</li>
<li><strong>Hosting without an origin server.</strong> The client is a static
Vite build served as plain files — there is no backend anywhere. This page
you're reading works the same way.</li>
</ul>
<h2>What's in the repo</h2>
<div class="card">
<h3>client/src/app/ — the app</h3>
<p>TODO: what your app code does. TypeScript, no framework: typed wire
protocol plus the app's own logic and UI.</p>
</div>
<div class="card">
<h3>client/src/net/ — the p2p layer</h3>
<p>A thin js-libp2p assembly: relay bootstrap from
<code>/.well-known/ap2p</code>, a room-scoped protocol with a sealed-hello
membership handshake, reconnection, and the six-method surface the app
consumes.</p>
</div>
<div class="card">
<h3>deploy/ — the publish pipeline</h3>
<p><code>publish-repo.sh</code> builds this very site: landing page + bare
mirror exploded to loose objects (static file servers and git's dumb-HTTP protocol
agree on "every path must exist"), with an anonymity gate that refuses to
publish identity-bearing bytes.</p>
</div>
<h2>Run it yourself</h2>
<pre><code>cd client && npm install && npm run dev # :4173
# open two tabs on the same #room URL</code></pre>
<p>Deploy: <code>npm run build</code>, then publish <code>client/dist/</code> as
static files anywhere — IPFS, a CDN, a folder behind nginx. It needs nothing but
a libp2p circuit relay it's allowed to talk to (see <code>src/app/config.ts</code>).</p>
<h2>Guarantees & limits, honestly</h2>
<ul>
<li>The relay operator sees connection metadata, opaque room ids, and frame
sizes/timing. Not content, not names, not what was said.</li>
<li>Anyone with the room link can join — capability model. Guard the link
like you'd guard the room.</li>
<li>TODO: any app-specific trust caveats (who referees, what a malicious
member could do).</li>
<li>MIT licensed. Built on WebRTC and WebCrypto.</li>
</ul>
<footer>
Live: <a href="https://bursa.ardegazu.ro/">bursa.ardegazu.ro</a> ·
this repo: <code>git clone https://git.ardegazu.ro/bursa.git</code> ·
built on <a href="https://libp2p.io">js-libp2p</a>
</footer>
</main>
</body>
</html>
|