@arkade-os/lnurl-client 0.0.0-stage → 0.7.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/README.md +499 -3
- package/dist/addresses-CPAzIbJ_.d.ts +514 -0
- package/dist/arkade.d.ts +333 -0
- package/dist/arkade.js +558 -0
- package/dist/browser.d.ts +6 -0
- package/dist/browser.js +60 -0
- package/dist/chunk-4ELYU6DY.js +1417 -0
- package/dist/chunk-H7W5RHP2.js +58 -0
- package/dist/hd.d.ts +16 -0
- package/dist/hd.js +389 -0
- package/dist/index.d.ts +796 -0
- package/dist/index.js +86 -0
- package/package.json +59 -6
package/dist/arkade.d.ts
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { U as UnitAmount, V as VerifyExpectation, Q as QuotedAmount, D as DomainCapabilities, P as PayRequest, a as PaymentPage, H as HdReceiveAllocationPage, b as HdReceiveConfig } from './addresses-CPAzIbJ_.js';
|
|
2
|
+
export { c as HdReceiveAllocation } from './addresses-CPAzIbJ_.js';
|
|
3
|
+
import { PaymentRequest, PaymentRail, RouteQuote, RouterPreferences, PaymentOption, ActivityResolver, PaymentHandle } from '@arkade-os/sdk';
|
|
4
|
+
import { LnurlClient, PaymentSyncStore, StoredPayment, PendingConfirmations } from './index.js';
|
|
5
|
+
|
|
6
|
+
declare const LNURL_ARKADE_RAIL = "lnurl-arkade";
|
|
7
|
+
declare const LNURL_LIGHTNING_RAIL = "lnurl-lightning";
|
|
8
|
+
/** What an lnurl rail records on its quote, under `meta.lnurl`. */
|
|
9
|
+
interface LnurlQuoteMeta {
|
|
10
|
+
/** The LNURL or Lightning address the quote pays, as the payer entered it. */
|
|
11
|
+
target: string;
|
|
12
|
+
/** The inner rail that pays it. */
|
|
13
|
+
via: string;
|
|
14
|
+
verify?: string;
|
|
15
|
+
verifyBatch?: string;
|
|
16
|
+
/** What `verify` answers must be about: pass it as `pollVerify`'s `expect`. */
|
|
17
|
+
expect?: VerifyExpectation;
|
|
18
|
+
/** What was asked for in a unit, when the payment was priced in one. */
|
|
19
|
+
quote?: QuotedAmount;
|
|
20
|
+
}
|
|
21
|
+
/** The SDK's request, plus an amount in one of the target's `units` instead of sats.
|
|
22
|
+
* The router hands every rail the same object, so only the lnurl rails read it. */
|
|
23
|
+
type LnurlPaymentRequest = PaymentRequest & {
|
|
24
|
+
unitAmount?: UnitAmount;
|
|
25
|
+
};
|
|
26
|
+
/** The lnurl meta of a quote, or undefined for a quote no lnurl rail made. */
|
|
27
|
+
declare function lnurlQuoteMeta(quote: RouteQuote): LnurlQuoteMeta | undefined;
|
|
28
|
+
interface LnurlRailDeps {
|
|
29
|
+
/** Payer surface only; needs no `baseUrl`. */
|
|
30
|
+
client: LnurlClient;
|
|
31
|
+
/** Pays the Arkade destination the callback returns — normally `arkRail()`. */
|
|
32
|
+
arkade: PaymentRail;
|
|
33
|
+
/** Pays the BOLT11 the callback returns — normally `solverLightningRail(...)`.
|
|
34
|
+
* Omit it and no lightning rail is registered, rather than one that cannot pay. */
|
|
35
|
+
lightning?: PaymentRail;
|
|
36
|
+
comment?: string;
|
|
37
|
+
/** How long one target's payRequest is reused across `available()`/`quote()`. */
|
|
38
|
+
ttlMs?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Both rails for one client, sharing one resolve.
|
|
42
|
+
*
|
|
43
|
+
* Returned together because the sharing is the point: `options()` calls
|
|
44
|
+
* `available()` on every matching rail, and separate factories would each
|
|
45
|
+
* fetch the same payRequest.
|
|
46
|
+
*/
|
|
47
|
+
declare function lnurlRails(deps: LnurlRailDeps): PaymentRail[];
|
|
48
|
+
|
|
49
|
+
declare function arkadePaymentRouter(opts: {
|
|
50
|
+
wallet: LnurlWallet;
|
|
51
|
+
router?: LnurlPaymentRouter;
|
|
52
|
+
lightning?: PaymentRail;
|
|
53
|
+
client?: LnurlClient;
|
|
54
|
+
comment?: string;
|
|
55
|
+
}): LnurlPaymentRouter;
|
|
56
|
+
|
|
57
|
+
/** The wallet-shaped facade: what a receiver holding an `@arkade-os/sdk` wallet
|
|
58
|
+
* would otherwise wire by hand. The low-level surface stays exported beneath it. */
|
|
59
|
+
|
|
60
|
+
interface LnurlWallet {
|
|
61
|
+
readonly identity: ArkadeSigner;
|
|
62
|
+
getAddress(): Promise<string>;
|
|
63
|
+
getBoardingAddress(): Promise<string>;
|
|
64
|
+
}
|
|
65
|
+
interface LnurlPaymentRouter {
|
|
66
|
+
use(rail: PaymentRail): this;
|
|
67
|
+
remove(id: string): this;
|
|
68
|
+
options(req: LnurlPaymentRequest, prefs?: RouterPreferences): Promise<PaymentOption[]>;
|
|
69
|
+
route(req: LnurlPaymentRequest, prefs?: RouterPreferences): Promise<RouteQuote>;
|
|
70
|
+
}
|
|
71
|
+
/** The 1023 limit is LUD-01's, not bech32's default 90. */
|
|
72
|
+
declare function encodeLnurl(url: string): string;
|
|
73
|
+
/** A wallet supplies the signer and both addresses. Without one — a script, a
|
|
74
|
+
* test, a server holding only a key — name them; only sending needs a wallet. */
|
|
75
|
+
type ArkadeLnurlSource = {
|
|
76
|
+
wallet: LnurlWallet;
|
|
77
|
+
router?: LnurlPaymentRouter;
|
|
78
|
+
identity?: never;
|
|
79
|
+
arkadeAddress?: never;
|
|
80
|
+
hd?: HdReceiveConfig;
|
|
81
|
+
} | {
|
|
82
|
+
wallet?: never;
|
|
83
|
+
router?: never;
|
|
84
|
+
identity: ArkadeSigner;
|
|
85
|
+
arkadeAddress: string;
|
|
86
|
+
boardingAddress?: string;
|
|
87
|
+
hd?: never;
|
|
88
|
+
} | {
|
|
89
|
+
wallet?: never;
|
|
90
|
+
router?: never;
|
|
91
|
+
identity: ArkadeSigner;
|
|
92
|
+
hd: HdReceiveConfig;
|
|
93
|
+
arkadeAddress?: never;
|
|
94
|
+
boardingAddress?: never;
|
|
95
|
+
};
|
|
96
|
+
type ArkadeLnurlOptions = ArkadeLnurlSource & ArkadeLnurlConfig;
|
|
97
|
+
interface ArkadeLnurlConfig {
|
|
98
|
+
baseUrl: string;
|
|
99
|
+
/** Defaults to `baseUrl`'s hostname, as the server derives it: a LUD-16
|
|
100
|
+
* domain cannot carry a port. */
|
|
101
|
+
domain?: string;
|
|
102
|
+
store?: PaymentSyncStore;
|
|
103
|
+
lightningRail?: PaymentRail;
|
|
104
|
+
client?: LnurlClient;
|
|
105
|
+
}
|
|
106
|
+
/** A claim code is checked only against the reserved name it unlocks, so it never travels alone. */
|
|
107
|
+
type NameOptions = {
|
|
108
|
+
username?: string;
|
|
109
|
+
claimCode?: never;
|
|
110
|
+
} | {
|
|
111
|
+
username: string;
|
|
112
|
+
claimCode: string;
|
|
113
|
+
};
|
|
114
|
+
/** `nameless` is mutually exclusive with `username`/`claimCode` at the type
|
|
115
|
+
* level, matching the server's 400 `invalid_username` on combining them. */
|
|
116
|
+
type ClaimOptions = (NameOptions & {
|
|
117
|
+
nameless?: never;
|
|
118
|
+
}) | {
|
|
119
|
+
nameless: true;
|
|
120
|
+
username?: never;
|
|
121
|
+
claimCode?: never;
|
|
122
|
+
};
|
|
123
|
+
/** One claimed or listed address, holding everything scoped to it. */
|
|
124
|
+
interface Receiver {
|
|
125
|
+
readonly handle: string;
|
|
126
|
+
/** `user@domain`; undefined for a nameless receiver. */
|
|
127
|
+
readonly lightningAddress: string | undefined;
|
|
128
|
+
/** For a QR. The session LNURL when flagged (survives {@link upgrade}), else `.well-known`. */
|
|
129
|
+
readonly lnurl: string;
|
|
130
|
+
/** Addressed through `baseUrl`, not the LUD-16 domain, which drops the port.
|
|
131
|
+
* One fetch answers every call for 30 s, or until a write through this facade
|
|
132
|
+
* (`claim`, `upgrade`); `resolve(lnurl)` always asks the server. */
|
|
133
|
+
payRequest(): Promise<PayRequest>;
|
|
134
|
+
payments(opts?: {
|
|
135
|
+
since?: number;
|
|
136
|
+
limit?: number;
|
|
137
|
+
}): Promise<PaymentPage>;
|
|
138
|
+
allocations(opts?: {
|
|
139
|
+
after?: number;
|
|
140
|
+
limit?: number;
|
|
141
|
+
}): Promise<HdReceiveAllocationPage>;
|
|
142
|
+
sync(): Promise<{
|
|
143
|
+
synced: number;
|
|
144
|
+
failures: unknown[];
|
|
145
|
+
}>;
|
|
146
|
+
/** Names a nameless receiver in place; everything handed out while nameless
|
|
147
|
+
* keeps working. Does not re-bind the Arkade identity, already on the row. */
|
|
148
|
+
upgrade(opts?: NameOptions): Promise<Receiver>;
|
|
149
|
+
}
|
|
150
|
+
interface ArkadeLnurl {
|
|
151
|
+
/** Derived once; signs twice on the first call, nothing on later ones. */
|
|
152
|
+
token(): Promise<string>;
|
|
153
|
+
capabilities(): Promise<DomainCapabilities>;
|
|
154
|
+
/** Registers an address — named, random or nameless per `opts` — and binds
|
|
155
|
+
* the identity. Until the bind lands the address advertises no
|
|
156
|
+
* `paymentOptions` at all, so offline receive does not exist. */
|
|
157
|
+
claim(opts?: ClaimOptions): Promise<Receiver>;
|
|
158
|
+
owned(): Promise<Receiver | undefined>;
|
|
159
|
+
router(): LnurlPaymentRouter;
|
|
160
|
+
/** `amount` is sats, or an amount in one of the target's `units`, e.g. `{ unit: "USD", amount: 500 }`. */
|
|
161
|
+
options(target: string, amount: number | UnitAmount, prefs?: RouterPreferences): Promise<PaymentOption[]>;
|
|
162
|
+
}
|
|
163
|
+
/** Ordered so the Arkade leg outranks the Lightning one for the same address:
|
|
164
|
+
* it delivers the full amount with no counterparty. */
|
|
165
|
+
declare const DEFAULT_RAIL_PRIORITY: string[];
|
|
166
|
+
declare function arkadeLnurl(opts: ArkadeLnurlOptions): ArkadeLnurl;
|
|
167
|
+
|
|
168
|
+
/** "5.00 USD": how a quoted amount reads in an activity row. */
|
|
169
|
+
declare const quotedLabel: (q: QuotedAmount) => string;
|
|
170
|
+
/** Namespaced so it cannot clobber the SDK's own resolvers. */
|
|
171
|
+
declare const LNURL_RESOLVER_ID = "lnurl:payments";
|
|
172
|
+
declare const SENT_RESOLVER_ID = "lnurl:sends";
|
|
173
|
+
declare const LNURL_GROUP_PREFIX = "lnurl:";
|
|
174
|
+
declare const SENT_GROUP_PREFIX = "sent:";
|
|
175
|
+
declare const railOf: (p: StoredPayment) => string;
|
|
176
|
+
declare function absorbedPaymentKey(activityId: string): string | undefined;
|
|
177
|
+
/** What a wallet knows about a payment it made. Nothing else does: the server
|
|
178
|
+
* that recorded a send was the recipient's, so its record is theirs, not ours. */
|
|
179
|
+
interface SentPayment {
|
|
180
|
+
/** Arkade txid — the join key to the wallet's own activity row. */
|
|
181
|
+
txid: string;
|
|
182
|
+
/** What the user typed: a Lightning address, an LNURL, or a bare address. */
|
|
183
|
+
target: string;
|
|
184
|
+
railId: string;
|
|
185
|
+
amountSat: number;
|
|
186
|
+
feeSat: number;
|
|
187
|
+
createdAt: number;
|
|
188
|
+
swapId?: string;
|
|
189
|
+
preimage?: string;
|
|
190
|
+
/** The LUD-21 verify URL and LUD-XX verifyBatch endpoint the quote carried, kept so a
|
|
191
|
+
* confirmation still pending when the app closes can be resumed. */
|
|
192
|
+
verify?: string;
|
|
193
|
+
verifyBatch?: string;
|
|
194
|
+
expect?: VerifyExpectation;
|
|
195
|
+
/** Set once the receiver's LUD-21 verify answers, where a rail hands one out. */
|
|
196
|
+
receiverConfirmed?: boolean;
|
|
197
|
+
/** What the payer asked to pay in a LUD-XX unit; absent when they paid in sats. */
|
|
198
|
+
quote?: QuotedAmount;
|
|
199
|
+
}
|
|
200
|
+
/** What to keep on file after a completed send: `incoming` replaces the record
|
|
201
|
+
* sharing its txid, so a later verify result updates that row rather than
|
|
202
|
+
* duplicating it. Storage — reading the existing set, writing the result — is
|
|
203
|
+
* the caller's. */
|
|
204
|
+
declare function mergeSentPayment(existing: SentPayment[], incoming: SentPayment): SentPayment[];
|
|
205
|
+
/** Labels a payment this wallet MADE, from what it recorded at send time. Joined
|
|
206
|
+
* on the rail's txid, never inferred from amount and timing as an incoming quote
|
|
207
|
+
* may be: naming a recipient the money did not go to is worse than naming none. */
|
|
208
|
+
declare function sentActivityResolver(sends: () => SentPayment[]): ActivityResolver;
|
|
209
|
+
/** Joined on `payoutReference`, never `paymentReference`: the latter is what the
|
|
210
|
+
* service observed, which on two of the three rails is an output this wallet
|
|
211
|
+
* never holds. */
|
|
212
|
+
declare function lnurlActivityResolver(payments: () => StoredPayment[]): ActivityResolver;
|
|
213
|
+
|
|
214
|
+
interface LnurlSentPaymentStore {
|
|
215
|
+
read(): SentPayment[];
|
|
216
|
+
write(records: SentPayment[]): void;
|
|
217
|
+
}
|
|
218
|
+
interface LnurlSendTrackerOptions {
|
|
219
|
+
onError(error: unknown): void;
|
|
220
|
+
confirmations?: PendingConfirmations;
|
|
221
|
+
}
|
|
222
|
+
interface LnurlSendTracker {
|
|
223
|
+
all(): SentPayment[];
|
|
224
|
+
record(handle: PaymentHandle, quote: RouteQuote, target: string): () => void;
|
|
225
|
+
watch(txid: string, verify: string, verifyBatch?: string, startedAt?: number, expect?: VerifyExpectation): void;
|
|
226
|
+
resume(): void;
|
|
227
|
+
mark(txid: string, confirmed: boolean): void;
|
|
228
|
+
forget(): void;
|
|
229
|
+
}
|
|
230
|
+
/** Shared send bookkeeping over the application's synchronous persistence. */
|
|
231
|
+
declare function createLnurlSendTracker(store: LnurlSentPaymentStore, options: LnurlSendTrackerOptions): LnurlSendTracker;
|
|
232
|
+
|
|
233
|
+
type LnurlRailType = "lightning" | "arkade" | "onchain";
|
|
234
|
+
declare function lnurlRailLimits(payRequest: PayRequest): {
|
|
235
|
+
type: string;
|
|
236
|
+
min: number;
|
|
237
|
+
max: number;
|
|
238
|
+
}[];
|
|
239
|
+
declare function resolveLnurlRails(receiver: Pick<Receiver, "payRequest">, amountSat: number, rails: readonly LnurlRailType[], own: {
|
|
240
|
+
arkade: string;
|
|
241
|
+
onchain: string;
|
|
242
|
+
}, client?: Pick<LnurlClient, "requestInvoice">): Promise<PromiseSettledResult<string>[]>;
|
|
243
|
+
|
|
244
|
+
interface ReceiverBootstrapOptions {
|
|
245
|
+
/** Discovery does not allocate a receiver unless explicitly enabled. */
|
|
246
|
+
autoClaimNameless?: boolean;
|
|
247
|
+
}
|
|
248
|
+
type ReceiverBootstrapResult = {
|
|
249
|
+
kind: "ready";
|
|
250
|
+
receiver: Receiver;
|
|
251
|
+
claimed: boolean;
|
|
252
|
+
capabilities?: DomainCapabilities;
|
|
253
|
+
capabilitiesError?: unknown;
|
|
254
|
+
} | {
|
|
255
|
+
kind: "onboarding";
|
|
256
|
+
capabilities: DomainCapabilities;
|
|
257
|
+
};
|
|
258
|
+
declare function bootstrapReceiver(facade: Pick<ArkadeLnurl, "owned" | "capabilities" | "claim">, opts?: ReceiverBootstrapOptions): Promise<ReceiverBootstrapResult>;
|
|
259
|
+
declare function claimOrAdopt(facade: Pick<ArkadeLnurl, "owned" | "claim">, opts?: ClaimOptions): Promise<Receiver>;
|
|
260
|
+
|
|
261
|
+
/** The slice of `@arkade-os/sdk`'s `Identity` these helpers need. */
|
|
262
|
+
interface ArkadeSigner {
|
|
263
|
+
signMessage(message: Uint8Array, signatureType: "schnorr" | "ecdsa"): Promise<Uint8Array>;
|
|
264
|
+
compressedPublicKey(): Promise<Uint8Array>;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* True when `address` decodes as an Arkade address.
|
|
268
|
+
*
|
|
269
|
+
* The core package deliberately cannot do this — decoding needs the SDK — so
|
|
270
|
+
* without this helper a malformed address is only caught server-side, a round
|
|
271
|
+
* trip later.
|
|
272
|
+
*
|
|
273
|
+
* @param address - Bech32m Arkade address.
|
|
274
|
+
* @returns Whether it decodes.
|
|
275
|
+
*/
|
|
276
|
+
declare function isArkadeAddress(address: string): boolean;
|
|
277
|
+
/**
|
|
278
|
+
* Derives the session token from an `Identity`, signing with ECDSA.
|
|
279
|
+
*
|
|
280
|
+
* Prefer this over calling {@link deriveSessionTokenWithSigner} yourself: it
|
|
281
|
+
* pins the signature type. Schnorr is `Identity.signMessage`'s default and is
|
|
282
|
+
* randomised without an explicit aux, which would mint a fresh token per call
|
|
283
|
+
* and orphan the address — and a schnorr signature is 64 bytes exactly like a
|
|
284
|
+
* compact ECDSA one, so nothing about the bytes reveals the mistake.
|
|
285
|
+
*
|
|
286
|
+
* Produces the same token as `deriveSessionToken(privateKeyHex, domain)`.
|
|
287
|
+
*
|
|
288
|
+
* **Signs twice**, inherited from {@link deriveSessionTokenWithSigner}, to
|
|
289
|
+
* prove the signer is deterministic before a token derived from it is used as
|
|
290
|
+
* an address's identity. Free for a software key; an `Identity` backed by a
|
|
291
|
+
* device that prompts will prompt twice, once per call. Derive once per domain
|
|
292
|
+
* and hold the result for the session rather than calling it per request.
|
|
293
|
+
*
|
|
294
|
+
* @param identity - Anything with `@arkade-os/sdk`'s `signMessage`.
|
|
295
|
+
* @param domain - The LUD-16 domain this token is for.
|
|
296
|
+
* @returns The session token as hex, valid only at that domain.
|
|
297
|
+
*/
|
|
298
|
+
declare function deriveSessionTokenForIdentity(identity: ArkadeSigner, domain: string): Promise<string>;
|
|
299
|
+
/**
|
|
300
|
+
* The identity's compressed public key as hex — the `claimPublicKey` that
|
|
301
|
+
* `registerArkadeIdentity` wants, in the form the server validates.
|
|
302
|
+
*
|
|
303
|
+
* @param identity - Anything with `@arkade-os/sdk`'s `compressedPublicKey`.
|
|
304
|
+
* @returns 66-hex-char compressed key.
|
|
305
|
+
*/
|
|
306
|
+
declare function claimPublicKeyOf(identity: ArkadeSigner): Promise<string>;
|
|
307
|
+
/**
|
|
308
|
+
* Builds the `registerArkadeIdentity` request from an `Identity`, validating the
|
|
309
|
+
* Arkade address before it reaches the wire.
|
|
310
|
+
*
|
|
311
|
+
* An optional `boardingAddress` registers the onchain rail in the same call,
|
|
312
|
+
* unchecked: it is a Bitcoin address on a network this helper cannot know.
|
|
313
|
+
*
|
|
314
|
+
* @param params - The identity, its Arkade address, the owning token and handle.
|
|
315
|
+
* @returns The request body to hand to `registerArkadeIdentity`.
|
|
316
|
+
*/
|
|
317
|
+
declare function arkadeIdentityRequest(params: {
|
|
318
|
+
identity: ArkadeSigner;
|
|
319
|
+
arkadeAddress: string;
|
|
320
|
+
token: string;
|
|
321
|
+
handle: string;
|
|
322
|
+
boardingAddress?: string;
|
|
323
|
+
domain?: string;
|
|
324
|
+
}): Promise<{
|
|
325
|
+
token: string;
|
|
326
|
+
handle: string;
|
|
327
|
+
arkadeAddress: string;
|
|
328
|
+
claimPublicKey: string;
|
|
329
|
+
boardingAddress?: string;
|
|
330
|
+
domain?: string;
|
|
331
|
+
}>;
|
|
332
|
+
|
|
333
|
+
export { type ArkadeLnurl, type ArkadeLnurlConfig, type ArkadeLnurlOptions, type ArkadeLnurlSource, type ArkadeSigner, type ClaimOptions, DEFAULT_RAIL_PRIORITY, HdReceiveAllocationPage, HdReceiveConfig, LNURL_ARKADE_RAIL, LNURL_GROUP_PREFIX, LNURL_LIGHTNING_RAIL, LNURL_RESOLVER_ID, type LnurlPaymentRequest, type LnurlPaymentRouter, type LnurlQuoteMeta, type LnurlRailDeps, type LnurlRailType, type LnurlSendTracker, type LnurlSendTrackerOptions, type LnurlSentPaymentStore, type LnurlWallet, type NameOptions, type Receiver, type ReceiverBootstrapOptions, type ReceiverBootstrapResult, SENT_GROUP_PREFIX, SENT_RESOLVER_ID, type SentPayment, absorbedPaymentKey, arkadeIdentityRequest, arkadeLnurl, arkadePaymentRouter, bootstrapReceiver, claimOrAdopt, claimPublicKeyOf, createLnurlSendTracker, deriveSessionTokenForIdentity, encodeLnurl, isArkadeAddress, lnurlActivityResolver, lnurlQuoteMeta, lnurlRailLimits, lnurlRails, mergeSentPayment, quotedLabel, railOf, resolveLnurlRails, sentActivityResolver };
|