@waiaas/daemon 2.4.0-rc.2 → 2.4.0-rc.3
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 +1 -0
- package/dist/api/routes/admin.d.ts.map +1 -1
- package/dist/api/routes/admin.js +23 -32
- package/dist/api/routes/admin.js.map +1 -1
- package/dist/api/routes/openapi-schemas.d.ts +57 -0
- package/dist/api/routes/openapi-schemas.d.ts.map +1 -1
- package/dist/api/routes/openapi-schemas.js +14 -1
- package/dist/api/routes/openapi-schemas.js.map +1 -1
- package/dist/api/routes/transactions.d.ts +2 -0
- package/dist/api/routes/transactions.d.ts.map +1 -1
- package/dist/api/routes/transactions.js +1 -0
- package/dist/api/routes/transactions.js.map +1 -1
- package/dist/api/routes/wallets.d.ts.map +1 -1
- package/dist/api/routes/wallets.js +9 -0
- package/dist/api/routes/wallets.js.map +1 -1
- package/dist/api/server.d.ts +2 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +1 -0
- package/dist/api/server.js.map +1 -1
- package/dist/infrastructure/database/compatibility.js +2 -2
- package/dist/infrastructure/database/compatibility.js.map +1 -1
- package/dist/infrastructure/database/migrate.d.ts +1 -1
- package/dist/infrastructure/database/migrate.d.ts.map +1 -1
- package/dist/infrastructure/database/migrate.js +17 -3
- package/dist/infrastructure/database/migrate.js.map +1 -1
- package/dist/infrastructure/database/schema.d.ts +20 -0
- package/dist/infrastructure/database/schema.d.ts.map +1 -1
- package/dist/infrastructure/database/schema.js +2 -0
- package/dist/infrastructure/database/schema.js.map +1 -1
- package/dist/infrastructure/settings/setting-keys.d.ts +2 -2
- package/dist/infrastructure/settings/setting-keys.d.ts.map +1 -1
- package/dist/infrastructure/settings/setting-keys.js +10 -1
- package/dist/infrastructure/settings/setting-keys.js.map +1 -1
- package/dist/infrastructure/telegram/telegram-auth.d.ts +1 -1
- package/dist/infrastructure/telegram/telegram-auth.d.ts.map +1 -1
- package/dist/infrastructure/telegram/telegram-auth.js +1 -1
- package/dist/infrastructure/telegram/telegram-auth.js.map +1 -1
- package/dist/infrastructure/telegram/telegram-bot-service.d.ts +9 -0
- package/dist/infrastructure/telegram/telegram-bot-service.d.ts.map +1 -1
- package/dist/infrastructure/telegram/telegram-bot-service.js +46 -1
- package/dist/infrastructure/telegram/telegram-bot-service.js.map +1 -1
- package/dist/infrastructure/telegram/telegram-types.d.ts +1 -0
- package/dist/infrastructure/telegram/telegram-types.d.ts.map +1 -1
- package/dist/lifecycle/daemon.d.ts +2 -0
- package/dist/lifecycle/daemon.d.ts.map +1 -1
- package/dist/lifecycle/daemon.js +63 -0
- package/dist/lifecycle/daemon.js.map +1 -1
- package/dist/pipeline/stages.d.ts +2 -0
- package/dist/pipeline/stages.d.ts.map +1 -1
- package/dist/pipeline/stages.js +14 -0
- package/dist/pipeline/stages.js.map +1 -1
- package/dist/services/signing-sdk/approval-channel-router.d.ts +65 -0
- package/dist/services/signing-sdk/approval-channel-router.d.ts.map +1 -0
- package/dist/services/signing-sdk/approval-channel-router.js +147 -0
- package/dist/services/signing-sdk/approval-channel-router.js.map +1 -0
- package/dist/services/signing-sdk/channels/index.d.ts +10 -0
- package/dist/services/signing-sdk/channels/index.d.ts.map +1 -0
- package/dist/services/signing-sdk/channels/index.js +8 -0
- package/dist/services/signing-sdk/channels/index.js.map +1 -0
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.d.ts +66 -0
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.d.ts.map +1 -0
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.js +257 -0
- package/dist/services/signing-sdk/channels/ntfy-signing-channel.js.map +1 -0
- package/dist/services/signing-sdk/channels/telegram-signing-channel.d.ts +56 -0
- package/dist/services/signing-sdk/channels/telegram-signing-channel.d.ts.map +1 -0
- package/dist/services/signing-sdk/channels/telegram-signing-channel.js +87 -0
- package/dist/services/signing-sdk/channels/telegram-signing-channel.js.map +1 -0
- package/dist/services/signing-sdk/index.d.ts +34 -0
- package/dist/services/signing-sdk/index.d.ts.map +1 -0
- package/dist/services/signing-sdk/index.js +25 -0
- package/dist/services/signing-sdk/index.js.map +1 -0
- package/dist/services/signing-sdk/sign-request-builder.d.ts +61 -0
- package/dist/services/signing-sdk/sign-request-builder.d.ts.map +1 -0
- package/dist/services/signing-sdk/sign-request-builder.js +157 -0
- package/dist/services/signing-sdk/sign-request-builder.js.map +1 -0
- package/dist/services/signing-sdk/sign-response-handler.d.ts +92 -0
- package/dist/services/signing-sdk/sign-response-handler.d.ts.map +1 -0
- package/dist/services/signing-sdk/sign-response-handler.js +303 -0
- package/dist/services/signing-sdk/sign-response-handler.js.map +1 -0
- package/dist/services/signing-sdk/wallet-link-registry.d.ts +44 -0
- package/dist/services/signing-sdk/wallet-link-registry.d.ts.map +1 -0
- package/dist/services/signing-sdk/wallet-link-registry.js +116 -0
- package/dist/services/signing-sdk/wallet-link-registry.js.map +1 -0
- package/package.json +4 -4
- package/public/admin/assets/index-D7vqMezf.js +1 -0
- package/public/admin/index.html +1 -1
- package/public/admin/assets/index-BEqsuxTi.js +0 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TelegramSigningChannel -- sends SignRequests via Telegram inline button message.
|
|
3
|
+
*
|
|
4
|
+
* When a PENDING_APPROVAL transaction triggers a SignRequest:
|
|
5
|
+
* 1. Builds the SignRequest via SignRequestBuilder
|
|
6
|
+
* 2. Registers the request with SignResponseHandler for later matching
|
|
7
|
+
* 3. Sends a Telegram message to the admin chat with an inline "Open in Wallet"
|
|
8
|
+
* button containing the universal link URL
|
|
9
|
+
*
|
|
10
|
+
* Unlike NtfySigningChannel, TelegramSigningChannel does NOT subscribe to a response
|
|
11
|
+
* topic. The response arrives via the /sign_response Telegram bot command, which
|
|
12
|
+
* delegates to SignResponseHandler. This is a one-way push channel.
|
|
13
|
+
*
|
|
14
|
+
* Implements ISigningChannel interface for consistent channel abstraction.
|
|
15
|
+
*
|
|
16
|
+
* @see internal/design/73-signing-protocol-v1.md (Section 7.2, 7.3)
|
|
17
|
+
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
18
|
+
*/
|
|
19
|
+
import { escapeMarkdownV2 } from '../../../infrastructure/telegram/telegram-bot-service.js';
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// TelegramSigningChannel
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
export class TelegramSigningChannel {
|
|
24
|
+
signRequestBuilder;
|
|
25
|
+
signResponseHandler;
|
|
26
|
+
settings;
|
|
27
|
+
telegramApi;
|
|
28
|
+
constructor(opts) {
|
|
29
|
+
this.signRequestBuilder = opts.signRequestBuilder;
|
|
30
|
+
this.signResponseHandler = opts.signResponseHandler;
|
|
31
|
+
this.settings = opts.settingsService;
|
|
32
|
+
this.telegramApi = opts.telegramApi;
|
|
33
|
+
}
|
|
34
|
+
// -------------------------------------------------------------------------
|
|
35
|
+
// sendRequest -- send Telegram message with universal link inline button
|
|
36
|
+
// -------------------------------------------------------------------------
|
|
37
|
+
/**
|
|
38
|
+
* Send a SignRequest via Telegram message with an inline "Open in Wallet" button.
|
|
39
|
+
*
|
|
40
|
+
* @param params - Transaction metadata + walletId
|
|
41
|
+
* @returns requestId, requestTopic (empty for Telegram), responseTopic (empty)
|
|
42
|
+
* @throws Error if telegram chat_id is not configured
|
|
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. Get admin chat_id from settings
|
|
50
|
+
const chatIdStr = this.settings.get('notifications.telegram_chat_id');
|
|
51
|
+
if (!chatIdStr) {
|
|
52
|
+
throw new Error('Telegram chat_id is not configured in notifications.telegram_chat_id');
|
|
53
|
+
}
|
|
54
|
+
const chatId = parseInt(chatIdStr, 10);
|
|
55
|
+
if (isNaN(chatId)) {
|
|
56
|
+
throw new Error('Invalid telegram_chat_id: must be a numeric value');
|
|
57
|
+
}
|
|
58
|
+
// 4. Format display message with MarkdownV2 escaping
|
|
59
|
+
const header = '*WAIaaS Sign Request*';
|
|
60
|
+
const body = escapeMarkdownV2(request.displayMessage);
|
|
61
|
+
const txInfo = `TX: \`${escapeMarkdownV2(request.metadata.txId.slice(0, 8))}\\.\\.\\.\``;
|
|
62
|
+
const chain = `Chain: ${escapeMarkdownV2(request.chain)}/${escapeMarkdownV2(request.network)}`;
|
|
63
|
+
const text = `${header}\n\n${body}\n${txInfo}\n${chain}`;
|
|
64
|
+
// 5. Send Telegram message with inline keyboard (universal link button)
|
|
65
|
+
await this.telegramApi.sendMessage(chatId, text, {
|
|
66
|
+
inline_keyboard: [
|
|
67
|
+
[{ text: 'Open in Wallet', url: universalLinkUrl }],
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
// 6. Return result (no ntfy topics for Telegram channel)
|
|
71
|
+
return {
|
|
72
|
+
requestId: request.requestId,
|
|
73
|
+
requestTopic,
|
|
74
|
+
responseTopic: '',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// -------------------------------------------------------------------------
|
|
78
|
+
// shutdown -- no-op (no active subscriptions)
|
|
79
|
+
// -------------------------------------------------------------------------
|
|
80
|
+
/**
|
|
81
|
+
* Shutdown the channel. No-op for Telegram (no SSE subscriptions to clean up).
|
|
82
|
+
*/
|
|
83
|
+
shutdown() {
|
|
84
|
+
// No active subscriptions to clean up
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=telegram-signing-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram-signing-channel.js","sourceRoot":"","sources":["../../../../src/services/signing-sdk/channels/telegram-signing-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0DAA0D,CAAC;AAuB5F,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,MAAM,OAAO,sBAAsB;IAChB,kBAAkB,CAAqB;IACvC,mBAAmB,CAAsB;IACzC,QAAQ,CAAkB;IAC1B,WAAW,CAAc;IAE1C,YAAY,IAAgC;QAC1C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAC;QAClD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACtC,CAAC;IAED,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAE5E;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,MAAyB;QACzC,8CAA8C;QAC9C,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAC/C,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAE/C,kEAAkE;QAClE,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAElD,qCAAqC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;QACtE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QAED,qDAAqD;QACrD,MAAM,MAAM,GAAG,uBAAuB,CAAC;QACvC,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,SAAS,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QACzF,MAAM,KAAK,GAAG,UAAU,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/F,MAAM,IAAI,GAAG,GAAG,MAAM,OAAO,IAAI,KAAK,MAAM,KAAK,KAAK,EAAE,CAAC;QAEzD,wEAAwE;QACxE,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE;YAC/C,eAAe,EAAE;gBACf,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC;aACpD;SACF,CAAC,CAAC;QAEH,yDAAyD;QACzD,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,YAAY;YACZ,aAAa,EAAE,EAAE;SAClB,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,8CAA8C;IAC9C,4EAA4E;IAE5E;;OAEG;IACH,QAAQ;QACN,sCAAsC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* signing-sdk module -- unified exports for the daemon signing SDK.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - SignRequestBuilder: builds SignRequest from PENDING_APPROVAL transactions
|
|
6
|
+
* - SignResponseHandler: processes wallet app SignResponse (approve/reject)
|
|
7
|
+
* - WalletLinkRegistry: manages registered wallet configurations
|
|
8
|
+
* - NtfySigningChannel: ntfy-based publish/subscribe signing channel
|
|
9
|
+
* - TelegramSigningChannel: Telegram-based one-way push signing channel
|
|
10
|
+
* - ApprovalChannelRouter: routes to correct channel based on wallet's owner_approval_method
|
|
11
|
+
* - ISigningChannel: channel interface for future channel implementations
|
|
12
|
+
*
|
|
13
|
+
* @see internal/design/73-signing-protocol-v1.md
|
|
14
|
+
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
15
|
+
*/
|
|
16
|
+
export { SignRequestBuilder } from './sign-request-builder.js';
|
|
17
|
+
export type { BuildRequestParams, BuildRequestResult } from './sign-request-builder.js';
|
|
18
|
+
export { SignResponseHandler } from './sign-response-handler.js';
|
|
19
|
+
export type { SignResponseHandlerDeps, HandleResult } from './sign-response-handler.js';
|
|
20
|
+
export { WalletLinkRegistry } from './wallet-link-registry.js';
|
|
21
|
+
export { NtfySigningChannel } from './channels/index.js';
|
|
22
|
+
export type { NtfySigningChannelOpts, SendRequestParams, SendRequestResult } from './channels/index.js';
|
|
23
|
+
export { TelegramSigningChannel } from './channels/index.js';
|
|
24
|
+
export type { TelegramSigningChannelOpts } from './channels/index.js';
|
|
25
|
+
export { ApprovalChannelRouter } from './approval-channel-router.js';
|
|
26
|
+
export type { ApprovalChannelRouterDeps, RouteResult } from './approval-channel-router.js';
|
|
27
|
+
import type { SendRequestParams as _SendRequestParams } from './channels/index.js';
|
|
28
|
+
export interface ISigningChannel {
|
|
29
|
+
sendRequest(params: _SendRequestParams): Promise<{
|
|
30
|
+
requestId: string;
|
|
31
|
+
}>;
|
|
32
|
+
shutdown(): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/signing-sdk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAExF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExG,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAM3F,OAAO,KAAK,EAAE,iBAAiB,IAAI,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,QAAQ,IAAI,IAAI,CAAC;CAClB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* signing-sdk module -- unified exports for the daemon signing SDK.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - SignRequestBuilder: builds SignRequest from PENDING_APPROVAL transactions
|
|
6
|
+
* - SignResponseHandler: processes wallet app SignResponse (approve/reject)
|
|
7
|
+
* - WalletLinkRegistry: manages registered wallet configurations
|
|
8
|
+
* - NtfySigningChannel: ntfy-based publish/subscribe signing channel
|
|
9
|
+
* - TelegramSigningChannel: Telegram-based one-way push signing channel
|
|
10
|
+
* - ApprovalChannelRouter: routes to correct channel based on wallet's owner_approval_method
|
|
11
|
+
* - ISigningChannel: channel interface for future channel implementations
|
|
12
|
+
*
|
|
13
|
+
* @see internal/design/73-signing-protocol-v1.md
|
|
14
|
+
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
15
|
+
*/
|
|
16
|
+
// Core services
|
|
17
|
+
export { SignRequestBuilder } from './sign-request-builder.js';
|
|
18
|
+
export { SignResponseHandler } from './sign-response-handler.js';
|
|
19
|
+
export { WalletLinkRegistry } from './wallet-link-registry.js';
|
|
20
|
+
// Channels
|
|
21
|
+
export { NtfySigningChannel } from './channels/index.js';
|
|
22
|
+
export { TelegramSigningChannel } from './channels/index.js';
|
|
23
|
+
// Routing
|
|
24
|
+
export { ApprovalChannelRouter } from './approval-channel-router.js';
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/signing-sdk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,WAAW;AACX,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,UAAU;AACV,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignRequestBuilder -- builds SignRequest objects for PENDING_APPROVAL transactions.
|
|
3
|
+
*
|
|
4
|
+
* Transforms transaction metadata into a SignRequest with a signing message
|
|
5
|
+
* (doc 73 Section 5 template), response channel config, and a universal link URL
|
|
6
|
+
* for the target wallet app.
|
|
7
|
+
*
|
|
8
|
+
* Intentionally does NOT go through ApprovalWorkflow -- SignRequestBuilder is
|
|
9
|
+
* invoked *after* the pipeline has already set the transaction to PENDING_APPROVAL
|
|
10
|
+
* state. It produces the data needed to notify the owner via ntfy/Telegram channels.
|
|
11
|
+
*
|
|
12
|
+
* @see internal/design/73-signing-protocol-v1.md (Section 3, 5)
|
|
13
|
+
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
14
|
+
*/
|
|
15
|
+
import { type SignRequest } from '@waiaas/core';
|
|
16
|
+
import type { SettingsService } from '../../infrastructure/settings/settings-service.js';
|
|
17
|
+
import type { WalletLinkRegistry } from './wallet-link-registry.js';
|
|
18
|
+
export interface BuildRequestParams {
|
|
19
|
+
txId: string;
|
|
20
|
+
chain: 'solana' | 'evm';
|
|
21
|
+
network: string;
|
|
22
|
+
type: string;
|
|
23
|
+
from: string;
|
|
24
|
+
to: string;
|
|
25
|
+
amount?: string;
|
|
26
|
+
symbol?: string;
|
|
27
|
+
policyTier: 'APPROVAL' | 'DELAY';
|
|
28
|
+
walletName?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BuildRequestResult {
|
|
31
|
+
request: SignRequest;
|
|
32
|
+
universalLinkUrl: string;
|
|
33
|
+
requestTopic: string;
|
|
34
|
+
}
|
|
35
|
+
export declare class SignRequestBuilder {
|
|
36
|
+
private readonly settings;
|
|
37
|
+
private readonly walletLinkRegistry;
|
|
38
|
+
constructor(opts: {
|
|
39
|
+
settingsService: SettingsService;
|
|
40
|
+
walletLinkRegistry: WalletLinkRegistry;
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Build a SignRequest from a PENDING_APPROVAL transaction.
|
|
44
|
+
*
|
|
45
|
+
* @param params - Transaction metadata
|
|
46
|
+
* @returns The SignRequest, universal link URL, and ntfy request topic
|
|
47
|
+
* @throws WAIaaSError('SIGNING_SDK_DISABLED') if signing SDK is disabled
|
|
48
|
+
* @throws WAIaaSError('WALLET_NOT_REGISTERED') if no wallet is configured
|
|
49
|
+
*/
|
|
50
|
+
buildRequest(params: BuildRequestParams): BuildRequestResult;
|
|
51
|
+
/**
|
|
52
|
+
* Build signing message text per doc 73 Section 5 template.
|
|
53
|
+
* Amount/symbol line is omitted when both are absent.
|
|
54
|
+
*/
|
|
55
|
+
private buildSigningMessage;
|
|
56
|
+
/**
|
|
57
|
+
* Build a concise display message for wallet app UI.
|
|
58
|
+
*/
|
|
59
|
+
private buildDisplayMessage;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=sign-request-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign-request-builder.d.ts","sourceRoot":"","sources":["../../../src/services/signing-sdk/sign-request-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,KAAK,WAAW,EAGjB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AACzF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAOpE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,GAAG,KAAK,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;gBAE5C,IAAI,EAAE;QAChB,eAAe,EAAE,eAAe,CAAC;QACjC,kBAAkB,EAAE,kBAAkB,CAAC;KACxC;IASD;;;;;;;OAOG;IACH,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB;IAmG5D;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAM5B"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignRequestBuilder -- builds SignRequest objects for PENDING_APPROVAL transactions.
|
|
3
|
+
*
|
|
4
|
+
* Transforms transaction metadata into a SignRequest with a signing message
|
|
5
|
+
* (doc 73 Section 5 template), response channel config, and a universal link URL
|
|
6
|
+
* for the target wallet app.
|
|
7
|
+
*
|
|
8
|
+
* Intentionally does NOT go through ApprovalWorkflow -- SignRequestBuilder is
|
|
9
|
+
* invoked *after* the pipeline has already set the transaction to PENDING_APPROVAL
|
|
10
|
+
* state. It produces the data needed to notify the owner via ntfy/Telegram channels.
|
|
11
|
+
*
|
|
12
|
+
* @see internal/design/73-signing-protocol-v1.md (Section 3, 5)
|
|
13
|
+
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
14
|
+
*/
|
|
15
|
+
import { SignRequestSchema, WAIaaSError, } from '@waiaas/core';
|
|
16
|
+
import { generateId } from '../../infrastructure/database/id.js';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// SignRequestBuilder
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
export class SignRequestBuilder {
|
|
21
|
+
settings;
|
|
22
|
+
walletLinkRegistry;
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
this.settings = opts.settingsService;
|
|
25
|
+
this.walletLinkRegistry = opts.walletLinkRegistry;
|
|
26
|
+
}
|
|
27
|
+
// -------------------------------------------------------------------------
|
|
28
|
+
// buildRequest
|
|
29
|
+
// -------------------------------------------------------------------------
|
|
30
|
+
/**
|
|
31
|
+
* Build a SignRequest from a PENDING_APPROVAL transaction.
|
|
32
|
+
*
|
|
33
|
+
* @param params - Transaction metadata
|
|
34
|
+
* @returns The SignRequest, universal link URL, and ntfy request topic
|
|
35
|
+
* @throws WAIaaSError('SIGNING_SDK_DISABLED') if signing SDK is disabled
|
|
36
|
+
* @throws WAIaaSError('WALLET_NOT_REGISTERED') if no wallet is configured
|
|
37
|
+
*/
|
|
38
|
+
buildRequest(params) {
|
|
39
|
+
// 1. Check signing SDK enabled
|
|
40
|
+
const enabled = this.settings.get('signing_sdk.enabled');
|
|
41
|
+
if (enabled !== 'true') {
|
|
42
|
+
throw new WAIaaSError('SIGNING_SDK_DISABLED');
|
|
43
|
+
}
|
|
44
|
+
// 2. Determine wallet name
|
|
45
|
+
const walletName = params.walletName ||
|
|
46
|
+
this.settings.get('signing_sdk.preferred_wallet') ||
|
|
47
|
+
undefined;
|
|
48
|
+
if (!walletName) {
|
|
49
|
+
throw new WAIaaSError('WALLET_NOT_REGISTERED', {
|
|
50
|
+
message: 'No wallet name specified and no preferred_wallet configured',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// 3. Verify wallet exists (throws WALLET_NOT_REGISTERED if not found)
|
|
54
|
+
const walletConfig = this.walletLinkRegistry.getWallet(walletName);
|
|
55
|
+
// 4. Generate requestId (UUID v7)
|
|
56
|
+
const requestId = generateId();
|
|
57
|
+
// 5. Build signing message (doc 73 Section 5 template)
|
|
58
|
+
const now = new Date();
|
|
59
|
+
const message = this.buildSigningMessage(params, params.network, requestId, now);
|
|
60
|
+
// 6. Build display message (concise human-readable version)
|
|
61
|
+
const displayMessage = this.buildDisplayMessage(params);
|
|
62
|
+
// 7. Calculate expiresAt from settings
|
|
63
|
+
const expiryMinStr = this.settings.get('signing_sdk.request_expiry_min');
|
|
64
|
+
const expiryMin = parseInt(expiryMinStr, 10) || 30;
|
|
65
|
+
const expiresAt = new Date(now.getTime() + expiryMin * 60 * 1000);
|
|
66
|
+
// 8. Determine response channel
|
|
67
|
+
const preferredChannel = this.settings.get('signing_sdk.preferred_channel');
|
|
68
|
+
const responseTopicPrefix = this.settings.get('signing_sdk.ntfy_response_topic_prefix');
|
|
69
|
+
let responseChannel;
|
|
70
|
+
if (preferredChannel === 'telegram') {
|
|
71
|
+
// Telegram channel -- bot username from telegram settings
|
|
72
|
+
const botToken = this.settings.get('telegram.bot_token');
|
|
73
|
+
responseChannel = {
|
|
74
|
+
type: 'telegram',
|
|
75
|
+
botUsername: botToken ? 'waiaas_bot' : 'waiaas_bot',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Default: ntfy channel
|
|
80
|
+
const ntfyServer = this.settings.get('notifications.ntfy_server');
|
|
81
|
+
responseChannel = {
|
|
82
|
+
type: 'ntfy',
|
|
83
|
+
responseTopic: `${responseTopicPrefix}-${requestId}`,
|
|
84
|
+
...(ntfyServer !== 'https://ntfy.sh' ? { serverUrl: ntfyServer } : {}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// 9. Assemble SignRequest + validate with Zod
|
|
88
|
+
const request = SignRequestSchema.parse({
|
|
89
|
+
version: '1',
|
|
90
|
+
requestId,
|
|
91
|
+
chain: params.chain,
|
|
92
|
+
network: params.network,
|
|
93
|
+
message,
|
|
94
|
+
displayMessage,
|
|
95
|
+
metadata: {
|
|
96
|
+
txId: params.txId,
|
|
97
|
+
type: params.type,
|
|
98
|
+
from: params.from,
|
|
99
|
+
to: params.to,
|
|
100
|
+
...(params.amount !== undefined ? { amount: params.amount } : {}),
|
|
101
|
+
...(params.symbol !== undefined ? { symbol: params.symbol } : {}),
|
|
102
|
+
policyTier: params.policyTier,
|
|
103
|
+
},
|
|
104
|
+
responseChannel,
|
|
105
|
+
expiresAt: expiresAt.toISOString(),
|
|
106
|
+
});
|
|
107
|
+
// 10. Build universal link URL
|
|
108
|
+
const universalLinkUrl = this.walletLinkRegistry.buildSignUrl(walletName, request);
|
|
109
|
+
// 11. Build request topic for ntfy publish
|
|
110
|
+
const requestTopicPrefix = this.settings.get('signing_sdk.ntfy_request_topic_prefix');
|
|
111
|
+
const ntfyTopic = walletConfig.ntfy?.requestTopic ?? `${requestTopicPrefix}-${walletName}`;
|
|
112
|
+
return {
|
|
113
|
+
request,
|
|
114
|
+
universalLinkUrl,
|
|
115
|
+
requestTopic: ntfyTopic,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// -------------------------------------------------------------------------
|
|
119
|
+
// Private: buildSigningMessage (doc 73 Section 5 template)
|
|
120
|
+
// -------------------------------------------------------------------------
|
|
121
|
+
/**
|
|
122
|
+
* Build signing message text per doc 73 Section 5 template.
|
|
123
|
+
* Amount/symbol line is omitted when both are absent.
|
|
124
|
+
*/
|
|
125
|
+
buildSigningMessage(params, network, requestId, now) {
|
|
126
|
+
const lines = [
|
|
127
|
+
'WAIaaS Transaction Approval',
|
|
128
|
+
'',
|
|
129
|
+
`Transaction: ${params.txId}`,
|
|
130
|
+
`Type: ${params.type}`,
|
|
131
|
+
`From: ${params.from}`,
|
|
132
|
+
`To: ${params.to}`,
|
|
133
|
+
];
|
|
134
|
+
// Amount line: only include if amount is present
|
|
135
|
+
if (params.amount !== undefined) {
|
|
136
|
+
const amountLine = params.symbol
|
|
137
|
+
? `Amount: ${params.amount} ${params.symbol}`
|
|
138
|
+
: `Amount: ${params.amount}`;
|
|
139
|
+
lines.push(amountLine);
|
|
140
|
+
}
|
|
141
|
+
lines.push(`Network: ${network}`, `Policy Tier: ${params.policyTier}`, '', 'Approve this transaction by signing this message.', `Timestamp: ${now.toISOString()}`, `Nonce: ${requestId}`);
|
|
142
|
+
return lines.join('\n');
|
|
143
|
+
}
|
|
144
|
+
// -------------------------------------------------------------------------
|
|
145
|
+
// Private: buildDisplayMessage (human-readable summary)
|
|
146
|
+
// -------------------------------------------------------------------------
|
|
147
|
+
/**
|
|
148
|
+
* Build a concise display message for wallet app UI.
|
|
149
|
+
*/
|
|
150
|
+
buildDisplayMessage(params) {
|
|
151
|
+
const amountPart = params.amount
|
|
152
|
+
? ` ${params.amount}${params.symbol ? ' ' + params.symbol : ''}`
|
|
153
|
+
: '';
|
|
154
|
+
return `${params.type}${amountPart} from ${params.from.slice(0, 8)}... to ${params.to.slice(0, 8)}...`;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=sign-request-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign-request-builder.js","sourceRoot":"","sources":["../../../src/services/signing-sdk/sign-request-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignResponseHandler -- processes SignResponse from wallet apps.
|
|
3
|
+
*
|
|
4
|
+
* Handles approve/reject responses for PENDING_APPROVAL transactions:
|
|
5
|
+
* - Validates SignResponse schema (Zod)
|
|
6
|
+
* - Matches requestId to registered pending requests
|
|
7
|
+
* - Checks request expiration
|
|
8
|
+
* - Verifies signer address matches wallet owner
|
|
9
|
+
* - Verifies cryptographic signature (EVM: EIP-191, Solana: Ed25519)
|
|
10
|
+
* - Updates pending_approvals and transactions tables directly
|
|
11
|
+
*
|
|
12
|
+
* **Design Decision: ApprovalWorkflow bypass (intentional)**
|
|
13
|
+
* SignResponseHandler directly updates pending_approvals/transactions tables,
|
|
14
|
+
* bypassing ApprovalWorkflow. This is the same pattern used by Telegram bot
|
|
15
|
+
* approval (/approve, /reject commands). Rationale: SignResponseHandler performs
|
|
16
|
+
* its own cryptographic signature verification (SIWE/SIWS), making
|
|
17
|
+
* ApprovalWorkflow's verification step redundant.
|
|
18
|
+
*
|
|
19
|
+
* @see internal/design/73-signing-protocol-v1.md (Section 4, 10, 11)
|
|
20
|
+
* @see internal/design/74-wallet-sdk-daemon-components.md
|
|
21
|
+
*/
|
|
22
|
+
import type { Database as SQLiteDatabase } from 'better-sqlite3';
|
|
23
|
+
import { type SignRequest, type SignResponse } from '@waiaas/core';
|
|
24
|
+
export interface SignResponseHandlerDeps {
|
|
25
|
+
/** Raw better-sqlite3 database handle for direct SQL (same pattern as Telegram bot) */
|
|
26
|
+
sqlite: SQLiteDatabase;
|
|
27
|
+
}
|
|
28
|
+
export interface HandleResult {
|
|
29
|
+
action: 'approved' | 'rejected';
|
|
30
|
+
txId: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Verifies an EVM EIP-191 personal_sign signature.
|
|
34
|
+
* Default implementation uses viem's verifyMessage.
|
|
35
|
+
*/
|
|
36
|
+
export type EvmVerifyFn = (params: {
|
|
37
|
+
address: string;
|
|
38
|
+
message: string;
|
|
39
|
+
signature: string;
|
|
40
|
+
}) => Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Verifies a Solana Ed25519 signature.
|
|
43
|
+
* Default implementation uses @solana/kit's verifySignature.
|
|
44
|
+
*/
|
|
45
|
+
export type SolanaVerifyFn = (params: {
|
|
46
|
+
publicKeyAddress: string;
|
|
47
|
+
message: string;
|
|
48
|
+
signature: string;
|
|
49
|
+
}) => Promise<boolean>;
|
|
50
|
+
export declare class SignResponseHandler {
|
|
51
|
+
private readonly sqlite;
|
|
52
|
+
/**
|
|
53
|
+
* In-memory store: requestId -> { request, createdAt }.
|
|
54
|
+
* Lost on daemon restart (acceptable -- 1-shot requests with expiry).
|
|
55
|
+
*/
|
|
56
|
+
private readonly pendingRequests;
|
|
57
|
+
/**
|
|
58
|
+
* Set of already-processed requestIds (for duplicate detection).
|
|
59
|
+
* Also lost on daemon restart.
|
|
60
|
+
*/
|
|
61
|
+
private readonly processedRequests;
|
|
62
|
+
/** Expiration timers by requestId */
|
|
63
|
+
private readonly expirationTimers;
|
|
64
|
+
/** Injectable verification functions (for testing) */
|
|
65
|
+
private readonly evmVerify;
|
|
66
|
+
private readonly solanaVerify;
|
|
67
|
+
constructor(deps: SignResponseHandlerDeps, opts?: {
|
|
68
|
+
evmVerify?: EvmVerifyFn;
|
|
69
|
+
solanaVerify?: SolanaVerifyFn;
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* Register a SignRequest for later response matching.
|
|
73
|
+
* Sets an expiration timer to auto-remove the request after expiresAt.
|
|
74
|
+
*/
|
|
75
|
+
registerRequest(request: SignRequest): void;
|
|
76
|
+
/**
|
|
77
|
+
* Process a SignResponse: validate, match, verify signature, update DB.
|
|
78
|
+
*
|
|
79
|
+
* @param signResponse - The response from the wallet app
|
|
80
|
+
* @returns { action: 'approved' | 'rejected', txId }
|
|
81
|
+
* @throws WAIaaSError with appropriate error code on validation failure
|
|
82
|
+
*/
|
|
83
|
+
handle(signResponse: SignResponse): Promise<HandleResult>;
|
|
84
|
+
private handleApprove;
|
|
85
|
+
private handleReject;
|
|
86
|
+
private clearTimer;
|
|
87
|
+
/**
|
|
88
|
+
* Clear all pending timers. Call during daemon shutdown.
|
|
89
|
+
*/
|
|
90
|
+
destroy(): void;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=sign-response-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign-response-handler.d.ts","sourceRoot":"","sources":["../../../src/services/signing-sdk/sign-response-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,YAAY,EAGlB,MAAM,cAAc,CAAC;AAMtB,MAAM,WAAW,uBAAuB;IACtC,uFAAuF;IACvF,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAUD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AA4CvB,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IAExC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAG5B;IAEJ;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqB;IAEvD,qCAAqC;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoD;IAErF,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;gBAG5C,IAAI,EAAE,uBAAuB,EAC7B,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,WAAW,CAAC;QACxB,YAAY,CAAC,EAAE,cAAc,CAAC;KAC/B;IAWH;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IA0B3C;;;;;;OAMG;IACG,MAAM,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;YAuEjD,aAAa;YAoEb,YAAY;IAiE1B,OAAO,CAAC,UAAU;IAYlB;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB"}
|