@canton-network/core-wallet-store-sql 0.20.2 → 0.21.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.
@@ -0,0 +1,228 @@
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 { sql } from 'kysely';
4
+ import { isPostgres } from '../utils.js';
5
+ async function tableExists(db, tableName, isPg) {
6
+ if (isPg) {
7
+ const result = await sql `
8
+ SELECT EXISTS (
9
+ SELECT FROM information_schema.tables
10
+ WHERE table_schema = 'public'
11
+ AND table_name = ${tableName}
12
+ ) AS exists
13
+ `.execute(db);
14
+ return result.rows[0]?.exists ?? false;
15
+ }
16
+ else {
17
+ const result = await sql `
18
+ SELECT name
19
+ FROM sqlite_master
20
+ WHERE type='table' AND name = ${tableName}
21
+ `.execute(db);
22
+ return result.rows.length > 0;
23
+ }
24
+ }
25
+ export async function up(db) {
26
+ const isPg = await isPostgres(db);
27
+ if (isPg) {
28
+ // PostgreSQL: idempotent PK change to (party_id, network_id)
29
+ // Drop current PK if it isn't already the composite (party_id, network_id)
30
+ await sql `
31
+ DO $$
32
+ DECLARE
33
+ pk_name text;
34
+ pk_def text;
35
+ BEGIN
36
+ SELECT c.conname, pg_get_constraintdef(c.oid)
37
+ INTO pk_name, pk_def
38
+ FROM pg_constraint c
39
+ WHERE c.conrelid = 'public.wallets'::regclass
40
+ AND c.contype = 'p';
41
+
42
+ IF pk_name IS NOT NULL
43
+ AND pk_def NOT ILIKE 'PRIMARY KEY (party_id, network_id)%' THEN
44
+ EXECUTE format('ALTER TABLE public.wallets DROP CONSTRAINT %I', pk_name);
45
+ END IF;
46
+ END $$;
47
+ `.execute(db);
48
+ // Ensure network_id has no NULLs and is NOT NULL (required for PK)
49
+ await sql `
50
+ DO $$
51
+ BEGIN
52
+ IF EXISTS (SELECT 1 FROM public.wallets WHERE network_id IS NULL) THEN
53
+ RAISE EXCEPTION 'Cannot add composite PK: wallets.network_id has NULLs';
54
+ END IF;
55
+ END $$;
56
+ `.execute(db);
57
+ await sql `
58
+ ALTER TABLE public.wallets
59
+ ALTER COLUMN network_id SET NOT NULL
60
+ `.execute(db);
61
+ // Drop any leftover UNIQUE index that still enforces uniqueness on party_id alone
62
+ await sql `
63
+ DO $$
64
+ DECLARE r record;
65
+ BEGIN
66
+ FOR r IN
67
+ SELECT indexname
68
+ FROM pg_indexes
69
+ WHERE schemaname='public'
70
+ AND tablename='wallets'
71
+ AND indexdef ILIKE 'CREATE UNIQUE INDEX % ON % ("party_id")%'
72
+ LOOP
73
+ EXECUTE format('DROP INDEX IF EXISTS %I', r.indexname);
74
+ END LOOP;
75
+ END $$;
76
+ `.execute(db);
77
+ // Add the new composite primary key
78
+ await sql `
79
+ DO $$
80
+ DECLARE
81
+ has_pk boolean;
82
+ BEGIN
83
+ SELECT EXISTS (
84
+ SELECT 1
85
+ FROM pg_constraint c
86
+ WHERE c.conrelid = 'public.wallets'::regclass
87
+ AND c.contype = 'p'
88
+ AND pg_get_constraintdef(c.oid) ILIKE 'PRIMARY KEY (party_id, network_id)%'
89
+ ) INTO has_pk;
90
+
91
+ IF NOT has_pk THEN
92
+ EXECUTE 'ALTER TABLE public.wallets
93
+ ADD CONSTRAINT wallets_pkey PRIMARY KEY (party_id, network_id)';
94
+ END IF;
95
+ END $$;
96
+ `.execute(db);
97
+ }
98
+ else {
99
+ // SQLite: Recreate table (SQLite doesn't support altering primary keys)
100
+ // Drop temporary table if it exists
101
+ await db.schema.dropTable('wallets_new').ifExists().execute();
102
+ const hasWallets = await tableExists(db, 'wallets', false);
103
+ const hasWalletsNew = await tableExists(db, 'wallets_new', false);
104
+ if (!hasWallets && hasWalletsNew) {
105
+ await db.schema
106
+ .alterTable('wallets_new')
107
+ .renameTo('wallets')
108
+ .execute();
109
+ return;
110
+ }
111
+ await db.schema
112
+ .createTable('wallets_new')
113
+ .addColumn('party_id', 'text', (col) => col.notNull())
114
+ .addColumn('network_id', 'text', (col) => col.references('networks.id').onDelete('cascade').notNull())
115
+ .addColumn('primary', 'boolean', (col) => col.notNull().defaultTo(false))
116
+ .addColumn('hint', 'text', (col) => col.notNull())
117
+ .addColumn('public_key', 'text', (col) => col.notNull())
118
+ .addColumn('namespace', 'text', (col) => col.notNull())
119
+ .addColumn('user_id', 'text', (col) => col.notNull())
120
+ .addColumn('signing_provider_id', 'text', (col) => col.notNull())
121
+ .addColumn('status', 'text')
122
+ .addColumn('external_tx_id', 'text')
123
+ .addColumn('topology_transactions', 'text')
124
+ .addColumn('disabled', 'integer', (col) => col.notNull().defaultTo(0))
125
+ .addColumn('reason', 'text')
126
+ .addPrimaryKeyConstraint('wallets_pk', ['party_id', 'network_id'])
127
+ .execute();
128
+ await sql `
129
+ INSERT INTO wallets_new (
130
+ party_id, network_id, "primary", hint, public_key, namespace,
131
+ user_id, signing_provider_id, status, external_tx_id,
132
+ topology_transactions, disabled, reason
133
+ )
134
+ SELECT
135
+ party_id, network_id, "primary", hint, public_key, namespace,
136
+ user_id, signing_provider_id, status, external_tx_id,
137
+ topology_transactions, COALESCE(disabled, 0) AS disabled, reason
138
+ FROM wallets
139
+ `.execute(db);
140
+ await db.schema.dropTable('wallets').execute();
141
+ await db.schema.alterTable('wallets_new').renameTo('wallets').execute();
142
+ }
143
+ }
144
+ export async function down(db) {
145
+ const isPg = await isPostgres(db);
146
+ if (isPg) {
147
+ if (!(await tableExists(db, 'wallets', true)))
148
+ return;
149
+ // PostgreSQL: Use ALTER TABLE to revert to single primary key
150
+ // drop the composite primary key
151
+ await sql `
152
+ DO $$
153
+ DECLARE
154
+ pk_name text;
155
+ BEGIN
156
+ SELECT c.conname
157
+ INTO pk_name
158
+ FROM pg_constraint c
159
+ WHERE c.conrelid = 'public.wallets'::regclass
160
+ AND c.contype = 'p';
161
+
162
+ IF pk_name IS NOT NULL THEN
163
+ EXECUTE format('ALTER TABLE public.wallets DROP CONSTRAINT %I', pk_name);
164
+ END IF;
165
+ END $$;
166
+ `.execute(db);
167
+ // Keep only one wallet per party_id (data loss if duplicates exist)
168
+ // Use DISTINCT ON to pick first row per party_id
169
+ await sql `
170
+ DELETE FROM public.wallets w1
171
+ WHERE EXISTS (
172
+ SELECT 1
173
+ FROM public.wallets w2
174
+ WHERE w2.party_id = w1.party_id
175
+ AND w2.network_id < w1.network_id
176
+ )
177
+ `.execute(db);
178
+ // Make network_id nullable again
179
+ await sql `
180
+ ALTER TABLE public.wallets
181
+ ALTER COLUMN network_id DROP NOT NULL
182
+ `.execute(db);
183
+ // Add back single-column PK on party_id
184
+ await sql `
185
+ ALTER TABLE public.wallets
186
+ ADD CONSTRAINT wallets_pkey PRIMARY KEY (party_id)
187
+ `.execute(db);
188
+ }
189
+ else {
190
+ // SQLite: Recreate table with single primary key
191
+ // Create old table structure with single primary key
192
+ await db.schema
193
+ .createTable('wallets_new')
194
+ .addColumn('party_id', 'text', (col) => col.primaryKey())
195
+ .addColumn('network_id', 'text', (col) => col.references('networks.id').onDelete('cascade'))
196
+ .addColumn('primary', 'boolean', (col) => col.notNull().defaultTo(false))
197
+ .addColumn('hint', 'text', (col) => col.notNull())
198
+ .addColumn('public_key', 'text', (col) => col.notNull())
199
+ .addColumn('namespace', 'text', (col) => col.notNull())
200
+ .addColumn('user_id', 'text', (col) => col.notNull())
201
+ .addColumn('signing_provider_id', 'text', (col) => col.notNull())
202
+ .addColumn('status', 'text')
203
+ .addColumn('external_tx_id', 'text')
204
+ .addColumn('topology_transactions', 'text')
205
+ .addColumn('disabled', 'integer', (col) => col.notNull().defaultTo(0))
206
+ .addColumn('reason', 'text')
207
+ .execute();
208
+ await sql `
209
+ INSERT INTO wallets_new (
210
+ party_id, network_id, "primary", hint, public_key, namespace,
211
+ user_id, signing_provider_id, status, external_tx_id,
212
+ topology_transactions, disabled, reason
213
+ )
214
+ SELECT
215
+ w.party_id, w.network_id, w."primary", w.hint, w.public_key, w.namespace,
216
+ w.user_id, w.signing_provider_id, w.status, w.external_tx_id,
217
+ w.topology_transactions, w.disabled, w.reason
218
+ FROM wallets w
219
+ INNER JOIN (
220
+ SELECT party_id, MIN(rowid) as min_rowid
221
+ FROM wallets
222
+ GROUP BY party_id
223
+ ) ranked ON w.party_id = ranked.party_id AND w.rowid = ranked.min_rowid
224
+ `.execute(db);
225
+ await db.schema.dropTable('wallets').execute();
226
+ await db.schema.alterTable('wallets_new').renameTo('wallets').execute();
227
+ }
228
+ }
@@ -0,0 +1,5 @@
1
+ import { Kysely } from 'kysely';
2
+ import { DB } from '../schema.js';
3
+ export declare function up(db: Kysely<DB>): Promise<void>;
4
+ export declare function down(db: Kysely<DB>): Promise<void>;
5
+ //# sourceMappingURL=007-add-unique-primary-per-network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"007-add-unique-primary-per-network.d.ts","sourceRoot":"","sources":["../../src/migrations/007-add-unique-primary-per-network.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAO,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGjC,wBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDtD;AAED,wBAAsB,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxD"}
@@ -0,0 +1,62 @@
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 { sql } from 'kysely';
4
+ import { isPostgres } from '../utils.js';
5
+ export async function up(db) {
6
+ const isPg = await isPostgres(db);
7
+ // Cleanup duplicate primary wallets (keep first per network/user)
8
+ if (isPg) {
9
+ // PostgreSQL
10
+ await sql `
11
+ UPDATE wallets w
12
+ SET "primary" = false
13
+ FROM (
14
+ SELECT party_id, network_id, user_id,
15
+ ROW_NUMBER() OVER (PARTITION BY network_id, user_id ORDER BY party_id) as rn
16
+ FROM wallets
17
+ WHERE "primary" = true
18
+ ) ranked
19
+ WHERE w.party_id = ranked.party_id
20
+ AND w.network_id = ranked.network_id
21
+ AND w.user_id = ranked.user_id
22
+ AND ranked.rn > 1
23
+ AND w."primary" = true
24
+ `.execute(db);
25
+ }
26
+ else {
27
+ // SQLite
28
+ await sql `
29
+ UPDATE wallets
30
+ SET "primary" = 0
31
+ WHERE rowid NOT IN (
32
+ SELECT MIN(rowid)
33
+ FROM wallets
34
+ WHERE "primary" = 1
35
+ GROUP BY network_id, user_id
36
+ )
37
+ AND "primary" = 1
38
+ `.execute(db);
39
+ }
40
+ // Ensure only one primary wallet per network per user
41
+ if (isPg) {
42
+ // PostgreSQL
43
+ await sql `
44
+ CREATE UNIQUE INDEX IF NOT EXISTS wallets_one_primary_per_network_user
45
+ ON wallets(network_id, user_id)
46
+ WHERE "primary" = true
47
+ `.execute(db);
48
+ }
49
+ else {
50
+ // SQLite
51
+ await sql `
52
+ CREATE UNIQUE INDEX IF NOT EXISTS wallets_one_primary_per_network_user
53
+ ON wallets(network_id, user_id)
54
+ WHERE "primary" = 1
55
+ `.execute(db);
56
+ }
57
+ }
58
+ export async function down(db) {
59
+ await sql `
60
+ DROP INDEX IF EXISTS wallets_one_primary_per_network_user
61
+ `.execute(db);
62
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js CHANGED
@@ -50,9 +50,11 @@ export const toNetwork = (table) => {
50
50
  ledgerApi: {
51
51
  baseUrl: table.ledgerApiBaseUrl,
52
52
  },
53
- auth: authSchema.parse(JSON.parse(table.auth)),
53
+ auth: authSchema.parse(typeof table.auth === 'string' ? JSON.parse(table.auth) : table.auth),
54
54
  adminAuth: table.adminAuth
55
- ? authSchema.parse(JSON.parse(table.adminAuth))
55
+ ? authSchema.parse(typeof table.adminAuth === 'string'
56
+ ? JSON.parse(table.adminAuth)
57
+ : table.adminAuth)
56
58
  : undefined,
57
59
  };
58
60
  };
@@ -91,7 +93,7 @@ export const toWallet = (table) => {
91
93
  throw new Error(`Missing wallet disabled reason: ${table.partyId}`);
92
94
  }
93
95
  return {
94
- primary: table.primary === 1,
96
+ primary: Boolean(table.primary),
95
97
  status: toWalletStatus(table.status),
96
98
  partyId: table.partyId,
97
99
  hint: table.hint,
@@ -1,6 +1,6 @@
1
1
  import { Logger } from 'pino';
2
2
  import { AuthContext, AuthAware, Idp } from '@canton-network/core-wallet-auth';
3
- import { Store as BaseStore, Wallet, PartyId, Session, WalletFilter, Transaction, Network, StoreConfig, UpdateWallet } from '@canton-network/core-wallet-store';
3
+ import { Store as BaseStore, Wallet, PartyId, Session, WalletFilter, Transaction, Network, StoreConfig, UpdateWallet, CurrentNetworkWalletFilter } from '@canton-network/core-wallet-store';
4
4
  import { Kysely } from 'kysely';
5
5
  import { DB } from './schema.js';
6
6
  export declare class StoreSql implements BaseStore, AuthAware<StoreSql> {
@@ -10,11 +10,12 @@ export declare class StoreSql implements BaseStore, AuthAware<StoreSql> {
10
10
  constructor(db: Kysely<DB>, logger: Logger, authContext?: AuthContext);
11
11
  withAuthContext(context?: AuthContext): StoreSql;
12
12
  private assertConnected;
13
- getWallets(filter?: WalletFilter): Promise<Array<Wallet>>;
13
+ getAllWallets(filter?: WalletFilter): Promise<Array<Wallet>>;
14
+ getWallets(filter?: CurrentNetworkWalletFilter): Promise<Array<Wallet>>;
14
15
  getPrimaryWallet(): Promise<Wallet | undefined>;
15
16
  setPrimaryWallet(partyId: PartyId): Promise<void>;
16
17
  addWallet(wallet: Wallet): Promise<void>;
17
- updateWallet({ status, partyId, externalTxId, }: UpdateWallet): Promise<void>;
18
+ updateWallet({ status, partyId, networkId, externalTxId, }: UpdateWallet): Promise<void>;
18
19
  removeWallet(partyId: PartyId): Promise<void>;
19
20
  getSession(): Promise<Session | undefined>;
20
21
  setSession(session: Session): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"store-sql.d.ts","sourceRoot":"","sources":["../src/store-sql.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EACH,WAAW,EAEX,SAAS,EAET,GAAG,EACN,MAAM,kCAAkC,CAAA;AACzC,OAAO,EACH,KAAK,IAAI,SAAS,EAClB,MAAM,EACN,OAAO,EACP,OAAO,EACP,YAAY,EACZ,WAAW,EACX,OAAO,EACP,WAAW,EACX,YAAY,EACf,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAmB,MAAM,EAAiB,MAAM,QAAQ,CAAA;AAE/D,OAAO,EACH,EAAE,EASL,MAAM,aAAa,CAAA;AAEpB,qBAAa,QAAS,YAAW,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC;IAIvD,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IAJlB,WAAW,EAAE,WAAW,GAAG,SAAS,CAAA;gBAGxB,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EACd,MAAM,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,WAAW;IAM7B,eAAe,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,QAAQ;IAIhD,OAAO,CAAC,eAAe;IAMjB,UAAU,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IA6C7D,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK/C,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCxC,YAAY,CAAC,EACf,MAAM,EACN,OAAO,EACP,YAAY,GACf,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7C,UAAU,IAAI,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAU1C,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB3C,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAWnC,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAQ/B,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAalC,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAe/B,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW/C,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBrC,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAmBvC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB/C,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBvD,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAenE,gBAAgB,IAAI,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;CASxD;AAED,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,eAqB7C,CAAA"}
1
+ {"version":3,"file":"store-sql.d.ts","sourceRoot":"","sources":["../src/store-sql.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Kysely } from 'kysely';
2
+ import { DB } from './schema';
3
+ export declare function isPostgres(db: Kysely<DB>): Promise<boolean>;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAO,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAA;AAE7B,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAQjE"}
package/dist/utils.js ADDED
@@ -0,0 +1,13 @@
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 { sql } from 'kysely';
4
+ export async function isPostgres(db) {
5
+ try {
6
+ // Try to query PostgreSQL system catalog
7
+ await sql `SELECT 1 FROM pg_database LIMIT 1`.execute(db);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canton-network/core-wallet-store-sql",
3
- "version": "0.20.2",
3
+ "version": "0.21.0",
4
4
  "type": "module",
5
5
  "description": "SQL implementation of the Store API",
6
6
  "license": "Apache-2.0",
@@ -25,13 +25,14 @@
25
25
  "test": "yarn node --experimental-vm-modules $(yarn bin jest)"
26
26
  },
27
27
  "dependencies": {
28
- "@canton-network/core-ledger-client": "^0.25.2",
29
- "@canton-network/core-rpc-errors": "^0.13.3",
30
- "@canton-network/core-wallet-auth": "^0.17.3",
31
- "@canton-network/core-wallet-store": "^0.20.2",
28
+ "@canton-network/core-ledger-client": "^0.26.0",
29
+ "@canton-network/core-rpc-errors": "^0.14.0",
30
+ "@canton-network/core-wallet-auth": "^0.18.0",
31
+ "@canton-network/core-wallet-store": "^0.21.0",
32
32
  "better-sqlite3": "^12.6.2",
33
33
  "commander": "^14.0.2",
34
34
  "kysely": "^0.28.10",
35
+ "pg": "^8.16.3",
35
36
  "pino": "^10.2.1",
36
37
  "umzug": "^3.8.2",
37
38
  "zod": "^4.3.5"
@@ -42,6 +43,7 @@
42
43
  "@swc/jest": "^0.2.39",
43
44
  "@types/better-sqlite3": "^7.6.13",
44
45
  "@types/jest": "^30.0.0",
46
+ "@types/pg": "^8",
45
47
  "jest": "^30.2.0",
46
48
  "pino-test": "^1.1.0",
47
49
  "ts-jest": "^29.4.6",