fiberprobe 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.
- package/README.md +197 -0
- package/dist/client/errors.d.ts +70 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +132 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/index.d.ts +112 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +162 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +154 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +6 -0
- package/dist/client/types.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/payment/checker.d.ts +165 -0
- package/dist/payment/checker.d.ts.map +1 -0
- package/dist/payment/checker.js +388 -0
- package/dist/payment/checker.js.map +1 -0
- package/dist/payment/events.d.ts +135 -0
- package/dist/payment/events.d.ts.map +1 -0
- package/dist/payment/events.js +256 -0
- package/dist/payment/events.js.map +1 -0
- package/dist/payment/probe-crypto.d.ts +11 -0
- package/dist/payment/probe-crypto.d.ts.map +1 -0
- package/dist/payment/probe-crypto.js +21 -0
- package/dist/payment/probe-crypto.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PaymentChecker — pre-flight payment feasibility analysis for Fiber Network.
|
|
3
|
+
*
|
|
4
|
+
* Solves two problems every Fiber application faces:
|
|
5
|
+
*
|
|
6
|
+
* 1. canPay() — Will this payment succeed before I try to send it?
|
|
7
|
+
* 2. canReceive() — Do I have enough inbound capacity to receive a payment?
|
|
8
|
+
*
|
|
9
|
+
* Design note: send_payment's dry_run flag was evaluated as a data source
|
|
10
|
+
* for canPay() and rejected. Live testnet testing confirmed dry-run payment
|
|
11
|
+
* sessions are never queryable via get_payment, even immediately after
|
|
12
|
+
* creation — the RPC returns "Payment session not found" on instant lookup.
|
|
13
|
+
* This means dry_run cannot supply route or fee detail synchronously or
|
|
14
|
+
* asynchronously.
|
|
15
|
+
*
|
|
16
|
+
* canPay() instead performs static graph reachability analysis:
|
|
17
|
+
* 1. parseInvoice() resolves the destination pubkey and amount
|
|
18
|
+
* 2. listChannels() checks for a direct channel to the destination
|
|
19
|
+
* 3. graphChannels() + BFS finds a multi-hop path if no direct channel exists
|
|
20
|
+
* 4. Each hop is scored against published outbound_liquidity, exactly as
|
|
21
|
+
* a live router would need to evaluate route viability
|
|
22
|
+
*
|
|
23
|
+
* canReceive() scans open ChannelReady channels and sums usable inbound
|
|
24
|
+
* capacity, correctly accounting for in-flight received TLCs.
|
|
25
|
+
*/
|
|
26
|
+
import { FiberError, RouteNotFoundError } from '../client/errors.js';
|
|
27
|
+
import { generateFakePaymentHash } from './probe-crypto.js';
|
|
28
|
+
// ── Internal helpers ──────────────────────────────────────────────────────────
|
|
29
|
+
function parseHexAmount(hex) {
|
|
30
|
+
if (!hex.startsWith('0x') && !hex.startsWith('0X')) {
|
|
31
|
+
throw new Error(`Expected hex amount string, got: ${hex}`);
|
|
32
|
+
}
|
|
33
|
+
return BigInt(hex);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Score a single hop against published graph liquidity data.
|
|
37
|
+
* Same rationale as the original dry-run-based scoring, applied here to
|
|
38
|
+
* statically discovered graph edges instead of live router hop data.
|
|
39
|
+
*/
|
|
40
|
+
function scoreHop(channel, amountToForward) {
|
|
41
|
+
const shortId = channel.channel_outpoint.slice(0, 14) + '…';
|
|
42
|
+
const published = [
|
|
43
|
+
channel.update_info_of_node1?.outbound_liquidity,
|
|
44
|
+
channel.update_info_of_node2?.outbound_liquidity,
|
|
45
|
+
].filter((l) => l != null);
|
|
46
|
+
if (published.length === 0) {
|
|
47
|
+
return { score: 0.70 };
|
|
48
|
+
}
|
|
49
|
+
const liquidities = published.map(parseHexAmount);
|
|
50
|
+
const conservative = liquidities.reduce((a, b) => (a < b ? a : b));
|
|
51
|
+
if (conservative === 0n) {
|
|
52
|
+
return { score: 0.05, issue: `Channel ${shortId} reports zero outbound liquidity` };
|
|
53
|
+
}
|
|
54
|
+
const ratio = Number(conservative) / Number(amountToForward);
|
|
55
|
+
if (ratio >= 3.0)
|
|
56
|
+
return { score: 0.95 };
|
|
57
|
+
if (ratio >= 1.5)
|
|
58
|
+
return { score: 0.82 };
|
|
59
|
+
if (ratio >= 1.0)
|
|
60
|
+
return { score: 0.65, issue: `Channel ${shortId} has tight liquidity` };
|
|
61
|
+
return { score: 0.20, issue: `Channel ${shortId} may have insufficient liquidity for this amount` };
|
|
62
|
+
}
|
|
63
|
+
function computeConfidence(hopScores, hopCount) {
|
|
64
|
+
if (hopScores.length === 0)
|
|
65
|
+
return 0;
|
|
66
|
+
const weakestHop = Math.min(...hopScores);
|
|
67
|
+
const hopPenalty = Math.max(0, (hopCount - 1) * 0.03);
|
|
68
|
+
return Math.round(Math.max(0, weakestHop - hopPenalty) * 100);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Breadth-first search over the public channel graph to find a path from
|
|
72
|
+
* `from` to `to`. Returns the sequence of GraphChannel edges forming the
|
|
73
|
+
* path, or null if no path exists within maxHops.
|
|
74
|
+
*
|
|
75
|
+
* BFS guarantees the shortest hop-count path is found first, which is the
|
|
76
|
+
* most useful default for a payment router — fewer hops means fewer points
|
|
77
|
+
* of failure and typically lower cumulative fees.
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* Fetches the entire public channel graph by paginating through graph_channels()
|
|
81
|
+
* until last_cursor stops changing or the safety cap is reached. Testnet graphs
|
|
82
|
+
* can exceed the default page size of any single call, so a naive single-page
|
|
83
|
+
* fetch can silently miss channels — including the caller's own, as discovered
|
|
84
|
+
* during live testing when a real ChannelReady channel was absent from the
|
|
85
|
+
* first 500-entry page.
|
|
86
|
+
*
|
|
87
|
+
* @param maxPages - Safety cap on number of pages fetched. Defaults to 20
|
|
88
|
+
* (i.e. up to 20 * limit channels).
|
|
89
|
+
*/
|
|
90
|
+
async function fetchAllGraphChannels(client, pageSize = 500, maxPages = 20) {
|
|
91
|
+
const all = [];
|
|
92
|
+
let cursor;
|
|
93
|
+
for (let page = 0; page < maxPages; page++) {
|
|
94
|
+
const result = await client.graphChannels(pageSize, cursor);
|
|
95
|
+
all.push(...result.channels);
|
|
96
|
+
if (result.channels.length < pageSize)
|
|
97
|
+
break;
|
|
98
|
+
if (result.last_cursor === cursor)
|
|
99
|
+
break;
|
|
100
|
+
cursor = result.last_cursor;
|
|
101
|
+
}
|
|
102
|
+
return all;
|
|
103
|
+
}
|
|
104
|
+
function findPath(from, to, channels, maxHops) {
|
|
105
|
+
// Build adjacency: pubkey -> list of { neighbor, channel }
|
|
106
|
+
const adjacency = new Map();
|
|
107
|
+
for (const ch of channels) {
|
|
108
|
+
if (!adjacency.has(ch.node1))
|
|
109
|
+
adjacency.set(ch.node1, []);
|
|
110
|
+
if (!adjacency.has(ch.node2))
|
|
111
|
+
adjacency.set(ch.node2, []);
|
|
112
|
+
adjacency.get(ch.node1).push({ neighbor: ch.node2, channel: ch });
|
|
113
|
+
adjacency.get(ch.node2).push({ neighbor: ch.node1, channel: ch });
|
|
114
|
+
}
|
|
115
|
+
if (from === to)
|
|
116
|
+
return [];
|
|
117
|
+
const visited = new Set([from]);
|
|
118
|
+
const queue = [{ node: from, path: [] }];
|
|
119
|
+
while (queue.length > 0) {
|
|
120
|
+
const { node, path } = queue.shift();
|
|
121
|
+
if (path.length >= maxHops)
|
|
122
|
+
continue;
|
|
123
|
+
const edges = adjacency.get(node) ?? [];
|
|
124
|
+
for (const { neighbor, channel } of edges) {
|
|
125
|
+
if (neighbor === to) {
|
|
126
|
+
return [...path, channel];
|
|
127
|
+
}
|
|
128
|
+
if (!visited.has(neighbor)) {
|
|
129
|
+
visited.add(neighbor);
|
|
130
|
+
queue.push({ node: neighbor, path: [...path, channel] });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
// ── PaymentChecker ────────────────────────────────────────────────────────────
|
|
137
|
+
/**
|
|
138
|
+
* Pre-flight payment feasibility analysis for Fiber Network applications.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* const checker = new PaymentChecker(client)
|
|
143
|
+
*
|
|
144
|
+
* const result = await checker.canPay({ invoice: 'fibt...' })
|
|
145
|
+
* if (!result.canPay) {
|
|
146
|
+
* console.error(result.error?.message)
|
|
147
|
+
* return
|
|
148
|
+
* }
|
|
149
|
+
* console.log(`Confidence: ${result.confidence}% Hops: ${result.hopCount}`)
|
|
150
|
+
*
|
|
151
|
+
* const rx = await checker.canReceive({ amount: '0x174876e800' })
|
|
152
|
+
* if (!rx.canReceive) console.warn('Low inbound capacity:', rx.issues)
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export class PaymentChecker {
|
|
156
|
+
client;
|
|
157
|
+
constructor(client) {
|
|
158
|
+
this.client = client;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Performs a pre-flight feasibility check for an outgoing Fiber payment.
|
|
162
|
+
*
|
|
163
|
+
* Process:
|
|
164
|
+
* 1. Resolves the destination pubkey and amount from the invoice.
|
|
165
|
+
* 2. Checks for a direct ChannelReady channel to the destination —
|
|
166
|
+
* if found, this is the highest-confidence path.
|
|
167
|
+
* 3. Otherwise, searches the public network graph via BFS to find
|
|
168
|
+
* the shortest multi-hop path to the destination.
|
|
169
|
+
* 4. Scores each hop against published outbound liquidity data and
|
|
170
|
+
* combines scores using weakest-link logic, since a payment fails
|
|
171
|
+
* if any single hop lacks capacity.
|
|
172
|
+
*/
|
|
173
|
+
async canPay(params) {
|
|
174
|
+
const maxHops = params.maxHops ?? 5;
|
|
175
|
+
// Step 1: Resolve destination from the invoice
|
|
176
|
+
let destinationPubkey;
|
|
177
|
+
let amount;
|
|
178
|
+
try {
|
|
179
|
+
const parsed = await this.client.parseInvoice(params.invoice);
|
|
180
|
+
const payeeAttr = parsed.invoice.data.attrs.find((a) => 'payee_public_key' in a);
|
|
181
|
+
if (!payeeAttr?.payee_public_key) {
|
|
182
|
+
return {
|
|
183
|
+
canPay: false,
|
|
184
|
+
confidence: 0,
|
|
185
|
+
issues: ['Invoice does not specify a destination public key'],
|
|
186
|
+
error: new RouteNotFoundError('Invoice missing payee_public_key'),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
destinationPubkey = payeeAttr.payee_public_key;
|
|
190
|
+
amount = parsed.invoice.amount;
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
194
|
+
return {
|
|
195
|
+
canPay: false,
|
|
196
|
+
confidence: 0,
|
|
197
|
+
issues: [`Failed to parse invoice: ${raw}`],
|
|
198
|
+
error: FiberError.parse(raw),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const amountToForward = parseHexAmount(amount);
|
|
202
|
+
// Step 2: Check for a direct ChannelReady channel to the destination
|
|
203
|
+
const myChannels = await this.client.listChannels({ include_closed: false });
|
|
204
|
+
const directChannel = myChannels.find((ch) => ch.pubkey === destinationPubkey && ch.state.state_name === 'ChannelReady');
|
|
205
|
+
if (directChannel) {
|
|
206
|
+
const localBalance = parseHexAmount(directChannel.local_balance);
|
|
207
|
+
const issues = [];
|
|
208
|
+
let confidence;
|
|
209
|
+
if (localBalance >= amountToForward * 3n) {
|
|
210
|
+
confidence = 95;
|
|
211
|
+
}
|
|
212
|
+
else if (localBalance >= amountToForward) {
|
|
213
|
+
confidence = 75;
|
|
214
|
+
issues.push('Direct channel capacity is limited relative to payment amount');
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
return {
|
|
218
|
+
canPay: false,
|
|
219
|
+
confidence: 0,
|
|
220
|
+
destinationPubkey,
|
|
221
|
+
amount,
|
|
222
|
+
issues: ['Direct channel exists but local balance is insufficient'],
|
|
223
|
+
error: FiberError.parse('insufficient_capacity'),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
canPay: true,
|
|
228
|
+
confidence,
|
|
229
|
+
destinationPubkey,
|
|
230
|
+
amount,
|
|
231
|
+
hopCount: 0,
|
|
232
|
+
issues,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
// Step 3: No direct channel — search the public graph
|
|
236
|
+
const allChannels = await fetchAllGraphChannels(this.client);
|
|
237
|
+
// We need our own node's pubkey to start the search from
|
|
238
|
+
const myNodeInfo = await this.client.nodeInfo();
|
|
239
|
+
const path = findPath(myNodeInfo.pubkey, destinationPubkey, allChannels, maxHops);
|
|
240
|
+
if (!path) {
|
|
241
|
+
return {
|
|
242
|
+
canPay: false,
|
|
243
|
+
confidence: 0,
|
|
244
|
+
destinationPubkey,
|
|
245
|
+
amount,
|
|
246
|
+
issues: [`No route found to destination within ${maxHops} hops`],
|
|
247
|
+
error: new RouteNotFoundError(`No path to ${destinationPubkey} within ${maxHops} hops`),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
// Step 4: Score each hop
|
|
251
|
+
const issues = [];
|
|
252
|
+
const hopScores = [];
|
|
253
|
+
for (const channel of path) {
|
|
254
|
+
const { score, issue } = scoreHop(channel, amountToForward);
|
|
255
|
+
hopScores.push(score);
|
|
256
|
+
if (issue)
|
|
257
|
+
issues.push(issue);
|
|
258
|
+
}
|
|
259
|
+
const confidence = computeConfidence(hopScores, path.length);
|
|
260
|
+
return {
|
|
261
|
+
canPay: true,
|
|
262
|
+
confidence,
|
|
263
|
+
destinationPubkey,
|
|
264
|
+
amount,
|
|
265
|
+
hopCount: path.length,
|
|
266
|
+
issues,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Checks whether this node has sufficient inbound capacity to receive a payment.
|
|
271
|
+
*
|
|
272
|
+
* Usable inbound per channel = remote_balance − received_tlc_balance.
|
|
273
|
+
* Only ChannelReady + enabled channels are included.
|
|
274
|
+
*/
|
|
275
|
+
async canReceive(params) {
|
|
276
|
+
const targetAmount = parseHexAmount(params.amount);
|
|
277
|
+
const channels = await this.client.listChannels({ include_closed: false });
|
|
278
|
+
const issues = [];
|
|
279
|
+
const breakdown = [];
|
|
280
|
+
let total = 0n;
|
|
281
|
+
for (const ch of channels) {
|
|
282
|
+
if (ch.state.state_name !== 'ChannelReady')
|
|
283
|
+
continue;
|
|
284
|
+
const isUdtChannel = ch.funding_udt_type_script != null;
|
|
285
|
+
if (params.udtTypeScriptHash !== undefined && !isUdtChannel)
|
|
286
|
+
continue;
|
|
287
|
+
if (params.udtTypeScriptHash === undefined && isUdtChannel)
|
|
288
|
+
continue;
|
|
289
|
+
const remoteBalance = parseHexAmount(ch.remote_balance);
|
|
290
|
+
const inflightInbound = parseHexAmount(ch.received_tlc_balance);
|
|
291
|
+
const usable = remoteBalance > inflightInbound
|
|
292
|
+
? remoteBalance - inflightInbound
|
|
293
|
+
: 0n;
|
|
294
|
+
const entry = {
|
|
295
|
+
channelId: ch.channel_id,
|
|
296
|
+
pubkey: ch.pubkey,
|
|
297
|
+
usableInbound: usable,
|
|
298
|
+
isEnabled: ch.enabled,
|
|
299
|
+
};
|
|
300
|
+
breakdown.push(entry);
|
|
301
|
+
if (!ch.enabled) {
|
|
302
|
+
issues.push(`Channel ${ch.channel_id.slice(0, 14)}… is ChannelReady but disabled for forwarding`);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
total += usable;
|
|
306
|
+
}
|
|
307
|
+
if (total < targetAmount) {
|
|
308
|
+
const shortfall = targetAmount - total;
|
|
309
|
+
issues.push(`Total usable inbound: ${total} shannon. Shortfall: ${shortfall} shannon. ` +
|
|
310
|
+
`Ask a peer to push liquidity to your side, or open a new channel.`);
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
canReceive: total >= targetAmount,
|
|
314
|
+
totalInboundCapacity: total,
|
|
315
|
+
activeChannelCount: breakdown.filter((c) => c.isEnabled).length,
|
|
316
|
+
channelBreakdown: breakdown,
|
|
317
|
+
issues,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Performs a live liquidity probe against a real destination pubkey.
|
|
322
|
+
*
|
|
323
|
+
* Sends a real HTLC using a randomly generated, never-revealed preimage.
|
|
324
|
+
* Funds cannot be lost: since the preimage is never shared, no node along
|
|
325
|
+
* the route -- including the destination -- can ever claim the payment.
|
|
326
|
+
*
|
|
327
|
+
* Terminal outcomes:
|
|
328
|
+
* - Destination returns IncorrectOrUnknownPaymentDetails: the entire
|
|
329
|
+
* route had enough live liquidity right now to carry this exact
|
|
330
|
+
* amount. This is a genuine empirical signal, not a static estimate.
|
|
331
|
+
* - Any other failure (e.g. TemporaryChannelFailure): a specific hop
|
|
332
|
+
* lacks liquidity or is unreachable. Parsed into a typed FiberError.
|
|
333
|
+
*
|
|
334
|
+
* This is slower and costs a brief HTLC lock on every hop versus canPay(),
|
|
335
|
+
* so use canPay() as the fast default and probePay() when you need
|
|
336
|
+
* ground-truth confidence immediately before a real payment.
|
|
337
|
+
*/
|
|
338
|
+
async probePay(params) {
|
|
339
|
+
const start = Date.now();
|
|
340
|
+
const { paymentHash } = await generateFakePaymentHash();
|
|
341
|
+
const timeoutMs = (params.timeoutSeconds ?? 15) * 1000;
|
|
342
|
+
try {
|
|
343
|
+
await this.client.sendPayment({
|
|
344
|
+
target_pubkey: params.targetPubkey,
|
|
345
|
+
amount: params.amount,
|
|
346
|
+
payment_hash: paymentHash,
|
|
347
|
+
keysend: false,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
352
|
+
return { isViable: false, terminalError: raw, error: FiberError.parse(raw), latencyMs: Date.now() - start };
|
|
353
|
+
}
|
|
354
|
+
// Poll for the terminal state. The probe self-resolves quickly in
|
|
355
|
+
// practice (observed ~130ms against live testnet nodes in this project)
|
|
356
|
+
// because the fake hash is rejected as soon as the HTLC reaches the
|
|
357
|
+
// destination -- there is no real invoice to wait on.
|
|
358
|
+
let intervalMs = 200;
|
|
359
|
+
while (Date.now() - start < timeoutMs) {
|
|
360
|
+
try {
|
|
361
|
+
const payment = await this.client.getPayment(paymentHash);
|
|
362
|
+
if (payment.status === 'Success') {
|
|
363
|
+
// Should not happen with a fake hash, but handle it safely.
|
|
364
|
+
return { isViable: true, latencyMs: Date.now() - start };
|
|
365
|
+
}
|
|
366
|
+
if (payment.status === 'Failed') {
|
|
367
|
+
const raw = payment.failed_error ?? '';
|
|
368
|
+
if (raw.includes('IncorrectOrUnknownPaymentDetails')) {
|
|
369
|
+
return { isViable: true, terminalError: raw, latencyMs: Date.now() - start };
|
|
370
|
+
}
|
|
371
|
+
return { isViable: false, terminalError: raw, error: FiberError.parse(raw), latencyMs: Date.now() - start };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
// Payment session not yet queryable -- keep polling until timeout.
|
|
376
|
+
}
|
|
377
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
378
|
+
intervalMs = Math.min(intervalMs * 1.5, 1500);
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
isViable: false,
|
|
382
|
+
terminalError: 'Probe timed out before resolving',
|
|
383
|
+
error: FiberError.parse('payment_timeout'),
|
|
384
|
+
latencyMs: Date.now() - start,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checker.js","sourceRoot":"","sources":["../../src/payment/checker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FiberEventEmitter — event-driven payment and invoice lifecycle for Fiber Network.
|
|
3
|
+
*
|
|
4
|
+
* The Fiber RPC does not expose a push-based subscription interface over the
|
|
5
|
+
* standard JSON-RPC port. This module bridges that gap with per-item adaptive
|
|
6
|
+
* polling: each watched payment, invoice, or channel gets its own backoff
|
|
7
|
+
* schedule so recently-started items are checked frequently while long-running
|
|
8
|
+
* ones are polled progressively less often.
|
|
9
|
+
*
|
|
10
|
+
* This is architecturally cleaner than a single global polling loop because:
|
|
11
|
+
* - Items at different lifecycle stages don't share a tick
|
|
12
|
+
* - Backoff is independent per item — a stale payment doesn't slow invoice checks
|
|
13
|
+
* - Callers receive a cancel function, giving them explicit lifecycle control
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const emitter = new FiberEventEmitter(client)
|
|
18
|
+
*
|
|
19
|
+
* // Watch a payment until it settles
|
|
20
|
+
* const cancel = emitter.watchPayment('0xabc...', {
|
|
21
|
+
* onSettled: (payment) => console.log('Payment settled:', payment.status),
|
|
22
|
+
* onFailed: (err) => console.error('Payment failed:', err.suggestion),
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* // Watch an invoice until it's paid
|
|
26
|
+
* emitter.watchInvoice('0xdef...', {
|
|
27
|
+
* onPaid: (invoice) => console.log('Paid!', invoice.invoice_address),
|
|
28
|
+
* onExpired: (invoice) => console.warn('Invoice expired'),
|
|
29
|
+
* })
|
|
30
|
+
*
|
|
31
|
+
* // Clean up everything at once
|
|
32
|
+
* emitter.destroy()
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
import type { FiberClient } from '../client/index.js';
|
|
36
|
+
import type { Payment, InvoiceResult, Channel } from '../client/types.js';
|
|
37
|
+
import { FiberError } from '../client/errors.js';
|
|
38
|
+
/**
|
|
39
|
+
* Backoff profile controlling how poll intervals grow over time.
|
|
40
|
+
* All durations are in milliseconds.
|
|
41
|
+
*/
|
|
42
|
+
export interface BackoffProfile {
|
|
43
|
+
/** Initial polling interval. Default: 500ms */
|
|
44
|
+
initialMs: number;
|
|
45
|
+
/** Multiplier applied after each poll. Default: 1.5 */
|
|
46
|
+
multiplier: number;
|
|
47
|
+
/** Maximum polling interval. Default: 10_000ms (10s) */
|
|
48
|
+
maxMs: number;
|
|
49
|
+
/** Maximum number of poll attempts before giving up. Default: 60 */
|
|
50
|
+
maxAttempts: number;
|
|
51
|
+
}
|
|
52
|
+
export interface WatchPaymentOptions {
|
|
53
|
+
/** Called when the payment reaches Success or Failed status. */
|
|
54
|
+
onSettled?: (payment: Payment) => void;
|
|
55
|
+
/** Called when the payment fails. Receives a structured FiberError. */
|
|
56
|
+
onFailed?: (error: FiberError, payment: Payment) => void;
|
|
57
|
+
/** Called on each poll while the payment is still Inflight. */
|
|
58
|
+
onProgress?: (payment: Payment, attempt: number) => void;
|
|
59
|
+
/** Called when maxAttempts is reached without a terminal status. */
|
|
60
|
+
onTimeout?: (lastPayment: Payment | null) => void;
|
|
61
|
+
backoff?: Partial<BackoffProfile>;
|
|
62
|
+
}
|
|
63
|
+
export interface WatchInvoiceOptions {
|
|
64
|
+
/** Called when the invoice status becomes Paid. */
|
|
65
|
+
onPaid?: (invoice: InvoiceResult) => void;
|
|
66
|
+
/** Called when the invoice status becomes Expired or Cancelled. */
|
|
67
|
+
onExpired?: (invoice: InvoiceResult) => void;
|
|
68
|
+
/** Called on each poll while the invoice is still Open. */
|
|
69
|
+
onProgress?: (invoice: InvoiceResult, attempt: number) => void;
|
|
70
|
+
/** Called when maxAttempts is reached without a terminal status. */
|
|
71
|
+
onTimeout?: (lastInvoice: InvoiceResult | null) => void;
|
|
72
|
+
backoff?: Partial<BackoffProfile>;
|
|
73
|
+
}
|
|
74
|
+
export interface WatchChannelOptions {
|
|
75
|
+
/** Called when the channel reaches ChannelReady state. */
|
|
76
|
+
onReady?: (channel: Channel) => void;
|
|
77
|
+
/** Called when the channel reaches Closed state. */
|
|
78
|
+
onClosed?: (channel: Channel) => void;
|
|
79
|
+
/** Called on each poll while the channel is still opening. */
|
|
80
|
+
onProgress?: (channel: Channel, attempt: number) => void;
|
|
81
|
+
/** Called when maxAttempts is reached without a terminal state. */
|
|
82
|
+
onTimeout?: (lastChannel: Channel | null) => void;
|
|
83
|
+
backoff?: Partial<BackoffProfile>;
|
|
84
|
+
}
|
|
85
|
+
/** Function returned by all watch methods. Call it to cancel the watcher. */
|
|
86
|
+
export type CancelFn = () => void;
|
|
87
|
+
export declare class FiberEventEmitter {
|
|
88
|
+
private readonly client;
|
|
89
|
+
private readonly watchers;
|
|
90
|
+
private watcherCount;
|
|
91
|
+
constructor(client: FiberClient);
|
|
92
|
+
/**
|
|
93
|
+
* Polls get_payment until the payment reaches a terminal status (Success/Failed)
|
|
94
|
+
* or maxAttempts is exhausted.
|
|
95
|
+
*
|
|
96
|
+
* @param paymentHash - The payment hash to watch
|
|
97
|
+
* @param options - Callbacks and optional backoff overrides
|
|
98
|
+
* @returns A cancel function — call it to stop polling immediately
|
|
99
|
+
*/
|
|
100
|
+
watchPayment(paymentHash: string, options?: WatchPaymentOptions): CancelFn;
|
|
101
|
+
/**
|
|
102
|
+
* Polls get_invoice until the invoice is Paid, Expired, or Cancelled,
|
|
103
|
+
* or maxAttempts is exhausted.
|
|
104
|
+
*
|
|
105
|
+
* @param paymentHash - The payment hash identifying the invoice to watch
|
|
106
|
+
* @param options - Callbacks and optional backoff overrides
|
|
107
|
+
* @returns A cancel function
|
|
108
|
+
*/
|
|
109
|
+
watchInvoice(paymentHash: string, options?: WatchInvoiceOptions): CancelFn;
|
|
110
|
+
/**
|
|
111
|
+
* Polls list_channels filtered to a specific channel_id until the channel
|
|
112
|
+
* reaches ChannelReady or Closed, or maxAttempts is exhausted.
|
|
113
|
+
*
|
|
114
|
+
* Useful for giving users feedback during the channel-opening flow without
|
|
115
|
+
* requiring them to poll manually.
|
|
116
|
+
*
|
|
117
|
+
* @param channelId - The channel_id to watch
|
|
118
|
+
* @param options - Callbacks and optional backoff overrides
|
|
119
|
+
* @returns A cancel function
|
|
120
|
+
*/
|
|
121
|
+
watchChannel(channelId: string, options?: WatchChannelOptions): CancelFn;
|
|
122
|
+
/**
|
|
123
|
+
* Returns the number of currently active watchers.
|
|
124
|
+
* Useful for debugging and testing.
|
|
125
|
+
*/
|
|
126
|
+
get activeWatcherCount(): number;
|
|
127
|
+
/**
|
|
128
|
+
* Cancels all active watchers and clears all timers.
|
|
129
|
+
* Call this when tearing down the application or component.
|
|
130
|
+
*/
|
|
131
|
+
destroy(): void;
|
|
132
|
+
private cleanup;
|
|
133
|
+
private resolveProfile;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/payment/events.ts"],"names":[],"mappings":"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"}
|