@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.
- package/dist/index.cjs +112 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -28
- package/dist/index.js.map +1 -1
- package/dist/migrations/006-change-wallet-primary-key-to-composite.d.ts +5 -0
- package/dist/migrations/006-change-wallet-primary-key-to-composite.d.ts.map +1 -0
- package/dist/migrations/006-change-wallet-primary-key-to-composite.js +228 -0
- package/dist/migrations/007-add-unique-primary-per-network.d.ts +5 -0
- package/dist/migrations/007-add-unique-primary-per-network.d.ts.map +1 -0
- package/dist/migrations/007-add-unique-primary-per-network.js +62 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +5 -3
- package/dist/store-sql.d.ts +4 -3
- package/dist/store-sql.d.ts.map +1 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +13 -0
- package/package.json +7 -5
|
@@ -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 @@
|
|
|
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
|
+
}
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,GAAG,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AAC1E,OAAO,EACH,MAAM,EACN,WAAW,EACX,OAAO,EACP,OAAO,EACP,YAAY,EACf,MAAM,mCAAmC,CAAA;AAE1C,UAAU,cAAc;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;CACrB;AAED,UAAU,QAAQ;IACd,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,OAAO,GAAG,aAAa,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC;AAED,UAAU,YAAY;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAE1B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC;AAED,UAAU,WAAW;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,gBAAgB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,UAAU,YAAa,SAAQ,OAAO;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,EAAE;IACf,UAAU,EAAE,cAAc,CAAA;IAC1B,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,EAAE,YAAY,CAAA;IACtB,OAAO,EAAE,WAAW,CAAA;IACpB,YAAY,EAAE,gBAAgB,CAAA;IAC9B,QAAQ,EAAE,YAAY,CAAA;CACzB;AAED,eAAO,MAAM,KAAK,GAAI,OAAO,QAAQ,KAAG,GAqBvC,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,KAAK,GAAG,KAAG,QAiBlC,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,OAAO,YAAY,KAAG,
|
|
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(
|
|
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
|
|
96
|
+
primary: Boolean(table.primary),
|
|
95
97
|
status: toWalletStatus(table.status),
|
|
96
98
|
partyId: table.partyId,
|
|
97
99
|
hint: table.hint,
|
package/dist/store-sql.d.ts
CHANGED
|
@@ -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
|
-
|
|
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>;
|
package/dist/store-sql.d.ts.map
CHANGED
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"store-sql.d.ts","sourceRoot":"","sources":["../src/store-sql.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
ADDED
|
@@ -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.
|
|
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.
|
|
29
|
-
"@canton-network/core-rpc-errors": "^0.
|
|
30
|
-
"@canton-network/core-wallet-auth": "^0.
|
|
31
|
-
"@canton-network/core-wallet-store": "^0.
|
|
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",
|