@toon-protocol/client-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +302 -0
  2. package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js +25 -0
  3. package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js.map +1 -0
  4. package/dist/chunk-32QD72IL.js +83 -0
  5. package/dist/chunk-32QD72IL.js.map +1 -0
  6. package/dist/chunk-3NAWISI5.js +2245 -0
  7. package/dist/chunk-3NAWISI5.js.map +1 -0
  8. package/dist/chunk-5KFXUT5Q.js +11321 -0
  9. package/dist/chunk-5KFXUT5Q.js.map +1 -0
  10. package/dist/chunk-F22GNSF6.js +12 -0
  11. package/dist/chunk-F22GNSF6.js.map +1 -0
  12. package/dist/chunk-FSS45ZX3.js +2633 -0
  13. package/dist/chunk-FSS45ZX3.js.map +1 -0
  14. package/dist/chunk-LR7W2ISE.js +657 -0
  15. package/dist/chunk-LR7W2ISE.js.map +1 -0
  16. package/dist/chunk-SKQTKZIH.js +278 -0
  17. package/dist/chunk-SKQTKZIH.js.map +1 -0
  18. package/dist/chunk-VA7XC4FD.js +185 -0
  19. package/dist/chunk-VA7XC4FD.js.map +1 -0
  20. package/dist/chunk-ZQKYZJWT.js +359 -0
  21. package/dist/chunk-ZQKYZJWT.js.map +1 -0
  22. package/dist/daemon.d.ts +1 -0
  23. package/dist/daemon.js +141 -0
  24. package/dist/daemon.js.map +1 -0
  25. package/dist/ed25519-2QVPINLS.js +27 -0
  26. package/dist/ed25519-2QVPINLS.js.map +1 -0
  27. package/dist/gateway-QOK47RKS-SEGTXBR3.js +16 -0
  28. package/dist/gateway-QOK47RKS-SEGTXBR3.js.map +1 -0
  29. package/dist/hmac-26UC6YKX.js +12 -0
  30. package/dist/hmac-26UC6YKX.js.map +1 -0
  31. package/dist/index.d.ts +965 -0
  32. package/dist/index.js +68 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/mcp.d.ts +1 -0
  35. package/dist/mcp.js +81 -0
  36. package/dist/mcp.js.map +1 -0
  37. package/dist/sha512-WYC446ZM.js +34 -0
  38. package/dist/sha512-WYC446ZM.js.map +1 -0
  39. package/dist/socks5-WTJBYGME-6COK4LXW.js +139 -0
  40. package/dist/socks5-WTJBYGME-6COK4LXW.js.map +1 -0
  41. package/package.json +60 -0
package/README.md ADDED
@@ -0,0 +1,302 @@
1
+ # @toon-protocol/client-mcp
2
+
3
+ Let a Claude agent — **Claude Desktop or Claude Code** — act as a full TOON
4
+ Protocol client: **pay-to-write** publishing, **free** reads/subscriptions,
5
+ payment-channel/balance management, and mill swaps.
6
+
7
+ The agent surface is an **MCP server** — bin **`toon-mcp`**, which registers
8
+ with the host under the server name **`toon-client`** (this is the name that
9
+ appears in Claude's MCP server list and in the `initialize` handshake;
10
+ `mcpServers.toon` in config is just your local alias). The two long-lived
11
+ connections that can't live in an ephemeral agent session — a **BTP** session
12
+ (paid writes via the connector/apex, optionally over a managed `.anyone`
13
+ SOCKS5h proxy) and a **town-relay Nostr-WS** subscription (free reads) — live in
14
+ an **always-on detached daemon** (`toon-clientd`). The MCP server is a thin
15
+ stdio proxy that auto-spawns the daemon and never holds chain keys.
16
+
17
+ | | Name |
18
+ |---|---|
19
+ | npm package | `@toon-protocol/client-mcp` |
20
+ | MCP server name (handshake) | `toon-client` |
21
+ | MCP server bin | `toon-mcp` |
22
+ | Daemon bin | `toon-clientd` |
23
+
24
+ ```
25
+ Claude (Desktop / Code)
26
+ │ stdio (MCP)
27
+
28
+ toon-mcp ──HTTP──▶ toon-clientd (detached, always-on)
29
+ ├─ ToonClient: BTP session + payment channels + signer
30
+ └─ RelaySubscription: persistent town-relay Nostr-WS
31
+ ```
32
+
33
+ ## Architecture
34
+
35
+ | Layer | Bin / module | Responsibility |
36
+ |---|---|---|
37
+ | **Daemon** | `toon-clientd` | Owns one `ToonClient` (BTP + managed anon + channels + mnemonic keystore + network targeting) **plus** a persistent town-relay subscription. Loopback HTTP control API, single-instance PID lock, channel nonce-watermark persistence, graceful shutdown. |
38
+ | **MCP server** | `toon-mcp` | `@modelcontextprotocol/sdk` stdio server. Maps tools → daemon HTTP; auto-spawns the daemon detached if down; reports "bootstrapping — retry" while anon boots; holds no keys. |
39
+ | **Skill** | `.claude/skills/toon-client/` | Teaches the agent pay-to-write / free-read / settlement semantics. |
40
+
41
+ ## Tools
42
+
43
+ The `toon-client` MCP server exposes **8 tools**:
44
+
45
+ | MCP tool | Daemon endpoint | Backing |
46
+ |---|---|---|
47
+ | `toon_status` | `GET /status` | ready/bootstrapping, transport, relay health, per-chain settlement, active chain |
48
+ | `toon_identity` | `GET /status` | Nostr pubkey + EVM/Solana/Mina addresses (no keys) |
49
+ | `toon_publish(event,{destination?,fee?})` | `POST /publish` | `signBalanceProof` + `publishEvent` (paid write) |
50
+ | `toon_subscribe(filters,{subId?})` | `POST /subscribe` | register a persistent free-read subscription |
51
+ | `toon_read({subId?,cursor?,limit?})` | `GET /events` | drain buffered events by cursor (free) |
52
+ | `toon_open_channel({destination?})` | `POST /channels` | `openChannel` (pre-open / fetch a channel) |
53
+ | `toon_channels` | `GET /channels` | `getTrackedChannels` + nonce watermark + cumulative spend |
54
+ | `toon_swap(destination,amount,{toonData?})` | `POST /swap` | `sendSwapPacket` (mill swap) |
55
+
56
+ ## Install
57
+
58
+ ```bash
59
+ pnpm add -g @toon-protocol/client-mcp # installs both bins
60
+ ```
61
+
62
+ This installs two bins: `toon-clientd` and `toon-mcp`. To run a bin straight
63
+ from npm without a global install, name it explicitly (the package name is not a
64
+ bin, so plain `npx @toon-protocol/client-mcp` fails):
65
+
66
+ ```bash
67
+ npx -y -p @toon-protocol/client-mcp toon-mcp # MCP stdio server
68
+ npx -y -p @toon-protocol/client-mcp toon-clientd # daemon
69
+ ```
70
+
71
+ ## First run (zero-config onboarding)
72
+
73
+ On the **first** `toon-clientd run`/`start` (including the auto-spawn from
74
+ `toon-mcp`), the daemon onboards a brand-new user with no manual setup:
75
+
76
+ - **Identity** — if no mnemonic is configured, it generates a fresh BIP-39
77
+ mnemonic, encrypts it to `~/.toon-client/keystore.json`, records
78
+ `keystorePath` in `config.json`, and prints the seed phrase + derived
79
+ addresses **once** (back it up). The keystore is encrypted with
80
+ `TOON_CLIENT_KEYSTORE_PASSWORD` when set, otherwise a default password so the
81
+ identity reloads on every restart with **no env var required**.
82
+ - **Transport scaffolding** — it writes a starter `~/.toon-client/config.json`
83
+ carrying the `btpUrl`/`relayUrl`/`managedAnonProxy` knobs plus a `_help`
84
+ block documenting direct-vs-`.anyone` selection.
85
+
86
+ The one thing you must supply is the apex you pay: set **`btpUrl`** (and usually
87
+ `relayUrl`) in the scaffolded config, then publish. Everything below is for
88
+ overriding those auto-provisioned defaults.
89
+
90
+ ## Configure the daemon
91
+
92
+ The daemon reads `~/.toon-client/config.json` (override with `TOON_CLIENT_CONFIG`).
93
+ The **mnemonic is never stored in plaintext by default** — it is auto-generated
94
+ into an encrypted keystore (scrypt + AES-256-GCM, mode 0600) on first run, or you
95
+ can supply your own via env or an imported keystore.
96
+
97
+ ```jsonc
98
+ // ~/.toon-client/config.json
99
+ {
100
+ "network": "testnet", // settlement presets (#209)
101
+ "keystorePath": "~/.toon-client/keystore.json",
102
+ "btpUrl": "ws://<apex-host>.anyone:3000/btp",
103
+ "relayUrl": "wss://<relay-host>.anyone/", // free reads
104
+ "destination": "g.townhouse.town",
105
+ "feePerEvent": "1",
106
+ "httpPort": 8787,
107
+ // HS / direct-apex mode: bootstrap finds 0 peers, so name the apex's
108
+ // settlement address directly (mirrors the docker entrypoint):
109
+ "apex": {
110
+ "destination": "g.townhouse.town",
111
+ "peerId": "town",
112
+ "chain": "evm",
113
+ "chainKey": "evm:base:84532",
114
+ "chainId": 84532,
115
+ "settlementAddress": "0x<apex-receive-addr>",
116
+ "tokenAddress": "0x<usdc>",
117
+ "tokenNetwork": "0x<token-network>"
118
+ }
119
+ }
120
+ ```
121
+
122
+ Environment overrides: `TOON_CLIENT_MNEMONIC`, `TOON_CLIENT_KEYSTORE_PASSWORD`,
123
+ `TOON_CLIENT_BTP_URL`, `TOON_CLIENT_RELAY_URL`, `TOON_CLIENT_SOCKS`,
124
+ `TOON_CLIENT_HTTP_PORT`, `TOON_CLIENT_NETWORK`, `TOON_CLIENT_HOME`.
125
+
126
+ **Transport is inferred from the URLs — no separate "direct vs hidden-service"
127
+ switch.** The daemon parses the host of each URL independently:
128
+
129
+ - `btpUrl`/`relayUrl` on a normal host (`ws://1.2.3.4:3000/btp`, `wss://…`) →
130
+ **direct**, dialed as-is.
131
+ - `btpUrl` on a `.anyone` host → the ToonClient auto-starts a managed `anon`
132
+ SOCKS5h proxy and routes paid writes (and reads) through it.
133
+ - `btpUrl` **direct** but `relayUrl` on a `.anyone` host → the daemon starts its
134
+ own managed `anon` proxy just for the free-read subscription; paid writes stay
135
+ direct. (Mixed transports — a direct apex with a hidden-service relay — work
136
+ out of the box.)
137
+
138
+ No explicit `socksProxy` is needed for any of these. Set `socksProxy` only to
139
+ point at your own external proxy, or `managedAnonProxy: false` to opt out of the
140
+ managed proxy entirely. The first bootstrap pays the anon warm-up cost (~30–90s)
141
+ **once** — the detached daemon then stays up. A read-proxy failure surfaces under
142
+ `relay.proxyError` in `toon_status` and never blocks direct paid writes.
143
+
144
+ ### Create an encrypted keystore
145
+
146
+ ```bash
147
+ TOON_CLIENT_MNEMONIC="word word ..." \
148
+ TOON_CLIENT_KEYSTORE_PASSWORD="…" \
149
+ node -e "import('@toon-protocol/client').then(m => m.importKeystore(process.env.HOME+'/.toon-client/keystore.json', process.env.TOON_CLIENT_MNEMONIC, process.env.TOON_CLIENT_KEYSTORE_PASSWORD))"
150
+ ```
151
+
152
+ ## Daemon lifecycle (Claude Code only — it has a shell)
153
+
154
+ ```bash
155
+ toon-clientd start # spawn detached, wait until reachable
156
+ toon-clientd status # print status JSON
157
+ toon-clientd stop # SIGTERM the locked PID
158
+ toon-clientd run # run in the foreground (what the detached spawn runs)
159
+ ```
160
+
161
+ The MCP server auto-spawns the daemon, so `start` is optional.
162
+
163
+ ## Register with Claude
164
+
165
+ ### Claude Code
166
+
167
+ ```bash
168
+ claude mcp add toon -- toon-mcp
169
+ ```
170
+
171
+ …or add to `.mcp.json` in your project:
172
+
173
+ ```json
174
+ {
175
+ "mcpServers": {
176
+ "toon": { "command": "toon-mcp" }
177
+ }
178
+ }
179
+ ```
180
+
181
+ ### Claude Desktop
182
+
183
+ Add to `claude_desktop_config.json`:
184
+
185
+ ```json
186
+ {
187
+ "mcpServers": {
188
+ "toon": {
189
+ "command": "toon-mcp",
190
+ "env": {
191
+ "TOON_CLIENT_KEYSTORE_PASSWORD": "…"
192
+ }
193
+ }
194
+ }
195
+ }
196
+ ```
197
+
198
+ Then restart Claude Desktop. The TOON tools appear in the tool list; the first
199
+ `toon_publish` after a cold start may report "bootstrapping — retry" while the
200
+ anon proxy + BTP session come up.
201
+
202
+ ## Usage example
203
+
204
+ You don't call these tools by hand — the agent does, in response to plain
205
+ requests. A typical "post a note, then read it back" flow:
206
+
207
+ > **You:** Post a note to TOON saying "gm from my agent", then show me when it lands.
208
+
209
+ The agent runs:
210
+
211
+ 1. **`toon_status`** → confirm the client is up.
212
+ ```json
213
+ { "ready": true, "bootstrapping": false, "settlementChain": "evm",
214
+ "relay": { "connected": true }, "identity": { "evmAddress": "0x99ed…" } }
215
+ ```
216
+ (If it returns `bootstrapping: true` or a "retry shortly" message, wait ~30–90s
217
+ for the anon proxy + BTP session, then retry.)
218
+
219
+ 2. **`toon_subscribe`** for its own author so it can read the note back:
220
+ ```json
221
+ { "filters": { "authors": ["<my-hex-pubkey>"], "kinds": [1] } }
222
+ → { "subId": "sub-1" }
223
+ ```
224
+
225
+ 3. **`toon_publish`** the signed kind:1 event (the daemon signs the payment-channel
226
+ claim and forwards it over BTP):
227
+ ```json
228
+ { "event": { "kind": 1, "content": "gm from my agent", "id": "…", "sig": "…", … } }
229
+ → { "eventId": "0d0c1f98…", "channelId": "0xc73a77…", "nonce": 7 }
230
+ ```
231
+
232
+ 4. **`toon_read`** until the event appears (free; cursor long-poll):
233
+ ```json
234
+ { "subId": "sub-1" }
235
+ → { "events": [ { "id": "0d0c1f98…", "content": "gm from my agent", … } ],
236
+ "cursor": 12, "hasMore": false }
237
+ ```
238
+
239
+ 5. **`toon_channels`** to show what it cost:
240
+ ```json
241
+ → { "channels": [ { "channelId": "0xc73a77…", "nonce": 7, "cumulativeAmount": "7" } ] }
242
+ ```
243
+
244
+ Other common calls: **`toon_open_channel`** to pre-open a channel before a burst
245
+ of publishes, and **`toon_swap({ destination, amount })`** to pay a mill peer and
246
+ receive a target-chain claim.
247
+
248
+ > **CLI equivalent** (handy for scripting/debugging — the MCP tools map 1:1 to
249
+ > these daemon endpoints):
250
+ > ```bash
251
+ > toon-clientd start # boot the daemon
252
+ > curl -s localhost:8787/status | jq # toon_status
253
+ > curl -s -XPOST localhost:8787/subscribe \
254
+ > -H content-type:application/json \
255
+ > -d '{"filters":{"authors":["<hex>"],"kinds":[1]}}' # toon_subscribe
256
+ > curl -s -XPOST localhost:8787/publish \
257
+ > -H content-type:application/json \
258
+ > -d '{"event":{…signed kind:1…}}' # toon_publish
259
+ > curl -s 'localhost:8787/events?subId=sub-1' | jq # toon_read
260
+ > curl -s localhost:8787/channels | jq # toon_channels
261
+ > ```
262
+
263
+ ## Security
264
+
265
+ - The daemon holds the mnemonic/keystore; the agent sees **only addresses and
266
+ results**, never private keys.
267
+ - A single-instance PID lock prevents two daemons from racing the channel nonce
268
+ watermark (which would corrupt the payment proof).
269
+ - The control plane binds `127.0.0.1` only (no auth layer — it never leaves
270
+ loopback).
271
+
272
+ ## Tests
273
+
274
+ ```bash
275
+ pnpm --filter @toon-protocol/client-mcp test # unit
276
+ RUN_LIVE_HS_E2E=1 …env… \
277
+ pnpm --filter @toon-protocol/client-mcp test:integration # gated live-HS round-trip
278
+ ```
279
+
280
+ The gated integration test boots the daemon against a live `.anyone` HS apex,
281
+ publishes a paid event, reads it back through the subscription, verifies the
282
+ channel nonce advanced, restarts the daemon, and confirms the nonce watermark
283
+ persisted. See `src/__integration__/`.
284
+
285
+ ## Publishing
286
+
287
+ This package is **published to npm automatically by CI/CD**, in lockstep with the
288
+ repo's release tag (the same `vX.Y.Z` semantic-release cuts for
289
+ `@toon-protocol/townhouse`). On a release, `publish-townhouse-images.yml` builds
290
+ this package, sets its version to the tag, and runs
291
+ `pnpm --filter @toon-protocol/client-mcp publish --access public`.
292
+
293
+ It is **self-contained**: its `@toon-protocol/*` workspace deps (`client`, `core`)
294
+ are **bundled into `dist`** at build time (tsup `noExternal`), so the published
295
+ `package.json` carries **zero `@toon-protocol/*` runtime deps** — only npm
296
+ packages (`fastify`, `@modelcontextprotocol/sdk`, `nostr-tools`, `viem`, `ws`,
297
+ `@toon-format/toon`) plus optional chain libs (`o1js`, `mina-signer`,
298
+ `@solana/web3.js`, `socks-proxy-agent`) installed only when you use those chains.
299
+ A guard test (`src/package-structure.test.ts`) fails the build if a
300
+ `@toon-protocol/*` runtime dep ever leaks in.
301
+
302
+ To publish manually: `pnpm --filter @toon-protocol/client-mcp build && pnpm --filter @toon-protocol/client-mcp publish --access public`.
@@ -0,0 +1,25 @@
1
+ import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
2
+ import {
3
+ ANON_ASSETS,
4
+ ANON_VERSION,
5
+ defaultCacheDir,
6
+ ensureAnonBinary,
7
+ renderTorrc,
8
+ selectAnonAsset,
9
+ startManagedAnonProxy,
10
+ tcpProbe,
11
+ waitForAnonSocks
12
+ } from "./chunk-SKQTKZIH.js";
13
+ import "./chunk-F22GNSF6.js";
14
+ export {
15
+ ANON_ASSETS,
16
+ ANON_VERSION,
17
+ defaultCacheDir,
18
+ ensureAnonBinary,
19
+ renderTorrc,
20
+ selectAnonAsset,
21
+ startManagedAnonProxy,
22
+ tcpProbe,
23
+ waitForAnonSocks
24
+ };
25
+ //# sourceMappingURL=anon-proxy-W3KMM7GU-FN7ZJY7P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,83 @@
1
+ import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
2
+ import {
3
+ Hash,
4
+ abytes,
5
+ aexists,
6
+ ahash,
7
+ clean,
8
+ toBytes
9
+ } from "./chunk-VA7XC4FD.js";
10
+
11
+ // ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/hmac.js
12
+ var HMAC = class extends Hash {
13
+ constructor(hash, _key) {
14
+ super();
15
+ this.finished = false;
16
+ this.destroyed = false;
17
+ ahash(hash);
18
+ const key = toBytes(_key);
19
+ this.iHash = hash.create();
20
+ if (typeof this.iHash.update !== "function")
21
+ throw new Error("Expected instance of class which extends utils.Hash");
22
+ this.blockLen = this.iHash.blockLen;
23
+ this.outputLen = this.iHash.outputLen;
24
+ const blockLen = this.blockLen;
25
+ const pad = new Uint8Array(blockLen);
26
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
27
+ for (let i = 0; i < pad.length; i++)
28
+ pad[i] ^= 54;
29
+ this.iHash.update(pad);
30
+ this.oHash = hash.create();
31
+ for (let i = 0; i < pad.length; i++)
32
+ pad[i] ^= 54 ^ 92;
33
+ this.oHash.update(pad);
34
+ clean(pad);
35
+ }
36
+ update(buf) {
37
+ aexists(this);
38
+ this.iHash.update(buf);
39
+ return this;
40
+ }
41
+ digestInto(out) {
42
+ aexists(this);
43
+ abytes(out, this.outputLen);
44
+ this.finished = true;
45
+ this.iHash.digestInto(out);
46
+ this.oHash.update(out);
47
+ this.oHash.digestInto(out);
48
+ this.destroy();
49
+ }
50
+ digest() {
51
+ const out = new Uint8Array(this.oHash.outputLen);
52
+ this.digestInto(out);
53
+ return out;
54
+ }
55
+ _cloneInto(to) {
56
+ to || (to = Object.create(Object.getPrototypeOf(this), {}));
57
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
58
+ to = to;
59
+ to.finished = finished;
60
+ to.destroyed = destroyed;
61
+ to.blockLen = blockLen;
62
+ to.outputLen = outputLen;
63
+ to.oHash = oHash._cloneInto(to.oHash);
64
+ to.iHash = iHash._cloneInto(to.iHash);
65
+ return to;
66
+ }
67
+ clone() {
68
+ return this._cloneInto();
69
+ }
70
+ destroy() {
71
+ this.destroyed = true;
72
+ this.oHash.destroy();
73
+ this.iHash.destroy();
74
+ }
75
+ };
76
+ var hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
77
+ hmac.create = (hash, key) => new HMAC(hash, key);
78
+
79
+ export {
80
+ HMAC,
81
+ hmac
82
+ };
83
+ //# sourceMappingURL=chunk-32QD72IL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/hmac.ts"],"sourcesContent":["/**\n * HMAC: RFC2104 message authentication code.\n * @module\n */\nimport { abytes, aexists, ahash, clean, Hash, toBytes, type CHash, type Input } from './utils.ts';\n\nexport class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {\n oHash: T;\n iHash: T;\n blockLen: number;\n outputLen: number;\n private finished = false;\n private destroyed = false;\n\n constructor(hash: CHash, _key: Input) {\n super();\n ahash(hash);\n const key = toBytes(_key);\n this.iHash = hash.create() as T;\n if (typeof this.iHash.update !== 'function')\n throw new Error('Expected instance of class which extends utils.Hash');\n this.blockLen = this.iHash.blockLen;\n this.outputLen = this.iHash.outputLen;\n const blockLen = this.blockLen;\n const pad = new Uint8Array(blockLen);\n // blockLen can be bigger than outputLen\n pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36;\n this.iHash.update(pad);\n // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n this.oHash = hash.create() as T;\n // Undo internal XOR && apply outer XOR\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c;\n this.oHash.update(pad);\n clean(pad);\n }\n update(buf: Input): this {\n aexists(this);\n this.iHash.update(buf);\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n abytes(out, this.outputLen);\n this.finished = true;\n this.iHash.digestInto(out);\n this.oHash.update(out);\n this.oHash.digestInto(out);\n this.destroy();\n }\n digest(): Uint8Array {\n const out = new Uint8Array(this.oHash.outputLen);\n this.digestInto(out);\n return out;\n }\n _cloneInto(to?: HMAC<T>): HMAC<T> {\n // Create new instance without calling constructor since key already in state and we don't know it.\n to ||= Object.create(Object.getPrototypeOf(this), {});\n const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n to = to as this;\n to.finished = finished;\n to.destroyed = destroyed;\n to.blockLen = blockLen;\n to.outputLen = outputLen;\n to.oHash = oHash._cloneInto(to.oHash);\n to.iHash = iHash._cloneInto(to.iHash);\n return to;\n }\n clone(): HMAC<T> {\n return this._cloneInto();\n }\n destroy(): void {\n this.destroyed = true;\n this.oHash.destroy();\n this.iHash.destroy();\n }\n}\n\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n * @example\n * import { hmac } from '@noble/hashes/hmac';\n * import { sha256 } from '@noble/hashes/sha2';\n * const mac1 = hmac(sha256, 'key', 'message');\n */\nexport const hmac: {\n (hash: CHash, key: Input, message: Input): Uint8Array;\n create(hash: CHash, key: Input): HMAC<any>;\n} = (hash: CHash, key: Input, message: Input): Uint8Array =>\n new HMAC<any>(hash, key).update(message).digest();\nhmac.create = (hash: CHash, key: Input) => new HMAC<any>(hash, key);\n"],"mappings":";;;;;;;;;;;AAMM,IAAO,OAAP,cAAuC,KAAa;EAQxD,YAAY,MAAa,MAAW;AAClC,UAAK;AAJC,SAAA,WAAW;AACX,SAAA,YAAY;AAIlB,UAAM,IAAI;AACV,UAAM,MAAM,QAAQ,IAAI;AACxB,SAAK,QAAQ,KAAK,OAAM;AACxB,QAAI,OAAO,KAAK,MAAM,WAAW;AAC/B,YAAM,IAAI,MAAM,qDAAqD;AACvE,SAAK,WAAW,KAAK,MAAM;AAC3B,SAAK,YAAY,KAAK,MAAM;AAC5B,UAAM,WAAW,KAAK;AACtB,UAAM,MAAM,IAAI,WAAW,QAAQ;AAEnC,QAAI,IAAI,IAAI,SAAS,WAAW,KAAK,OAAM,EAAG,OAAO,GAAG,EAAE,OAAM,IAAK,GAAG;AACxE,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ;AAAK,UAAI,CAAC,KAAK;AAC/C,SAAK,MAAM,OAAO,GAAG;AAErB,SAAK,QAAQ,KAAK,OAAM;AAExB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ;AAAK,UAAI,CAAC,KAAK,KAAO;AACtD,SAAK,MAAM,OAAO,GAAG;AACrB,UAAM,GAAG;EACX;EACA,OAAO,KAAU;AACf,YAAQ,IAAI;AACZ,SAAK,MAAM,OAAO,GAAG;AACrB,WAAO;EACT;EACA,WAAW,KAAe;AACxB,YAAQ,IAAI;AACZ,WAAO,KAAK,KAAK,SAAS;AAC1B,SAAK,WAAW;AAChB,SAAK,MAAM,WAAW,GAAG;AACzB,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,WAAW,GAAG;AACzB,SAAK,QAAO;EACd;EACA,SAAM;AACJ,UAAM,MAAM,IAAI,WAAW,KAAK,MAAM,SAAS;AAC/C,SAAK,WAAW,GAAG;AACnB,WAAO;EACT;EACA,WAAW,IAAY;AAErB,WAAA,KAAO,OAAO,OAAO,OAAO,eAAe,IAAI,GAAG,CAAA,CAAE;AACpD,UAAM,EAAE,OAAO,OAAO,UAAU,WAAW,UAAU,UAAS,IAAK;AACnE,SAAK;AACL,OAAG,WAAW;AACd,OAAG,YAAY;AACf,OAAG,WAAW;AACd,OAAG,YAAY;AACf,OAAG,QAAQ,MAAM,WAAW,GAAG,KAAK;AACpC,OAAG,QAAQ,MAAM,WAAW,GAAG,KAAK;AACpC,WAAO;EACT;EACA,QAAK;AACH,WAAO,KAAK,WAAU;EACxB;EACA,UAAO;AACL,SAAK,YAAY;AACjB,SAAK,MAAM,QAAO;AAClB,SAAK,MAAM,QAAO;EACpB;;AAaK,IAAM,OAGT,CAAC,MAAa,KAAY,YAC5B,IAAI,KAAU,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,OAAM;AACjD,KAAK,SAAS,CAAC,MAAa,QAAe,IAAI,KAAU,MAAM,GAAG;","names":[]}