@canton-network/wallet-gateway-remote 1.4.0 → 1.5.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 (116) 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 +60 -4
  10. package/dist/config/Config.d.ts.map +1 -1
  11. package/dist/config/Config.js +1 -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.map +1 -1
  15. package/dist/dapp-api/controller.js +54 -24
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +10 -0
  18. package/dist/init.d.ts.map +1 -1
  19. package/dist/init.js +3 -6
  20. package/dist/ledger/transaction-service.d.ts +14 -11
  21. package/dist/ledger/transaction-service.d.ts.map +1 -1
  22. package/dist/ledger/transaction-service.js +95 -8
  23. package/dist/ledger/transaction-service.test.d.ts +2 -0
  24. package/dist/ledger/transaction-service.test.d.ts.map +1 -0
  25. package/dist/ledger/transaction-service.test.js +356 -0
  26. package/dist/ledger/wallet-allocation/signing-providers/fireblocks-wallet-allocator.d.ts +5 -2
  27. package/dist/ledger/wallet-allocation/signing-providers/fireblocks-wallet-allocator.d.ts.map +1 -1
  28. package/dist/ledger/wallet-allocation/signing-providers/fireblocks-wallet-allocator.js +7 -6
  29. package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts +11 -5
  30. package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts.map +1 -1
  31. package/dist/ledger/wallet-allocation/wallet-allocation-service.js +28 -14
  32. package/dist/ledger/wallet-allocation/wallet-allocation-service.test.js +550 -19
  33. package/dist/ledger/wallet-sync-service.js +3 -3
  34. package/dist/middleware/apiKeyAuth.d.ts +6 -0
  35. package/dist/middleware/apiKeyAuth.d.ts.map +1 -0
  36. package/dist/middleware/apiKeyAuth.js +88 -0
  37. package/dist/middleware/apiKeyAuth.test.d.ts +2 -0
  38. package/dist/middleware/apiKeyAuth.test.d.ts.map +1 -0
  39. package/dist/middleware/apiKeyAuth.test.js +126 -0
  40. package/dist/middleware/jsonRpcHandler.d.ts +11 -1
  41. package/dist/middleware/jsonRpcHandler.d.ts.map +1 -1
  42. package/dist/middleware/jsonRpcHandler.js +14 -15
  43. package/dist/middleware/jsonRpcHandler.test.d.ts +2 -0
  44. package/dist/middleware/jsonRpcHandler.test.d.ts.map +1 -0
  45. package/dist/middleware/jsonRpcHandler.test.js +254 -0
  46. package/dist/middleware/jwtAuth.d.ts.map +1 -1
  47. package/dist/middleware/jwtAuth.js +4 -0
  48. package/dist/middleware/jwtAuth.test.d.ts +2 -0
  49. package/dist/middleware/jwtAuth.test.d.ts.map +1 -0
  50. package/dist/middleware/jwtAuth.test.js +93 -0
  51. package/dist/middleware/rateLimit.test.js +12 -0
  52. package/dist/middleware/sessionHandler.js +1 -1
  53. package/dist/middleware/sessionHandler.test.d.ts +2 -0
  54. package/dist/middleware/sessionHandler.test.d.ts.map +1 -0
  55. package/dist/middleware/sessionHandler.test.js +121 -0
  56. package/dist/notification/NotificationService.test.d.ts +2 -0
  57. package/dist/notification/NotificationService.test.d.ts.map +1 -0
  58. package/dist/notification/NotificationService.test.js +110 -0
  59. package/dist/signing/signing-drivers.d.ts +7 -0
  60. package/dist/signing/signing-drivers.d.ts.map +1 -0
  61. package/dist/signing/signing-drivers.js +3 -0
  62. package/dist/user-api/controller.d.ts +6 -4
  63. package/dist/user-api/controller.d.ts.map +1 -1
  64. package/dist/user-api/controller.js +111 -94
  65. package/dist/user-api/controller.test.d.ts +2 -0
  66. package/dist/user-api/controller.test.d.ts.map +1 -0
  67. package/dist/user-api/controller.test.js +862 -0
  68. package/dist/user-api/rpc-gen/index.d.ts +12 -0
  69. package/dist/user-api/rpc-gen/index.d.ts.map +1 -1
  70. package/dist/user-api/rpc-gen/index.js +4 -0
  71. package/dist/user-api/rpc-gen/typings.d.ts +52 -3
  72. package/dist/user-api/rpc-gen/typings.d.ts.map +1 -1
  73. package/dist/utils.d.ts +17 -1
  74. package/dist/utils.d.ts.map +1 -1
  75. package/dist/utils.js +53 -2
  76. package/dist/utils.test.d.ts +2 -0
  77. package/dist/utils.test.d.ts.map +1 -0
  78. package/dist/utils.test.js +24 -0
  79. package/dist/web/frontend/404/index.html +2 -2
  80. package/dist/web/frontend/activities/index.html +3 -3
  81. package/dist/web/frontend/approve/index.html +4 -4
  82. package/dist/web/frontend/assets/404-MVLWUPwN.js +5 -0
  83. package/dist/web/frontend/assets/{activities-NY8oZAkH.js → activities-DaWkmGqA.js} +2 -2
  84. package/dist/web/frontend/assets/{addIdentityProvider-38ghz3RT.js → addIdentityProvider--rBb0ihb.js} +2 -2
  85. package/dist/web/frontend/assets/{addNetwork-BaDhbrZl.js → addNetwork-C6UDsRkU.js} +4 -4
  86. package/dist/web/frontend/assets/addParty-B3fFD1eM.js +45 -0
  87. package/dist/web/frontend/assets/approve-WbGL4E82.js +21 -0
  88. package/dist/web/frontend/assets/callback--tihEryB.js +1 -0
  89. package/dist/web/frontend/assets/{identityProviders-BZ9h_VOJ.js → identityProviders-Dra4qG6t.js} +2 -2
  90. package/dist/web/frontend/assets/{index-B-HiKugW.js → index-Bm76pXA_.js} +2 -2
  91. package/dist/web/frontend/assets/index-D1dC4Cl9.js +4477 -0
  92. package/dist/web/frontend/assets/{login-CqwMEG9J.js → login-BC8a-kD_.js} +2 -2
  93. package/dist/web/frontend/assets/{networks-BJvRi47M.js → networks-B3ztsogL.js} +2 -2
  94. package/dist/web/frontend/assets/{reviewIdentityProvider-ySlQnw5R.js → reviewIdentityProvider-Co420Dbk.js} +3 -3
  95. package/dist/web/frontend/assets/{reviewNetwork-DrVxeHd4.js → reviewNetwork-B-Sh8pCH.js} +3 -3
  96. package/dist/web/frontend/assets/{settings-BVNkaUyJ.js → settings-DvyUjqLl.js} +1 -1
  97. package/dist/web/frontend/assets/{state-qAsNw5qf.js → state-Bq65GwdF.js} +1 -1
  98. package/dist/web/frontend/assets/{utils-BDkHxi8V.js → utils-B2iziW8V.js} +1 -1
  99. package/dist/web/frontend/callback/index.html +2 -2
  100. package/dist/web/frontend/identity-providers/add/index.html +3 -3
  101. package/dist/web/frontend/identity-providers/index.html +3 -3
  102. package/dist/web/frontend/identity-providers/review/index.html +3 -3
  103. package/dist/web/frontend/index.html +1 -1
  104. package/dist/web/frontend/login/index.html +3 -3
  105. package/dist/web/frontend/networks/add/index.html +3 -3
  106. package/dist/web/frontend/networks/index.html +3 -3
  107. package/dist/web/frontend/networks/review/index.html +3 -3
  108. package/dist/web/frontend/parties/add/index.html +5 -5
  109. package/dist/web/frontend/parties/index.html +4 -4
  110. package/dist/web/frontend/settings/index.html +3 -3
  111. package/package.json +36 -32
  112. package/dist/web/frontend/assets/404-C7V2yl2z.js +0 -5
  113. package/dist/web/frontend/assets/addParty-j3JWZX5a.js +0 -41
  114. package/dist/web/frontend/assets/approve-43nVzAAC.js +0 -21
  115. package/dist/web/frontend/assets/callback-BBMiCjHR.js +0 -1
  116. package/dist/web/frontend/assets/index-DoNqknyE.js +0 -4042
@@ -4,7 +4,8 @@ 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';
7
+ import { networkStatus, ledgerPrepareParams, logDynamically } from '../utils.js';
8
+ import { rpcErrors } from '@canton-network/core-rpc-errors';
8
9
  export const dappController = (kernelInfo, dappUrl, userUrl, store, notificationService, _logger, origin, context) => {
9
10
  const logger = _logger.child({ component: 'dapp-controller' });
10
11
  return buildController({
@@ -127,6 +128,7 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
127
128
  },
128
129
  prepareExecute: async (params) => {
129
130
  const wallet = await store.getPrimaryWallet();
131
+ const wallets = await store.getWallets();
130
132
  const network = await store.getCurrentNetwork();
131
133
  if (context === undefined) {
132
134
  throw new Error('Unauthenticated context');
@@ -134,26 +136,54 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
134
136
  if (wallet === undefined) {
135
137
  throw new Error('No primary wallet found');
136
138
  }
139
+ let userId = context.userId;
140
+ const accessTokenProvider = AuthTokenProvider.fromToken(context.accessToken, logger);
141
+ if (context?.isApiKey) {
142
+ logger.info('Authenticated with API Key, fetching m2m token for ledger access');
143
+ userId = context.ledgerUserId;
144
+ }
137
145
  const ledgerClient = new LedgerClient({
138
146
  baseUrl: new URL(network.ledgerApi.baseUrl),
139
147
  logger,
140
- accessTokenProvider: AuthTokenProvider.fromToken(context.accessToken, logger),
148
+ accessTokenProvider,
141
149
  });
142
- const userId = context.userId;
143
150
  const notifier = notificationService.getNotifier(userId);
144
- params.commandId = params.commandId || v4();
145
- const commandId = params.commandId;
151
+ const commandId = params.commandId || v4();
146
152
  const transactionId = v4();
147
153
  notifier.emit('txChanged', { status: 'pending', commandId });
148
154
  const synchronizerId = network.synchronizerId ??
149
155
  (await ledgerClient.getSynchronizerId());
150
- const response = await prepareSubmission(context.userId, wallet.partyId, synchronizerId, params, ledgerClient);
156
+ let actAs = [wallet.partyId];
157
+ if (params.actAs && params.actAs.length > 0) {
158
+ actAs = params.actAs;
159
+ for (const actingParty of actAs) {
160
+ if (wallets.find((w) => w.partyId === actingParty) ===
161
+ undefined) {
162
+ throw rpcErrors.invalidRequest(`Acting party ${actingParty} does not belong to user`);
163
+ }
164
+ }
165
+ }
166
+ logDynamically(logger, 'prepareExecute: Submitting request to ledger', {
167
+ info: { transactionId },
168
+ debug: { commandId, userId, actAs },
169
+ });
170
+ const actAsParty = params.actAs || [wallet.partyId];
171
+ const prepared = await prepareSubmission(context.userId, actAsParty, synchronizerId, params, ledgerClient);
172
+ logDynamically(logger, 'prepareExecute: Received response from ledger', {
173
+ info: { transactionId },
174
+ debug: {
175
+ commandId,
176
+ userId,
177
+ partyId: actAsParty,
178
+ prepared,
179
+ },
180
+ });
151
181
  const transaction = {
152
182
  id: transactionId,
153
183
  commandId,
154
184
  status: 'pending',
155
- preparedTransaction: response.preparedTransaction,
156
- preparedTransactionHash: response.preparedTransactionHash,
185
+ preparedTransaction: prepared.preparedTransaction,
186
+ preparedTransactionHash: prepared.preparedTransactionHash,
157
187
  payload: params,
158
188
  origin: origin || null,
159
189
  createdAt: new Date(),
@@ -161,10 +191,10 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
161
191
  logger.info({
162
192
  actAs: params.actAs || [wallet.partyId],
163
193
  readAs: params.readAs || [],
164
- userId: context.userId,
194
+ userId,
165
195
  commandId,
166
196
  commands: params.commands?.[0],
167
- confirmationRequestTrafficCostEstimation: response.costEstimation
197
+ confirmationRequestTrafficCostEstimation: prepared.costEstimation
168
198
  ?.confirmationRequestTrafficCostEstimation,
169
199
  }, 'prepared transaction traffic estimation');
170
200
  await store.setTransaction(transaction);
@@ -221,21 +251,9 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
221
251
  userUrl: `${userUrl}/login/`,
222
252
  };
223
253
  },
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
254
  listAccounts: async () => {
234
255
  return await store.getWallets();
235
256
  },
236
- txChanged: async () => {
237
- throw new Error('Only for events.');
238
- },
239
257
  getActiveNetwork: async () => {
240
258
  const network = await store.getCurrentNetwork();
241
259
  return {
@@ -284,11 +302,23 @@ export const dappController = (kernelInfo, dappUrl, userUrl, store, notification
284
302
  }
285
303
  return wallet;
286
304
  },
305
+ connected: async () => {
306
+ throw new Error('Only for events.');
307
+ },
308
+ onStatusChanged: async () => {
309
+ throw new Error('Only for events.');
310
+ },
311
+ accountsChanged: async () => {
312
+ throw new Error('Only for events.');
313
+ },
314
+ txChanged: async () => {
315
+ throw new Error('Only for events.');
316
+ },
287
317
  messageSignature: function () {
288
318
  throw new Error('Only for events.');
289
319
  },
290
320
  });
291
321
  };
292
- async function prepareSubmission(userId, partyId, synchronizerId, params, ledgerClient) {
293
- return await ledgerClient.postWithRetry('/v2/interactive-submission/prepare', ledgerPrepareParams(userId, partyId, synchronizerId, params));
322
+ async function prepareSubmission(userId, partyIds, synchronizerId, params, ledgerClient) {
323
+ return await ledgerClient.postWithRetry('/v2/interactive-submission/prepare', ledgerPrepareParams(userId, partyIds, synchronizerId, params));
294
324
  }
@@ -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;AAuMvC,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAoKhE"}
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,6 +23,7 @@ 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 { apiKeyAuth } from './middleware/apiKeyAuth.js';
26
27
  let isReady = false;
27
28
  async function initializeDatabase(config, logger) {
28
29
  logger.info('Checking for database migrations...');
@@ -227,11 +228,7 @@ export async function initialize(opts, logger) {
227
228
  'selfSignedAccessToken',
228
229
  ],
229
230
  };
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' })));
231
+ 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
232
  logger.info({ ...config.server, port }, 'Server configuration');
236
233
  const kernelInfo = config.kernel;
237
234
  // register dapp API handlers
@@ -2,35 +2,38 @@ 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';
9
10
  export declare class TransactionService {
10
11
  private store;
11
12
  private logger;
12
13
  private signingDrivers;
13
14
  private notifier;
14
- constructor(store: Store, logger: Logger, signingDrivers: Partial<Record<SigningProvider, SigningDriverInterface>> | undefined, notifier: Notifier);
15
+ constructor(store: Store, logger: Logger, signingDrivers: SigningDrivers | undefined, notifier: Notifier);
16
+ sign(authContext: AuthContext, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
17
+ execute(userId: UserId, wallet: Wallet, transaction: Transaction, executeParams?: ExecuteParams, ledgerClient?: LedgerClient, network?: Network): Promise<ExecuteResult>;
15
18
  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>;
19
+ private signWithParticipant;
20
+ private signWithWalletKernel;
21
+ private signWithBlockdaemon;
22
+ private signWithFireblocks;
20
23
  /**
21
24
  * Dfns broadcasts the prepared transaction to Canton itself, so we get back
22
25
  * an updateId rather than a raw signature. We persist the updateId as the
23
26
  * signature payload (the controller short-circuits Dfns execute) and surface
24
27
  * the same SignResult shape the other external providers use.
25
28
  */
26
- signWithDfns(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
29
+ private signWithDfns;
27
30
  /**
28
31
  * Dfns has already broadcast the transaction at sign-time, so execute is a
29
32
  * state reconciliation: mark the stored transaction as executed and return
30
33
  * the updateId Dfns gave us. We deliberately don't post to the ledger here.
31
34
  */
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>;
35
+ private executeWithDfns;
36
+ private executeWithParticipant;
37
+ private executeWithExternal;
35
38
  }
36
39
  //# 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,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAW9D,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;YA6DX,iCAAiC;IAW/C,OAAO,CAAC,mBAAmB;YASb,oBAAoB;YAyDpB,mBAAmB;YAiHnB,kBAAkB;IAqHhC;;;;;OAKG;YACW,YAAY;IA2G1B;;;;OAIG;YACW,eAAe;YAgCf,sBAAsB;YAoDtB,mBAAmB;CAiEpC"}
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { SigningProvider, } from '@canton-network/core-signing-lib';
4
- import { ledgerPrepareParams } from '../utils.js';
4
+ import { ledgerPrepareParams, logDynamically, } from '../utils.js';
5
5
  function handleSigningError(result) {
6
6
  if ('error' in result) {
7
7
  throw new Error(`Error from signing driver: ${result.error_description}`);
@@ -15,6 +15,73 @@ export class TransactionService {
15
15
  this.signingDrivers = signingDrivers;
16
16
  this.notifier = notifier;
17
17
  }
18
+ async sign(authContext, wallet, signParams) {
19
+ const signingProvider = wallet.signingProviderId;
20
+ const driver = this.signingDrivers[signingProvider]?.controller(authContext.userId);
21
+ if (!driver) {
22
+ throw new Error(`No driver found for ${signingProvider}`);
23
+ }
24
+ switch (signingProvider) {
25
+ case SigningProvider.PARTICIPANT: {
26
+ return this.signWithParticipant(wallet);
27
+ }
28
+ case SigningProvider.WALLET_KERNEL: {
29
+ return this.signWithWalletKernel(authContext.userId, wallet, signParams);
30
+ }
31
+ case SigningProvider.BLOCKDAEMON: {
32
+ if (!authContext.email) {
33
+ throw new Error('Email is required for Blockdaemon wallet allocation');
34
+ }
35
+ return this.signWithBlockdaemon(authContext.email, wallet, signParams);
36
+ }
37
+ case SigningProvider.FIREBLOCKS: {
38
+ return this.signWithFireblocks(authContext.userId, wallet, signParams);
39
+ }
40
+ case SigningProvider.DFNS: {
41
+ return this.signWithDfns(authContext.userId, wallet, signParams);
42
+ }
43
+ default:
44
+ throw new Error(`Unsupported signing provider: ${wallet.signingProviderId}`);
45
+ }
46
+ }
47
+ execute(userId, wallet, transaction, executeParams, ledgerClient, network) {
48
+ switch (wallet.signingProviderId) {
49
+ case SigningProvider.PARTICIPANT: {
50
+ try {
51
+ if (!executeParams) {
52
+ throw new Error('Execute params are required for participant signing');
53
+ }
54
+ if (!ledgerClient) {
55
+ throw new Error('Ledger client is required for participant signing');
56
+ }
57
+ if (!network) {
58
+ throw new Error('Network is required for participant signing');
59
+ }
60
+ return this.executeWithParticipant(userId, executeParams, transaction, ledgerClient, network);
61
+ }
62
+ catch (error) {
63
+ this.logger.error(error, 'Failed to submit transaction');
64
+ throw error;
65
+ }
66
+ }
67
+ case SigningProvider.WALLET_KERNEL:
68
+ case SigningProvider.BLOCKDAEMON:
69
+ case SigningProvider.FIREBLOCKS: {
70
+ if (!executeParams) {
71
+ throw new Error('Execute params are required for external signing');
72
+ }
73
+ if (!ledgerClient) {
74
+ throw new Error('Ledger client is required for external signing');
75
+ }
76
+ return this.executeWithExternal(userId, executeParams, transaction, ledgerClient);
77
+ }
78
+ case SigningProvider.DFNS: {
79
+ return this.executeWithDfns(transaction);
80
+ }
81
+ default:
82
+ throw new Error(`Unsupported signing provider: ${wallet.signingProviderId}`);
83
+ }
84
+ }
18
85
  async loadPreparedTransactionForSigning(transactionId) {
19
86
  const existingTx = await this.store.getTransaction(transactionId);
20
87
  if (!existingTx) {
@@ -79,7 +146,7 @@ export class TransactionService {
79
146
  const driver = signingProvider.controller(userId);
80
147
  const tx = await this.loadPreparedTransactionForSigning(signParams.transactionId);
81
148
  let signingResult;
82
- if (tx && tx.externalTxId) {
149
+ if (tx.externalTxId) {
83
150
  signingResult = await driver
84
151
  .getTransaction({
85
152
  userId,
@@ -104,6 +171,10 @@ export class TransactionService {
104
171
  .then(handleSigningError);
105
172
  }
106
173
  const now = new Date();
174
+ logDynamically(this.logger, 'Blockdaemon signing result', {
175
+ info: { transactionId: tx.id, status: signingResult.status },
176
+ debug: { signingResult, tx },
177
+ });
107
178
  if (signingResult.status === 'signed') {
108
179
  if (!signingResult.signature) {
109
180
  throw new Error('No signature returned from signing driver');
@@ -164,7 +235,7 @@ export class TransactionService {
164
235
  const driver = signingProvider.controller(userId);
165
236
  const tx = await this.loadPreparedTransactionForSigning(signParams.transactionId);
166
237
  let signingResult;
167
- if (tx && tx.externalTxId) {
238
+ if (tx.externalTxId) {
168
239
  signingResult = await driver
169
240
  .getTransaction({
170
241
  userId,
@@ -185,6 +256,10 @@ export class TransactionService {
185
256
  .then(handleSigningError);
186
257
  }
187
258
  const now = new Date();
259
+ logDynamically(this.logger, 'Fireblocks signing result', {
260
+ info: { transactionId: tx.id, status: signingResult.status },
261
+ debug: { signingResult, tx },
262
+ });
188
263
  if (signingResult.status === 'signed') {
189
264
  if (!signingResult.signature) {
190
265
  throw new Error('No signature returned from signing driver');
@@ -273,6 +348,10 @@ export class TransactionService {
273
348
  .then(handleSigningError);
274
349
  }
275
350
  const now = new Date();
351
+ logDynamically(this.logger, 'Dfns signing result', {
352
+ info: { transactionId: tx.id, status: signingResult.status },
353
+ debug: { signingResult, tx },
354
+ });
276
355
  if (signingResult.status === 'signed') {
277
356
  if (!signingResult.signature) {
278
357
  throw new Error('No updateId returned from Dfns');
@@ -359,15 +438,19 @@ export class TransactionService {
359
438
  const { partyId } = executeParams;
360
439
  const { commandId } = transaction;
361
440
  const synchronizerId = network.synchronizerId ?? (await ledgerClient.getSynchronizerId());
362
- const prep = ledgerPrepareParams(userId, partyId, synchronizerId, transaction.payload);
363
- const res = await ledgerClient.postWithRetry('/v2/commands/submit-and-wait', prep);
441
+ const prep = ledgerPrepareParams(userId, [partyId], synchronizerId, transaction.payload);
442
+ const result = await ledgerClient.postWithRetry('/v2/commands/submit-and-wait', prep);
443
+ logDynamically(this.logger, 'Participant execution result', {
444
+ info: { transactionId: transaction.id },
445
+ debug: { result, transaction, executeParams, userId },
446
+ });
364
447
  const executedTx = {
365
448
  id: transaction.id,
366
449
  commandId,
367
450
  status: 'executed',
368
451
  preparedTransaction: transaction.preparedTransaction,
369
452
  preparedTransactionHash: transaction.preparedTransactionHash,
370
- payload: res,
453
+ payload: result,
371
454
  origin: transaction.origin ?? null,
372
455
  ...(transaction.createdAt && {
373
456
  createdAt: transaction.createdAt,
@@ -377,10 +460,10 @@ export class TransactionService {
377
460
  }),
378
461
  };
379
462
  await this.store.setTransactionStatus(transaction.id, 'executed', {
380
- payload: res,
463
+ payload: result,
381
464
  });
382
465
  this.notifier.emit('txChanged', executedTx);
383
- return res;
466
+ return result;
384
467
  }
385
468
  async executeWithExternal(userId, executeParams, transaction, ledgerClient) {
386
469
  const { partyId, signature, signedBy } = executeParams;
@@ -409,6 +492,10 @@ export class TransactionService {
409
492
  ],
410
493
  },
411
494
  });
495
+ logDynamically(this.logger, 'Externally signed execution result', {
496
+ info: { transactionId: transaction.id },
497
+ debug: { result, transaction, executeParams, userId },
498
+ });
412
499
  const executedTx = {
413
500
  id: transaction.id,
414
501
  commandId,
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transaction-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-service.test.d.ts","sourceRoot":"","sources":["../../src/ledger/transaction-service.test.ts"],"names":[],"mappings":""}