@canton-network/wallet-gateway-remote 1.1.0 → 1.2.1

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 (56) hide show
  1. package/README.md +14 -1
  2. package/dist/auth/jwt-auth-service.d.ts.map +1 -1
  3. package/dist/auth/jwt-auth-service.js +2 -3
  4. package/dist/env.d.ts +5 -0
  5. package/dist/env.d.ts.map +1 -1
  6. package/dist/env.js +5 -0
  7. package/dist/init.d.ts.map +1 -1
  8. package/dist/init.js +57 -1
  9. package/dist/ledger/transaction-service.d.ts +13 -0
  10. package/dist/ledger/transaction-service.d.ts.map +1 -1
  11. package/dist/ledger/transaction-service.js +117 -1
  12. package/dist/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.d.ts +23 -0
  13. package/dist/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.d.ts.map +1 -0
  14. package/dist/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.js +135 -0
  15. package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts +1 -0
  16. package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts.map +1 -1
  17. package/dist/ledger/wallet-allocation/wallet-allocation-service.js +17 -2
  18. package/dist/ledger/wallet-allocation/wallet-allocation-service.test.js +3 -3
  19. package/dist/user-api/controller.d.ts.map +1 -1
  20. package/dist/user-api/controller.js +6 -0
  21. package/dist/web/frontend/404/index.html +2 -2
  22. package/dist/web/frontend/activities/index.html +3 -3
  23. package/dist/web/frontend/approve/index.html +5 -5
  24. package/dist/web/frontend/assets/404-B-o9ppJB.js +5 -0
  25. package/dist/web/frontend/assets/{activities-4fnnetzm.js → activities-CGjCIjUH.js} +1 -1
  26. package/dist/web/frontend/assets/{addIdentityProvider-uy13wDEx.js → addIdentityProvider-CR4Wm9Tl.js} +2 -2
  27. package/dist/web/frontend/assets/{addNetwork-B9yARLXq.js → addNetwork-Dx0-SN4j.js} +3 -3
  28. package/dist/web/frontend/assets/addParty-COhk_rFn.js +41 -0
  29. package/dist/web/frontend/assets/{approve-DUxX18Xm.js → approve-B2w66l0J.js} +1 -1
  30. package/dist/web/frontend/assets/{callback-BGMELOxy.js → callback-BTVon_yQ.js} +1 -1
  31. package/dist/web/frontend/assets/{identityProviders-ByQNvF7K.js → identityProviders-CK8zSrd3.js} +2 -2
  32. package/dist/web/frontend/assets/{index-DcZcHMS1.js → index-CF4BKzgl.js} +2 -2
  33. package/dist/web/frontend/assets/{index-DvQio60y.js → index-DWz_3f3y.js} +1 -1
  34. package/dist/web/frontend/assets/{index-lfC4c213.js → index-_pMHlJoE.js} +94 -63
  35. package/dist/web/frontend/assets/{login-BtNyAQqL.js → login-CVoPNVDw.js} +2 -2
  36. package/dist/web/frontend/assets/{networks-B8bwNVkz.js → networks-D1nPvUzM.js} +2 -2
  37. package/dist/web/frontend/assets/{reviewIdentityProvider-CWDFtb4t.js → reviewIdentityProvider-CNSf2qQv.js} +4 -4
  38. package/dist/web/frontend/assets/{reviewNetwork-ZgS_rpXv.js → reviewNetwork-DGLK-Ume.js} +4 -4
  39. package/dist/web/frontend/assets/{settings-BiWW1vj2.js → settings-B1ga2TK0.js} +2 -2
  40. package/dist/web/frontend/assets/{state-BpQr_22x.js → state-B2k3ak7d.js} +1 -1
  41. package/dist/web/frontend/assets/{utils-BNCwV3PT.js → utils-CT9Hzi7v.js} +1 -1
  42. package/dist/web/frontend/callback/index.html +2 -2
  43. package/dist/web/frontend/identity-providers/add/index.html +3 -3
  44. package/dist/web/frontend/identity-providers/index.html +3 -3
  45. package/dist/web/frontend/identity-providers/review/index.html +3 -3
  46. package/dist/web/frontend/index.html +1 -1
  47. package/dist/web/frontend/login/index.html +4 -4
  48. package/dist/web/frontend/networks/add/index.html +3 -3
  49. package/dist/web/frontend/networks/index.html +3 -3
  50. package/dist/web/frontend/networks/review/index.html +3 -3
  51. package/dist/web/frontend/parties/add/index.html +6 -6
  52. package/dist/web/frontend/parties/index.html +4 -4
  53. package/dist/web/frontend/settings/index.html +3 -3
  54. package/package.json +21 -20
  55. package/dist/web/frontend/assets/404-BCjBS7OU.js +0 -5
  56. package/dist/web/frontend/assets/addParty-4qt8FiJv.js +0 -38
package/README.md CHANGED
@@ -44,9 +44,22 @@ wallet-gateway --config-schema
44
44
 
45
45
  The JSON-RPC API specs from `api-specs/` are generated into strongly-typed method builders for the remote RPC server. To update the codegen, run `yarn generate:dapp`.
46
46
 
47
+ ## Dfns
48
+
49
+ 1. Create a service account in the Dfns dashboard with permissions to create and sign with Canton wallets, then download its credentials.
50
+
51
+ 2. Set the following environment variables before starting the Gateway:
52
+ - `DFNS_ORG_ID` — your Dfns organization ID (required; the driver is skipped if unset)
53
+ - `DFNS_BASE_URL` — Dfns API base URL (defaults to `https://api.dfns.io`)
54
+ - `DFNS_CRED_ID` — service account credential ID
55
+ - `DFNS_PRIVATE_KEY` — service account private key (PEM)
56
+ - `DFNS_AUTH_TOKEN` — service account auth token
57
+
58
+ Dfns provisions and activates Canton wallets through its validator integration, so no additional Gateway configuration is required. Only `Canton` and `CantonTestnet` network wallets are supported. See [`@canton-network/core-signing-dfns`](../../core/signing-dfns/README.md) for full driver details.
59
+
47
60
  ## Fireblocks
48
61
 
49
- 1. Complete steps 1–3 from the instructions at https://github.com/hyperledger-labs/splice-wallet-kernel/tree/main/core/signing-fireblocks
62
+ 1. Complete steps 1–3 from the instructions at https://github.com/canton-network/wallet-gateway/tree/main/core/signing-fireblocks
50
63
 
51
64
  2. set the environment variable `FIREBLOCKS_API_KEY` (get it from `API User (ID)` column in fireblocks api users table).
52
65
 
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-auth-service.d.ts","sourceRoot":"","sources":["../../src/auth/jwt-auth-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,mCAAmC,CAAA;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAE7B;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,KAAK,EAAE,QAAQ,MAAM,KAAG,WA+H5D,CAAA"}
1
+ {"version":3,"file":"jwt-auth-service.d.ts","sourceRoot":"","sources":["../../src/auth/jwt-auth-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,mCAAmC,CAAA;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAE7B;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,KAAK,EAAE,QAAQ,MAAM,KAAG,WA8H5D,CAAA"}
@@ -33,9 +33,8 @@ export const jwtAuthService = (store, logger) => ({
33
33
  logger.warn(`No identity provider found for issuer: ${iss}`);
34
34
  return undefined;
35
35
  }
36
- const scope = decoded.scope;
37
- if (!scope) {
38
- logger.warn('JWT does not contain a scope');
36
+ if (!decoded.scope && !decoded.scp) {
37
+ logger.warn('JWT does not contain a scope claim');
39
38
  return undefined;
40
39
  }
41
40
  if (idp.type == 'self_signed') {
package/dist/env.d.ts CHANGED
@@ -4,6 +4,11 @@ export declare class Env {
4
4
  static BLOCKDAEMON_API_URL: (fallback: string) => string;
5
5
  static BLOCKDAEMON_API_KEY: (fallback: string) => string;
6
6
  static BLOCKDAEMON_CAIP2: (fallback: string) => string;
7
+ static DFNS_ORG_ID: () => string | undefined;
8
+ static DFNS_BASE_URL: (fallback: string) => string;
9
+ static DFNS_CRED_ID: () => string | undefined;
10
+ static DFNS_PRIVATE_KEY: () => string | undefined;
11
+ static DFNS_AUTH_TOKEN: () => string | undefined;
7
12
  static get(key: string, options: {
8
13
  required?: boolean;
9
14
  fallback: string;
package/dist/env.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAGA,qBAAa,GAAG;IACZ,MAAM,CAAC,kBAAkB,2BAAsC;IAC/D,MAAM,CAAC,iBAAiB,2BAAqC;IAC7D,MAAM,CAAC,mBAAmB,GAAI,UAAU,MAAM,YACE;IAChD,MAAM,CAAC,mBAAmB,GAAI,UAAU,MAAM,YACE;IAChD,MAAM,CAAC,iBAAiB,GAAI,UAAU,MAAM,YACE;IAE9C,MAAM,CAAC,GAAG,CACN,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAClD,MAAM;IACT,MAAM,CAAC,GAAG,CACN,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,MAAM;IACT,MAAM,CAAC,GAAG,CACN,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,GAChE,MAAM,GAAG,SAAS;CAcxB"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAGA,qBAAa,GAAG;IACZ,MAAM,CAAC,kBAAkB,2BAAsC;IAC/D,MAAM,CAAC,iBAAiB,2BAAqC;IAC7D,MAAM,CAAC,mBAAmB,GAAI,UAAU,MAAM,YACE;IAChD,MAAM,CAAC,mBAAmB,GAAI,UAAU,MAAM,YACE;IAChD,MAAM,CAAC,iBAAiB,GAAI,UAAU,MAAM,YACE;IAC9C,MAAM,CAAC,WAAW,2BAA+B;IACjD,MAAM,CAAC,aAAa,GAAI,UAAU,MAAM,YACE;IAC1C,MAAM,CAAC,YAAY,2BAAgC;IACnD,MAAM,CAAC,gBAAgB,2BAAoC;IAC3D,MAAM,CAAC,eAAe,2BAAmC;IAEzD,MAAM,CAAC,GAAG,CACN,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAClD,MAAM;IACT,MAAM,CAAC,GAAG,CACN,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,MAAM;IACT,MAAM,CAAC,GAAG,CACN,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,GAChE,MAAM,GAAG,SAAS;CAcxB"}
package/dist/env.js CHANGED
@@ -6,6 +6,11 @@ export class Env {
6
6
  static { this.BLOCKDAEMON_API_URL = (fallback) => Env.get('BLOCKDAEMON_API_URL', { fallback }); }
7
7
  static { this.BLOCKDAEMON_API_KEY = (fallback) => Env.get('BLOCKDAEMON_API_KEY', { fallback }); }
8
8
  static { this.BLOCKDAEMON_CAIP2 = (fallback) => Env.get('BLOCKDAEMON_CAIP2', { fallback }); }
9
+ static { this.DFNS_ORG_ID = () => Env.get('DFNS_ORG_ID'); }
10
+ static { this.DFNS_BASE_URL = (fallback) => Env.get('DFNS_BASE_URL', { fallback }); }
11
+ static { this.DFNS_CRED_ID = () => Env.get('DFNS_CRED_ID'); }
12
+ static { this.DFNS_PRIVATE_KEY = () => Env.get('DFNS_PRIVATE_KEY'); }
13
+ static { this.DFNS_AUTH_TOKEN = () => Env.get('DFNS_AUTH_TOKEN'); }
9
14
  static get(key, options) {
10
15
  const { fallback, required } = options || {};
11
16
  const value = process.env[key]?.trim() || fallback?.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAuB7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AA6IvC,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBA4IhE"}
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,iBAiKhE"}
package/dist/init.js CHANGED
@@ -6,9 +6,10 @@ 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
+ import DfnsSigningProvider from '@canton-network/core-signing-dfns';
12
13
  import FireblocksSigningProvider from '@canton-network/core-signing-fireblocks';
13
14
  import BlockdaemonSigningProvider from '@canton-network/core-signing-blockdaemon';
14
15
  import { jwtAuthService } from './auth/jwt-auth-service.js';
@@ -46,6 +47,44 @@ async function initializeDatabase(config, logger) {
46
47
  .catch(() => { });
47
48
  exists = false;
48
49
  }
50
+ else {
51
+ const appDb = connection(config.store);
52
+ try {
53
+ const idpsTable = await sql
54
+ .raw(`select exists(select 1 from information_schema.tables where table_schema='public' and table_name='idps') as exists;`)
55
+ .execute(appDb);
56
+ const networksTable = await sql
57
+ .raw(`select exists(select 1 from information_schema.tables where table_schema='public' and table_name='networks') as exists;`)
58
+ .execute(appDb);
59
+ const idpsExists = Boolean(idpsTable.rows[0]?.exists);
60
+ const networksExists = Boolean(networksTable.rows[0]?.exists);
61
+ let idpsHasRows = false;
62
+ let networksHasRows = false;
63
+ if (idpsExists) {
64
+ const idpsCount = await sql
65
+ .raw(`select count(*) as "rowCount" from idps;`)
66
+ .execute(appDb);
67
+ idpsHasRows = Number(idpsCount.rows[0]?.rowCount ?? 0) > 0;
68
+ }
69
+ if (networksExists) {
70
+ const networksCount = await sql
71
+ .raw(`select count(*) as "rowCount" from networks;`)
72
+ .execute(appDb);
73
+ networksHasRows =
74
+ Number(networksCount.rows[0]?.rowCount ?? 0) > 0;
75
+ }
76
+ if (!idpsExists ||
77
+ !networksExists ||
78
+ !idpsHasRows ||
79
+ !networksHasRows) {
80
+ logger.warn('Database exists but required tables are missing or empty. Attempting to bootstrap...');
81
+ exists = false;
82
+ }
83
+ }
84
+ finally {
85
+ await appDb.destroy();
86
+ }
87
+ }
49
88
  await db.destroy();
50
89
  }
51
90
  const db = connection(config.store);
@@ -161,6 +200,23 @@ export async function initialize(opts, logger) {
161
200
  caip2: Env.BLOCKDAEMON_CAIP2('canton:testnet'),
162
201
  }),
163
202
  };
203
+ if (Env.DFNS_ORG_ID() &&
204
+ Env.DFNS_CRED_ID() &&
205
+ Env.DFNS_PRIVATE_KEY() &&
206
+ Env.DFNS_AUTH_TOKEN()) {
207
+ drivers[SigningProvider.DFNS] = new DfnsSigningProvider({
208
+ orgId: Env.DFNS_ORG_ID(),
209
+ baseUrl: Env.DFNS_BASE_URL('https://api.dfns.io'),
210
+ credentials: {
211
+ credId: Env.DFNS_CRED_ID(),
212
+ privateKey: Env.DFNS_PRIVATE_KEY(),
213
+ authToken: Env.DFNS_AUTH_TOKEN(),
214
+ },
215
+ });
216
+ }
217
+ else {
218
+ logger.warn('Dfns env vars not fully set — Dfns signing provider will be unavailable');
219
+ }
164
220
  const allowedPaths = {
165
221
  [config.server.dappPath]: ['*'],
166
222
  [config.server.userPath]: [
@@ -17,6 +17,19 @@ export declare class TransactionService {
17
17
  signWithWalletKernel(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResultSigned>;
18
18
  signWithBlockdaemon(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
19
19
  signWithFireblocks(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
20
+ /**
21
+ * Dfns broadcasts the prepared transaction to Canton itself, so we get back
22
+ * an updateId rather than a raw signature. We persist the updateId as the
23
+ * signature payload (the controller short-circuits Dfns execute) and surface
24
+ * the same SignResult shape the other external providers use.
25
+ */
26
+ signWithDfns(userId: UserId, wallet: Wallet, signParams: SignParams): Promise<SignResult>;
27
+ /**
28
+ * Dfns has already broadcast the transaction at sign-time, so execute is a
29
+ * state reconciliation: mark the stored transaction as executed and return
30
+ * the updateId Dfns gave us. We deliberately don't post to the ledger here.
31
+ */
32
+ executeWithDfns(transaction: Transaction): Promise<ExecuteResult>;
20
33
  executeWithParticipant(userId: UserId, executeParams: ExecuteParams, transaction: Transaction, ledgerClient: LedgerClient, network: Network): Promise<ExecuteResult>;
21
34
  executeWithExternal(userId: UserId, executeParams: ExecuteParams, transaction: Transaction, ledgerClient: LedgerClient): Promise<ExecuteResult>;
22
35
  }
@@ -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;IA4GT,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;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"}
@@ -33,7 +33,7 @@ export class TransactionService {
33
33
  async signWithWalletKernel(userId, wallet, signParams) {
34
34
  const signingProvider = this.signingDrivers[SigningProvider.WALLET_KERNEL];
35
35
  if (!signingProvider) {
36
- throw new Error('Wallet Kernel signing driver not available');
36
+ throw new Error('Wallet Gateway signing driver not available');
37
37
  }
38
38
  const driver = signingProvider.controller(userId);
39
39
  const tx = await this.loadPreparedTransactionForSigning(signParams.transactionId);
@@ -239,6 +239,122 @@ export class TransactionService {
239
239
  };
240
240
  }
241
241
  }
242
+ /**
243
+ * Dfns broadcasts the prepared transaction to Canton itself, so we get back
244
+ * an updateId rather than a raw signature. We persist the updateId as the
245
+ * signature payload (the controller short-circuits Dfns execute) and surface
246
+ * the same SignResult shape the other external providers use.
247
+ */
248
+ async signWithDfns(userId, wallet, signParams) {
249
+ const signingProvider = this.signingDrivers[SigningProvider.DFNS];
250
+ if (!signingProvider) {
251
+ throw new Error('Dfns signing driver not available');
252
+ }
253
+ const driver = signingProvider.controller(userId);
254
+ const tx = await this.loadPreparedTransactionForSigning(signParams.transactionId);
255
+ let signingResult;
256
+ if (tx.externalTxId) {
257
+ signingResult = await driver
258
+ .getTransaction({
259
+ userId,
260
+ txId: tx.externalTxId,
261
+ })
262
+ .then(handleSigningError);
263
+ }
264
+ else {
265
+ signingResult = await driver
266
+ .signTransaction({
267
+ tx: tx.preparedTransaction,
268
+ txHash: tx.preparedTransactionHash,
269
+ keyIdentifier: {
270
+ publicKey: wallet.publicKey,
271
+ },
272
+ })
273
+ .then(handleSigningError);
274
+ }
275
+ const now = new Date();
276
+ if (signingResult.status === 'signed') {
277
+ if (!signingResult.signature) {
278
+ throw new Error('No updateId returned from Dfns');
279
+ }
280
+ const signedTx = {
281
+ id: tx.id,
282
+ commandId: tx.commandId,
283
+ status: signingResult.status,
284
+ preparedTransaction: tx.preparedTransaction,
285
+ preparedTransactionHash: tx.preparedTransactionHash,
286
+ origin: tx?.origin ?? null,
287
+ ...(tx?.createdAt && {
288
+ createdAt: tx.createdAt,
289
+ }),
290
+ signedAt: now,
291
+ externalTxId: signingResult.txId,
292
+ };
293
+ await this.store.setTransactionSigned(tx.id, now, signingResult.txId);
294
+ this.notifier.emit('txChanged', signedTx);
295
+ return {
296
+ status: signingResult.status,
297
+ signature: signingResult.signature,
298
+ signedBy: wallet.namespace,
299
+ partyId: wallet.partyId,
300
+ externalTxId: signingResult.txId,
301
+ };
302
+ }
303
+ else {
304
+ const status = signingResult.status === 'pending' ? 'pending' : 'failed';
305
+ const pendingTx = {
306
+ id: tx.id,
307
+ commandId: tx.commandId,
308
+ status,
309
+ preparedTransaction: tx.preparedTransaction,
310
+ preparedTransactionHash: tx.preparedTransactionHash,
311
+ externalTxId: signingResult.txId,
312
+ origin: tx?.origin ?? null,
313
+ ...(tx?.createdAt && {
314
+ createdAt: tx.createdAt,
315
+ }),
316
+ };
317
+ await this.store.setTransactionStatus(tx.id, status, {
318
+ externalTxId: signingResult.txId,
319
+ });
320
+ this.notifier.emit('txChanged', pendingTx);
321
+ return {
322
+ status: signingResult.status,
323
+ externalTxId: signingResult.txId,
324
+ partyId: wallet.partyId,
325
+ };
326
+ }
327
+ }
328
+ /**
329
+ * Dfns has already broadcast the transaction at sign-time, so execute is a
330
+ * state reconciliation: mark the stored transaction as executed and return
331
+ * the updateId Dfns gave us. We deliberately don't post to the ledger here.
332
+ */
333
+ async executeWithDfns(transaction) {
334
+ if (!transaction.externalTxId) {
335
+ throw new Error('Cannot execute Dfns transaction without externalTxId from Dfns');
336
+ }
337
+ const executedTx = {
338
+ id: transaction.id,
339
+ commandId: transaction.commandId,
340
+ status: 'executed',
341
+ preparedTransaction: transaction.preparedTransaction,
342
+ preparedTransactionHash: transaction.preparedTransactionHash,
343
+ origin: transaction.origin ?? null,
344
+ ...(transaction.createdAt && {
345
+ createdAt: transaction.createdAt,
346
+ }),
347
+ ...(transaction.signedAt && {
348
+ signedAt: transaction.signedAt,
349
+ }),
350
+ externalTxId: transaction.externalTxId,
351
+ };
352
+ await this.store.setTransactionStatus(transaction.id, 'executed', {
353
+ externalTxId: transaction.externalTxId,
354
+ });
355
+ this.notifier.emit('txChanged', executedTx);
356
+ return { updateId: transaction.externalTxId };
357
+ }
242
358
  async executeWithParticipant(userId, executeParams, transaction, ledgerClient, network) {
243
359
  const { partyId } = executeParams;
244
360
  const { commandId } = transaction;
@@ -0,0 +1,23 @@
1
+ import { UserId } from '@canton-network/core-wallet-auth';
2
+ import { Store, Wallet } from '@canton-network/core-wallet-store';
3
+ import { SigningDriverInterface } from '@canton-network/core-signing-lib';
4
+ import { Logger } from 'pino';
5
+ import { PartyAllocationService } from '../../party-allocation-service.js';
6
+ import { PartyHint, Primary } from '../../../user-api/rpc-gen/typings.js';
7
+ import type { WalletAllocator } from '../wallet-allocation-service.js';
8
+ /**
9
+ * Dfns sign-only allocator. The gateway runs the topology flow against its
10
+ * configured validator; Dfns is asked only to sign the topology hash, mirroring
11
+ * the bring-your-own-validator pattern used for other external providers.
12
+ */
13
+ export declare class DfnsWalletAllocator implements WalletAllocator {
14
+ private store;
15
+ private logger;
16
+ private partyAllocator;
17
+ private signingDriver;
18
+ constructor(store: Store, logger: Logger, partyAllocator: PartyAllocationService, signingDriver: SigningDriverInterface);
19
+ createWallet(userId: UserId, _email: string | undefined, partyHint: PartyHint, primary?: Primary): Promise<Wallet>;
20
+ allocateParty(userId: UserId, _email: string | undefined, existingWallet: Wallet): Promise<void>;
21
+ private finalizeWallet;
22
+ }
23
+ //# sourceMappingURL=dfns-wallet-allocator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dfns-wallet-allocator.d.ts","sourceRoot":"","sources":["../../../../src/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AACzD,OAAO,EAAE,KAAK,EAAgB,MAAM,EAAE,MAAM,mCAAmC,CAAA;AAC/E,OAAO,EAEH,sBAAsB,EAEzB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAA;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAYtE;;;;GAIG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IAEnD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,aAAa;gBAHb,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,sBAAsB,EACtC,aAAa,EAAE,sBAAsB;IAG3C,YAAY,CACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,OAAe,GACzB,OAAO,CAAC,MAAM,CAAC;IA4DZ,aAAa,CACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC;YA+DF,cAAc;CA+C/B"}
@@ -0,0 +1,135 @@
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 { SigningProvider, } from '@canton-network/core-signing-lib';
4
+ import { WALLET_DISABLED_REASON } from '@canton-network/core-types';
5
+ function handleSigningError(result) {
6
+ if ('error' in result) {
7
+ throw new Error(`Error from signing driver: ${result.error_description}`);
8
+ }
9
+ return result;
10
+ }
11
+ /**
12
+ * Dfns sign-only allocator. The gateway runs the topology flow against its
13
+ * configured validator; Dfns is asked only to sign the topology hash, mirroring
14
+ * the bring-your-own-validator pattern used for other external providers.
15
+ */
16
+ export class DfnsWalletAllocator {
17
+ constructor(store, logger, partyAllocator, signingDriver) {
18
+ this.store = store;
19
+ this.logger = logger;
20
+ this.partyAllocator = partyAllocator;
21
+ this.signingDriver = signingDriver;
22
+ }
23
+ async createWallet(userId, _email, partyHint, primary = false) {
24
+ const driver = this.signingDriver.controller(userId);
25
+ const key = await driver
26
+ .createKey({ name: partyHint })
27
+ .then(handleSigningError);
28
+ const namespace = this.partyAllocator.createFingerprintFromKey(key.publicKey);
29
+ const transactions = await this.partyAllocator.generateTopologyTransactions(partyHint, key.publicKey);
30
+ const topologyTransactions = transactions.topologyTransactions ?? [];
31
+ const internalTxId = crypto
32
+ .randomUUID()
33
+ .replace(/-/g, '')
34
+ .substring(0, 16);
35
+ const txPayload = JSON.stringify(topologyTransactions);
36
+ const { status, txId } = await driver
37
+ .signTransaction({
38
+ tx: Buffer.from(txPayload).toString('base64'),
39
+ txHash: transactions.multiHash,
40
+ keyIdentifier: { id: key.id, publicKey: key.publicKey },
41
+ internalTxId,
42
+ })
43
+ .then(handleSigningError);
44
+ const network = await this.store.getCurrentNetwork();
45
+ const walletBase = {
46
+ partyId: `${partyHint}::${namespace}`,
47
+ hint: partyHint,
48
+ namespace,
49
+ signingProviderId: SigningProvider.DFNS,
50
+ networkId: network.id,
51
+ primary,
52
+ publicKey: key.publicKey,
53
+ externalTxId: txId,
54
+ topologyTransactions: topologyTransactions.join(', '),
55
+ rights: [],
56
+ };
57
+ const wallet = await this.finalizeWallet(walletBase, userId, status, txId, topologyTransactions, namespace, driver);
58
+ await this.store.addWallet(wallet);
59
+ return wallet;
60
+ }
61
+ async allocateParty(userId, _email, existingWallet) {
62
+ if (!existingWallet.externalTxId ||
63
+ !existingWallet.topologyTransactions) {
64
+ throw new Error('Existing wallet is missing field externalTxId or topologyTransactions');
65
+ }
66
+ const driver = this.signingDriver.controller(userId);
67
+ const { signature, status, metadata } = await driver
68
+ .getTransaction({ txId: existingWallet.externalTxId })
69
+ .then(handleSigningError);
70
+ let walletUpdate = {
71
+ partyId: existingWallet.partyId,
72
+ networkId: existingWallet.networkId,
73
+ };
74
+ if (status === 'signed') {
75
+ if (!signature) {
76
+ throw new Error('Transaction signed but no signature found in result');
77
+ }
78
+ const partyId = await this.partyAllocator.allocatePartyWithExistingWallet(existingWallet.namespace, existingWallet.topologyTransactions.split(', '), signature, userId);
79
+ walletUpdate = {
80
+ ...walletUpdate,
81
+ partyId,
82
+ status: 'allocated',
83
+ reason: '',
84
+ };
85
+ }
86
+ else if (status === 'pending') {
87
+ walletUpdate = {
88
+ ...walletUpdate,
89
+ status: 'initialized',
90
+ reason: WALLET_DISABLED_REASON.TOPOLOGY_TRANSACTION_PENDING,
91
+ };
92
+ }
93
+ else {
94
+ this.logger.warn(`Topology transaction for wallet ${existingWallet.partyId} was ${status} with ${JSON.stringify(metadata)}`);
95
+ const reason = status === 'rejected'
96
+ ? WALLET_DISABLED_REASON.TOPOLOGY_TRANSACTION_REJECTED
97
+ : WALLET_DISABLED_REASON.TOPOLOGY_TRANSACTION_FAILED;
98
+ walletUpdate = {
99
+ ...walletUpdate,
100
+ status: 'removed',
101
+ disabled: true,
102
+ reason,
103
+ };
104
+ }
105
+ return this.store.updateWallet(walletUpdate);
106
+ }
107
+ async finalizeWallet(walletBase, userId, status, txId, topologyTransactions, namespace, driver) {
108
+ if (status === 'signed') {
109
+ const { signature } = await driver
110
+ .getTransaction({ txId })
111
+ .then(handleSigningError);
112
+ if (!signature) {
113
+ throw new Error('Transaction signed but no signature found in result');
114
+ }
115
+ const partyId = await this.partyAllocator.allocatePartyWithExistingWallet(namespace, topologyTransactions, signature, userId);
116
+ return { ...walletBase, partyId, status: 'allocated' };
117
+ }
118
+ if (status === 'pending') {
119
+ return {
120
+ ...walletBase,
121
+ status: 'initialized',
122
+ reason: WALLET_DISABLED_REASON.TOPOLOGY_TRANSACTION_PENDING,
123
+ };
124
+ }
125
+ const reason = status === 'rejected'
126
+ ? WALLET_DISABLED_REASON.TOPOLOGY_TRANSACTION_REJECTED
127
+ : WALLET_DISABLED_REASON.TOPOLOGY_TRANSACTION_FAILED;
128
+ return {
129
+ ...walletBase,
130
+ status: 'removed',
131
+ disabled: true,
132
+ reason,
133
+ };
134
+ }
135
+ }
@@ -13,6 +13,7 @@ export declare class WalletAllocationService {
13
13
  private readonly kernelAllocator?;
14
14
  private readonly fireblocksAllocator?;
15
15
  private readonly blockdaemonAllocator?;
16
+ private readonly dfnsAllocator?;
16
17
  constructor(store: Store, logger: Logger, partyAllocator: PartyAllocationService, signingDrivers?: Partial<Record<SigningProvider, SigningDriverInterface>>);
17
18
  createWallet(userId: UserId, email: string | undefined, partyHint: PartyHint, primary: Primary, signingProviderId: SigningProvider): Promise<Wallet>;
18
19
  allocateParty(userId: UserId, email: string | undefined, existingWallet: Wallet, signingProviderId: SigningProvider): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"wallet-allocation-service.d.ts","sourceRoot":"","sources":["../../../src/ledger/wallet-allocation/wallet-allocation-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAA;AACjE,OAAO,EACH,sBAAsB,EACtB,eAAe,EAClB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAMtE,MAAM,WAAW,eAAe;IAC5B,YAAY,CACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,GACjB,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,aAAa,CACT,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB;AAED,qBAAa,uBAAuB;IAChC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA4B;IACjE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAuB;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAA2B;IAChE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAA4B;gBAG9D,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,sBAAsB,EACtC,cAAc,GAAE,OAAO,CACnB,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAC7C;IAuCG,YAAY,CACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,EAChB,iBAAiB,EAAE,eAAe,GACnC,OAAO,CAAC,MAAM,CAAC;IAqDL,aAAa,CACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,eAAe,GACnC,OAAO,CAAC,IAAI,CAAC;CAgDnB"}
1
+ {"version":3,"file":"wallet-allocation-service.d.ts","sourceRoot":"","sources":["../../../src/ledger/wallet-allocation/wallet-allocation-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAA;AACjE,OAAO,EACH,sBAAsB,EACtB,eAAe,EAClB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAOtE,MAAM,WAAW,eAAe;IAC5B,YAAY,CACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,GACjB,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,aAAa,CACT,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB;AAED,qBAAa,uBAAuB;IAChC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA4B;IACjE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAuB;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAA2B;IAChE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAA4B;IAClE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAqB;gBAGhD,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,sBAAsB,EACtC,cAAc,GAAE,OAAO,CACnB,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAC7C;IAiDG,YAAY,CACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,EAChB,iBAAiB,EAAE,eAAe,GACnC,OAAO,CAAC,MAAM,CAAC;IA+DL,aAAa,CACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,eAAe,GACnC,OAAO,CAAC,IAAI,CAAC;CAyDnB"}
@@ -5,6 +5,7 @@ import { ParticipantWalletAllocator } from './signing-providers/participant-wall
5
5
  import { KernelWalletAllocator } from './signing-providers/kernel-wallet-allocator.js';
6
6
  import { FireblocksWalletAllocator } from './signing-providers/fireblocks-wallet-allocator.js';
7
7
  import { BlockdaemonWalletAllocator } from './signing-providers/blockdaemon-wallet-allocator.js';
8
+ import { DfnsWalletAllocator } from './signing-providers/dfns-wallet-allocator.js';
8
9
  export class WalletAllocationService {
9
10
  constructor(store, logger, partyAllocator, signingDrivers = {}) {
10
11
  this.participantAllocator = new ParticipantWalletAllocator(store, logger, partyAllocator);
@@ -20,6 +21,10 @@ export class WalletAllocationService {
20
21
  if (blockdaemonDriver) {
21
22
  this.blockdaemonAllocator = new BlockdaemonWalletAllocator(store, logger, partyAllocator, blockdaemonDriver);
22
23
  }
24
+ const dfnsDriver = signingDrivers[SigningProvider.DFNS];
25
+ if (dfnsDriver) {
26
+ this.dfnsAllocator = new DfnsWalletAllocator(store, logger, partyAllocator, dfnsDriver);
27
+ }
23
28
  }
24
29
  async createWallet(userId, email, partyHint, primary, signingProviderId) {
25
30
  switch (signingProviderId) {
@@ -27,7 +32,7 @@ export class WalletAllocationService {
27
32
  return this.participantAllocator.createWallet(userId, email, partyHint, primary);
28
33
  case SigningProvider.WALLET_KERNEL:
29
34
  if (!this.kernelAllocator) {
30
- throw new Error('Wallet Kernel signing driver not available');
35
+ throw new Error('Wallet Gateway signing driver not available');
31
36
  }
32
37
  return this.kernelAllocator.createWallet(userId, email, partyHint, primary);
33
38
  case SigningProvider.FIREBLOCKS:
@@ -43,6 +48,11 @@ export class WalletAllocationService {
43
48
  throw new Error('Email is required for Blockdaemon wallet allocation');
44
49
  }
45
50
  return this.blockdaemonAllocator.createWallet(userId, email, partyHint, primary);
51
+ case SigningProvider.DFNS:
52
+ if (!this.dfnsAllocator) {
53
+ throw new Error('Dfns signing driver not available');
54
+ }
55
+ return this.dfnsAllocator.createWallet(userId, email, partyHint, primary);
46
56
  default:
47
57
  throw new Error(`Unsupported signing provider: ${signingProviderId}`);
48
58
  }
@@ -53,7 +63,7 @@ export class WalletAllocationService {
53
63
  return this.participantAllocator.allocateParty(userId, email, existingWallet);
54
64
  case SigningProvider.WALLET_KERNEL:
55
65
  if (!this.kernelAllocator) {
56
- throw new Error('Wallet Kernel signing driver not available');
66
+ throw new Error('Wallet Gateway signing driver not available');
57
67
  }
58
68
  return this.kernelAllocator.allocateParty(userId, email, existingWallet);
59
69
  case SigningProvider.FIREBLOCKS:
@@ -69,6 +79,11 @@ export class WalletAllocationService {
69
79
  throw new Error('Email is required for Blockdaemon wallet allocation');
70
80
  }
71
81
  return this.blockdaemonAllocator.allocateParty(userId, email, existingWallet);
82
+ case SigningProvider.DFNS:
83
+ if (!this.dfnsAllocator) {
84
+ throw new Error('Dfns signing driver not available');
85
+ }
86
+ return this.dfnsAllocator.allocateParty(userId, email, existingWallet);
72
87
  default:
73
88
  throw new Error(`Unsupported signing provider: ${signingProviderId}`);
74
89
  }
@@ -156,7 +156,7 @@ describe('WalletAllocationService', () => {
156
156
  });
157
157
  });
158
158
  });
159
- describe('Wallet Kernel', () => {
159
+ describe('Wallet Gateway', () => {
160
160
  it('createWallet initializes new wallet and adds to store', async () => {
161
161
  const expectedParty = createAllocatedParty('bob::fingerprint', 'bob', 'fingerprint');
162
162
  mockPartyAllocator.createFingerprintFromKey.mockReturnValue('fingerprint');
@@ -198,9 +198,9 @@ describe('WalletAllocationService', () => {
198
198
  status: 'allocated',
199
199
  });
200
200
  });
201
- it('throws when Wallet Kernel signing driver not available', async () => {
201
+ it('throws when Wallet Gateway signing driver not available', async () => {
202
202
  const serviceWithoutDriver = createService({});
203
- await expect(serviceWithoutDriver.createWallet('user-1', undefined, 'bob', false, SigningProvider.WALLET_KERNEL)).rejects.toThrow('Wallet Kernel signing driver not available');
203
+ await expect(serviceWithoutDriver.createWallet('user-1', undefined, 'bob', false, SigningProvider.WALLET_KERNEL)).rejects.toThrow('Wallet Gateway signing driver not available');
204
204
  });
205
205
  });
206
206
  describe('Fireblocks', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/user-api/controller.ts"],"names":[],"mappings":"AA6BA,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;AAChD,OAAO,EACH,sBAAsB,EACtB,eAAe,EAClB,MAAM,kCAAkC,CAAA;AASzC,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;;;;;;;;;;;;;;;;;;;;;;;CAwyBvB,CAAA"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/user-api/controller.ts"],"names":[],"mappings":"AA6BA,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;AAChD,OAAO,EACH,sBAAsB,EACtB,eAAe,EAClB,MAAM,kCAAkC,CAAA;AASzC,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;;;;;;;;;;;;;;;;;;;;;;;CAkzBvB,CAAA"}
@@ -259,6 +259,9 @@ export const userController = (kernelInfo, userUrl, store, notificationService,
259
259
  case SigningProvider.FIREBLOCKS: {
260
260
  return transactionService.signWithFireblocks(userId, wallet, signParams);
261
261
  }
262
+ case SigningProvider.DFNS: {
263
+ return transactionService.signWithDfns(userId, wallet, signParams);
264
+ }
262
265
  default:
263
266
  throw new Error(`Unsupported signing provider: ${wallet.signingProviderId}`);
264
267
  }
@@ -302,6 +305,9 @@ export const userController = (kernelInfo, userUrl, store, notificationService,
302
305
  case SigningProvider.FIREBLOCKS: {
303
306
  return transactionService.executeWithExternal(userId, executeParams, transaction, ledgerClient);
304
307
  }
308
+ case SigningProvider.DFNS: {
309
+ return transactionService.executeWithDfns(transaction);
310
+ }
305
311
  default:
306
312
  throw new Error(`Unsupported signing provider: ${wallet.signingProviderId}`);
307
313
  }
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Wallet Gateway - Not found</title>
7
- <script type="module" crossorigin src="../assets/404-BCjBS7OU.js"></script>
8
- <link rel="modulepreload" crossorigin href="../assets/index-lfC4c213.js">
7
+ <script type="module" crossorigin src="../assets/404-B-o9ppJB.js"></script>
8
+ <link rel="modulepreload" crossorigin href="../assets/index-_pMHlJoE.js">
9
9
  </head>
10
10
 
11
11
  <body>
@@ -4,9 +4,9 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Wallet Gateway - Activities</title>
7
- <script type="module" crossorigin src="../assets/activities-4fnnetzm.js"></script>
8
- <link rel="modulepreload" crossorigin href="../assets/index-lfC4c213.js">
9
- <link rel="modulepreload" crossorigin href="../assets/state-BpQr_22x.js">
7
+ <script type="module" crossorigin src="../assets/activities-CGjCIjUH.js"></script>
8
+ <link rel="modulepreload" crossorigin href="../assets/index-_pMHlJoE.js">
9
+ <link rel="modulepreload" crossorigin href="../assets/state-B2k3ak7d.js">
10
10
  <link rel="modulepreload" crossorigin href="../assets/index-CiMGhYb1.js">
11
11
  </head>
12
12
  <body>