lnurlcash-kit 0.8.0 → 0.9.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,51 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.9.0 - 2026-09-09
4
+
5
+ **`fetchMintAddress` reads three more fields.** The reference mint publishes
6
+ them and this dropped all three on the floor, because the parser maps field by
7
+ field and an unrecognised name is discarded by design.
8
+
9
+ - `nodeUris` - every address the SERVICE's node announces. `nodeUri` is the
10
+ first of them; a node behind Tor as well as clearnet has more, and a caller
11
+ that can only reach the other one needs the list. Undefined rather than `[]`
12
+ when there are none, so `nodeUris?.length` and `'nodeUris' in info` agree.
13
+ - `sunsetDate` - the day the SERVICE plans to close, ISO-8601. Advance warning
14
+ while there is still time to spend, deliberately not the same thing as a mint
15
+ that has already stopped minting. Validated as a real calendar day and
16
+ dropped otherwise: the one thing a WALLET does with this is put it in front
17
+ of a holder, and a wrong date there is worse than no date.
18
+ - `outstandingNotesMsat` - what the SERVICE says it owes. Its own claim about
19
+ its own database, with nothing to check it against, so read it next to what
20
+ the node holds rather than on its own.
21
+
22
+ ## 0.8.1 - 2026-09-04
23
+
24
+ **`settleNote` could report a burned note as settled, losing it outright.**
25
+ Settling reads what a split's change or a merge's output is really worth, which
26
+ puts `k1` on the wire, so a rotate follows to replace the secret it just
27
+ exposed. That rotate is best-effort by design: a SERVICE that refuses it has
28
+ burned nothing, so keeping the exposed `k1` beats failing the whole settle.
29
+
30
+ The fallback was a bare `catch`, which also covered a rotate that MAY HAVE
31
+ LANDED - an ambiguous one, an unverifiable one, or a spent-or-unknown refusal,
32
+ which is exactly what a mutation the SERVICE already applied looks like asked a
33
+ second time. In every one of those the SERVICE had burned the `k1` being
34
+ returned and minted a note under `h`, and the fresh secret `rotateNote()`
35
+ attaches to the error was the only copy of it anywhere. Discarding it handed
36
+ back a dead secret shaped like a success and dropped the live one.
37
+
38
+ - `settleNote` now rethrows anything that could describe an applied mutation:
39
+ `AmbiguousMintError`, and any error carrying `newSecretsOf(err)`. Only a
40
+ refusal that burned nothing still returns the exposed `k1`.
41
+ - It also rethrows anything that is not an `LnurlcashError`. The bare `catch`
42
+ swallowed `TypeError` and friends alongside the protocol errors the fallback
43
+ was for, so a bug in this library was reported as a settled note too.
44
+ - **Behavioural change, no API change.** A caller that treated `settleNote` as
45
+ something that never throws now sees these errors. That is the point: each
46
+ one carries secrets that must be persisted before anything else.
47
+ - Fixed in the sibling implementations the same day - Rust, Go, Python and
48
+ Kotlin all carried it.
4
49
 
5
50
  ## 0.8.0 - 2026-09-04
6
51
 
package/README.md CHANGED
@@ -117,8 +117,8 @@ fresh secret got discarded along with the note the service had just minted.
117
117
  Node's `fetch` does not retry on its own, but a browser resends an idempotent
118
118
  request that failed on a stale pooled connection, and Go and the JDK do the
119
119
  same by their own routes — the hazard broke the
120
- [Kotlin](https://github.com/TheCryptoDonkey/lnurlcash-kotlin) and
121
- [Go](https://github.com/TheCryptoDonkey/lnurlcash-go) siblings during
120
+ [Kotlin](https://github.com/lnurlcash/lnurlcash-kotlin) and
121
+ [Go](https://github.com/lnurlcash/lnurlcash-go) siblings during
122
122
  development, by two different mechanisms.
123
123
 
124
124
  LUD-25 closed it. A service MUST answer a byte-identical rotate, split or
@@ -319,7 +319,7 @@ still money. Do not mint under it. `restoreFromSeed` walks it alongside the
319
319
  specified scheme so none of those notes goes missing.
320
320
 
321
321
  Both schemes ship with
322
- [conformance vectors](https://github.com/TheCryptoDonkey/lnurlcash-conformance)
322
+ [conformance vectors](https://github.com/lnurlcash/lnurlcash-conformance)
323
323
  for the ports.
324
324
 
325
325
  ```ts
@@ -616,14 +616,14 @@ The reference implementations, both dni's, both MIT:
616
616
 
617
617
  Everything else built on LNURLcash — the other wallets and mints, the
618
618
  hardware vault, the sibling language ports — is indexed in
619
- [awesome-lnurlcash](https://github.com/TheCryptoDonkey/awesome-lnurlcash).
619
+ [awesome-lnurlcash](https://github.com/lnurlcash/awesome-lnurlcash).
620
620
 
621
621
  Changes made on extraction are listed in [CHANGELOG.md](CHANGELOG.md); two
622
622
  are behavioural fixes worth reading if you are porting from that code.
623
623
 
624
624
  ## Conformance
625
625
 
626
- Tested against [lnurlcash-conformance](https://github.com/TheCryptoDonkey/lnurlcash-conformance):
626
+ Tested against [lnurlcash-conformance](https://github.com/lnurlcash/lnurlcash-conformance):
627
627
  language-neutral vectors plus a mock mint that can be told to misbehave —
628
628
  drop a connection mid-mutation, sign in the wrong byte order, lie about a
629
629
  note's value, never settle a melt. If you are writing an LNURLcash
package/SECURITY.md CHANGED
@@ -9,7 +9,7 @@ Only the latest `0.x` release is supported. Pin an exact version.
9
9
 
10
10
  Report privately through GitHub's advisory form:
11
11
 
12
- <https://github.com/TheCryptoDonkey/lnurlcash-kit/security/advisories/new>
12
+ <https://github.com/lnurlcash/lnurlcash-kit/security/advisories/new>
13
13
 
14
14
  Please do not open a public issue for anything that could be used to take
15
15
  somebody's notes.
package/dist/index.d.ts CHANGED
@@ -69,6 +69,9 @@ type MintAddressInfo = {
69
69
  nodeCapacityMsat?: number;
70
70
  nodeNumChannels?: number;
71
71
  nodeNumPeers?: number;
72
+ nodeUris?: string[];
73
+ sunsetDate?: string;
74
+ outstandingNotesMsat?: number;
72
75
  name?: string;
73
76
  description?: string;
74
77
  contact?: MintContact;
package/dist/index.js CHANGED
@@ -904,6 +904,16 @@ var asFees = (value) => {
904
904
  };
905
905
  var asBoolean = (value) => typeof value === "boolean" ? value : void 0;
906
906
  var asPubkeyList = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : void 0;
907
+ var asStringList = (value) => {
908
+ if (!Array.isArray(value)) return void 0;
909
+ const entries = value.filter((item) => typeof item === "string" && item.length > 0);
910
+ return entries.length ? entries : void 0;
911
+ };
912
+ var asIsoDate = (value) => {
913
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return void 0;
914
+ const parsed = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
915
+ return !Number.isNaN(parsed.getTime()) && parsed.toISOString().slice(0, 10) === value ? value : void 0;
916
+ };
907
917
  var fetchMintAddress = async (url, options = {}) => {
908
918
  const body = await lnurlFetch(url, resolveOptions(options));
909
919
  if (body?.tag !== "withdrawRequest" || typeof body.callback !== "string" || typeof body.payLink !== "string" || typeof body.maxWithdrawable !== "number") {
@@ -929,6 +939,9 @@ var fetchMintAddress = async (url, options = {}) => {
929
939
  nodeCapacityMsat: asNumber(body.nodeCapacity) ?? asNumber(body.nodeCapacityMsat),
930
940
  nodeNumChannels: asNumber(body.nodeNumChannels),
931
941
  nodeNumPeers: asNumber(body.nodeNumPeers),
942
+ nodeUris: asStringList(body.nodeUris),
943
+ sunsetDate: asIsoDate(body.sunsetDate),
944
+ outstandingNotesMsat: asNumber(body.outstandingNotesMsat),
932
945
  name: asString(body.name),
933
946
  description: asString(body.description),
934
947
  contact: asContact(body.contact),
@@ -1179,7 +1192,13 @@ var settleNote = async (baseUrl, k1, expectedAmountMsat, signature, options = {}
1179
1192
  signature: rotated.signature,
1180
1193
  callback: info.callback
1181
1194
  };
1182
- } catch {
1195
+ } catch (err) {
1196
+ if (err instanceof AmbiguousMintError || newSecretsOf(err).length > 0) {
1197
+ throw err;
1198
+ }
1199
+ if (!(err instanceof LnurlcashError)) {
1200
+ throw err;
1201
+ }
1183
1202
  return {
1184
1203
  k1,
1185
1204
  amountMsat: info.maxWithdrawable,
package/llms.txt CHANGED
@@ -164,4 +164,4 @@ ProtocolError a non-mutating response did not match the spec, which
164
164
  ## Conformance
165
165
 
166
166
  Vectors and an adversarial mock mint:
167
- https://github.com/TheCryptoDonkey/lnurlcash-conformance
167
+ https://github.com/lnurlcash/lnurlcash-conformance
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lnurlcash-kit",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "LNURLcash (LUD-25) bearer note client for TypeScript - mint, rotate, split, merge, melt, and verify offline",
5
5
  "author": "TheCryptoDonkey",
6
6
  "license": "MIT",
@@ -9,11 +9,11 @@
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "git+https://github.com/TheCryptoDonkey/lnurlcash-kit.git"
12
+ "url": "git+https://github.com/lnurlcash/lnurlcash-kit.git"
13
13
  },
14
- "homepage": "https://github.com/TheCryptoDonkey/lnurlcash-kit#readme",
14
+ "homepage": "https://github.com/lnurlcash/lnurlcash-kit#readme",
15
15
  "bugs": {
16
- "url": "https://github.com/TheCryptoDonkey/lnurlcash-kit/issues"
16
+ "url": "https://github.com/lnurlcash/lnurlcash-kit/issues"
17
17
  },
18
18
  "type": "module",
19
19
  "sideEffects": false,