@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
@@ -4,9 +4,18 @@ import { assertConnected, AuthTokenProvider, } from '@canton-network/core-wallet
4
4
  import buildController from './rpc-gen/index.js';
5
5
  import { LedgerClient, } from '@canton-network/core-ledger-client';
6
6
  import { v4 } from 'uuid';
7
- import { networkStatus, ledgerPrepareParams } from '../utils.js';
8
- export const dappController = (kernelInfo, dappUrl, userUrl, store, notificationService, _logger, origin, context) => {
7
+ import { networkStatus, ledgerPrepareParams, logDynamically } from '../utils.js';
8
+ import { TransactionService } from '../ledger/transaction-service.js';
9
+ import { rpcErrors } from '@canton-network/core-rpc-errors';
10
+ export const dappController = (kernelInfo, dappUrl, userUrl, store, notificationService, _logger, origin, deps, context) => {
9
11
  const logger = _logger.child({ component: 'dapp-controller' });
12
+ function assertActAsPartiesBelongToUser(actAs, wallets) {
13
+ for (const party of actAs) {
14
+ if (wallets.find((w) => w.partyId === party) === undefined) {
15
+ throw rpcErrors.invalidRequest(`Acting party ${party} does not belong to user`);
16
+ }
17
+ }
18
+ }
10
19
  return buildController({
11
20
  connect: async () => {
12
21
  if (!context || !(await store.getSession())) {
@@ -126,51 +135,116 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
126
135
  return result;
127
136
  },
128
137
  prepareExecute: async (params) => {
129
- const wallet = await store.getPrimaryWallet();
138
+ const primaryWallet = await store.getPrimaryWallet();
139
+ const wallets = await store.getWallets();
130
140
  const network = await store.getCurrentNetwork();
131
141
  if (context === undefined) {
132
142
  throw new Error('Unauthenticated context');
133
143
  }
144
+ // determine user ID
145
+ const gatewayUserId = context.userId;
146
+ let ledgerUserId = context.userId;
147
+ const accessTokenProvider = AuthTokenProvider.fromToken(context.accessToken, logger);
148
+ if (context?.isApiKey) {
149
+ logger.info('Authenticated with API Key, fetching m2m token for ledger access');
150
+ ledgerUserId = context.ledgerUserId;
151
+ }
152
+ // determine party ID
153
+ let actAs = params.actAs || [];
154
+ if (actAs.length === 0) {
155
+ if (!primaryWallet) {
156
+ throw new Error('No primary wallet found. Create or sync a wallet and set it as primary before prepareExecute.');
157
+ }
158
+ actAs = [primaryWallet.partyId];
159
+ }
160
+ assertActAsPartiesBelongToUser(actAs, wallets);
161
+ // determine wallet
162
+ const wallet = wallets.find((w) => w.partyId === actAs[0]);
134
163
  if (wallet === undefined) {
135
- throw new Error('No primary wallet found');
164
+ throw new Error('No wallet found for the first acting party. Create or sync a wallet and set it as primary before prepareExecute.');
136
165
  }
137
166
  const ledgerClient = new LedgerClient({
138
167
  baseUrl: new URL(network.ledgerApi.baseUrl),
139
168
  logger,
140
- accessTokenProvider: AuthTokenProvider.fromToken(context.accessToken, logger),
169
+ accessTokenProvider,
141
170
  });
142
- const userId = context.userId;
143
- const notifier = notificationService.getNotifier(userId);
144
- params.commandId = params.commandId || v4();
145
- const commandId = params.commandId;
171
+ const notifier = notificationService.getNotifier(gatewayUserId);
172
+ const commandId = params.commandId || v4();
146
173
  const transactionId = v4();
147
174
  notifier.emit('txChanged', { status: 'pending', commandId });
148
175
  const synchronizerId = network.synchronizerId ??
149
176
  (await ledgerClient.getSynchronizerId());
150
- const response = await prepareSubmission(context.userId, wallet.partyId, synchronizerId, params, ledgerClient);
177
+ logDynamically(logger, 'prepareExecute: Submitting request to ledger', {
178
+ info: { transactionId },
179
+ debug: {
180
+ commandId,
181
+ gatewayUserId,
182
+ ledgerUserId,
183
+ actAs,
184
+ params,
185
+ },
186
+ });
187
+ const prepared = await prepareSubmission(ledgerUserId, actAs, synchronizerId, params, ledgerClient);
188
+ logDynamically(logger, 'prepareExecute: Received response from ledger', {
189
+ info: { transactionId },
190
+ debug: {
191
+ commandId,
192
+ gatewayUserId,
193
+ ledgerUserId,
194
+ actAs,
195
+ prepared,
196
+ },
197
+ });
151
198
  const transaction = {
152
199
  id: transactionId,
153
200
  commandId,
154
201
  status: 'pending',
155
- preparedTransaction: response.preparedTransaction,
156
- preparedTransactionHash: response.preparedTransactionHash,
202
+ preparedTransaction: prepared.preparedTransaction,
203
+ preparedTransactionHash: prepared.preparedTransactionHash,
157
204
  payload: params,
158
205
  origin: origin || null,
159
206
  createdAt: new Date(),
160
207
  };
161
208
  logger.info({
162
- actAs: params.actAs || [wallet.partyId],
209
+ actAs,
163
210
  readAs: params.readAs || [],
164
- userId: context.userId,
211
+ gatewayUserId,
212
+ ledgerUserId,
165
213
  commandId,
166
214
  commands: params.commands?.[0],
167
- confirmationRequestTrafficCostEstimation: response.costEstimation
215
+ confirmationRequestTrafficCostEstimation: prepared.costEstimation
168
216
  ?.confirmationRequestTrafficCostEstimation,
169
217
  }, 'prepared transaction traffic estimation');
170
218
  await store.setTransaction(transaction);
219
+ const approveUrl = `${userUrl}/approve/index.html?transactionId=${transactionId}&commandId=${commandId}&closeafteraction`;
220
+ if (context.isApiKey) {
221
+ logger.info({
222
+ gatewayUserId,
223
+ ledgerUserId,
224
+ commandId,
225
+ transactionId,
226
+ signingProviderId: wallet.signingProviderId,
227
+ }, 'Service account straight-through prepare/sign/execute');
228
+ const transactionService = new TransactionService(store, logger, deps.signingDrivers, notifier);
229
+ try {
230
+ await transactionService.signAndExecute(context, network, wallet, transaction);
231
+ }
232
+ catch (error) {
233
+ logger.error({
234
+ err: error,
235
+ gatewayUserId,
236
+ ledgerUserId,
237
+ commandId,
238
+ transactionId,
239
+ actAs,
240
+ signingProviderId: wallet.signingProviderId,
241
+ }, 'Service account sign/execute failed after prepare');
242
+ throw error;
243
+ }
244
+ }
171
245
  return {
172
246
  // closeafteraction query param flag makes approving or deleting tx close the popup
173
- userUrl: `${userUrl}/approve/index.html?transactionId=${transactionId}&commandId=${commandId}&closeafteraction`,
247
+ userUrl: approveUrl,
174
248
  };
175
249
  },
176
250
  status: async () => {
@@ -221,21 +295,9 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
221
295
  userUrl: `${userUrl}/login/`,
222
296
  };
223
297
  },
224
- connected: async () => {
225
- throw new Error('Only for events.');
226
- },
227
- onStatusChanged: async () => {
228
- throw new Error('Only for events.');
229
- },
230
- accountsChanged: async () => {
231
- throw new Error('Only for events.');
232
- },
233
298
  listAccounts: async () => {
234
299
  return await store.getWallets();
235
300
  },
236
- txChanged: async () => {
237
- throw new Error('Only for events.');
238
- },
239
301
  getActiveNetwork: async () => {
240
302
  const network = await store.getCurrentNetwork();
241
303
  return {
@@ -284,11 +346,23 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
284
346
  }
285
347
  return wallet;
286
348
  },
349
+ connected: async () => {
350
+ throw new Error('Only for events.');
351
+ },
352
+ onStatusChanged: async () => {
353
+ throw new Error('Only for events.');
354
+ },
355
+ accountsChanged: async () => {
356
+ throw new Error('Only for events.');
357
+ },
358
+ txChanged: async () => {
359
+ throw new Error('Only for events.');
360
+ },
287
361
  messageSignature: function () {
288
362
  throw new Error('Only for events.');
289
363
  },
290
364
  });
291
365
  };
292
- async function prepareSubmission(userId, partyId, synchronizerId, params, ledgerClient) {
293
- return await ledgerClient.postWithRetry('/v2/interactive-submission/prepare', ledgerPrepareParams(userId, partyId, synchronizerId, params));
366
+ async function prepareSubmission(userId, partyIds, synchronizerId, params, ledgerClient) {
367
+ return await ledgerClient.postWithRetry('/v2/interactive-submission/prepare', ledgerPrepareParams(userId, partyIds, synchronizerId, params));
294
368
  }
@@ -107,8 +107,8 @@ async function createStore(logger, context, options = {}) {
107
107
  }
108
108
  return store;
109
109
  }
110
- function createController(store, notificationService, logger, context, requestOrigin = origin) {
111
- return dappController(kernelInfo, dappUrl, userUrl, store, notificationService, logger, requestOrigin, context);
110
+ function createController(store, notificationService, logger, context, requestOrigin = origin, deps) {
111
+ return dappController(kernelInfo, dappUrl, userUrl, store, notificationService, logger, requestOrigin, deps || { signingDrivers: {} }, context);
112
112
  }
113
113
  describe('dappController', () => {
114
114
  let logger;
@@ -1,9 +1,10 @@
1
1
  import express from 'express';
2
2
  import { Logger } from 'pino';
3
3
  import { Store } from '@canton-network/core-wallet-store';
4
- import { AuthService, AuthAware } from '@canton-network/core-wallet-auth';
4
+ import { AuthAware } from '@canton-network/core-wallet-auth';
5
5
  import { Server } from 'http';
6
6
  import { NotificationService } from '../notification/NotificationService.js';
7
7
  import { KernelInfo, ServerConfig } from '../config/Config.js';
8
- export declare const dapp: (route: string, app: express.Express, logger: Logger, server: Server, kernelInfo: KernelInfo, dappUrl: string, userUrl: string, serverConfig: ServerConfig, notificationService: NotificationService, authService: AuthService, store: Store & AuthAware<Store>) => Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>;
8
+ import { DappControllerDeps } from './controller.js';
9
+ export declare const dapp: (route: string, app: express.Express, logger: Logger, server: Server, kernelInfo: KernelInfo, dappUrl: string, userUrl: string, serverConfig: ServerConfig, notificationService: NotificationService, store: Store & AuthAware<Store>, controllerDeps: DappControllerDeps) => Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>;
9
10
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dapp-api/server.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,SAAS,CAAA;AAG7B,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAG7B,OAAO,EAAE,KAAK,EAAE,MAAM,mCAAmC,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAO9D,eAAO,MAAM,IAAI,GACb,OAAO,MAAM,EACb,KAAK,OAAO,CAAC,OAAO,EACpB,QAAQ,MAAM,EACd,QAAQ,MAAM,EACd,YAAY,UAAU,EACtB,SAAS,MAAM,EACf,SAAS,MAAM,EACf,cAAc,YAAY,EAC1B,qBAAqB,mBAAmB,EACxC,aAAa,WAAW,EACxB,OAAO,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,kGA4FlC,CAAA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dapp-api/server.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,SAAS,CAAA;AAG7B,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAG7B,OAAO,EAAE,KAAK,EAAE,MAAM,mCAAmC,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAOpD,eAAO,MAAM,IAAI,GACb,OAAO,MAAM,EACb,KAAK,OAAO,CAAC,OAAO,EACpB,QAAQ,MAAM,EACd,QAAQ,MAAM,EACd,YAAY,UAAU,EACtB,SAAS,MAAM,EACf,SAAS,MAAM,EACf,cAAc,YAAY,EAC1B,qBAAqB,mBAAmB,EACxC,OAAO,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,EAC/B,gBAAgB,kBAAkB,kGA6FrC,CAAA"}
@@ -7,7 +7,7 @@ function writeSSE(res, event, data) {
7
7
  res.write(`event: ${event}\n`);
8
8
  res.write(`data: ${JSON.stringify(data)}\n\n`);
9
9
  }
10
- export const dapp = (route, app, logger, server, kernelInfo, dappUrl, userUrl, serverConfig, notificationService, authService, store) => {
10
+ export const dapp = (route, app, logger, server, kernelInfo, dappUrl, userUrl, serverConfig, notificationService, store, controllerDeps) => {
11
11
  app.use(cors({
12
12
  origin: serverConfig.allowedOrigins,
13
13
  }));
@@ -67,7 +67,7 @@ export const dapp = (route, app, logger, server, kernelInfo, dappUrl, userUrl, s
67
67
  app.use(route, (req, res, next) => {
68
68
  const origin = req.headers.origin ?? null;
69
69
  jsonRpcHandler({
70
- controller: dappController(kernelInfo, dappUrl, userUrl, store.withAuthContext(req.authContext), notificationService, logger, origin, req.authContext),
70
+ controller: dappController(kernelInfo, dappUrl, userUrl, store.withAuthContext(req.authContext), notificationService, logger, origin, controllerDeps, req.authContext),
71
71
  logger,
72
72
  })(req, res, next);
73
73
  });
@@ -11,11 +11,6 @@ import { NotificationService } from '../notification/NotificationService.js';
11
11
  import { pino } from 'pino';
12
12
  import { sink } from 'pino-test';
13
13
  import { createServer } from 'http';
14
- const authService = {
15
- verifyToken: async () => {
16
- return new Promise((resolve) => resolve({ userId: 'user123', accessToken: 'token123' }));
17
- },
18
- };
19
14
  const configPath = '../test/config.json';
20
15
  const config = ConfigUtils.loadConfigFile(configPath);
21
16
  const store = new StoreInternal(config.bootstrap, pino(sink()));
@@ -26,7 +21,7 @@ test('call connect rpc', async () => {
26
21
  app.use(express.json());
27
22
  const server = createServer(app);
28
23
  const { dappApiUrl, publicUrl } = deriveUrls(config);
29
- const response = await request(dapp('/api/v0/dapp', app, pino(sink()), server, config.kernel, dappApiUrl, publicUrl, config.server, notificationService, authService, store))
24
+ const response = await request(dapp('/api/v0/dapp', app, pino(sink()), server, config.kernel, dappApiUrl, publicUrl, config.server, notificationService, store, { signingDrivers: {} }))
30
25
  .post('/api/v0/dapp')
31
26
  .send({ jsonrpc: '2.0', id: 0, method: 'connect', params: [] })
32
27
  .set('Accept', 'application/json');
@@ -16,6 +16,9 @@ declare const _default: {
16
16
  requestRateLimit: number;
17
17
  trustProxy: false;
18
18
  admin: string;
19
+ signingWorker: {
20
+ pollInterval: number;
21
+ };
19
22
  };
20
23
  signingStore: {
21
24
  connection: {
@@ -1 +1 @@
1
- {"version":3,"file":"example-config.d.ts","sourceRoot":"","sources":["../src/example-config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,wBAkGqB"}
1
+ {"version":3,"file":"example-config.d.ts","sourceRoot":"","sources":["../src/example-config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,wBAqGqB"}
@@ -18,6 +18,9 @@ export default {
18
18
  requestRateLimit: 10000,
19
19
  trustProxy: false,
20
20
  admin: 'sub',
21
+ signingWorker: {
22
+ pollInterval: 5000,
23
+ },
21
24
  },
22
25
  signingStore: {
23
26
  connection: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAkFA,QAAA,MAAM,OAAO;;;;;;;CAAiB,CAAA;AAE9B,MAAM,MAAM,UAAU,GAAG,OAAO,OAAO,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4FA,QAAA,MAAM,OAAO;;;;;;;CAAiB,CAAA;AAE9B,MAAM,MAAM,UAAU,GAAG,OAAO,OAAO,CAAA"}
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ import z from 'zod';
13
13
  import { rawConfigSchema } from './config/Config.js';
14
14
  import exampleConfig from './example-config.js';
15
15
  import { GATEWAY_VERSION } from './version.js';
16
+ import { nestedRedact } from './utils.js';
16
17
  const program = new Command()
17
18
  .name('wallet-gateway')
18
19
  .version(GATEWAY_VERSION)
@@ -49,6 +50,15 @@ const program = new Command()
49
50
  // Define project-global logger
50
51
  const logger = pino({
51
52
  name: 'main',
53
+ redact: {
54
+ paths: nestedRedact([
55
+ 'accessToken',
56
+ 'access_token',
57
+ 'clientSecret',
58
+ 'jwt',
59
+ ]),
60
+ censor: '*****',
61
+ },
52
62
  level: logLevel,
53
63
  ...(logFormat === 'pretty'
54
64
  ? {
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AA2B7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAsMvC,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAkKhE"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAyB7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAyMvC,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAmLhE"}
package/dist/init.js CHANGED
@@ -6,7 +6,7 @@ import { web } from './web/server.js';
6
6
  import { StoreSql, bootstrap, connection, migrator, } from '@canton-network/core-wallet-store-sql';
7
7
  import { StoreSql as SigningStoreSql, bootstrap as signingBootstrap, connection as signingConnection, migrator as signingMigrator, } from '@canton-network/core-signing-store-sql';
8
8
  import { ConfigUtils } from './config/ConfigUtils.js';
9
- import { SigningProvider, } from '@canton-network/core-signing-lib';
9
+ import { SigningProvider } from '@canton-network/core-signing-lib';
10
10
  import { ParticipantSigningDriver } from '@canton-network/core-signing-participant';
11
11
  import { InternalSigningDriver } from '@canton-network/core-signing-internal';
12
12
  import DfnsSigningProvider from '@canton-network/core-signing-dfns';
@@ -23,7 +23,10 @@ import { sessionHandler } from './middleware/sessionHandler.js';
23
23
  import { NotificationService } from './notification/NotificationService.js';
24
24
  import { sql } from 'kysely';
25
25
  import { Env } from './env.js';
26
+ import { SigningWorker } from './signing/signing-worker.js';
27
+ import { apiKeyAuth } from './middleware/apiKeyAuth.js';
26
28
  let isReady = false;
29
+ let signingWorker;
27
30
  async function initializeDatabase(config, logger) {
28
31
  logger.info('Checking for database migrations...');
29
32
  let exists = true;
@@ -227,15 +230,24 @@ export async function initialize(opts, logger) {
227
230
  'selfSignedAccessToken',
228
231
  ],
229
232
  };
230
- app.use('/api/*splat', express.json());
231
- app.use('/api/*splat', preAuthRateLimit);
232
- app.use('/api/*splat', jwtAuth(authService, logger.child({ component: 'JwtHandler' })));
233
- app.use('/api/*splat', postAuthRateLimit);
234
- app.use('/api/*splat', sessionHandler(store, allowedPaths, logger.child({ component: 'SessionHandler' })));
233
+ app.use('/api/*splat', express.json(), preAuthRateLimit, apiKeyAuth(store, config.server.dappPath, logger.child({ component: 'ApiKeyHandler' })), jwtAuth(authService, logger.child({ component: 'JwtHandler' })), postAuthRateLimit, sessionHandler(store, allowedPaths, logger.child({ component: 'SessionHandler' })));
235
234
  logger.info({ ...config.server, port }, 'Server configuration');
236
235
  const kernelInfo = config.kernel;
236
+ const signingWorkerLogger = logger.child({
237
+ component: 'SigningWorker',
238
+ });
239
+ signingWorker = new SigningWorker({
240
+ intervalMs: config.server.signingWorker.pollInterval,
241
+ signingDrivers: drivers,
242
+ store,
243
+ notificationService,
244
+ logger: signingWorkerLogger,
245
+ });
246
+ signingWorker.start();
237
247
  // register dapp API handlers
238
- dapp(config.server.dappPath, app, logger, server, kernelInfo, dappApiUrl, publicUrl, config.server, notificationService, authService, store);
248
+ dapp(config.server.dappPath, app, logger, server, kernelInfo, dappApiUrl, publicUrl, config.server, notificationService, store, {
249
+ signingDrivers: drivers,
250
+ });
239
251
  // register user API handlers
240
252
  user(config.server.userPath, app, logger, kernelInfo, publicUrl, notificationService, drivers, store, config.server.admin);
241
253
  // register web handler
@@ -2,35 +2,40 @@ import { Logger } from 'pino';
2
2
  import { LedgerClient } from '@canton-network/core-ledger-client';
3
3
  import { Store, Transaction, Wallet, Network } from '@canton-network/core-wallet-store';
4
4
  import type { SignResult } from '../user-api/rpc-gen/typings.js';
5
- import { SigningDriverInterface, SigningProvider } from '@canton-network/core-signing-lib';
6
- import { ExecuteParams, ExecuteResult, SignParams, SignResultSigned } from '../user-api/rpc-gen/typings.js';
5
+ import type { SigningDrivers } from '../signing/signing-drivers.js';
6
+ import { ExecuteParams, ExecuteResult, SignParams } from '../user-api/rpc-gen/typings.js';
7
7
  import { UserId } from '../dapp-api/rpc-gen/typings.js';
8
8
  import { Notifier } from '../notification/NotificationService.js';
9
+ import { AuthContext } from '@canton-network/core-wallet-auth';
10
+ export type SignAndExecuteResult = SignResult | ExecuteResult;
9
11
  export declare class TransactionService {
10
12
  private store;
11
13
  private logger;
12
14
  private signingDrivers;
13
15
  private notifier;
14
- constructor(store: Store, logger: Logger, signingDrivers: Partial<Record<SigningProvider, SigningDriverInterface>> | undefined, notifier: Notifier);
16
+ constructor(store: Store, logger: Logger, signingDrivers: SigningDrivers | undefined, notifier: Notifier);
17
+ sign(authContext: AuthContext, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
18
+ execute(userId: UserId, wallet: Wallet, transaction: Transaction, executeParams?: ExecuteParams, ledgerClient?: LedgerClient, network?: Network): Promise<ExecuteResult>;
19
+ signAndExecute(authContext: AuthContext, network: Network, wallet: Wallet, transaction: Transaction): Promise<SignAndExecuteResult>;
15
20
  private loadPreparedTransactionForSigning;
16
- signWithParticipant(wallet: Wallet): SignResultSigned;
17
- signWithWalletKernel(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResultSigned>;
18
- signWithBlockdaemon(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
19
- signWithFireblocks(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
21
+ private signWithParticipant;
22
+ private signWithWalletKernel;
23
+ private signWithBlockdaemon;
24
+ private signWithFireblocks;
20
25
  /**
21
26
  * Dfns broadcasts the prepared transaction to Canton itself, so we get back
22
27
  * an updateId rather than a raw signature. We persist the updateId as the
23
28
  * signature payload (the controller short-circuits Dfns execute) and surface
24
29
  * the same SignResult shape the other external providers use.
25
30
  */
26
- signWithDfns(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
31
+ private signWithDfns;
27
32
  /**
28
33
  * Dfns has already broadcast the transaction at sign-time, so execute is a
29
34
  * state reconciliation: mark the stored transaction as executed and return
30
35
  * the updateId Dfns gave us. We deliberately don't post to the ledger here.
31
36
  */
32
- executeWithDfns(transaction: Transaction): Promise<ExecuteResult>;
33
- executeWithParticipant(userId: UserId, executeParams: ExecuteParams, transaction: Transaction, ledgerClient: LedgerClient, network: Network): Promise<ExecuteResult>;
34
- executeWithExternal(userId: UserId, executeParams: ExecuteParams, transaction: Transaction, ledgerClient: LedgerClient): Promise<ExecuteResult>;
37
+ private executeWithDfns;
38
+ private executeWithParticipant;
39
+ private executeWithExternal;
35
40
  }
36
41
  //# sourceMappingURL=transaction-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transaction-service.d.ts","sourceRoot":"","sources":["../../src/ledger/transaction-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACjE,OAAO,EACH,KAAK,EACL,WAAW,EACX,MAAM,EACN,OAAO,EACV,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,EAGH,sBAAsB,EACtB,eAAe,EAElB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EACH,aAAa,EACb,aAAa,EACb,UAAU,EACV,gBAAgB,EACnB,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAA;AAYjE,qBAAa,kBAAkB;IAEvB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IAGtB,OAAO,CAAC,QAAQ;gBALR,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,OAAO,CAC3B,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAClD,YAAK,EACE,QAAQ,EAAE,QAAQ;YAGhB,iCAAiC;IAWxC,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAS/C,oBAAoB,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACvB,OAAO,CAAC,gBAAgB,CAAC;IAqDf,mBAAmB,CAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACvB,OAAO,CAAC,UAAU,CAAC;IAwGT,kBAAkB,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACvB,OAAO,CAAC,UAAU,CAAC;IA4GtB;;;;;OAKG;IACU,YAAY,CACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACvB,OAAO,CAAC,UAAU,CAAC;IAkGtB;;;;OAIG;IACU,eAAe,CACxB,WAAW,EAAE,WAAW,GACzB,OAAO,CAAC,aAAa,CAAC;IA8BZ,sBAAsB,CAC/B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,OAAO,GACjB,OAAO,CAAC,aAAa,CAAC;IAyCZ,mBAAmB,CAC5B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,GAC3B,OAAO,CAAC,aAAa,CAAC;CAuD5B"}
1
+ {"version":3,"file":"transaction-service.d.ts","sourceRoot":"","sources":["../../src/ledger/transaction-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACjE,OAAO,EACH,KAAK,EACL,WAAW,EACX,MAAM,EACN,OAAO,EACV,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAOhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EACH,aAAa,EACb,aAAa,EACb,UAAU,EAEb,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAA;AAMjE,OAAO,EACH,WAAW,EAEd,MAAM,kCAAkC,CAAA;AAEzC,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,aAAa,CAAA;AAW7D,qBAAa,kBAAkB;IAEvB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,QAAQ;gBAHR,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,YAAK,EACnC,QAAQ,EAAE,QAAQ;IAGjB,IAAI,CACb,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACvB,OAAO,CAAC,UAAU,CAAC;IAiDf,OAAO,CACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,aAAa,CAAC,EAAE,aAAa,EAC7B,YAAY,CAAC,EAAE,YAAY,EAC3B,OAAO,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,aAAa,CAAC;IAiEZ,cAAc,CACvB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,GACzB,OAAO,CAAC,oBAAoB,CAAC;YAyDlB,iCAAiC;IAkB/C,OAAO,CAAC,mBAAmB;YASb,oBAAoB;YAyDpB,mBAAmB;YAiHnB,kBAAkB;IAqHhC;;;;;OAKG;YACW,YAAY;IA2G1B;;;;OAIG;YACW,eAAe;YAgCf,sBAAsB;YAoDtB,mBAAmB;CAiEpC"}