@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.
- package/README.md +14 -1
- package/dist/auth/jwt-auth-service.d.ts.map +1 -1
- package/dist/auth/jwt-auth-service.js +2 -3
- package/dist/env.d.ts +5 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +5 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +57 -1
- package/dist/ledger/transaction-service.d.ts +13 -0
- package/dist/ledger/transaction-service.d.ts.map +1 -1
- package/dist/ledger/transaction-service.js +117 -1
- package/dist/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.d.ts +23 -0
- package/dist/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.d.ts.map +1 -0
- package/dist/ledger/wallet-allocation/signing-providers/dfns-wallet-allocator.js +135 -0
- package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts +1 -0
- package/dist/ledger/wallet-allocation/wallet-allocation-service.d.ts.map +1 -1
- package/dist/ledger/wallet-allocation/wallet-allocation-service.js +17 -2
- package/dist/ledger/wallet-allocation/wallet-allocation-service.test.js +3 -3
- package/dist/user-api/controller.d.ts.map +1 -1
- package/dist/user-api/controller.js +6 -0
- package/dist/web/frontend/404/index.html +2 -2
- package/dist/web/frontend/activities/index.html +3 -3
- package/dist/web/frontend/approve/index.html +5 -5
- package/dist/web/frontend/assets/404-B-o9ppJB.js +5 -0
- package/dist/web/frontend/assets/{activities-4fnnetzm.js → activities-CGjCIjUH.js} +1 -1
- package/dist/web/frontend/assets/{addIdentityProvider-uy13wDEx.js → addIdentityProvider-CR4Wm9Tl.js} +2 -2
- package/dist/web/frontend/assets/{addNetwork-B9yARLXq.js → addNetwork-Dx0-SN4j.js} +3 -3
- package/dist/web/frontend/assets/addParty-COhk_rFn.js +41 -0
- package/dist/web/frontend/assets/{approve-DUxX18Xm.js → approve-B2w66l0J.js} +1 -1
- package/dist/web/frontend/assets/{callback-BGMELOxy.js → callback-BTVon_yQ.js} +1 -1
- package/dist/web/frontend/assets/{identityProviders-ByQNvF7K.js → identityProviders-CK8zSrd3.js} +2 -2
- package/dist/web/frontend/assets/{index-DcZcHMS1.js → index-CF4BKzgl.js} +2 -2
- package/dist/web/frontend/assets/{index-DvQio60y.js → index-DWz_3f3y.js} +1 -1
- package/dist/web/frontend/assets/{index-lfC4c213.js → index-_pMHlJoE.js} +94 -63
- package/dist/web/frontend/assets/{login-BtNyAQqL.js → login-CVoPNVDw.js} +2 -2
- package/dist/web/frontend/assets/{networks-B8bwNVkz.js → networks-D1nPvUzM.js} +2 -2
- package/dist/web/frontend/assets/{reviewIdentityProvider-CWDFtb4t.js → reviewIdentityProvider-CNSf2qQv.js} +4 -4
- package/dist/web/frontend/assets/{reviewNetwork-ZgS_rpXv.js → reviewNetwork-DGLK-Ume.js} +4 -4
- package/dist/web/frontend/assets/{settings-BiWW1vj2.js → settings-B1ga2TK0.js} +2 -2
- package/dist/web/frontend/assets/{state-BpQr_22x.js → state-B2k3ak7d.js} +1 -1
- package/dist/web/frontend/assets/{utils-BNCwV3PT.js → utils-CT9Hzi7v.js} +1 -1
- package/dist/web/frontend/callback/index.html +2 -2
- package/dist/web/frontend/identity-providers/add/index.html +3 -3
- package/dist/web/frontend/identity-providers/index.html +3 -3
- package/dist/web/frontend/identity-providers/review/index.html +3 -3
- package/dist/web/frontend/index.html +1 -1
- package/dist/web/frontend/login/index.html +4 -4
- package/dist/web/frontend/networks/add/index.html +3 -3
- package/dist/web/frontend/networks/index.html +3 -3
- package/dist/web/frontend/networks/review/index.html +3 -3
- package/dist/web/frontend/parties/add/index.html +6 -6
- package/dist/web/frontend/parties/index.html +4 -4
- package/dist/web/frontend/settings/index.html +3 -3
- package/package.json +21 -20
- package/dist/web/frontend/assets/404-BCjBS7OU.js +0 -5
- 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/
|
|
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,
|
|
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
|
-
|
|
37
|
-
|
|
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;
|
|
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();
|
package/dist/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;
|
|
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;
|
|
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
|
|
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;
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;
|
|
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-
|
|
8
|
-
<link rel="modulepreload" crossorigin href="../assets/index-
|
|
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-
|
|
8
|
-
<link rel="modulepreload" crossorigin href="../assets/index-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="../assets/state-
|
|
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>
|