@canton-network/wallet-gateway-remote 1.4.0 → 1.6.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.
Files changed (141) hide show
  1. package/dist/auth/jwt-auth-service.d.ts.map +1 -1
  2. package/dist/auth/jwt-auth-service.js +6 -5
  3. package/dist/auth/jwt-auth-service.test.d.ts +2 -0
  4. package/dist/auth/jwt-auth-service.test.d.ts.map +1 -0
  5. package/dist/auth/jwt-auth-service.test.js +259 -0
  6. package/dist/auth/jwt-unsafe-auth-service.test.d.ts +2 -0
  7. package/dist/auth/jwt-unsafe-auth-service.test.d.ts.map +1 -0
  8. package/dist/auth/jwt-unsafe-auth-service.test.js +120 -0
  9. package/dist/config/Config.d.ts +69 -4
  10. package/dist/config/Config.d.ts.map +1 -1
  11. package/dist/config/Config.js +6 -0
  12. package/dist/config/ConfigUtils.d.ts.map +1 -1
  13. package/dist/config/ConfigUtils.js +3 -0
  14. package/dist/dapp-api/controller.d.ts +5 -1
  15. package/dist/dapp-api/controller.d.ts.map +1 -1
  16. package/dist/dapp-api/controller.js +104 -30
  17. package/dist/dapp-api/controller.test.js +2 -2
  18. package/dist/dapp-api/server.d.ts +3 -2
  19. package/dist/dapp-api/server.d.ts.map +1 -1
  20. package/dist/dapp-api/server.js +2 -2
  21. package/dist/dapp-api/server.test.js +1 -6
  22. package/dist/example-config.d.ts +3 -0
  23. package/dist/example-config.d.ts.map +1 -1
  24. package/dist/example-config.js +3 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +10 -0
  27. package/dist/init.d.ts.map +1 -1
  28. package/dist/init.js +19 -7
  29. package/dist/ledger/transaction-service.d.ts +16 -11
  30. package/dist/ledger/transaction-service.d.ts.map +1 -1
  31. package/dist/ledger/transaction-service.js +135 -8
  32. package/dist/ledger/transaction-service.test.d.ts +2 -0
  33. package/dist/ledger/transaction-service.test.d.ts.map +1 -0
  34. package/dist/ledger/transaction-service.test.js +390 -0
  35. package/dist/ledger/wallet-allocation/signing-providers/fireblocks-wallet-allocator.d.ts +5 -2
  36. package/dist/ledger/wallet-allocation/signing-providers/fireblocks-wallet-allocator.d.ts.map +1 -1
  37. package/dist/ledger/wallet-allocation/signing-providers/fireblocks-wallet-allocator.js +7 -6
  38. package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts +11 -5
  39. package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts.map +1 -1
  40. package/dist/ledger/wallet-allocation/wallet-allocation-service.js +28 -14
  41. package/dist/ledger/wallet-allocation/wallet-allocation-service.test.js +550 -19
  42. package/dist/ledger/wallet-sync-service.js +3 -3
  43. package/dist/middleware/apiKeyAuth.d.ts +6 -0
  44. package/dist/middleware/apiKeyAuth.d.ts.map +1 -0
  45. package/dist/middleware/apiKeyAuth.js +90 -0
  46. package/dist/middleware/apiKeyAuth.test.d.ts +2 -0
  47. package/dist/middleware/apiKeyAuth.test.d.ts.map +1 -0
  48. package/dist/middleware/apiKeyAuth.test.js +126 -0
  49. package/dist/middleware/jsonRpcHandler.d.ts +11 -1
  50. package/dist/middleware/jsonRpcHandler.d.ts.map +1 -1
  51. package/dist/middleware/jsonRpcHandler.js +14 -15
  52. package/dist/middleware/jsonRpcHandler.test.d.ts +2 -0
  53. package/dist/middleware/jsonRpcHandler.test.d.ts.map +1 -0
  54. package/dist/middleware/jsonRpcHandler.test.js +254 -0
  55. package/dist/middleware/jwtAuth.d.ts.map +1 -1
  56. package/dist/middleware/jwtAuth.js +4 -0
  57. package/dist/middleware/jwtAuth.test.d.ts +2 -0
  58. package/dist/middleware/jwtAuth.test.d.ts.map +1 -0
  59. package/dist/middleware/jwtAuth.test.js +93 -0
  60. package/dist/middleware/rateLimit.test.js +12 -0
  61. package/dist/middleware/sessionHandler.js +1 -1
  62. package/dist/middleware/sessionHandler.test.d.ts +2 -0
  63. package/dist/middleware/sessionHandler.test.d.ts.map +1 -0
  64. package/dist/middleware/sessionHandler.test.js +121 -0
  65. package/dist/notification/NotificationService.test.d.ts +2 -0
  66. package/dist/notification/NotificationService.test.d.ts.map +1 -0
  67. package/dist/notification/NotificationService.test.js +110 -0
  68. package/dist/signing/service-account-session.d.ts +16 -0
  69. package/dist/signing/service-account-session.d.ts.map +1 -0
  70. package/dist/signing/service-account-session.js +25 -0
  71. package/dist/signing/service-account-session.test.d.ts +2 -0
  72. package/dist/signing/service-account-session.test.d.ts.map +1 -0
  73. package/dist/signing/service-account-session.test.js +89 -0
  74. package/dist/signing/signing-drivers.d.ts +7 -0
  75. package/dist/signing/signing-drivers.d.ts.map +1 -0
  76. package/dist/signing/signing-drivers.js +3 -0
  77. package/dist/signing/signing-worker.d.ts +83 -0
  78. package/dist/signing/signing-worker.d.ts.map +1 -0
  79. package/dist/signing/signing-worker.js +206 -0
  80. package/dist/signing/signing-worker.test.d.ts +2 -0
  81. package/dist/signing/signing-worker.test.d.ts.map +1 -0
  82. package/dist/signing/signing-worker.test.js +152 -0
  83. package/dist/user-api/controller.d.ts +6 -4
  84. package/dist/user-api/controller.d.ts.map +1 -1
  85. package/dist/user-api/controller.js +119 -95
  86. package/dist/user-api/controller.test.d.ts +2 -0
  87. package/dist/user-api/controller.test.d.ts.map +1 -0
  88. package/dist/user-api/controller.test.js +862 -0
  89. package/dist/user-api/rpc-gen/index.d.ts +12 -0
  90. package/dist/user-api/rpc-gen/index.d.ts.map +1 -1
  91. package/dist/user-api/rpc-gen/index.js +4 -0
  92. package/dist/user-api/rpc-gen/typings.d.ts +52 -3
  93. package/dist/user-api/rpc-gen/typings.d.ts.map +1 -1
  94. package/dist/utils.d.ts +17 -1
  95. package/dist/utils.d.ts.map +1 -1
  96. package/dist/utils.js +53 -2
  97. package/dist/utils.test.d.ts +2 -0
  98. package/dist/utils.test.d.ts.map +1 -0
  99. package/dist/utils.test.js +24 -0
  100. package/dist/web/frontend/404/index.html +2 -2
  101. package/dist/web/frontend/activities/index.html +3 -3
  102. package/dist/web/frontend/approve/index.html +4 -4
  103. package/dist/web/frontend/assets/{404-C7V2yl2z.js → 404-C4hCL2o8.js} +2 -2
  104. package/dist/web/frontend/assets/{activities-NY8oZAkH.js → activities-Bq7yMMQY.js} +2 -2
  105. package/dist/web/frontend/assets/addIdentityProvider-DRJWLhHF.js +28 -0
  106. package/dist/web/frontend/assets/addNetwork-CJUaKP1q.js +38 -0
  107. package/dist/web/frontend/assets/addParty-2ObTLGIL.js +45 -0
  108. package/dist/web/frontend/assets/approve-BuA5DGC2.js +21 -0
  109. package/dist/web/frontend/assets/callback-C5vJWFLq.js +1 -0
  110. package/dist/web/frontend/assets/{identityProviders-BZ9h_VOJ.js → identityProviders-78FbpzYL.js} +2 -2
  111. package/dist/web/frontend/assets/{index-B-HiKugW.js → index-BTH_md6b.js} +3 -3
  112. package/dist/web/frontend/assets/index-CFnOucPK.js +4737 -0
  113. package/dist/web/frontend/assets/{login-CqwMEG9J.js → login-Dyn1o6fW.js} +2 -2
  114. package/dist/web/frontend/assets/{networks-BJvRi47M.js → networks-_el10AWP.js} +2 -2
  115. package/dist/web/frontend/assets/reviewIdentityProvider-DodUZ2mY.js +43 -0
  116. package/dist/web/frontend/assets/reviewNetwork-BFMtmKEL.js +43 -0
  117. package/dist/web/frontend/assets/settings-BBmkIfYm.js +37 -0
  118. package/dist/web/frontend/assets/{state-qAsNw5qf.js → state-DkxLvywv.js} +1 -1
  119. package/dist/web/frontend/assets/{utils-BDkHxi8V.js → utils-DvJKIYxT.js} +1 -1
  120. package/dist/web/frontend/callback/index.html +2 -2
  121. package/dist/web/frontend/identity-providers/add/index.html +3 -3
  122. package/dist/web/frontend/identity-providers/index.html +3 -3
  123. package/dist/web/frontend/identity-providers/review/index.html +3 -3
  124. package/dist/web/frontend/index.html +1 -1
  125. package/dist/web/frontend/login/index.html +3 -3
  126. package/dist/web/frontend/networks/add/index.html +3 -3
  127. package/dist/web/frontend/networks/index.html +3 -3
  128. package/dist/web/frontend/networks/review/index.html +3 -3
  129. package/dist/web/frontend/parties/add/index.html +5 -5
  130. package/dist/web/frontend/parties/index.html +4 -4
  131. package/dist/web/frontend/settings/index.html +3 -3
  132. package/package.json +36 -32
  133. package/dist/web/frontend/assets/addIdentityProvider-38ghz3RT.js +0 -28
  134. package/dist/web/frontend/assets/addNetwork-BaDhbrZl.js +0 -38
  135. package/dist/web/frontend/assets/addParty-j3JWZX5a.js +0 -41
  136. package/dist/web/frontend/assets/approve-43nVzAAC.js +0 -21
  137. package/dist/web/frontend/assets/callback-BBMiCjHR.js +0 -1
  138. package/dist/web/frontend/assets/index-DoNqknyE.js +0 -4042
  139. package/dist/web/frontend/assets/reviewIdentityProvider-ySlQnw5R.js +0 -43
  140. package/dist/web/frontend/assets/reviewNetwork-DrVxeHd4.js +0 -43
  141. package/dist/web/frontend/assets/settings-BVNkaUyJ.js +0 -37
@@ -0,0 +1,206 @@
1
+ // Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { TransactionService } from '../ledger/transaction-service.js';
4
+ import { resolveAutomationRunContext } from './service-account-session.js';
5
+ /**
6
+ * Background poller that completes service-account transactions stuck in external
7
+ * custody approval.
8
+ *
9
+ * ## When this runs
10
+ *
11
+ * During M2M automation (`prepareExecute` → `signAndExecute`), external signing
12
+ * providers (Fireblocks, Blockdaemon, Dfns) may return `pending` instead of a
13
+ * signature. The gateway persists the transaction with `status: 'pending'` and
14
+ * an `externalTxId` from the provider. This worker picks up those rows on each
15
+ * tick via {@link Store.listAllPendingTransactions} (rows with an
16
+ * `externalTxId` are processed; others are skipped).
17
+ *
18
+ * Participant and wallet-kernel sign synchronously and never appear here.
19
+ *
20
+ * ## What happens on each tick
21
+ *
22
+ * For every pending row the worker resolves an M2M auth context
23
+ * ({@link resolveAutomationRunContext}), loads the user's primary wallet, and
24
+ * calls {@link TransactionService.signAndExecute}.
25
+ *
26
+ * Although the worker always invokes `signAndExecute`, **retries do not submit a
27
+ * new sign request**. `TransactionService.sign()` checks whether the stored
28
+ * transaction already has an `externalTxId`:
29
+ *
30
+ * - **First pass** (no `externalTxId`): `driver.signTransaction()` submits to
31
+ * custody and stores the returned `externalTxId`.
32
+ * - **Subsequent ticks** (`externalTxId` present): `driver.getTransaction()`
33
+ * polls the existing custody request for an updated status/signature.
34
+ *
35
+ * `signAndExecute` then:
36
+ *
37
+ * - returns early while the provider still reports `pending` (worker logs and
38
+ * waits for the next tick), or
39
+ * - calls `execute()` once signing is `signed` (Dfns is special: it broadcasts
40
+ * at sign-time, so execute only reconciles local state).
41
+ *
42
+ * A transaction is re-read before processing so a concurrent DApp call or an
43
+ * earlier tick that already completed it is skipped.
44
+ *
45
+ * ## Lifecycle
46
+ *
47
+ * Started once at gateway init (`start()`). Ticks are serialized: if a tick is
48
+ * still running, the next interval callback is a no-op. Use `stop()` on shutdown.
49
+ */
50
+ export class SigningWorker {
51
+ constructor(options) {
52
+ this.options = options;
53
+ this.running = false;
54
+ }
55
+ /** Starts the interval timer. Idempotent if already started. */
56
+ start() {
57
+ this.options.logger.info('Starting signing worker');
58
+ if (this.timer) {
59
+ return;
60
+ }
61
+ this.timer = setInterval(() => {
62
+ void this.tick();
63
+ }, this.options.intervalMs);
64
+ this.options.logger.info({ intervalMs: this.options.intervalMs }, 'Signing worker started');
65
+ }
66
+ /** Clears the interval timer. */
67
+ stop() {
68
+ if (this.timer) {
69
+ clearInterval(this.timer);
70
+ this.timer = undefined;
71
+ }
72
+ }
73
+ /**
74
+ * One poll cycle: list all pending transactions and attempt to complete
75
+ * external-custody rows via {@link processPending}. Safe to call directly in
76
+ * tests.
77
+ */
78
+ async tick() {
79
+ this.options.logger.trace(`Signing worker: executing a tick`);
80
+ if (this.running) {
81
+ return;
82
+ }
83
+ this.running = true;
84
+ try {
85
+ const pending = await this.options.store.listAllPendingTransactions();
86
+ for (const tx of pending) {
87
+ if (!tx.externalTxId) {
88
+ continue;
89
+ }
90
+ await this.processPending(tx);
91
+ }
92
+ }
93
+ catch (error) {
94
+ this.options.logger.error({ err: error }, 'Signing worker tick failed');
95
+ }
96
+ finally {
97
+ this.running = false;
98
+ }
99
+ }
100
+ /**
101
+ * Drives a single pending transaction through `signAndExecute`. Skips when
102
+ * automation context, submitting wallet, or refreshed `pending` status is missing.
103
+ * Errors are logged per transaction; other rows in the same tick still run.
104
+ */
105
+ async processPending(transaction) {
106
+ const logger = this.options.logger;
107
+ const { userId, networkId, externalTxId } = transaction;
108
+ if (!externalTxId || !userId || !networkId) {
109
+ logger.debug({ transaction }, 'Skipping signing worker tick: missing required fields');
110
+ return;
111
+ }
112
+ const runContext = await resolveAutomationRunContext(this.options.store, userId, networkId, logger);
113
+ if (!runContext) {
114
+ logger.debug({ runContext, transactionId: transaction.id }, 'Skipping signing worker tick: no run context');
115
+ return;
116
+ }
117
+ const store = runContext.scopedStore;
118
+ const wallet = await resolveWalletFromTransaction(transaction, store, logger);
119
+ if (!wallet) {
120
+ logger.warn({
121
+ userId,
122
+ networkId,
123
+ transactionId: transaction.id,
124
+ commandId: transaction.commandId,
125
+ }, 'Skipping signing worker tick: could not deduce submitting wallet from transaction payload');
126
+ return;
127
+ }
128
+ const refreshedTx = await store.getTransaction(transaction.id);
129
+ if (!refreshedTx || refreshedTx.status !== 'pending') {
130
+ logger.debug({ refreshedTx }, 'Skipping signing worker tick: transaction no longer pending');
131
+ return;
132
+ }
133
+ const notifier = this.options.notificationService.getNotifier(userId);
134
+ const transactionLogger = this.options.logger.child({
135
+ component: 'TransactionService',
136
+ });
137
+ const transactionService = new TransactionService(store, transactionLogger, this.options.signingDrivers, notifier);
138
+ try {
139
+ const result = await transactionService.signAndExecute(runContext.authContext, runContext.network, wallet, refreshedTx);
140
+ if ('status' in result && result.status === 'pending') {
141
+ logger.info({
142
+ userId,
143
+ networkId,
144
+ transactionId: transaction.id,
145
+ commandId: transaction.commandId,
146
+ externalTxId: result.externalTxId,
147
+ signingProviderId: wallet.signingProviderId,
148
+ }, 'Signing worker: transaction still awaiting external signing');
149
+ }
150
+ else {
151
+ logger.info({
152
+ userId,
153
+ networkId,
154
+ transactionId: transaction.id,
155
+ commandId: transaction.commandId,
156
+ externalTxId: transaction.externalTxId,
157
+ partyId: wallet.partyId,
158
+ signingProviderId: wallet.signingProviderId,
159
+ result,
160
+ }, 'Signing worker completed service account transaction');
161
+ }
162
+ }
163
+ catch (error) {
164
+ logger.error({
165
+ err: error,
166
+ userId,
167
+ networkId,
168
+ transactionId: transaction.id,
169
+ commandId: transaction.commandId,
170
+ externalTxId: transaction.externalTxId,
171
+ partyId: wallet.partyId,
172
+ signingProviderId: wallet.signingProviderId,
173
+ }, 'Signing worker failed to complete service account transaction');
174
+ }
175
+ }
176
+ }
177
+ /**
178
+ * Given the transaction, attempt to resolve the original wallet that submitted it.
179
+ * It's not guaranteed that the primary wallet was used, so we check the `actAs` field in the payload and find a wallet with a matching party ID.
180
+ *
181
+ * Returns `undefined` if the wallet cannot be resolved.
182
+ */
183
+ async function resolveWalletFromTransaction(tx, store, logger) {
184
+ logger.debug({ tx, store }, 'Resolving wallet from transaction payload');
185
+ // first see if we can determine the wallet from the payload's actAs field.
186
+ // If not, we will default to the primary wallet.
187
+ let wallet = undefined;
188
+ const payload = tx.payload;
189
+ if (payload && typeof payload === 'object') {
190
+ const actAs = payload.actAs;
191
+ if (Array.isArray(actAs) && actAs.length !== 0) {
192
+ if (actAs.length > 1) {
193
+ logger.warn({ actAs }, 'Transaction has multiple acting parties; using the first one to resolve wallet');
194
+ }
195
+ const partyId = actAs[0];
196
+ const wallets = await store.getAllWallets();
197
+ wallet = wallets.find((wallet) => wallet.partyId === partyId);
198
+ }
199
+ }
200
+ if (!wallet) {
201
+ // No actAs was given: lets default to the primary party.
202
+ wallet = await store.getPrimaryWallet();
203
+ logger.debug({ wallet, tx }, 'Transaction has no actAs; using primary wallet');
204
+ }
205
+ return wallet;
206
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signing-worker.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing-worker.test.d.ts","sourceRoot":"","sources":["../../src/signing/signing-worker.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ // Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
4
+ import { pino } from 'pino';
5
+ import { sink } from 'pino-test';
6
+ import { SigningWorker } from './signing-worker.js';
7
+ import { SigningProvider } from '@canton-network/core-signing-lib';
8
+ const mocks = vi.hoisted(() => ({
9
+ signAndExecute: vi.fn().mockResolvedValue({ commandId: 'cmd-1' }),
10
+ }));
11
+ vi.mock('@canton-network/core-wallet-auth', async () => {
12
+ const actual = await vi.importActual('@canton-network/core-wallet-auth');
13
+ return {
14
+ ...actual,
15
+ AuthTokenProvider: {
16
+ fromGatewayConfig: vi.fn().mockReturnValue({
17
+ getAuthContext: vi.fn().mockResolvedValue({
18
+ userId: 'service_account',
19
+ accessToken: 'abc',
20
+ }),
21
+ }),
22
+ },
23
+ };
24
+ });
25
+ vi.mock('../ledger/transaction-service.js', () => ({
26
+ TransactionService: vi.fn(function TransactionServiceMock() {
27
+ return { signAndExecute: mocks.signAndExecute };
28
+ }),
29
+ }));
30
+ const idp = {
31
+ id: 'idp1',
32
+ type: 'oauth',
33
+ issuer: 'https://issuer.example',
34
+ configUrl: 'https://issuer.example/.well-known/openid-configuration',
35
+ };
36
+ const m2mNetwork = {
37
+ id: 'net-m2m',
38
+ name: 'm2m',
39
+ description: '',
40
+ synchronizerId: 'sync::fp',
41
+ identityProviderId: 'idp1',
42
+ ledgerApi: { baseUrl: 'http://ledger' },
43
+ auth: {
44
+ method: 'authorization_code',
45
+ clientId: 'user',
46
+ audience: 'aud',
47
+ scope: 'scope',
48
+ },
49
+ serviceAccountAuth: {
50
+ method: 'client_credentials',
51
+ clientId: 'svc',
52
+ clientSecret: 'secret',
53
+ audience: 'aud',
54
+ scope: 'scope',
55
+ },
56
+ };
57
+ const wallet = {
58
+ primary: true,
59
+ partyId: 'party::ns',
60
+ status: 'allocated',
61
+ hint: 'party',
62
+ publicKey: 'pk',
63
+ namespace: 'ns',
64
+ networkId: 'net-m2m',
65
+ signingProviderId: SigningProvider.FIREBLOCKS,
66
+ rights: [],
67
+ };
68
+ const aliceWallet = {
69
+ primary: false,
70
+ partyId: 'alice::ns2',
71
+ status: 'allocated',
72
+ hint: 'alice',
73
+ publicKey: 'pk2',
74
+ namespace: 'ns2',
75
+ networkId: 'net-m2m',
76
+ signingProviderId: SigningProvider.FIREBLOCKS,
77
+ rights: [],
78
+ };
79
+ const pendingTransaction = {
80
+ id: 'tx-1',
81
+ commandId: 'cmd-1',
82
+ status: 'pending',
83
+ preparedTransaction: 'blob',
84
+ preparedTransactionHash: 'hash',
85
+ externalTxId: 'ext-1',
86
+ origin: null,
87
+ userId: 'user-1',
88
+ networkId: 'net-m2m',
89
+ };
90
+ function createWorker(storeOverrides = {}) {
91
+ const scopedStore = {
92
+ setSession: vi.fn().mockResolvedValue(undefined),
93
+ getPrimaryWallet: vi.fn().mockResolvedValue(wallet),
94
+ getAllWallets: vi.fn().mockResolvedValue([wallet, aliceWallet]),
95
+ getTransaction: vi.fn().mockResolvedValue(pendingTransaction),
96
+ };
97
+ const store = {
98
+ listAllPendingTransactions: vi
99
+ .fn()
100
+ .mockResolvedValue([pendingTransaction]),
101
+ getIdp: vi.fn().mockResolvedValue(idp),
102
+ getNetwork: vi.fn().mockResolvedValue(m2mNetwork),
103
+ withAuthContext: vi.fn().mockReturnValue(scopedStore),
104
+ ...storeOverrides,
105
+ };
106
+ const logger = pino({ level: 'silent' }, sink());
107
+ return {
108
+ worker: new SigningWorker({
109
+ intervalMs: 1000,
110
+ signingDrivers: {},
111
+ store: store,
112
+ notificationService: {
113
+ getNotifier: vi.fn(() => ({ emit: vi.fn() })),
114
+ },
115
+ logger,
116
+ }),
117
+ store,
118
+ scopedStore,
119
+ };
120
+ }
121
+ describe('SigningWorker', () => {
122
+ afterEach(() => vi.clearAllMocks());
123
+ it('completes pending external transactions with a primary wallet', async () => {
124
+ const { worker } = createWorker();
125
+ await worker.tick();
126
+ expect(mocks.signAndExecute.mock.calls[0][2].partyId).toBe('party::ns');
127
+ });
128
+ it('uses a non-primary wallet when actAs payload is present', async () => {
129
+ const { worker } = createWorker({
130
+ listAllPendingTransactions: vi.fn().mockResolvedValue([
131
+ {
132
+ ...pendingTransaction,
133
+ payload: { actAs: ['alice::ns2'] },
134
+ },
135
+ ]),
136
+ });
137
+ await worker.tick();
138
+ expect(mocks.signAndExecute).toHaveBeenCalledOnce();
139
+ expect(mocks.signAndExecute.mock.calls[0][2].partyId).toBe('alice::ns2');
140
+ });
141
+ it('skips pending transactions without an externalTxId', async () => {
142
+ const { worker } = createWorker({
143
+ listAllPendingTransactions: vi
144
+ .fn()
145
+ .mockResolvedValue([
146
+ { ...pendingTransaction, externalTxId: undefined },
147
+ ]),
148
+ });
149
+ await worker.tick();
150
+ expect(mocks.signAndExecute).not.toHaveBeenCalled();
151
+ });
152
+ });
@@ -3,9 +3,8 @@ import { Logger } from 'pino';
3
3
  import { NotificationService } from '../notification/NotificationService.js';
4
4
  import { AuthContext } from '@canton-network/core-wallet-auth';
5
5
  import { KernelInfo } from '../config/Config.js';
6
- import { SigningDriverInterface, SigningProvider } from '@canton-network/core-signing-lib';
7
- type AvailableSigningDrivers = Partial<Record<SigningProvider, SigningDriverInterface>>;
8
- export declare const userController: (kernelInfo: KernelInfo, userUrl: string, store: Store, notificationService: NotificationService, authContext: AuthContext | undefined, drivers: AvailableSigningDrivers, _logger: Logger, adminUserId?: string) => {
6
+ import type { SigningDrivers } from '../signing/signing-drivers.js';
7
+ export declare const userController: (kernelInfo: KernelInfo, userUrl: string, store: Store, notificationService: NotificationService, authContext: AuthContext | undefined, drivers: SigningDrivers, _logger: Logger, adminUserId?: string) => {
9
8
  addNetwork: import("./rpc-gen/typings.js").AddNetwork;
10
9
  removeNetwork: import("./rpc-gen/typings.js").RemoveNetwork;
11
10
  listNetworks: import("./rpc-gen/typings.js").ListNetworks;
@@ -34,6 +33,9 @@ export declare const userController: (kernelInfo: KernelInfo, userUrl: string, s
34
33
  listTransactions: import("./rpc-gen/typings.js").ListTransactions;
35
34
  deleteTransaction: import("./rpc-gen/typings.js").DeleteTransaction;
36
35
  getUser: import("./rpc-gen/typings.js").GetUser;
36
+ generateApiKey: import("./rpc-gen/typings.js").GenerateApiKey;
37
+ listApiKeys: import("./rpc-gen/typings.js").ListApiKeys;
38
+ removeApiKey: import("./rpc-gen/typings.js").RemoveApiKey;
39
+ listSigningProviderVaults: import("./rpc-gen/typings.js").ListSigningProviderVaults;
37
40
  };
38
- export {};
39
41
  //# sourceMappingURL=controller.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/user-api/controller.ts"],"names":[],"mappings":"AAyCA,OAAO,EAAE,KAAK,EAAW,MAAM,mCAAmC,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,EAEH,WAAW,EAMd,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAEH,sBAAsB,EACtB,eAAe,EAClB,MAAM,kCAAkC,CAAA;AAUzC,KAAK,uBAAuB,GAAG,OAAO,CAClC,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAClD,CAAA;AAED,eAAO,MAAM,cAAc,GACvB,YAAY,UAAU,EACtB,SAAS,MAAM,EACf,OAAO,KAAK,EACZ,qBAAqB,mBAAmB,EACxC,aAAa,WAAW,GAAG,SAAS,EACpC,SAAS,uBAAuB,EAChC,SAAS,MAAM,EACf,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwhCvB,CAAA"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/user-api/controller.ts"],"names":[],"mappings":"AA+CA,OAAO,EAAE,KAAK,EAAW,MAAM,mCAAmC,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,EAEH,WAAW,EAKd,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAYnE,eAAO,MAAM,cAAc,GACvB,YAAY,UAAU,EACtB,SAAS,MAAM,EACf,OAAO,KAAK,EACZ,qBAAqB,mBAAmB,EACxC,aAAa,WAAW,GAAG,SAAS,EACpC,SAAS,cAAc,EACvB,SAAS,MAAM,EACf,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgiCvB,CAAA"}