lnurlcash-kit 0.1.2 → 0.2.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 +325 -0
- package/README.md +314 -0
- package/dist/index.d.ts +168 -68
- package/dist/index.js +515 -134
- package/llms.txt +67 -6
- package/package.json +1 -1
package/llms.txt
CHANGED
|
@@ -24,9 +24,32 @@ splitNote(callback, k1s, amountMsat, opts?) -> {k1, change, signature?, changeSi
|
|
|
24
24
|
mergeNotes(callback, k1s, opts?) -> {k1, signature?}
|
|
25
25
|
meltNote(callback, k1, bolt11, opts?) -> {pr?, verify?}
|
|
26
26
|
settleNote(baseUrl, k1, expectedMsat, sig?, opts?) -> {k1, amountMsat, signature?, callback}
|
|
27
|
+
settleNoteForValue(noteUrl, {mints, minMsat, requireSignature?}, opts?)
|
|
28
|
+
-> {note, newUrl} server side: accept a note as payment, rotate to settle
|
|
27
29
|
probeBurnedNote(url, opts?) -> 'live' | 'gone' | 'unknown'
|
|
28
|
-
verifyNoteSignature(k1, amountMsat, sigHex,
|
|
29
|
-
|
|
30
|
+
verifyNoteSignature(k1, amountMsat, sigHex, pubkeyHex | pubkeyHex[]) -> boolean
|
|
31
|
+
verifyNoteSignatureAgainst(k1, amountMsat, sigHex, keys) -> {valid, pubkey}
|
|
32
|
+
fetchMintAddress(url, opts?) -> {mintPubkey?, payLink, name?, motd?, contact?,
|
|
33
|
+
tosUrl?, fees?, version?, previousPubkeys?, mintToHash?, node*?}
|
|
34
|
+
experimental, often absent
|
|
35
|
+
mintPubkey verifies note signatures. It is NOT the node key in nodeUri.
|
|
36
|
+
nodePubkey is a deprecated alias for mintPubkey, dropped next breaking change.
|
|
37
|
+
mintToHash is the fallback copy of the payRequest's flag - see 13.
|
|
38
|
+
deriveNoteRoot(seedBytes) -> Uint8Array HMAC-SHA256("lnurlcash-note-v1", seed)
|
|
39
|
+
deriveNoteSecret(root, host, index) -> k1 HMAC-SHA256(root, host + ":" + index)
|
|
40
|
+
derivedSecretSource(root, host, start) -> RandomSecret & {index()}
|
|
41
|
+
restoreNotes(baseUrl, root, host, {gap?, start?}, opts?) -> {found[], next}
|
|
42
|
+
fetchPayRequest(url, opts?) -> {callback, minSendable, maxSendable, metadata,
|
|
43
|
+
withdrawLink?, mintFee?, mintToHash?} mintToHash: mint accepts an `h`
|
|
44
|
+
fetchInvoiceVerification(url, opts?)
|
|
45
|
+
requestInvoice(cb, msat, {h?, ...opts}?) -> {pr, verify?, disposable, mintToHash}
|
|
46
|
+
claimMintedNote(withdrawLink, k1, opts?)
|
|
47
|
+
-> {state: 'minted'|'unminted'|'pending'|'spent', k1, amountMsat, callback}
|
|
48
|
+
encodePaymentRequest(req) -> "lnurlcashreq1..." base64url(JCS JSON), prefix
|
|
49
|
+
decodePaymentRequest(str, {now?}) -> PaymentRequest throws ProtocolError
|
|
50
|
+
isPaymentRequest(str) -> boolean true for an expired one too
|
|
51
|
+
paymentRequestAmountMsat(req) -> msat request amount is in SAT, this is the
|
|
52
|
+
only sat-denominated field in the library; never multiply by hand
|
|
30
53
|
parseMintFee(metadata) / applyMintFee(gross, fee) / grossUpForMintFee(net, fee)
|
|
31
54
|
createClient(opts) -> all of the above with opts bound
|
|
32
55
|
|
|
@@ -38,26 +61,64 @@ Options (always last): {fetch?, timeoutMs?, offline?, randomSecret?}
|
|
|
38
61
|
`amount` in a note URL is an unverified claim.
|
|
39
62
|
2. On rotate/split/merge the WALLET generates the replacement secret and
|
|
40
63
|
discloses only sha256(secret). Never accept a service-supplied k1.
|
|
41
|
-
3.
|
|
42
|
-
|
|
43
|
-
failure destroys money the service may already have minted.
|
|
64
|
+
3. On ANY error from a mutation call newSecretsOf(err) FIRST, persist what
|
|
65
|
+
it returns, then call probeBurnedNote to learn what happened. Treating a
|
|
66
|
+
failure as a failure destroys money the service may already have minted.
|
|
67
|
+
AmbiguousMutationError always carries secrets; so does a NoteSpentError
|
|
68
|
+
or NoteUnknownError from a mutation, because that is also what a retried
|
|
69
|
+
GET looks like once its first attempt burned the input.
|
|
44
70
|
4. RequestRefusedError means nothing was sent - safe to treat as no-op.
|
|
45
71
|
5. A melt's OK means IN FLIGHT, not spent. PendingNoteError means retry, not
|
|
46
72
|
spent.
|
|
47
73
|
6. Rotate immediately after claiming a minted note: the mint generated that
|
|
48
74
|
preimage, and LUD-21 verify exposes it to anyone who saw the invoice.
|
|
75
|
+
Does not apply to a note minted with `h` - see 13.
|
|
49
76
|
7. Never log note URLs. The secret is in the query string.
|
|
50
77
|
8. Never branch on error message text. Branch on the error class.
|
|
78
|
+
9. lnurlcashreq1 means ONE schema: {v: 1, id (16 hex), amount (whole sat as
|
|
79
|
+
a decimal string), currency: "sat", methodDetails: {mints}, to?, memo?,
|
|
80
|
+
expires?}, JCS-canonicalised, base64url, no padding. Validation is
|
|
81
|
+
strict, an unrecognised field included. At the expiry is expired. Pass
|
|
82
|
+
{now: 0} to show a user what they scanned. The decoder also reads the
|
|
83
|
+
short {a, m, u} form an early 402 rail emitted under this prefix, but
|
|
84
|
+
NEVER emit it.
|
|
85
|
+
10. Accepting a note as payment MUST end in a rotate. Checking its value
|
|
86
|
+
and granting access without rotating leaves the payer able to spend it
|
|
87
|
+
again; the rotate is both the ownership transfer and the replay check.
|
|
88
|
+
11. A mint may rotate its signing key. Verify against its current key plus
|
|
89
|
+
the previousPubkeys it publishes; a note that verifies only against a
|
|
90
|
+
retired key should be rotated to be re-signed. An empty key list is a
|
|
91
|
+
rejection.
|
|
92
|
+
12. With derived secrets, persist the per-host counter in the SAME write
|
|
93
|
+
that stages the new records and BEFORE the hash goes on the wire. A
|
|
94
|
+
split consumes two indices, a rotate one; read source.index() for the
|
|
95
|
+
next unused one. Bumping late re-derives a secret the mint has already
|
|
96
|
+
seen.
|
|
97
|
+
13. Name the note you are buying where the mint offers it. Read mintToHash
|
|
98
|
+
off fetchPayRequest FIRST (fetchMintAddress is the fallback for a mint
|
|
99
|
+
that only says it on that optional document), then derive a secret,
|
|
100
|
+
persist it, and pass h = hashK1(secret) to requestInvoice. The mint
|
|
101
|
+
credits the note at that hash, the payment preimage is then not a valid
|
|
102
|
+
k1, and you claim with claimMintedNote rather than polling verify - no
|
|
103
|
+
rotate needed, and the note is seed-derived from birth so restoreNotes
|
|
104
|
+
finds it. Persist the secret BEFORE requesting the invoice. Three
|
|
105
|
+
places carry the flag: the payRequest and the mint address both mean
|
|
106
|
+
"I accept an h", InvoiceResult.mintToHash means "I bound THIS quote to
|
|
107
|
+
your hash". Anything not exactly true is no. A mint that advertises
|
|
108
|
+
nowhere ignores the h and the preimage path is unchanged.
|
|
51
109
|
|
|
52
110
|
## Error classes
|
|
53
111
|
|
|
54
112
|
RequestRefusedError nothing sent, note untouched
|
|
55
113
|
ServiceRejectedError processed and refused (definitive)
|
|
56
114
|
PendingNoteError a melt is in flight on this k1 - retry
|
|
57
|
-
NoteSpentError authoritative: already burned
|
|
115
|
+
NoteSpentError authoritative: already burned - but from a MUTATION it
|
|
116
|
+
may be a retry whose first attempt landed; read
|
|
117
|
+
newSecretsOf(err) before believing it
|
|
58
118
|
NoteUnknownError service does not recognise it
|
|
59
119
|
AmbiguousMintError outcome UNKNOWN - assume nothing
|
|
60
120
|
AmbiguousMutationError carries .newSecrets - persist them
|
|
121
|
+
newSecretsOf(err) -> string[] the secrets any error is carrying, or none
|
|
61
122
|
ProtocolError a non-mutating response did not match the spec
|
|
62
123
|
|
|
63
124
|
## Conformance
|
package/package.json
CHANGED