@forgesworn/moneyer 0.15.0 → 0.16.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.1 - 2026-09-24
4
+
5
+ Documentation only; no code changes.
6
+
7
+ - `llms.txt` gives the real signatures of `buildStats`,
8
+ `statsSnapshotContent`, `verifyStatsSnapshot`, `signStats`, `runMelt` and
9
+ `reconcilePendingMelts`, with the melt job and deps shapes, and notes that
10
+ the `url` `createMoneyer` returns is the full origin, port included.
11
+ - The README carries the npm install command.
12
+ - package.json gains search keywords.
13
+
14
+ ## 0.16.0 - 2026-09-16
15
+
16
+ - Bump `@lnurlcash/kit` from 0.14.2 to 0.18.1: the previous pin predated the
17
+ entire Schnorr `ck1` migration, so any note produced by a current wallet
18
+ was already unverifiable here. Brings the `ck1`/address-proof sha256
19
+ digest fix (signing `sha256(message)` instead of the raw string, matching
20
+ most conforming Schnorr signers) and a legacy-read fallback for notes
21
+ minted under the intermediate raw-message scheme.
22
+ - `spentRef` follows `recoverNoteOwnershipPubkey`'s new signature: it now
23
+ takes the `ck1` string directly and returns `{pubkeyXOnly, legacy}` rather
24
+ than raw recovered bytes.
25
+ - `claimMintedNote` now classifies a melt-in-flight note by catching the
26
+ kit's own `PendingNoteError`, replacing a `ServiceError{reason:'pending'}`
27
+ check the kit stopped throwing. The bump had silently broken this: an
28
+ unhandled `PendingNoteError` would have surfaced to a bound-mint quote's
29
+ poller as an unreachable-mint error rather than "pending" - untested
30
+ before this bump, now covered.
31
+
3
32
  ## 0.15.0 - 2026-09-15
4
33
 
5
34
  - Use `@lnurlcash/kit` 0.14 as the protocol implementation. Removed kit
package/README.md CHANGED
@@ -43,7 +43,11 @@ lesson, that behaviour is kept deliberately and tested.
43
43
 
44
44
  ## Run
45
45
 
46
- Install the published package and build it:
46
+ ```bash
47
+ npm install @forgesworn/moneyer
48
+ ```
49
+
50
+ Or build from source:
47
51
 
48
52
  ```bash
49
53
  git clone https://github.com/forgesworn/moneyer
@@ -717,7 +721,7 @@ decoding and preimage verification on the melt path). The companion wallet
717
721
  is [`@forgesworn/notecase`](https://github.com/forgesworn/notecase).
718
722
 
719
723
  Other mints, wallets and libraries speaking the same protocol are indexed
720
- in [awesome-lnurlcash](https://github.com/TheCryptoDonkey/awesome-lnurlcash).
724
+ in [awesome-lnurlcash](https://github.com/lnurlcash/awesome-lnurlcash).
721
725
 
722
726
  ## Licence
723
727
 
package/dist/claim.js CHANGED
@@ -1,4 +1,4 @@
1
- import { NoteSpentError, NoteUnknownError, ServiceError, buildNoteUrl, fetchNoteInfo, isPreimage } from '@lnurlcash/kit';
1
+ import { NoteSpentError, NoteUnknownError, PendingNoteError, buildNoteUrl, fetchNoteInfo, isPreimage } from '@lnurlcash/kit';
2
2
  /**
3
3
  * Inspect the note a wallet named before requesting its invoice.
4
4
  *
@@ -21,9 +21,8 @@ export const claimMintedNote = async (withdrawLink, k1) => {
21
21
  };
22
22
  }
23
23
  catch (error) {
24
- if (error instanceof ServiceError && error.reason.trim().toLowerCase() === 'pending') {
24
+ if (error instanceof PendingNoteError)
25
25
  return { ...blank, state: 'pending' };
26
- }
27
26
  if (error instanceof NoteSpentError)
28
27
  return { ...blank, state: 'spent' };
29
28
  if (error instanceof NoteUnknownError)
package/dist/landing.js CHANGED
@@ -101,7 +101,7 @@ ${config.tosUrl ? `<div class="kv"><span>terms</span><a href="${escapeHtml(confi
101
101
  <h2>${escapeHtml(MINT_KNOWS_HEADING)}</h2>
102
102
  ${MINT_KNOWS.map(paragraph => `<p>${escapeHtml(paragraph)}</p>`).join('\n')}
103
103
  </section>
104
- <p class="small">Works with any LUD-25 wallet - <a href="https://github.com/forgesworn/notecase">notecase</a> among them. Verify a note offline against the signing key above.<br/>Independent implementation of the <a href="https://github.com/lnurl/luds/pull/301">LNURLcash draft</a> - graded by <a href="https://github.com/TheCryptoDonkey/lnurlcash-conformance">lnurlcash-conformance</a>.</p>
104
+ <p class="small">Works with any LUD-25 wallet - <a href="https://github.com/forgesworn/notecase">notecase</a> among them. Verify a note offline against the signing key above.<br/>Independent implementation of the <a href="https://github.com/lnurl/luds/pull/301">LNURLcash draft</a> - graded by <a href="https://github.com/lnurlcash/lnurlcash-conformance">lnurlcash-conformance</a>.</p>
105
105
  </main>
106
106
  </body>
107
107
  </html>`;
package/dist/server.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createServer } from 'node:http';
2
2
  import { bytesToHex, hexToBytes, randomBytes } from '@noble/hashes/utils.js';
3
3
  import { finalizeEvent } from 'nostr-tools/pure';
4
- import { applyMintFee, decodeCk1, decodeCp1, encodeCs1WithAmount, grossUpForMintFee, hashK1, recoverNoteOwnershipPubkey } from '@lnurlcash/kit';
4
+ import { applyMintFee, decodeCp1, encodeCs1WithAmount, grossUpForMintFee, hashK1, recoverNoteOwnershipPubkey } from '@lnurlcash/kit';
5
5
  import { tryDecodeBolt11 } from 'farrier-kit/bolt11';
6
6
  import { NotePendingError, NoteStore, NoteUnavailableError, OutputCollisionError, swapFingerprint } from "./store.js";
7
7
  import { createNoteSigner } from "./signing.js";
@@ -32,9 +32,8 @@ const namedRef = (value) => {
32
32
  const spentRef = (k1) => {
33
33
  if (HEX32.test(k1))
34
34
  return { id: hashK1(k1), cp1: false };
35
- const signature = decodeCk1(k1);
36
- const pubkey = signature ? recoverNoteOwnershipPubkey(signature) : null;
37
- return pubkey ? { id: bytesToHex(pubkey), cp1: true } : null;
35
+ const owner = recoverNoteOwnershipPubkey(k1);
36
+ return owner ? { id: bytesToHex(owner.pubkeyXOnly), cp1: true } : null;
38
37
  };
39
38
  // LUD-25 renamed `h` to `p` on the lookup and `h`/`h2` to `p1`/`p2` on the
40
39
  // callback. The old names stay accepted; sending both spellings must agree.
package/llms.txt CHANGED
@@ -1,5 +1,9 @@
1
1
  # moneyer
2
2
 
3
+ > Custody-free Lightning bearer notes: paying an invoice mints a note whose
4
+ > spend secret is chosen by the buyer, never the mint. moneyer is an
5
+ > independent LNURLcash (LUD-25) mint for Node 24+.
6
+
3
7
  LNURLcash (LUD-25) mint for Node 24+. Strikes Lightning bearer notes:
4
8
  paying an invoice it issues mints a note whose spend secret is the
5
9
  invoice's payment preimage, or a secret the buyer named with `h` on the
@@ -67,6 +71,7 @@ Client library to build against a mint: @lnurlcash/kit
67
71
  ## Library API
68
72
 
69
73
  createMoneyer(config, deps?) -> {url, port, store, backend, signer, reconcile, close}
74
+ url is the full origin (http://host:port), port already included
70
75
  verifyAnnouncement(content, mintPubkey) -> {valid, document}
71
76
  kind 30078 / d=lnurlcash-mint: a mint announcing itself, content = its
72
77
  discovery document + sig by the note signing key. MONEYER_ANNOUNCE=true,
@@ -80,8 +85,22 @@ configFromEnv(env?) -> MoneyerConfig MONEYER_* environment variables
80
85
  createFakeBackend() -> LightningBackend with .control test hooks
81
86
  createClnBackend({url, rune}) / createLndBackend({url, macaroon})
82
87
  createNoteSigner(privHex) -> {pubkey, sign(noteId, amountMsat)}
88
+ privHex is a secp256k1 private key, as MONEYER_SIGNING_KEY; zero is rejected
83
89
  fakeBolt11({amountMsat, paymentHashHex, memo?}) -> decodable, unpayable invoice
84
90
  NoteStore - SQLite store; notes by sha256(k1), never secrets
91
+ runMelt(job, deps) -> Promise<void> / reconcilePendingMelts(store, backend, inFlight, log?)
92
+ the melt discipline: burn only on confirmed payment, restore only on confirmed
93
+ non-payment. The /w/cb handler drives both; outcomes land in the store, not in a
94
+ return value. job = {paymentHash, noteId, pr, amountMsat, payAmountMsat?},
95
+ deps = {store, backend, feeLimitMsat(amountMsat), confirmDelaysMs?, log?}
96
+ buildStats({liabilities, localBalanceMsat?, reconciledAt?, at?, ratioOnly?}) -> MintStats
97
+ liabilities = store.liabilities() -> {outstandingMsat, outstandingNotes,
98
+ pendingMsat, pendingMelts, oldestPendingMeltAgeSecs}
99
+ statsSnapshotContent(stats, privHex) -> string the published content: stats JSON plus sig
100
+ verifyStatsSnapshot(content, pubkey) -> {valid, stats}
101
+ signStats(stats, privHex) -> string the signature alone, hex r || s || recovery id
102
+ kind 30078, d = lnurlcash-liabilities: a signed liabilities snapshot for
103
+ third-party solvency checks
85
104
 
86
105
  ## Endpoints
87
106
 
package/package.json CHANGED
@@ -1,9 +1,26 @@
1
1
  {
2
2
  "name": "@forgesworn/moneyer",
3
- "version": "0.15.0",
3
+ "version": "0.16.1",
4
4
  "description": "An LNURLcash (LUD-25) mint - strikes Lightning bearer notes. Independent implementation, cln/lnd funding sources, SQLite, zero HTTP framework.",
5
5
  "author": "TheCryptoDonkey",
6
6
  "license": "MIT",
7
+ "keywords": [
8
+ "lnurlcash",
9
+ "lud-25",
10
+ "lud-12",
11
+ "lud-03",
12
+ "lud-06",
13
+ "lnurl",
14
+ "lightning-network",
15
+ "bitcoin",
16
+ "mint",
17
+ "bearer-notes",
18
+ "cln",
19
+ "lnd",
20
+ "sqlite",
21
+ "nostr",
22
+ "typescript"
23
+ ],
7
24
  "repository": {
8
25
  "type": "git",
9
26
  "url": "git+https://github.com/forgesworn/moneyer.git"
@@ -56,7 +73,7 @@
56
73
  "live:bound-mint": "npm run build && node scripts/live-bound-mint-check.mjs"
57
74
  },
58
75
  "dependencies": {
59
- "@lnurlcash/kit": "0.14.2",
76
+ "@lnurlcash/kit": "0.18.1",
60
77
  "@noble/curves": "^2.3.0",
61
78
  "@noble/hashes": "^2.3.0",
62
79
  "@scure/base": "^1.2.4",
@@ -70,7 +87,7 @@
70
87
  "@types/node": "^24.0.0",
71
88
  "animejs": "^4.0.0",
72
89
  "happy-dom": "^20.0.0",
73
- "lnurlcash-conformance": "0.11.0",
90
+ "lnurlcash-conformance": "0.13.1",
74
91
  "playwright": "^1.62.1",
75
92
  "typescript": "^5.7.0",
76
93
  "uqr": "^0.1.2",