@fiber-pay/runtime 0.1.0-rc.4 → 0.1.0-rc.6
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 +4 -4
- package/dist/index.d.ts +13 -2
- package/dist/index.js +111 -17
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -126,10 +126,10 @@ fiber-pay logs --source runtime --follow
|
|
|
126
126
|
|
|
127
127
|
When started from `fiber-pay node start` or `fiber-pay runtime start`, runtime/fnn logs are persisted to:
|
|
128
128
|
|
|
129
|
-
- `<data-dir>/logs
|
|
130
|
-
- `<data-dir>/logs
|
|
131
|
-
- `<data-dir>/logs
|
|
129
|
+
- `<data-dir>/logs/<YYYY-MM-DD>/fnn.stdout.log`
|
|
130
|
+
- `<data-dir>/logs/<YYYY-MM-DD>/fnn.stderr.log`
|
|
131
|
+
- `<data-dir>/logs/<YYYY-MM-DD>/runtime.alerts.jsonl`
|
|
132
132
|
|
|
133
|
-
`<data-dir>/runtime.meta.json` stores
|
|
133
|
+
`<data-dir>/runtime.meta.json` is written at startup and stores the log file paths for that startup day, along with `logsBaseDir`, so agents can read those files directly during troubleshooting. Because logs rotate daily at UTC midnight while `runtime.meta.json` is not rewritten, its stored per-file paths can become stale; for other days' logs, use `logsBaseDir` together with the appropriate `<YYYY-MM-DD>` directory (or the `fiber-pay logs --date/--list-dates` options).
|
|
134
134
|
|
|
135
135
|
You can view these files directly via CLI without `cat` using `fiber-pay logs` (alias: `fiber-pay log`).
|
package/dist/index.d.ts
CHANGED
|
@@ -88,7 +88,10 @@ interface ChannelJobAlertData {
|
|
|
88
88
|
idempotencyKey: string;
|
|
89
89
|
retryCount: number;
|
|
90
90
|
action?: string;
|
|
91
|
+
peerId?: string;
|
|
92
|
+
temporaryChannelId?: `0x${string}`;
|
|
91
93
|
channelId?: `0x${string}`;
|
|
94
|
+
fundingAmount?: string;
|
|
92
95
|
error?: string;
|
|
93
96
|
}
|
|
94
97
|
interface AlertBackend {
|
|
@@ -228,7 +231,12 @@ interface FileAlertConfig {
|
|
|
228
231
|
type: 'file';
|
|
229
232
|
path: string;
|
|
230
233
|
}
|
|
231
|
-
|
|
234
|
+
interface DailyFileAlertConfig {
|
|
235
|
+
type: 'daily-file';
|
|
236
|
+
baseLogsDir: string;
|
|
237
|
+
filename?: string;
|
|
238
|
+
}
|
|
239
|
+
type AlertBackendConfig = StdoutAlertConfig | WebhookAlertConfig | WebsocketAlertConfig | FileAlertConfig | DailyFileAlertConfig;
|
|
232
240
|
interface RuntimeConfig {
|
|
233
241
|
fiberRpcUrl: string;
|
|
234
242
|
channelPollIntervalMs: number;
|
|
@@ -305,6 +313,9 @@ declare class FiberMonitorService extends EventEmitter {
|
|
|
305
313
|
private extractPaymentHash;
|
|
306
314
|
private extractInvoiceHash;
|
|
307
315
|
private extractChannelId;
|
|
316
|
+
private extractChannelPeerId;
|
|
317
|
+
private extractTemporaryChannelId;
|
|
318
|
+
private extractChannelFundingAmount;
|
|
308
319
|
private normalizeHash;
|
|
309
320
|
}
|
|
310
321
|
|
|
@@ -658,4 +669,4 @@ declare class PaymentProofManager {
|
|
|
658
669
|
private ensureDirectory;
|
|
659
670
|
}
|
|
660
671
|
|
|
661
|
-
export { type Alert, type AlertBackend, type AlertBackendConfig, type AlertFilter, type AlertInput, type AlertPriority, type AlertType, type ChannelBalanceChangedData, type ChannelJob, type ChannelJobAction, type ChannelJobAlertData, type ChannelJobParams, type ChannelJobResult, type ChannelStateChangedData, type ClassifiedError, type ErrorCategory, FiberMonitorService, type FileAlertConfig, type InvoiceJob, type InvoiceJobAction, type InvoiceJobAlertData, type InvoiceJobParams, type InvoiceJobResult, type Job, type JobEvent, type JobEventType, type JobFilter, JobManager, type JobState, type JobType, MemoryStore, type PaymentJob, type PaymentJobAlertData, type PaymentJobParams, type PaymentJobResult, type PaymentProof, PaymentProofManager, type PaymentProofSummary, type PeerEventData, type PendingTlcChangedData, type RetryPolicy, type RpcHealthData, RpcMonitorProxy, type RuntimeConfig, type RuntimeConfigInput, type RuntimeJob, SqliteJobStore, type StdoutAlertConfig, TERMINAL_JOB_STATES, type TrackedInvoiceState, type TrackedPaymentState, type WebhookAlertConfig, type WebsocketAlertConfig, alertPriorityOrder, alertTypeValues, classifyRpcError, computeRetryDelay, createRuntimeConfig, defaultPaymentRetryPolicy, defaultRuntimeConfig, formatRuntimeAlert, isAlertPriority, isAlertType, parseListenAddress, paymentStateMachine, shouldRetry, startRuntimeService };
|
|
672
|
+
export { type Alert, type AlertBackend, type AlertBackendConfig, type AlertFilter, type AlertInput, type AlertPriority, type AlertType, type ChannelBalanceChangedData, type ChannelJob, type ChannelJobAction, type ChannelJobAlertData, type ChannelJobParams, type ChannelJobResult, type ChannelStateChangedData, type ClassifiedError, type DailyFileAlertConfig, type ErrorCategory, FiberMonitorService, type FileAlertConfig, type InvoiceJob, type InvoiceJobAction, type InvoiceJobAlertData, type InvoiceJobParams, type InvoiceJobResult, type Job, type JobEvent, type JobEventType, type JobFilter, JobManager, type JobState, type JobType, MemoryStore, type PaymentJob, type PaymentJobAlertData, type PaymentJobParams, type PaymentJobResult, type PaymentProof, PaymentProofManager, type PaymentProofSummary, type PeerEventData, type PendingTlcChangedData, type RetryPolicy, type RpcHealthData, RpcMonitorProxy, type RuntimeConfig, type RuntimeConfigInput, type RuntimeJob, SqliteJobStore, type StdoutAlertConfig, TERMINAL_JOB_STATES, type TrackedInvoiceState, type TrackedPaymentState, type WebhookAlertConfig, type WebsocketAlertConfig, alertPriorityOrder, alertTypeValues, classifyRpcError, computeRetryDelay, createRuntimeConfig, defaultPaymentRetryPolicy, defaultRuntimeConfig, formatRuntimeAlert, isAlertPriority, isAlertType, parseListenAddress, paymentStateMachine, shouldRetry, startRuntimeService };
|
package/dist/index.js
CHANGED
|
@@ -219,7 +219,7 @@ var AlertManager = class {
|
|
|
219
219
|
|
|
220
220
|
// src/alerts/backends/file-jsonl.ts
|
|
221
221
|
import { appendFileSync, mkdirSync } from "fs";
|
|
222
|
-
import { dirname } from "path";
|
|
222
|
+
import { dirname, join } from "path";
|
|
223
223
|
var JsonlFileAlertBackend = class {
|
|
224
224
|
path;
|
|
225
225
|
constructor(path) {
|
|
@@ -231,6 +231,27 @@ var JsonlFileAlertBackend = class {
|
|
|
231
231
|
`, "utf-8");
|
|
232
232
|
}
|
|
233
233
|
};
|
|
234
|
+
function todayDateString() {
|
|
235
|
+
const now = /* @__PURE__ */ new Date();
|
|
236
|
+
const y = now.getUTCFullYear();
|
|
237
|
+
const m = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
238
|
+
const d = String(now.getUTCDate()).padStart(2, "0");
|
|
239
|
+
return `${y}-${m}-${d}`;
|
|
240
|
+
}
|
|
241
|
+
var DailyJsonlFileAlertBackend = class {
|
|
242
|
+
baseLogsDir;
|
|
243
|
+
filename;
|
|
244
|
+
constructor(baseLogsDir, filename = "runtime.alerts.jsonl") {
|
|
245
|
+
this.baseLogsDir = baseLogsDir;
|
|
246
|
+
this.filename = filename;
|
|
247
|
+
}
|
|
248
|
+
async send(alert) {
|
|
249
|
+
const dateDir = join(this.baseLogsDir, todayDateString());
|
|
250
|
+
mkdirSync(dateDir, { recursive: true });
|
|
251
|
+
appendFileSync(join(dateDir, this.filename), `${JSON.stringify(alert)}
|
|
252
|
+
`, "utf-8");
|
|
253
|
+
}
|
|
254
|
+
};
|
|
234
255
|
|
|
235
256
|
// src/alerts/backends/stdout.ts
|
|
236
257
|
var StdoutAlertBackend = class {
|
|
@@ -953,7 +974,8 @@ async function* runChannelJob(job, rpc, policy, signal) {
|
|
|
953
974
|
}
|
|
954
975
|
});
|
|
955
976
|
yield current;
|
|
956
|
-
|
|
977
|
+
const waitForClosed = current.params.waitForClosed ?? Boolean(shutdownParams.force);
|
|
978
|
+
if (!waitForClosed) {
|
|
957
979
|
current = transitionJobState(current, channelStateMachine, "payment_success");
|
|
958
980
|
yield current;
|
|
959
981
|
return;
|
|
@@ -1379,6 +1401,19 @@ async function* runPaymentJob(job, rpc, policy, signal) {
|
|
|
1379
1401
|
yield current;
|
|
1380
1402
|
continue;
|
|
1381
1403
|
}
|
|
1404
|
+
if (current.params.sendPaymentParams.dry_run) {
|
|
1405
|
+
current = transitionJobState(current, paymentStateMachine, "payment_success", {
|
|
1406
|
+
patch: {
|
|
1407
|
+
result: {
|
|
1408
|
+
paymentHash: sendResult.payment_hash,
|
|
1409
|
+
status: "DryRunSuccess",
|
|
1410
|
+
fee: sendResult.fee
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
yield current;
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1382
1417
|
current = transitionJobState(current, paymentStateMachine, "payment_inflight");
|
|
1383
1418
|
if (paymentHash) {
|
|
1384
1419
|
current = {
|
|
@@ -2132,11 +2167,13 @@ var HealthMonitor = class extends BaseMonitor {
|
|
|
2132
2167
|
};
|
|
2133
2168
|
|
|
2134
2169
|
// src/monitors/tracker-utils.ts
|
|
2170
|
+
function isNotFoundError(error) {
|
|
2171
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2172
|
+
return /not found|does not exist|no such/i.test(message);
|
|
2173
|
+
}
|
|
2135
2174
|
function isExpectedTrackerError(error) {
|
|
2136
2175
|
const message = error instanceof Error ? error.message : String(error);
|
|
2137
|
-
return /
|
|
2138
|
-
message
|
|
2139
|
-
);
|
|
2176
|
+
return /temporarily unavailable|connection refused|timed out|timeout/i.test(message);
|
|
2140
2177
|
}
|
|
2141
2178
|
|
|
2142
2179
|
// src/monitors/invoice-tracker.ts
|
|
@@ -2208,6 +2245,21 @@ var InvoiceTracker = class extends BaseMonitor {
|
|
|
2208
2245
|
}
|
|
2209
2246
|
}
|
|
2210
2247
|
} catch (error) {
|
|
2248
|
+
if (isNotFoundError(error)) {
|
|
2249
|
+
this.store.updateTrackedInvoice(invoice.paymentHash, "Cancelled");
|
|
2250
|
+
await this.alerts.emit({
|
|
2251
|
+
type: "invoice_cancelled",
|
|
2252
|
+
priority: "medium",
|
|
2253
|
+
source: this.name,
|
|
2254
|
+
data: {
|
|
2255
|
+
paymentHash: invoice.paymentHash,
|
|
2256
|
+
previousStatus: invoice.status,
|
|
2257
|
+
currentStatus: "Cancelled",
|
|
2258
|
+
reason: "not_found"
|
|
2259
|
+
}
|
|
2260
|
+
});
|
|
2261
|
+
continue;
|
|
2262
|
+
}
|
|
2211
2263
|
if (isExpectedTrackerError(error)) {
|
|
2212
2264
|
continue;
|
|
2213
2265
|
}
|
|
@@ -2277,6 +2329,21 @@ var PaymentTracker = class extends BaseMonitor {
|
|
|
2277
2329
|
}
|
|
2278
2330
|
}
|
|
2279
2331
|
} catch (error) {
|
|
2332
|
+
if (isNotFoundError(error)) {
|
|
2333
|
+
this.store.updateTrackedPayment(payment.paymentHash, "Failed");
|
|
2334
|
+
await this.alerts.emit({
|
|
2335
|
+
type: "outgoing_payment_failed",
|
|
2336
|
+
priority: "high",
|
|
2337
|
+
source: this.name,
|
|
2338
|
+
data: {
|
|
2339
|
+
paymentHash: payment.paymentHash,
|
|
2340
|
+
previousStatus: payment.status,
|
|
2341
|
+
currentStatus: "Failed",
|
|
2342
|
+
reason: "not_found"
|
|
2343
|
+
}
|
|
2344
|
+
});
|
|
2345
|
+
continue;
|
|
2346
|
+
}
|
|
2280
2347
|
if (isExpectedTrackerError(error)) {
|
|
2281
2348
|
continue;
|
|
2282
2349
|
}
|
|
@@ -2515,7 +2582,8 @@ function collectJsonRpcMethods(requestBody) {
|
|
|
2515
2582
|
const methods = /* @__PURE__ */ new Map();
|
|
2516
2583
|
for (const item of normalizeJsonRpcRequest(requestBody)) {
|
|
2517
2584
|
if (item.id !== void 0 && typeof item.method === "string") {
|
|
2518
|
-
|
|
2585
|
+
const dryRun = isDryRunRequest(item);
|
|
2586
|
+
methods.set(item.id, { method: item.method, dryRun });
|
|
2519
2587
|
}
|
|
2520
2588
|
}
|
|
2521
2589
|
return methods;
|
|
@@ -2526,17 +2594,17 @@ function captureTrackedHashes(methodById, responseBody, handlers) {
|
|
|
2526
2594
|
if (message.error || message.id === void 0) {
|
|
2527
2595
|
continue;
|
|
2528
2596
|
}
|
|
2529
|
-
const
|
|
2530
|
-
if (!
|
|
2597
|
+
const meta = methodById.get(message.id);
|
|
2598
|
+
if (!meta) {
|
|
2531
2599
|
continue;
|
|
2532
2600
|
}
|
|
2533
|
-
if (method === "new_invoice") {
|
|
2601
|
+
if (meta.method === "new_invoice") {
|
|
2534
2602
|
const paymentHash = extractInvoicePaymentHash(message.result);
|
|
2535
2603
|
if (paymentHash) {
|
|
2536
2604
|
handlers.onInvoiceTracked(paymentHash);
|
|
2537
2605
|
}
|
|
2538
2606
|
}
|
|
2539
|
-
if (method === "send_payment") {
|
|
2607
|
+
if (meta.method === "send_payment" && !meta.dryRun) {
|
|
2540
2608
|
const paymentHash = extractPaymentHash(message.result);
|
|
2541
2609
|
if (paymentHash) {
|
|
2542
2610
|
handlers.onPaymentTracked(paymentHash);
|
|
@@ -2588,6 +2656,13 @@ function extractPaymentHash(result) {
|
|
|
2588
2656
|
}
|
|
2589
2657
|
return typeof result.payment_hash === "string" ? result.payment_hash : void 0;
|
|
2590
2658
|
}
|
|
2659
|
+
function isDryRunRequest(message) {
|
|
2660
|
+
if (!Array.isArray(message.params) || message.params.length === 0) {
|
|
2661
|
+
return false;
|
|
2662
|
+
}
|
|
2663
|
+
const firstParam = message.params[0];
|
|
2664
|
+
return isObject(firstParam) && firstParam.dry_run === true;
|
|
2665
|
+
}
|
|
2591
2666
|
|
|
2592
2667
|
// src/proxy/monitor-routes.ts
|
|
2593
2668
|
function handleMonitorEndpoint(req, res, deps) {
|
|
@@ -3352,6 +3427,8 @@ var FiberMonitorService = class extends EventEmitter2 {
|
|
|
3352
3427
|
this.alerts.onEmit((alert) => {
|
|
3353
3428
|
this.emit("alert", alert);
|
|
3354
3429
|
});
|
|
3430
|
+
const jobManager = this.jobManager;
|
|
3431
|
+
const jobStore = this.jobStore;
|
|
3355
3432
|
this.proxy = new RpcMonitorProxy(
|
|
3356
3433
|
{
|
|
3357
3434
|
listen: this.config.proxy.listen,
|
|
@@ -3368,13 +3445,13 @@ var FiberMonitorService = class extends EventEmitter2 {
|
|
|
3368
3445
|
listTrackedPayments: () => this.store.listTrackedPayments(),
|
|
3369
3446
|
listAlerts: (filters) => this.store.listAlerts(filters),
|
|
3370
3447
|
getStatus: () => this.getStatus(),
|
|
3371
|
-
createPaymentJob:
|
|
3372
|
-
createInvoiceJob:
|
|
3373
|
-
createChannelJob:
|
|
3374
|
-
getJob:
|
|
3375
|
-
listJobs:
|
|
3376
|
-
cancelJob:
|
|
3377
|
-
listJobEvents:
|
|
3448
|
+
createPaymentJob: jobManager ? (params, options) => jobManager.ensurePayment(params, options) : void 0,
|
|
3449
|
+
createInvoiceJob: jobManager ? (params, options) => jobManager.manageInvoice(params, options) : void 0,
|
|
3450
|
+
createChannelJob: jobManager ? (params, options) => jobManager.manageChannel(params, options) : void 0,
|
|
3451
|
+
getJob: jobManager ? (id) => jobManager.getJob(id) : void 0,
|
|
3452
|
+
listJobs: jobManager ? (filter) => jobManager.listJobs(filter) : void 0,
|
|
3453
|
+
cancelJob: jobManager ? (id) => jobManager.cancelJob(id) : void 0,
|
|
3454
|
+
listJobEvents: jobStore ? (jobId) => jobStore.listJobEvents(jobId) : void 0
|
|
3378
3455
|
}
|
|
3379
3456
|
);
|
|
3380
3457
|
}
|
|
@@ -3449,6 +3526,9 @@ var FiberMonitorService = class extends EventEmitter2 {
|
|
|
3449
3526
|
if (alertConfig.type === "file") {
|
|
3450
3527
|
return new JsonlFileAlertBackend(alertConfig.path);
|
|
3451
3528
|
}
|
|
3529
|
+
if (alertConfig.type === "daily-file") {
|
|
3530
|
+
return new DailyJsonlFileAlertBackend(alertConfig.baseLogsDir, alertConfig.filename);
|
|
3531
|
+
}
|
|
3452
3532
|
const [host, portText] = alertConfig.listen.split(":");
|
|
3453
3533
|
return new WebsocketAlertBackend({
|
|
3454
3534
|
host,
|
|
@@ -3522,7 +3602,10 @@ var FiberMonitorService = class extends EventEmitter2 {
|
|
|
3522
3602
|
idempotencyKey: channelJob.idempotencyKey,
|
|
3523
3603
|
retryCount: channelJob.retryCount,
|
|
3524
3604
|
action: channelJob.params.action,
|
|
3605
|
+
peerId: this.extractChannelPeerId(channelJob),
|
|
3606
|
+
temporaryChannelId: this.extractTemporaryChannelId(channelJob),
|
|
3525
3607
|
channelId: this.extractChannelId(channelJob),
|
|
3608
|
+
fundingAmount: this.extractChannelFundingAmount(channelJob),
|
|
3526
3609
|
error
|
|
3527
3610
|
};
|
|
3528
3611
|
}
|
|
@@ -3554,6 +3637,17 @@ var FiberMonitorService = class extends EventEmitter2 {
|
|
|
3554
3637
|
job.result?.channelId ?? job.result?.acceptedChannelId ?? job.params.channelId ?? job.params.shutdownChannelParams?.channel_id
|
|
3555
3638
|
);
|
|
3556
3639
|
}
|
|
3640
|
+
extractChannelPeerId(job) {
|
|
3641
|
+
return job.params.peerId ?? job.params.openChannelParams?.peer_id;
|
|
3642
|
+
}
|
|
3643
|
+
extractTemporaryChannelId(job) {
|
|
3644
|
+
return this.normalizeHash(
|
|
3645
|
+
job.result?.temporaryChannelId ?? job.params.acceptChannelParams?.temporary_channel_id
|
|
3646
|
+
);
|
|
3647
|
+
}
|
|
3648
|
+
extractChannelFundingAmount(job) {
|
|
3649
|
+
return job.params.openChannelParams?.funding_amount;
|
|
3650
|
+
}
|
|
3557
3651
|
normalizeHash(value) {
|
|
3558
3652
|
if (!value || !value.startsWith("0x")) {
|
|
3559
3653
|
return void 0;
|