@waiaas/daemon 2.11.0-rc.21 → 2.11.0-rc.23
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 +5 -5
- package/dist/api/routes/admin-notifications.d.ts.map +1 -1
- package/dist/api/routes/admin-notifications.js +2 -15
- package/dist/api/routes/admin-notifications.js.map +1 -1
- package/dist/api/routes/openapi-schemas.d.ts +29 -7
- package/dist/api/routes/openapi-schemas.d.ts.map +1 -1
- package/dist/api/routes/openapi-schemas.js +7 -5
- package/dist/api/routes/openapi-schemas.js.map +1 -1
- package/dist/api/routes/wallet-apps.d.ts.map +1 -1
- package/dist/api/routes/wallet-apps.js +20 -13
- package/dist/api/routes/wallet-apps.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/infrastructure/config/loader.d.ts +0 -10
- package/dist/infrastructure/config/loader.d.ts.map +1 -1
- package/dist/infrastructure/config/loader.js +0 -2
- package/dist/infrastructure/config/loader.js.map +1 -1
- package/dist/infrastructure/database/migrations/v51-v59.d.ts +2 -1
- package/dist/infrastructure/database/migrations/v51-v59.d.ts.map +1 -1
- package/dist/infrastructure/database/migrations/v51-v59.js +88 -2
- package/dist/infrastructure/database/migrations/v51-v59.js.map +1 -1
- package/dist/infrastructure/database/schema-ddl.d.ts +1 -1
- package/dist/infrastructure/database/schema-ddl.d.ts.map +1 -1
- package/dist/infrastructure/database/schema-ddl.js +4 -3
- package/dist/infrastructure/database/schema-ddl.js.map +1 -1
- package/dist/infrastructure/database/schema.d.ts +19 -0
- package/dist/infrastructure/database/schema.d.ts.map +1 -1
- package/dist/infrastructure/database/schema.js +1 -0
- package/dist/infrastructure/database/schema.js.map +1 -1
- package/dist/infrastructure/settings/hot-reload.d.ts.map +1 -1
- package/dist/infrastructure/settings/hot-reload.js +0 -2
- package/dist/infrastructure/settings/hot-reload.js.map +1 -1
- package/dist/infrastructure/settings/setting-keys.d.ts.map +1 -1
- package/dist/infrastructure/settings/setting-keys.js +1 -5
- package/dist/infrastructure/settings/setting-keys.js.map +1 -1
- package/dist/infrastructure/telegram/telegram-bot-service.d.ts.map +1 -1
- package/dist/infrastructure/telegram/telegram-bot-service.js +3 -2
- package/dist/infrastructure/telegram/telegram-bot-service.js.map +1 -1
- package/dist/lifecycle/daemon-startup.js +3 -3
- package/dist/lifecycle/daemon-startup.js.map +1 -1
- package/dist/notifications/index.d.ts +0 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +0 -1
- package/dist/notifications/index.js.map +1 -1
- package/dist/services/signing-sdk/approval-channel-router.d.ts +7 -7
- package/dist/services/signing-sdk/approval-channel-router.d.ts.map +1 -1
- package/dist/services/signing-sdk/approval-channel-router.js +13 -13
- package/dist/services/signing-sdk/approval-channel-router.js.map +1 -1
- package/dist/services/signing-sdk/channels/index.d.ts +2 -2
- package/dist/services/signing-sdk/channels/index.d.ts.map +1 -1
- package/dist/services/signing-sdk/channels/index.js +1 -1
- package/dist/services/signing-sdk/channels/index.js.map +1 -1
- package/dist/services/signing-sdk/channels/push-relay-signing-channel.d.ts +59 -0
- package/dist/services/signing-sdk/channels/push-relay-signing-channel.d.ts.map +1 -0
- package/dist/services/signing-sdk/channels/push-relay-signing-channel.js +190 -0
- package/dist/services/signing-sdk/channels/push-relay-signing-channel.js.map +1 -0
- package/dist/services/signing-sdk/channels/telegram-signing-channel.d.ts +1 -1
- package/dist/services/signing-sdk/channels/telegram-signing-channel.js +1 -1
- package/dist/services/signing-sdk/channels/wallet-notification-channel.d.ts +6 -7
- package/dist/services/signing-sdk/channels/wallet-notification-channel.d.ts.map +1 -1
- package/dist/services/signing-sdk/channels/wallet-notification-channel.js +38 -55
- package/dist/services/signing-sdk/channels/wallet-notification-channel.js.map +1 -1
- package/dist/services/signing-sdk/index.d.ts +3 -3
- package/dist/services/signing-sdk/index.d.ts.map +1 -1
- package/dist/services/signing-sdk/index.js +2 -2
- package/dist/services/signing-sdk/index.js.map +1 -1
- package/dist/services/signing-sdk/preset-auto-setup.js +2 -2
- package/dist/services/signing-sdk/preset-auto-setup.js.map +1 -1
- package/dist/services/signing-sdk/sign-request-builder.d.ts +2 -2
- package/dist/services/signing-sdk/sign-request-builder.d.ts.map +1 -1
- package/dist/services/signing-sdk/sign-request-builder.js +17 -25
- package/dist/services/signing-sdk/sign-request-builder.js.map +1 -1
- package/dist/services/signing-sdk/wallet-app-service.d.ts +4 -0
- package/dist/services/signing-sdk/wallet-app-service.d.ts.map +1 -1
- package/dist/services/signing-sdk/wallet-app-service.js +12 -5
- package/dist/services/signing-sdk/wallet-app-service.js.map +1 -1
- package/package.json +5 -5
- package/public/admin/assets/index-CpFF2lCo.js +3 -0
- package/public/admin/index.html +1 -1
- package/dist/notifications/channels/ntfy.d.ts +0 -13
- package/dist/notifications/channels/ntfy.d.ts.map +0 -1
- package/dist/notifications/channels/ntfy.js +0 -75
- package/dist/notifications/channels/ntfy.js.map +0 -1
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.d.ts +0 -66
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.d.ts.map +0 -1
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.js +0 -270
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.js.map +0 -1
- package/public/admin/assets/index-CdYTlzvu.js +0 -3
package/public/admin/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta name="theme-color" content="#0c0c0c" />
|
|
7
7
|
<meta name="color-scheme" content="dark" />
|
|
8
8
|
<title>WAIaaS Admin</title>
|
|
9
|
-
<script type="module" crossorigin src="/admin/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/admin/assets/index-CpFF2lCo.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/admin/assets/index-CTHU1J8K.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { INotificationChannel, NotificationPayload } from '@waiaas/core';
|
|
2
|
-
export declare class NtfyChannel implements INotificationChannel {
|
|
3
|
-
readonly name = "ntfy";
|
|
4
|
-
private server;
|
|
5
|
-
private topic;
|
|
6
|
-
initialize(config: Record<string, unknown>): Promise<void>;
|
|
7
|
-
send(payload: NotificationPayload): Promise<void>;
|
|
8
|
-
/** Map event type to ntfy priority (1-5, where 5=max). */
|
|
9
|
-
private mapPriority;
|
|
10
|
-
/** Map event type to ntfy tags (emoji shortcodes). */
|
|
11
|
-
private mapTags;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=ntfy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy.d.ts","sourceRoot":"","sources":["../../../src/notifications/channels/ntfy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAG9E,qBAAa,WAAY,YAAW,oBAAoB;IACtD,QAAQ,CAAC,IAAI,UAAU;IACvB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAAM;IAEb,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1D,IAAI,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCvD,0DAA0D;IAC1D,OAAO,CAAC,WAAW;IAOnB,sDAAsD;IACtD,OAAO,CAAC,OAAO;CAShB"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { abbreviateId, abbreviateAddress } from './format-utils.js';
|
|
2
|
-
export class NtfyChannel {
|
|
3
|
-
name = 'ntfy';
|
|
4
|
-
server = 'https://ntfy.sh';
|
|
5
|
-
topic = '';
|
|
6
|
-
async initialize(config) {
|
|
7
|
-
this.server = String(config.ntfy_server ?? 'https://ntfy.sh');
|
|
8
|
-
this.topic = String(config.ntfy_topic ?? '');
|
|
9
|
-
if (!this.topic) {
|
|
10
|
-
throw new Error('NtfyChannel: ntfy_topic required');
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
async send(payload) {
|
|
14
|
-
// ntfy.sh: POST plain text with headers for title, priority, tags
|
|
15
|
-
const priority = this.mapPriority(payload.eventType);
|
|
16
|
-
const tags = this.mapTags(payload.eventType);
|
|
17
|
-
const url = `${this.server}/${this.topic}`;
|
|
18
|
-
const bodyParts = [payload.body];
|
|
19
|
-
if (payload.explorerUrl) {
|
|
20
|
-
bodyParts.push(`\nExplorer: ${payload.explorerUrl}`);
|
|
21
|
-
}
|
|
22
|
-
if (payload.walletId) {
|
|
23
|
-
const name = payload.walletName || payload.walletId;
|
|
24
|
-
const idAbbr = abbreviateId(payload.walletId);
|
|
25
|
-
bodyParts.push(`\n${name} (${idAbbr})`);
|
|
26
|
-
if (payload.walletAddress) {
|
|
27
|
-
const addrAbbr = abbreviateAddress(payload.walletAddress);
|
|
28
|
-
const net = payload.network ?? '';
|
|
29
|
-
bodyParts.push(net ? `${addrAbbr} · ${net}` : addrAbbr);
|
|
30
|
-
}
|
|
31
|
-
bodyParts.push(`Time: ${new Date(payload.timestamp * 1000).toISOString()}`);
|
|
32
|
-
}
|
|
33
|
-
const response = await fetch(url, {
|
|
34
|
-
method: 'POST',
|
|
35
|
-
headers: {
|
|
36
|
-
'Title': `[WAIaaS] ${payload.title}`,
|
|
37
|
-
'Priority': String(priority),
|
|
38
|
-
'Tags': tags,
|
|
39
|
-
},
|
|
40
|
-
body: bodyParts.join(''),
|
|
41
|
-
signal: AbortSignal.timeout(10_000),
|
|
42
|
-
});
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
const body = await response.text();
|
|
45
|
-
throw new Error(`NtfyChannel: ${response.status} ${body}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/** Map event type to ntfy priority (1-5, where 5=max). */
|
|
49
|
-
mapPriority(eventType) {
|
|
50
|
-
if (eventType.includes('KILL_SWITCH') || eventType.includes('AUTO_STOP'))
|
|
51
|
-
return 5; // urgent
|
|
52
|
-
if (eventType.includes('SUSPENDED') || eventType.includes('FAILED') || eventType.includes('VIOLATION'))
|
|
53
|
-
return 4; // high
|
|
54
|
-
if (eventType.includes('APPROVAL') || eventType.includes('EXPIR'))
|
|
55
|
-
return 3; // default
|
|
56
|
-
return 2; // low for informational
|
|
57
|
-
}
|
|
58
|
-
/** Map event type to ntfy tags (emoji shortcodes). */
|
|
59
|
-
mapTags(eventType) {
|
|
60
|
-
if (eventType.includes('KILL_SWITCH') || eventType.includes('AUTO_STOP'))
|
|
61
|
-
return 'rotating_light,warning';
|
|
62
|
-
if (eventType.includes('FAILED') || eventType.includes('VIOLATION'))
|
|
63
|
-
return 'x,warning';
|
|
64
|
-
if (eventType.includes('CONFIRMED') || eventType.includes('RECOVERED'))
|
|
65
|
-
return 'white_check_mark';
|
|
66
|
-
if (eventType.includes('APPROVAL'))
|
|
67
|
-
return 'bell';
|
|
68
|
-
if (eventType.includes('SESSION'))
|
|
69
|
-
return 'key';
|
|
70
|
-
if (eventType.includes('OWNER'))
|
|
71
|
-
return 'bust_in_silhouette';
|
|
72
|
-
return 'speech_balloon';
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
//# sourceMappingURL=ntfy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy.js","sourceRoot":"","sources":["../../../src/notifications/channels/ntfy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NtfySigningChannel -- publishes SignRequests to ntfy and subscribes to responses via SSE.
|
|
3
|
-
*
|
|
4
|
-
* When a PENDING_APPROVAL transaction triggers a SignRequest:
|
|
5
|
-
* 1. Publishes the request to the wallet's ntfy request topic (JSON format per doc 73 Section 7.2)
|
|
6
|
-
* 2. Subscribes to the response topic via SSE
|
|
7
|
-
* 3. Parses incoming SignResponse messages (base64url in ntfy message field)
|
|
8
|
-
* 4. Delegates to SignResponseHandler for approval/rejection processing
|
|
9
|
-
*
|
|
10
|
-
* @see internal/design/73-signing-protocol-v1.md (Section 7.2, 7.3)
|
|
11
|
-
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
12
|
-
*/
|
|
13
|
-
import type { SignRequestBuilder, BuildRequestParams } from '../sign-request-builder.js';
|
|
14
|
-
import type { SignResponseHandler } from '../sign-response-handler.js';
|
|
15
|
-
import type { SettingsService } from '../../../infrastructure/settings/settings-service.js';
|
|
16
|
-
export interface NtfySigningChannelOpts {
|
|
17
|
-
signRequestBuilder: SignRequestBuilder;
|
|
18
|
-
signResponseHandler: SignResponseHandler;
|
|
19
|
-
settingsService: SettingsService;
|
|
20
|
-
}
|
|
21
|
-
export interface SendRequestParams extends BuildRequestParams {
|
|
22
|
-
walletId: string;
|
|
23
|
-
}
|
|
24
|
-
export interface SendRequestResult {
|
|
25
|
-
requestId: string;
|
|
26
|
-
requestTopic: string;
|
|
27
|
-
responseTopic: string;
|
|
28
|
-
}
|
|
29
|
-
export declare class NtfySigningChannel {
|
|
30
|
-
private readonly signRequestBuilder;
|
|
31
|
-
private readonly signResponseHandler;
|
|
32
|
-
private readonly settings;
|
|
33
|
-
/** Active SSE subscriptions: requestId -> AbortController */
|
|
34
|
-
private readonly activeSubscriptions;
|
|
35
|
-
constructor(opts: NtfySigningChannelOpts);
|
|
36
|
-
/**
|
|
37
|
-
* Publish a SignRequest to ntfy request topic and subscribe to response topic.
|
|
38
|
-
*
|
|
39
|
-
* @param params - Transaction metadata + walletId for topic routing
|
|
40
|
-
* @returns requestId, requestTopic, responseTopic
|
|
41
|
-
*/
|
|
42
|
-
sendRequest(params: SendRequestParams): Promise<SendRequestResult>;
|
|
43
|
-
/**
|
|
44
|
-
* Cancel a specific SSE subscription by requestId.
|
|
45
|
-
*/
|
|
46
|
-
cancelSubscription(requestId: string): void;
|
|
47
|
-
/**
|
|
48
|
-
* Shutdown all active SSE subscriptions (daemon shutdown).
|
|
49
|
-
*/
|
|
50
|
-
shutdown(): void;
|
|
51
|
-
private getNtfyServer;
|
|
52
|
-
private publishToNtfy;
|
|
53
|
-
private subscribeToResponseTopic;
|
|
54
|
-
private connectSse;
|
|
55
|
-
/**
|
|
56
|
-
* Parse an SSE stream into NtfyMessage objects.
|
|
57
|
-
*
|
|
58
|
-
* ntfy SSE format:
|
|
59
|
-
* event: message
|
|
60
|
-
* data: {"id":"...","time":...,"event":"message","topic":"...","message":"..."}
|
|
61
|
-
*
|
|
62
|
-
* We only care about `data:` lines containing JSON with a `message` field.
|
|
63
|
-
*/
|
|
64
|
-
private parseSseStream;
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=ntfy-signing-channel.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy-signing-channel.d.ts","sourceRoot":"","sources":["../../../../src/services/signing-sdk/channels/ntfy-signing-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sDAAsD,CAAC;AAe5F,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,eAAe,EAAE,eAAe,CAAC;CAClC;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAcD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAE3C,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsC;gBAE9D,IAAI,EAAE,sBAAsB;IAUxC;;;;;OAKG;IACG,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsCxE;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQ3C;;OAEG;IACH,QAAQ,IAAI,IAAI;IAWhB,OAAO,CAAC,aAAa;YAaP,aAAa;IA8C3B,OAAO,CAAC,wBAAwB;YAyBlB,UAAU;IAoFxB;;;;;;;;OAQG;YACY,cAAc;CAuC9B"}
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NtfySigningChannel -- publishes SignRequests to ntfy and subscribes to responses via SSE.
|
|
3
|
-
*
|
|
4
|
-
* When a PENDING_APPROVAL transaction triggers a SignRequest:
|
|
5
|
-
* 1. Publishes the request to the wallet's ntfy request topic (JSON format per doc 73 Section 7.2)
|
|
6
|
-
* 2. Subscribes to the response topic via SSE
|
|
7
|
-
* 3. Parses incoming SignResponse messages (base64url in ntfy message field)
|
|
8
|
-
* 4. Delegates to SignResponseHandler for approval/rejection processing
|
|
9
|
-
*
|
|
10
|
-
* @see internal/design/73-signing-protocol-v1.md (Section 7.2, 7.3)
|
|
11
|
-
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
12
|
-
*/
|
|
13
|
-
import { SignResponseSchema, } from '@waiaas/core';
|
|
14
|
-
import { SIGNING_CHANNEL_FETCH_TIMEOUT_MS } from '../../../constants.js';
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
// Constants
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
const MAX_RECONNECT_ATTEMPTS = 3;
|
|
19
|
-
const RECONNECT_DELAY_MS = 5_000;
|
|
20
|
-
const DEFAULT_NTFY_SERVER = 'https://ntfy.sh';
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// NtfySigningChannel
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
export class NtfySigningChannel {
|
|
25
|
-
signRequestBuilder;
|
|
26
|
-
signResponseHandler;
|
|
27
|
-
settings;
|
|
28
|
-
/** Active SSE subscriptions: requestId -> AbortController */
|
|
29
|
-
activeSubscriptions = new Map();
|
|
30
|
-
constructor(opts) {
|
|
31
|
-
this.signRequestBuilder = opts.signRequestBuilder;
|
|
32
|
-
this.signResponseHandler = opts.signResponseHandler;
|
|
33
|
-
this.settings = opts.settingsService;
|
|
34
|
-
}
|
|
35
|
-
// -------------------------------------------------------------------------
|
|
36
|
-
// sendRequest -- publish to ntfy + subscribe for response
|
|
37
|
-
// -------------------------------------------------------------------------
|
|
38
|
-
/**
|
|
39
|
-
* Publish a SignRequest to ntfy request topic and subscribe to response topic.
|
|
40
|
-
*
|
|
41
|
-
* @param params - Transaction metadata + walletId for topic routing
|
|
42
|
-
* @returns requestId, requestTopic, responseTopic
|
|
43
|
-
*/
|
|
44
|
-
async sendRequest(params) {
|
|
45
|
-
// 1. Build SignRequest via SignRequestBuilder
|
|
46
|
-
const { request, universalLinkUrl, requestTopic } = this.signRequestBuilder.buildRequest(params);
|
|
47
|
-
// 2. Register request with SignResponseHandler for later matching
|
|
48
|
-
this.signResponseHandler.registerRequest(request);
|
|
49
|
-
// 3. Resolve ntfy server URL
|
|
50
|
-
const ntfyServer = this.getNtfyServer();
|
|
51
|
-
// 4. Publish to ntfy request topic (doc 73 Section 7.2)
|
|
52
|
-
await this.publishToNtfy(ntfyServer, requestTopic, request, universalLinkUrl);
|
|
53
|
-
// 5. Determine response topic
|
|
54
|
-
let responseTopic;
|
|
55
|
-
if (request.responseChannel.type === 'ntfy') {
|
|
56
|
-
responseTopic = request.responseChannel.responseTopic;
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
// Fallback: construct response topic from request
|
|
60
|
-
const prefix = this.settings.get('signing_sdk.ntfy_response_topic_prefix');
|
|
61
|
-
responseTopic = `${prefix}-${request.requestId}`;
|
|
62
|
-
}
|
|
63
|
-
// 6. Subscribe to response topic via SSE (background, non-blocking)
|
|
64
|
-
this.subscribeToResponseTopic(ntfyServer, responseTopic, request.requestId, request.expiresAt);
|
|
65
|
-
return {
|
|
66
|
-
requestId: request.requestId,
|
|
67
|
-
requestTopic,
|
|
68
|
-
responseTopic,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
// -------------------------------------------------------------------------
|
|
72
|
-
// Subscription management
|
|
73
|
-
// -------------------------------------------------------------------------
|
|
74
|
-
/**
|
|
75
|
-
* Cancel a specific SSE subscription by requestId.
|
|
76
|
-
*/
|
|
77
|
-
cancelSubscription(requestId) {
|
|
78
|
-
const controller = this.activeSubscriptions.get(requestId);
|
|
79
|
-
if (controller) {
|
|
80
|
-
controller.abort();
|
|
81
|
-
this.activeSubscriptions.delete(requestId);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Shutdown all active SSE subscriptions (daemon shutdown).
|
|
86
|
-
*/
|
|
87
|
-
shutdown() {
|
|
88
|
-
for (const [requestId, controller] of this.activeSubscriptions) {
|
|
89
|
-
controller.abort();
|
|
90
|
-
this.activeSubscriptions.delete(requestId);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// -------------------------------------------------------------------------
|
|
94
|
-
// Private: ntfy server URL
|
|
95
|
-
// -------------------------------------------------------------------------
|
|
96
|
-
getNtfyServer() {
|
|
97
|
-
try {
|
|
98
|
-
const server = this.settings.get('notifications.ntfy_server');
|
|
99
|
-
return server || DEFAULT_NTFY_SERVER;
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return DEFAULT_NTFY_SERVER;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// -------------------------------------------------------------------------
|
|
106
|
-
// Private: publish to ntfy (doc 73 Section 7.2)
|
|
107
|
-
// -------------------------------------------------------------------------
|
|
108
|
-
async publishToNtfy(ntfyServer, requestTopic, request, universalLinkUrl) {
|
|
109
|
-
const url = `${ntfyServer}/${requestTopic}`;
|
|
110
|
-
const encoded = Buffer.from(JSON.stringify(request), 'utf-8').toString('base64url');
|
|
111
|
-
const body = JSON.stringify({
|
|
112
|
-
topic: requestTopic,
|
|
113
|
-
message: encoded,
|
|
114
|
-
title: request.displayMessage,
|
|
115
|
-
priority: 5,
|
|
116
|
-
tags: ['waiaas', 'sign'],
|
|
117
|
-
actions: [
|
|
118
|
-
{
|
|
119
|
-
action: 'view',
|
|
120
|
-
label: 'Sign in wallet',
|
|
121
|
-
url: universalLinkUrl,
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
click: universalLinkUrl,
|
|
125
|
-
});
|
|
126
|
-
const controller = new AbortController();
|
|
127
|
-
const timeoutId = setTimeout(() => controller.abort(), SIGNING_CHANNEL_FETCH_TIMEOUT_MS);
|
|
128
|
-
try {
|
|
129
|
-
const res = await fetch(url, {
|
|
130
|
-
method: 'POST',
|
|
131
|
-
headers: { 'Content-Type': 'application/json' },
|
|
132
|
-
body,
|
|
133
|
-
signal: controller.signal,
|
|
134
|
-
});
|
|
135
|
-
if (!res.ok) {
|
|
136
|
-
throw new Error(`Failed to publish sign request to ntfy: HTTP ${res.status}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
finally {
|
|
140
|
-
clearTimeout(timeoutId);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// -------------------------------------------------------------------------
|
|
144
|
-
// Private: subscribe to response topic via SSE
|
|
145
|
-
// -------------------------------------------------------------------------
|
|
146
|
-
subscribeToResponseTopic(ntfyServer, responseTopic, requestId, expiresAt) {
|
|
147
|
-
const abortController = new AbortController();
|
|
148
|
-
this.activeSubscriptions.set(requestId, abortController);
|
|
149
|
-
// Set timeout for request expiration
|
|
150
|
-
const expiresAtMs = new Date(expiresAt).getTime();
|
|
151
|
-
const timeoutMs = Math.max(0, expiresAtMs - Date.now());
|
|
152
|
-
const timer = setTimeout(() => {
|
|
153
|
-
this.cancelSubscription(requestId);
|
|
154
|
-
}, timeoutMs);
|
|
155
|
-
// Unref timer so it doesn't prevent process exit
|
|
156
|
-
if (typeof timer === 'object' && 'unref' in timer) {
|
|
157
|
-
timer.unref();
|
|
158
|
-
}
|
|
159
|
-
// Start SSE connection (non-blocking)
|
|
160
|
-
void this.connectSse(ntfyServer, responseTopic, requestId, abortController, timer);
|
|
161
|
-
}
|
|
162
|
-
async connectSse(ntfyServer, responseTopic, requestId, abortController, expirationTimer, reconnectAttempt = 0) {
|
|
163
|
-
if (abortController.signal.aborted) {
|
|
164
|
-
clearTimeout(expirationTimer);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
try {
|
|
168
|
-
const url = `${ntfyServer}/${responseTopic}/sse`;
|
|
169
|
-
const res = await fetch(url, {
|
|
170
|
-
signal: abortController.signal,
|
|
171
|
-
});
|
|
172
|
-
if (!res.ok || !res.body) {
|
|
173
|
-
throw new Error(`SSE connection failed: HTTP ${res.status}`);
|
|
174
|
-
}
|
|
175
|
-
const reader = res.body.getReader();
|
|
176
|
-
for await (const ntfyMsg of this.parseSseStream(reader, abortController.signal)) {
|
|
177
|
-
if (abortController.signal.aborted)
|
|
178
|
-
break;
|
|
179
|
-
if (!ntfyMsg.message)
|
|
180
|
-
continue;
|
|
181
|
-
// ntfy message field contains base64url-encoded SignResponse
|
|
182
|
-
try {
|
|
183
|
-
const json = Buffer.from(ntfyMsg.message, 'base64url').toString('utf-8');
|
|
184
|
-
const parsed = JSON.parse(json);
|
|
185
|
-
const signResponse = SignResponseSchema.parse(parsed);
|
|
186
|
-
// Only process responses for this requestId
|
|
187
|
-
if (signResponse.requestId !== requestId)
|
|
188
|
-
continue;
|
|
189
|
-
// Delegate to SignResponseHandler
|
|
190
|
-
await this.signResponseHandler.handle(signResponse);
|
|
191
|
-
// Response processed -- close subscription
|
|
192
|
-
this.cancelSubscription(requestId);
|
|
193
|
-
clearTimeout(expirationTimer);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
catch {
|
|
197
|
-
// Ignore malformed messages or handler errors
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
// SSE stream ended normally -- clean up subscription (#194 Fix 3)
|
|
201
|
-
this.activeSubscriptions.delete(requestId);
|
|
202
|
-
clearTimeout(expirationTimer);
|
|
203
|
-
}
|
|
204
|
-
catch (_err) {
|
|
205
|
-
// Don't reconnect if explicitly aborted
|
|
206
|
-
if (abortController.signal.aborted) {
|
|
207
|
-
clearTimeout(expirationTimer);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
// Reconnect logic: max 3 attempts, 5s delay
|
|
211
|
-
if (reconnectAttempt < MAX_RECONNECT_ATTEMPTS) {
|
|
212
|
-
await new Promise((resolve) => setTimeout(resolve, RECONNECT_DELAY_MS));
|
|
213
|
-
return this.connectSse(ntfyServer, responseTopic, requestId, abortController, expirationTimer, reconnectAttempt + 1);
|
|
214
|
-
}
|
|
215
|
-
// Max reconnects exceeded -- clean up
|
|
216
|
-
this.activeSubscriptions.delete(requestId);
|
|
217
|
-
clearTimeout(expirationTimer);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
// -------------------------------------------------------------------------
|
|
221
|
-
// Private: SSE stream parser
|
|
222
|
-
// -------------------------------------------------------------------------
|
|
223
|
-
/**
|
|
224
|
-
* Parse an SSE stream into NtfyMessage objects.
|
|
225
|
-
*
|
|
226
|
-
* ntfy SSE format:
|
|
227
|
-
* event: message
|
|
228
|
-
* data: {"id":"...","time":...,"event":"message","topic":"...","message":"..."}
|
|
229
|
-
*
|
|
230
|
-
* We only care about `data:` lines containing JSON with a `message` field.
|
|
231
|
-
*/
|
|
232
|
-
async *parseSseStream(reader, signal) {
|
|
233
|
-
const decoder = new TextDecoder();
|
|
234
|
-
let buffer = '';
|
|
235
|
-
try {
|
|
236
|
-
while (!signal.aborted) {
|
|
237
|
-
const { done, value } = await reader.read();
|
|
238
|
-
if (done)
|
|
239
|
-
break;
|
|
240
|
-
buffer += decoder.decode(value, { stream: true });
|
|
241
|
-
const lines = buffer.split('\n');
|
|
242
|
-
// Keep the last incomplete line in buffer
|
|
243
|
-
buffer = lines.pop() ?? '';
|
|
244
|
-
for (const line of lines) {
|
|
245
|
-
if (!line.startsWith('data: '))
|
|
246
|
-
continue;
|
|
247
|
-
const dataStr = line.slice(6).trim();
|
|
248
|
-
if (!dataStr)
|
|
249
|
-
continue;
|
|
250
|
-
try {
|
|
251
|
-
const msg = JSON.parse(dataStr);
|
|
252
|
-
yield msg;
|
|
253
|
-
}
|
|
254
|
-
catch {
|
|
255
|
-
// Ignore malformed JSON
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
finally {
|
|
261
|
-
try {
|
|
262
|
-
reader.releaseLock();
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
// Reader may already be released
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
//# sourceMappingURL=ntfy-signing-channel.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy-signing-channel.js","sourceRoot":"","sources":["../../../../src/services/signing-sdk/channels/ntfy-signing-channel.ts"],"names":[],"mappings":"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"}
|