@canton-network/core-wallet-store-inmemory 0.10.0 → 0.12.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/StoreInternal.d.ts.map +1 -1
- package/dist/index.cjs +240 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +238 -3
- package/dist/index.js.map +1 -0
- package/package.json +9 -7
- package/dist/Store.test.d.ts +0 -2
- package/dist/Store.test.d.ts.map +0 -1
- package/dist/Store.test.js +0 -159
- package/dist/StoreInternal.js +0 -226
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoreInternal.d.ts","sourceRoot":"","sources":["../src/StoreInternal.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EACH,WAAW,EACX,MAAM,EACN,SAAS,
|
|
1
|
+
{"version":3,"file":"StoreInternal.d.ts","sourceRoot":"","sources":["../src/StoreInternal.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAC7B,OAAO,EACH,WAAW,EACX,MAAM,EACN,SAAS,EAGZ,MAAM,kCAAkC,CAAA;AACzC,OAAO,EACH,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,YAAY,EACZ,WAAW,EACX,OAAO,EACV,MAAM,mCAAmC,CAAA;AAM1C,UAAU,WAAW;IACjB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACtB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACtC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAChC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CAC3B;AAED,KAAK,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAGtC,qBAAa,aAAc,YAAW,KAAK,EAAE,SAAS,CAAC,aAAa,CAAC;IACjE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,WAAW,CAAQ;IAE3B,WAAW,EAAE,WAAW,GAAG,SAAS,CAAA;gBAGhC,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,MAAM;IAUxB,eAAe,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,aAAa;IASrD,MAAM,CAAC,aAAa,IAAI,WAAW;IAQnC,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,aAAa;YAOP,WAAW;IA6EnB,UAAU,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAkB7D,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK/C,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBjD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBxC,UAAU,IAAI,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAI1C,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3C,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW7C,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBrC,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAIvC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3C,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ7C,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAQvD,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;CAM5E"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var coreWalletAuth = require('@canton-network/core-wallet-auth');
|
|
4
|
+
var coreLedgerClient = require('@canton-network/core-ledger-client');
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
9
|
+
var StoreInternal = class _StoreInternal {
|
|
10
|
+
constructor(config, logger, authContext, userStorage) {
|
|
11
|
+
__publicField(this, "logger");
|
|
12
|
+
__publicField(this, "systemStorage");
|
|
13
|
+
__publicField(this, "userStorage");
|
|
14
|
+
__publicField(this, "authContext");
|
|
15
|
+
this.logger = logger.child({ component: "StoreInternal" });
|
|
16
|
+
this.systemStorage = config;
|
|
17
|
+
this.authContext = authContext;
|
|
18
|
+
this.userStorage = userStorage || /* @__PURE__ */ new Map();
|
|
19
|
+
this.syncWallets();
|
|
20
|
+
}
|
|
21
|
+
withAuthContext(context) {
|
|
22
|
+
return new _StoreInternal(
|
|
23
|
+
this.systemStorage,
|
|
24
|
+
this.logger,
|
|
25
|
+
context,
|
|
26
|
+
this.userStorage
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
static createStorage() {
|
|
30
|
+
return {
|
|
31
|
+
wallets: [],
|
|
32
|
+
transactions: /* @__PURE__ */ new Map(),
|
|
33
|
+
session: void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
assertConnected() {
|
|
37
|
+
return coreWalletAuth.assertConnected(this.authContext).userId;
|
|
38
|
+
}
|
|
39
|
+
getStorage() {
|
|
40
|
+
const userId = this.assertConnected();
|
|
41
|
+
if (!this.userStorage.has(userId)) {
|
|
42
|
+
this.userStorage.set(userId, _StoreInternal.createStorage());
|
|
43
|
+
}
|
|
44
|
+
return this.userStorage.get(userId);
|
|
45
|
+
}
|
|
46
|
+
updateStorage(storage) {
|
|
47
|
+
const userId = this.assertConnected();
|
|
48
|
+
this.userStorage.set(userId, storage);
|
|
49
|
+
}
|
|
50
|
+
// Wallet methods
|
|
51
|
+
async syncWallets() {
|
|
52
|
+
try {
|
|
53
|
+
const network = await this.getCurrentNetwork();
|
|
54
|
+
const userAccessTokenProvider = {
|
|
55
|
+
getUserAccessToken: async () => this.authContext.accessToken,
|
|
56
|
+
getAdminAccessToken: async () => this.authContext.accessToken
|
|
57
|
+
};
|
|
58
|
+
const ledgerClient = new coreLedgerClient.LedgerClient(
|
|
59
|
+
new URL(network.ledgerApi.baseUrl),
|
|
60
|
+
this.logger,
|
|
61
|
+
false,
|
|
62
|
+
void 0,
|
|
63
|
+
userAccessTokenProvider
|
|
64
|
+
);
|
|
65
|
+
const rights = await ledgerClient.getWithRetry(
|
|
66
|
+
"/v2/users/{user-id}/rights",
|
|
67
|
+
coreLedgerClient.defaultRetryableOptions,
|
|
68
|
+
{
|
|
69
|
+
path: {
|
|
70
|
+
"user-id": this.authContext.userId
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
const parties = rights.rights?.filter((right) => "CanActAs" in right.kind).map((right) => {
|
|
75
|
+
if ("CanActAs" in right.kind) {
|
|
76
|
+
return right.kind.CanActAs.value.party;
|
|
77
|
+
}
|
|
78
|
+
throw new Error("Unexpected right kind");
|
|
79
|
+
});
|
|
80
|
+
const existingWallets = await this.getWallets();
|
|
81
|
+
const existingPartyIds = new Set(
|
|
82
|
+
existingWallets.map((w) => w.partyId)
|
|
83
|
+
);
|
|
84
|
+
const participantWallets = parties?.filter(
|
|
85
|
+
(party) => !existingPartyIds.has(party)
|
|
86
|
+
// todo: filter on idp id
|
|
87
|
+
).map((party) => {
|
|
88
|
+
const [hint, namespace] = party.split("::");
|
|
89
|
+
return {
|
|
90
|
+
primary: false,
|
|
91
|
+
partyId: party,
|
|
92
|
+
hint,
|
|
93
|
+
publicKey: namespace,
|
|
94
|
+
namespace,
|
|
95
|
+
chainId: network.chainId,
|
|
96
|
+
signingProviderId: "participant"
|
|
97
|
+
// todo: determine based on partyDetails.isLocal
|
|
98
|
+
};
|
|
99
|
+
}) || [];
|
|
100
|
+
const storage = this.getStorage();
|
|
101
|
+
const wallets = [...storage.wallets, ...participantWallets];
|
|
102
|
+
const hasPrimary = wallets.some((w) => w.primary);
|
|
103
|
+
if (!hasPrimary && wallets.length > 0) {
|
|
104
|
+
wallets[0].primary = true;
|
|
105
|
+
}
|
|
106
|
+
this.logger.debug(wallets, "Wallets synchronized");
|
|
107
|
+
storage.wallets = wallets;
|
|
108
|
+
this.updateStorage(storage);
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async getWallets(filter = {}) {
|
|
114
|
+
const { chainIds, signingProviderIds } = filter;
|
|
115
|
+
const chainIdSet = chainIds ? new Set(chainIds) : null;
|
|
116
|
+
const signingProviderIdSet = signingProviderIds ? new Set(signingProviderIds) : null;
|
|
117
|
+
return this.getStorage().wallets.filter((wallet) => {
|
|
118
|
+
const matchedChainIds = chainIdSet ? chainIdSet.has(wallet.chainId) : true;
|
|
119
|
+
const matchedStorageProviderIdS = signingProviderIdSet ? signingProviderIdSet.has(wallet.signingProviderId) : true;
|
|
120
|
+
return matchedChainIds && matchedStorageProviderIdS;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async getPrimaryWallet() {
|
|
124
|
+
const wallets = await this.getWallets();
|
|
125
|
+
return wallets.find((w) => w.primary === true);
|
|
126
|
+
}
|
|
127
|
+
async setPrimaryWallet(partyId) {
|
|
128
|
+
const storage = this.getStorage();
|
|
129
|
+
if (!storage.wallets.some((w) => w.partyId === partyId)) {
|
|
130
|
+
throw new Error(`Wallet with partyId "${partyId}" not found`);
|
|
131
|
+
}
|
|
132
|
+
const wallets = storage.wallets.map((w) => {
|
|
133
|
+
if (w.partyId === partyId) {
|
|
134
|
+
w.primary = true;
|
|
135
|
+
} else {
|
|
136
|
+
w.primary = false;
|
|
137
|
+
}
|
|
138
|
+
return w;
|
|
139
|
+
});
|
|
140
|
+
storage.wallets = wallets;
|
|
141
|
+
this.updateStorage(storage);
|
|
142
|
+
}
|
|
143
|
+
async addWallet(wallet) {
|
|
144
|
+
const storage = this.getStorage();
|
|
145
|
+
if (storage.wallets.some((w) => w.partyId === wallet.partyId)) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`Wallet with partyId "${wallet.partyId}" already exists`
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
const wallets = await this.getWallets();
|
|
151
|
+
if (wallets.length === 0) {
|
|
152
|
+
wallet.primary = true;
|
|
153
|
+
}
|
|
154
|
+
if (wallet.primary) {
|
|
155
|
+
storage.wallets.map((w) => w.primary = false);
|
|
156
|
+
}
|
|
157
|
+
wallets.push(wallet);
|
|
158
|
+
storage.wallets = wallets;
|
|
159
|
+
this.updateStorage(storage);
|
|
160
|
+
}
|
|
161
|
+
// Session methods
|
|
162
|
+
async getSession() {
|
|
163
|
+
return this.getStorage().session;
|
|
164
|
+
}
|
|
165
|
+
async setSession(session) {
|
|
166
|
+
const storage = this.getStorage();
|
|
167
|
+
storage.session = session;
|
|
168
|
+
this.updateStorage(storage);
|
|
169
|
+
}
|
|
170
|
+
async removeSession() {
|
|
171
|
+
const storage = this.getStorage();
|
|
172
|
+
storage.session = void 0;
|
|
173
|
+
this.updateStorage(storage);
|
|
174
|
+
}
|
|
175
|
+
// Network methods
|
|
176
|
+
async getNetwork(chainId) {
|
|
177
|
+
this.assertConnected();
|
|
178
|
+
const networks = await this.listNetworks();
|
|
179
|
+
if (!networks) throw new Error("No networks available");
|
|
180
|
+
const network = networks.find((n) => n.chainId === chainId);
|
|
181
|
+
if (!network) throw new Error(`Network "${chainId}" not found`);
|
|
182
|
+
return network;
|
|
183
|
+
}
|
|
184
|
+
async getCurrentNetwork() {
|
|
185
|
+
const session = this.getStorage().session;
|
|
186
|
+
if (!session) {
|
|
187
|
+
throw new Error("No session found");
|
|
188
|
+
}
|
|
189
|
+
const chainId = session.network;
|
|
190
|
+
if (!chainId) {
|
|
191
|
+
throw new Error("No current network set in session");
|
|
192
|
+
}
|
|
193
|
+
const networks = await this.listNetworks();
|
|
194
|
+
const network = networks.find((n) => n.chainId === chainId);
|
|
195
|
+
if (!network) {
|
|
196
|
+
throw new Error(`Network "${chainId}" not found`);
|
|
197
|
+
}
|
|
198
|
+
return network;
|
|
199
|
+
}
|
|
200
|
+
async listNetworks() {
|
|
201
|
+
return this.systemStorage.networks;
|
|
202
|
+
}
|
|
203
|
+
async updateNetwork(network) {
|
|
204
|
+
this.assertConnected();
|
|
205
|
+
this.removeNetwork(network.chainId);
|
|
206
|
+
this.systemStorage.networks.push(network);
|
|
207
|
+
}
|
|
208
|
+
async addNetwork(network) {
|
|
209
|
+
const networkAlreadyExists = this.systemStorage.networks.find(
|
|
210
|
+
(n) => n.chainId === network.chainId
|
|
211
|
+
);
|
|
212
|
+
if (networkAlreadyExists) {
|
|
213
|
+
throw new Error(`Network ${network.chainId} already exists`);
|
|
214
|
+
} else {
|
|
215
|
+
this.systemStorage.networks.push(network);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async removeNetwork(chainId) {
|
|
219
|
+
this.assertConnected();
|
|
220
|
+
this.systemStorage.networks = this.systemStorage.networks.filter(
|
|
221
|
+
(n) => n.chainId !== chainId
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
// Transaction methods
|
|
225
|
+
async setTransaction(transaction) {
|
|
226
|
+
this.assertConnected();
|
|
227
|
+
const storage = this.getStorage();
|
|
228
|
+
storage.transactions.set(transaction.commandId, transaction);
|
|
229
|
+
this.updateStorage(storage);
|
|
230
|
+
}
|
|
231
|
+
async getTransaction(commandId) {
|
|
232
|
+
this.assertConnected();
|
|
233
|
+
const storage = this.getStorage();
|
|
234
|
+
return storage.transactions.get(commandId);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
exports.StoreInternal = StoreInternal;
|
|
239
|
+
//# sourceMappingURL=index.cjs.map
|
|
240
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StoreInternal.ts"],"names":["assertConnected","LedgerClient","defaultRetryableOptions"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Logger } from 'pino'\nimport {\n AuthContext,\n UserId,\n AuthAware,\n assertConnected,\n AccessTokenProvider,\n} from '@canton-network/core-wallet-auth'\nimport {\n Store,\n Wallet,\n PartyId,\n Session,\n WalletFilter,\n Transaction,\n Network,\n} from '@canton-network/core-wallet-store'\nimport {\n LedgerClient,\n defaultRetryableOptions,\n} from '@canton-network/core-ledger-client'\n\ninterface UserStorage {\n wallets: Array<Wallet>\n transactions: Map<string, Transaction>\n session: Session | undefined\n}\n\nexport interface StoreInternalConfig {\n networks: Array<Network>\n}\n\ntype Memory = Map<UserId, UserStorage>\n\n// TODO: remove AuthAware and instead provide wrapper in clients\nexport class StoreInternal implements Store, AuthAware<StoreInternal> {\n private logger: Logger\n private systemStorage: StoreInternalConfig\n private userStorage: Memory\n\n authContext: AuthContext | undefined\n\n constructor(\n config: StoreInternalConfig,\n logger: Logger,\n authContext?: AuthContext,\n userStorage?: Memory\n ) {\n this.logger = logger.child({ component: 'StoreInternal' })\n this.systemStorage = config\n this.authContext = authContext\n this.userStorage = userStorage || new Map()\n\n this.syncWallets()\n }\n\n withAuthContext(context?: AuthContext): StoreInternal {\n return new StoreInternal(\n this.systemStorage,\n this.logger,\n context,\n this.userStorage\n )\n }\n\n static createStorage(): UserStorage {\n return {\n wallets: [],\n transactions: new Map<string, Transaction>(),\n session: undefined,\n }\n }\n\n private assertConnected(): UserId {\n return assertConnected(this.authContext).userId\n }\n\n private getStorage(): UserStorage {\n const userId = this.assertConnected()\n if (!this.userStorage.has(userId)) {\n this.userStorage.set(userId, StoreInternal.createStorage())\n }\n return this.userStorage.get(userId)!\n }\n\n private updateStorage(storage: UserStorage): void {\n const userId = this.assertConnected()\n this.userStorage.set(userId, storage)\n }\n\n // Wallet methods\n\n private async syncWallets(): Promise<void> {\n try {\n const network = await this.getCurrentNetwork()\n\n // Get existing parties from participant\n const userAccessTokenProvider: AccessTokenProvider = {\n getUserAccessToken: async () => this.authContext!.accessToken,\n getAdminAccessToken: async () => this.authContext!.accessToken,\n }\n\n const ledgerClient = new LedgerClient(\n new URL(network.ledgerApi.baseUrl),\n this.logger,\n false,\n undefined,\n userAccessTokenProvider\n )\n const rights = await ledgerClient.getWithRetry(\n '/v2/users/{user-id}/rights',\n defaultRetryableOptions,\n {\n path: {\n 'user-id': this.authContext!.userId,\n },\n }\n )\n const parties = rights.rights\n ?.filter((right) => 'CanActAs' in right.kind)\n .map((right) => {\n if ('CanActAs' in right.kind) {\n return right.kind.CanActAs.value.party\n }\n throw new Error('Unexpected right kind')\n })\n\n // Merge Wallets\n const existingWallets = await this.getWallets()\n const existingPartyIds = new Set(\n existingWallets.map((w) => w.partyId)\n )\n const participantWallets: Array<Wallet> =\n parties\n ?.filter(\n (party) => !existingPartyIds.has(party)\n // todo: filter on idp id\n )\n .map((party) => {\n const [hint, namespace] = party.split('::')\n return {\n primary: false,\n partyId: party,\n hint: hint,\n publicKey: namespace,\n namespace: namespace,\n chainId: network.chainId,\n signingProviderId: 'participant', // todo: determine based on partyDetails.isLocal\n }\n }) || []\n const storage = this.getStorage()\n const wallets = [...storage.wallets, ...participantWallets]\n\n // Set primary wallet if none exists\n const hasPrimary = wallets.some((w) => w.primary)\n if (!hasPrimary && wallets.length > 0) {\n wallets[0].primary = true\n }\n\n this.logger.debug(wallets, 'Wallets synchronized')\n\n // Update storage with new wallets\n storage.wallets = wallets\n this.updateStorage(storage)\n } catch {\n return\n }\n }\n\n async getWallets(filter: WalletFilter = {}): Promise<Array<Wallet>> {\n const { chainIds, signingProviderIds } = filter\n const chainIdSet = chainIds ? new Set(chainIds) : null\n const signingProviderIdSet = signingProviderIds\n ? new Set(signingProviderIds)\n : null\n\n return this.getStorage().wallets.filter((wallet) => {\n const matchedChainIds = chainIdSet\n ? chainIdSet.has(wallet.chainId)\n : true\n const matchedStorageProviderIdS = signingProviderIdSet\n ? signingProviderIdSet.has(wallet.signingProviderId)\n : true\n return matchedChainIds && matchedStorageProviderIdS\n })\n }\n\n async getPrimaryWallet(): Promise<Wallet | undefined> {\n const wallets = await this.getWallets()\n return wallets.find((w) => w.primary === true)\n }\n\n async setPrimaryWallet(partyId: PartyId): Promise<void> {\n const storage = this.getStorage()\n if (!storage.wallets.some((w) => w.partyId === partyId)) {\n throw new Error(`Wallet with partyId \"${partyId}\" not found`)\n }\n const wallets = storage.wallets.map((w) => {\n if (w.partyId === partyId) {\n w.primary = true\n } else {\n w.primary = false\n }\n return w\n })\n storage.wallets = wallets\n this.updateStorage(storage)\n }\n\n async addWallet(wallet: Wallet): Promise<void> {\n const storage = this.getStorage()\n if (storage.wallets.some((w) => w.partyId === wallet.partyId)) {\n throw new Error(\n `Wallet with partyId \"${wallet.partyId}\" already exists`\n )\n }\n const wallets = await this.getWallets()\n\n if (wallets.length === 0) {\n // If this is the first wallet, set it as primary automatically\n wallet.primary = true\n }\n\n if (wallet.primary) {\n // If the new wallet is primary, set all others to non-primary\n storage.wallets.map((w) => (w.primary = false))\n }\n wallets.push(wallet)\n storage.wallets = wallets\n this.updateStorage(storage)\n }\n\n // Session methods\n async getSession(): Promise<Session | undefined> {\n return this.getStorage().session\n }\n\n async setSession(session: Session): Promise<void> {\n const storage = this.getStorage()\n storage.session = session\n this.updateStorage(storage)\n }\n\n async removeSession(): Promise<void> {\n const storage = this.getStorage()\n storage.session = undefined\n this.updateStorage(storage)\n }\n\n // Network methods\n async getNetwork(chainId: string): Promise<Network> {\n this.assertConnected()\n\n const networks = await this.listNetworks()\n if (!networks) throw new Error('No networks available')\n\n const network = networks.find((n) => n.chainId === chainId)\n if (!network) throw new Error(`Network \"${chainId}\" not found`)\n return network\n }\n\n async getCurrentNetwork(): Promise<Network> {\n const session = this.getStorage().session\n if (!session) {\n throw new Error('No session found')\n }\n const chainId = session.network\n if (!chainId) {\n throw new Error('No current network set in session')\n }\n\n const networks = await this.listNetworks()\n const network = networks.find((n) => n.chainId === chainId)\n if (!network) {\n throw new Error(`Network \"${chainId}\" not found`)\n }\n return network\n }\n\n async listNetworks(): Promise<Array<Network>> {\n return this.systemStorage.networks\n }\n\n async updateNetwork(network: Network): Promise<void> {\n this.assertConnected()\n this.removeNetwork(network.chainId) // Ensure no duplicates\n this.systemStorage.networks.push(network)\n }\n\n async addNetwork(network: Network): Promise<void> {\n const networkAlreadyExists = this.systemStorage.networks.find(\n (n) => n.chainId === network.chainId\n )\n if (networkAlreadyExists) {\n throw new Error(`Network ${network.chainId} already exists`)\n } else {\n this.systemStorage.networks.push(network)\n }\n }\n\n async removeNetwork(chainId: string): Promise<void> {\n this.assertConnected()\n this.systemStorage.networks = this.systemStorage.networks.filter(\n (n) => n.chainId !== chainId\n )\n }\n\n // Transaction methods\n async setTransaction(transaction: Transaction): Promise<void> {\n this.assertConnected()\n const storage = this.getStorage()\n\n storage.transactions.set(transaction.commandId, transaction)\n this.updateStorage(storage)\n }\n\n async getTransaction(commandId: string): Promise<Transaction | undefined> {\n this.assertConnected()\n const storage = this.getStorage()\n\n return storage.transactions.get(commandId)\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,238 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { assertConnected } from '@canton-network/core-wallet-auth';
|
|
2
|
+
import { LedgerClient, defaultRetryableOptions } from '@canton-network/core-ledger-client';
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7
|
+
var StoreInternal = class _StoreInternal {
|
|
8
|
+
constructor(config, logger, authContext, userStorage) {
|
|
9
|
+
__publicField(this, "logger");
|
|
10
|
+
__publicField(this, "systemStorage");
|
|
11
|
+
__publicField(this, "userStorage");
|
|
12
|
+
__publicField(this, "authContext");
|
|
13
|
+
this.logger = logger.child({ component: "StoreInternal" });
|
|
14
|
+
this.systemStorage = config;
|
|
15
|
+
this.authContext = authContext;
|
|
16
|
+
this.userStorage = userStorage || /* @__PURE__ */ new Map();
|
|
17
|
+
this.syncWallets();
|
|
18
|
+
}
|
|
19
|
+
withAuthContext(context) {
|
|
20
|
+
return new _StoreInternal(
|
|
21
|
+
this.systemStorage,
|
|
22
|
+
this.logger,
|
|
23
|
+
context,
|
|
24
|
+
this.userStorage
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
static createStorage() {
|
|
28
|
+
return {
|
|
29
|
+
wallets: [],
|
|
30
|
+
transactions: /* @__PURE__ */ new Map(),
|
|
31
|
+
session: void 0
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
assertConnected() {
|
|
35
|
+
return assertConnected(this.authContext).userId;
|
|
36
|
+
}
|
|
37
|
+
getStorage() {
|
|
38
|
+
const userId = this.assertConnected();
|
|
39
|
+
if (!this.userStorage.has(userId)) {
|
|
40
|
+
this.userStorage.set(userId, _StoreInternal.createStorage());
|
|
41
|
+
}
|
|
42
|
+
return this.userStorage.get(userId);
|
|
43
|
+
}
|
|
44
|
+
updateStorage(storage) {
|
|
45
|
+
const userId = this.assertConnected();
|
|
46
|
+
this.userStorage.set(userId, storage);
|
|
47
|
+
}
|
|
48
|
+
// Wallet methods
|
|
49
|
+
async syncWallets() {
|
|
50
|
+
try {
|
|
51
|
+
const network = await this.getCurrentNetwork();
|
|
52
|
+
const userAccessTokenProvider = {
|
|
53
|
+
getUserAccessToken: async () => this.authContext.accessToken,
|
|
54
|
+
getAdminAccessToken: async () => this.authContext.accessToken
|
|
55
|
+
};
|
|
56
|
+
const ledgerClient = new LedgerClient(
|
|
57
|
+
new URL(network.ledgerApi.baseUrl),
|
|
58
|
+
this.logger,
|
|
59
|
+
false,
|
|
60
|
+
void 0,
|
|
61
|
+
userAccessTokenProvider
|
|
62
|
+
);
|
|
63
|
+
const rights = await ledgerClient.getWithRetry(
|
|
64
|
+
"/v2/users/{user-id}/rights",
|
|
65
|
+
defaultRetryableOptions,
|
|
66
|
+
{
|
|
67
|
+
path: {
|
|
68
|
+
"user-id": this.authContext.userId
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
const parties = rights.rights?.filter((right) => "CanActAs" in right.kind).map((right) => {
|
|
73
|
+
if ("CanActAs" in right.kind) {
|
|
74
|
+
return right.kind.CanActAs.value.party;
|
|
75
|
+
}
|
|
76
|
+
throw new Error("Unexpected right kind");
|
|
77
|
+
});
|
|
78
|
+
const existingWallets = await this.getWallets();
|
|
79
|
+
const existingPartyIds = new Set(
|
|
80
|
+
existingWallets.map((w) => w.partyId)
|
|
81
|
+
);
|
|
82
|
+
const participantWallets = parties?.filter(
|
|
83
|
+
(party) => !existingPartyIds.has(party)
|
|
84
|
+
// todo: filter on idp id
|
|
85
|
+
).map((party) => {
|
|
86
|
+
const [hint, namespace] = party.split("::");
|
|
87
|
+
return {
|
|
88
|
+
primary: false,
|
|
89
|
+
partyId: party,
|
|
90
|
+
hint,
|
|
91
|
+
publicKey: namespace,
|
|
92
|
+
namespace,
|
|
93
|
+
chainId: network.chainId,
|
|
94
|
+
signingProviderId: "participant"
|
|
95
|
+
// todo: determine based on partyDetails.isLocal
|
|
96
|
+
};
|
|
97
|
+
}) || [];
|
|
98
|
+
const storage = this.getStorage();
|
|
99
|
+
const wallets = [...storage.wallets, ...participantWallets];
|
|
100
|
+
const hasPrimary = wallets.some((w) => w.primary);
|
|
101
|
+
if (!hasPrimary && wallets.length > 0) {
|
|
102
|
+
wallets[0].primary = true;
|
|
103
|
+
}
|
|
104
|
+
this.logger.debug(wallets, "Wallets synchronized");
|
|
105
|
+
storage.wallets = wallets;
|
|
106
|
+
this.updateStorage(storage);
|
|
107
|
+
} catch {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async getWallets(filter = {}) {
|
|
112
|
+
const { chainIds, signingProviderIds } = filter;
|
|
113
|
+
const chainIdSet = chainIds ? new Set(chainIds) : null;
|
|
114
|
+
const signingProviderIdSet = signingProviderIds ? new Set(signingProviderIds) : null;
|
|
115
|
+
return this.getStorage().wallets.filter((wallet) => {
|
|
116
|
+
const matchedChainIds = chainIdSet ? chainIdSet.has(wallet.chainId) : true;
|
|
117
|
+
const matchedStorageProviderIdS = signingProviderIdSet ? signingProviderIdSet.has(wallet.signingProviderId) : true;
|
|
118
|
+
return matchedChainIds && matchedStorageProviderIdS;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async getPrimaryWallet() {
|
|
122
|
+
const wallets = await this.getWallets();
|
|
123
|
+
return wallets.find((w) => w.primary === true);
|
|
124
|
+
}
|
|
125
|
+
async setPrimaryWallet(partyId) {
|
|
126
|
+
const storage = this.getStorage();
|
|
127
|
+
if (!storage.wallets.some((w) => w.partyId === partyId)) {
|
|
128
|
+
throw new Error(`Wallet with partyId "${partyId}" not found`);
|
|
129
|
+
}
|
|
130
|
+
const wallets = storage.wallets.map((w) => {
|
|
131
|
+
if (w.partyId === partyId) {
|
|
132
|
+
w.primary = true;
|
|
133
|
+
} else {
|
|
134
|
+
w.primary = false;
|
|
135
|
+
}
|
|
136
|
+
return w;
|
|
137
|
+
});
|
|
138
|
+
storage.wallets = wallets;
|
|
139
|
+
this.updateStorage(storage);
|
|
140
|
+
}
|
|
141
|
+
async addWallet(wallet) {
|
|
142
|
+
const storage = this.getStorage();
|
|
143
|
+
if (storage.wallets.some((w) => w.partyId === wallet.partyId)) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`Wallet with partyId "${wallet.partyId}" already exists`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const wallets = await this.getWallets();
|
|
149
|
+
if (wallets.length === 0) {
|
|
150
|
+
wallet.primary = true;
|
|
151
|
+
}
|
|
152
|
+
if (wallet.primary) {
|
|
153
|
+
storage.wallets.map((w) => w.primary = false);
|
|
154
|
+
}
|
|
155
|
+
wallets.push(wallet);
|
|
156
|
+
storage.wallets = wallets;
|
|
157
|
+
this.updateStorage(storage);
|
|
158
|
+
}
|
|
159
|
+
// Session methods
|
|
160
|
+
async getSession() {
|
|
161
|
+
return this.getStorage().session;
|
|
162
|
+
}
|
|
163
|
+
async setSession(session) {
|
|
164
|
+
const storage = this.getStorage();
|
|
165
|
+
storage.session = session;
|
|
166
|
+
this.updateStorage(storage);
|
|
167
|
+
}
|
|
168
|
+
async removeSession() {
|
|
169
|
+
const storage = this.getStorage();
|
|
170
|
+
storage.session = void 0;
|
|
171
|
+
this.updateStorage(storage);
|
|
172
|
+
}
|
|
173
|
+
// Network methods
|
|
174
|
+
async getNetwork(chainId) {
|
|
175
|
+
this.assertConnected();
|
|
176
|
+
const networks = await this.listNetworks();
|
|
177
|
+
if (!networks) throw new Error("No networks available");
|
|
178
|
+
const network = networks.find((n) => n.chainId === chainId);
|
|
179
|
+
if (!network) throw new Error(`Network "${chainId}" not found`);
|
|
180
|
+
return network;
|
|
181
|
+
}
|
|
182
|
+
async getCurrentNetwork() {
|
|
183
|
+
const session = this.getStorage().session;
|
|
184
|
+
if (!session) {
|
|
185
|
+
throw new Error("No session found");
|
|
186
|
+
}
|
|
187
|
+
const chainId = session.network;
|
|
188
|
+
if (!chainId) {
|
|
189
|
+
throw new Error("No current network set in session");
|
|
190
|
+
}
|
|
191
|
+
const networks = await this.listNetworks();
|
|
192
|
+
const network = networks.find((n) => n.chainId === chainId);
|
|
193
|
+
if (!network) {
|
|
194
|
+
throw new Error(`Network "${chainId}" not found`);
|
|
195
|
+
}
|
|
196
|
+
return network;
|
|
197
|
+
}
|
|
198
|
+
async listNetworks() {
|
|
199
|
+
return this.systemStorage.networks;
|
|
200
|
+
}
|
|
201
|
+
async updateNetwork(network) {
|
|
202
|
+
this.assertConnected();
|
|
203
|
+
this.removeNetwork(network.chainId);
|
|
204
|
+
this.systemStorage.networks.push(network);
|
|
205
|
+
}
|
|
206
|
+
async addNetwork(network) {
|
|
207
|
+
const networkAlreadyExists = this.systemStorage.networks.find(
|
|
208
|
+
(n) => n.chainId === network.chainId
|
|
209
|
+
);
|
|
210
|
+
if (networkAlreadyExists) {
|
|
211
|
+
throw new Error(`Network ${network.chainId} already exists`);
|
|
212
|
+
} else {
|
|
213
|
+
this.systemStorage.networks.push(network);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async removeNetwork(chainId) {
|
|
217
|
+
this.assertConnected();
|
|
218
|
+
this.systemStorage.networks = this.systemStorage.networks.filter(
|
|
219
|
+
(n) => n.chainId !== chainId
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
// Transaction methods
|
|
223
|
+
async setTransaction(transaction) {
|
|
224
|
+
this.assertConnected();
|
|
225
|
+
const storage = this.getStorage();
|
|
226
|
+
storage.transactions.set(transaction.commandId, transaction);
|
|
227
|
+
this.updateStorage(storage);
|
|
228
|
+
}
|
|
229
|
+
async getTransaction(commandId) {
|
|
230
|
+
this.assertConnected();
|
|
231
|
+
const storage = this.getStorage();
|
|
232
|
+
return storage.transactions.get(commandId);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export { StoreInternal };
|
|
237
|
+
//# sourceMappingURL=index.js.map
|
|
238
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StoreInternal.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Logger } from 'pino'\nimport {\n AuthContext,\n UserId,\n AuthAware,\n assertConnected,\n AccessTokenProvider,\n} from '@canton-network/core-wallet-auth'\nimport {\n Store,\n Wallet,\n PartyId,\n Session,\n WalletFilter,\n Transaction,\n Network,\n} from '@canton-network/core-wallet-store'\nimport {\n LedgerClient,\n defaultRetryableOptions,\n} from '@canton-network/core-ledger-client'\n\ninterface UserStorage {\n wallets: Array<Wallet>\n transactions: Map<string, Transaction>\n session: Session | undefined\n}\n\nexport interface StoreInternalConfig {\n networks: Array<Network>\n}\n\ntype Memory = Map<UserId, UserStorage>\n\n// TODO: remove AuthAware and instead provide wrapper in clients\nexport class StoreInternal implements Store, AuthAware<StoreInternal> {\n private logger: Logger\n private systemStorage: StoreInternalConfig\n private userStorage: Memory\n\n authContext: AuthContext | undefined\n\n constructor(\n config: StoreInternalConfig,\n logger: Logger,\n authContext?: AuthContext,\n userStorage?: Memory\n ) {\n this.logger = logger.child({ component: 'StoreInternal' })\n this.systemStorage = config\n this.authContext = authContext\n this.userStorage = userStorage || new Map()\n\n this.syncWallets()\n }\n\n withAuthContext(context?: AuthContext): StoreInternal {\n return new StoreInternal(\n this.systemStorage,\n this.logger,\n context,\n this.userStorage\n )\n }\n\n static createStorage(): UserStorage {\n return {\n wallets: [],\n transactions: new Map<string, Transaction>(),\n session: undefined,\n }\n }\n\n private assertConnected(): UserId {\n return assertConnected(this.authContext).userId\n }\n\n private getStorage(): UserStorage {\n const userId = this.assertConnected()\n if (!this.userStorage.has(userId)) {\n this.userStorage.set(userId, StoreInternal.createStorage())\n }\n return this.userStorage.get(userId)!\n }\n\n private updateStorage(storage: UserStorage): void {\n const userId = this.assertConnected()\n this.userStorage.set(userId, storage)\n }\n\n // Wallet methods\n\n private async syncWallets(): Promise<void> {\n try {\n const network = await this.getCurrentNetwork()\n\n // Get existing parties from participant\n const userAccessTokenProvider: AccessTokenProvider = {\n getUserAccessToken: async () => this.authContext!.accessToken,\n getAdminAccessToken: async () => this.authContext!.accessToken,\n }\n\n const ledgerClient = new LedgerClient(\n new URL(network.ledgerApi.baseUrl),\n this.logger,\n false,\n undefined,\n userAccessTokenProvider\n )\n const rights = await ledgerClient.getWithRetry(\n '/v2/users/{user-id}/rights',\n defaultRetryableOptions,\n {\n path: {\n 'user-id': this.authContext!.userId,\n },\n }\n )\n const parties = rights.rights\n ?.filter((right) => 'CanActAs' in right.kind)\n .map((right) => {\n if ('CanActAs' in right.kind) {\n return right.kind.CanActAs.value.party\n }\n throw new Error('Unexpected right kind')\n })\n\n // Merge Wallets\n const existingWallets = await this.getWallets()\n const existingPartyIds = new Set(\n existingWallets.map((w) => w.partyId)\n )\n const participantWallets: Array<Wallet> =\n parties\n ?.filter(\n (party) => !existingPartyIds.has(party)\n // todo: filter on idp id\n )\n .map((party) => {\n const [hint, namespace] = party.split('::')\n return {\n primary: false,\n partyId: party,\n hint: hint,\n publicKey: namespace,\n namespace: namespace,\n chainId: network.chainId,\n signingProviderId: 'participant', // todo: determine based on partyDetails.isLocal\n }\n }) || []\n const storage = this.getStorage()\n const wallets = [...storage.wallets, ...participantWallets]\n\n // Set primary wallet if none exists\n const hasPrimary = wallets.some((w) => w.primary)\n if (!hasPrimary && wallets.length > 0) {\n wallets[0].primary = true\n }\n\n this.logger.debug(wallets, 'Wallets synchronized')\n\n // Update storage with new wallets\n storage.wallets = wallets\n this.updateStorage(storage)\n } catch {\n return\n }\n }\n\n async getWallets(filter: WalletFilter = {}): Promise<Array<Wallet>> {\n const { chainIds, signingProviderIds } = filter\n const chainIdSet = chainIds ? new Set(chainIds) : null\n const signingProviderIdSet = signingProviderIds\n ? new Set(signingProviderIds)\n : null\n\n return this.getStorage().wallets.filter((wallet) => {\n const matchedChainIds = chainIdSet\n ? chainIdSet.has(wallet.chainId)\n : true\n const matchedStorageProviderIdS = signingProviderIdSet\n ? signingProviderIdSet.has(wallet.signingProviderId)\n : true\n return matchedChainIds && matchedStorageProviderIdS\n })\n }\n\n async getPrimaryWallet(): Promise<Wallet | undefined> {\n const wallets = await this.getWallets()\n return wallets.find((w) => w.primary === true)\n }\n\n async setPrimaryWallet(partyId: PartyId): Promise<void> {\n const storage = this.getStorage()\n if (!storage.wallets.some((w) => w.partyId === partyId)) {\n throw new Error(`Wallet with partyId \"${partyId}\" not found`)\n }\n const wallets = storage.wallets.map((w) => {\n if (w.partyId === partyId) {\n w.primary = true\n } else {\n w.primary = false\n }\n return w\n })\n storage.wallets = wallets\n this.updateStorage(storage)\n }\n\n async addWallet(wallet: Wallet): Promise<void> {\n const storage = this.getStorage()\n if (storage.wallets.some((w) => w.partyId === wallet.partyId)) {\n throw new Error(\n `Wallet with partyId \"${wallet.partyId}\" already exists`\n )\n }\n const wallets = await this.getWallets()\n\n if (wallets.length === 0) {\n // If this is the first wallet, set it as primary automatically\n wallet.primary = true\n }\n\n if (wallet.primary) {\n // If the new wallet is primary, set all others to non-primary\n storage.wallets.map((w) => (w.primary = false))\n }\n wallets.push(wallet)\n storage.wallets = wallets\n this.updateStorage(storage)\n }\n\n // Session methods\n async getSession(): Promise<Session | undefined> {\n return this.getStorage().session\n }\n\n async setSession(session: Session): Promise<void> {\n const storage = this.getStorage()\n storage.session = session\n this.updateStorage(storage)\n }\n\n async removeSession(): Promise<void> {\n const storage = this.getStorage()\n storage.session = undefined\n this.updateStorage(storage)\n }\n\n // Network methods\n async getNetwork(chainId: string): Promise<Network> {\n this.assertConnected()\n\n const networks = await this.listNetworks()\n if (!networks) throw new Error('No networks available')\n\n const network = networks.find((n) => n.chainId === chainId)\n if (!network) throw new Error(`Network \"${chainId}\" not found`)\n return network\n }\n\n async getCurrentNetwork(): Promise<Network> {\n const session = this.getStorage().session\n if (!session) {\n throw new Error('No session found')\n }\n const chainId = session.network\n if (!chainId) {\n throw new Error('No current network set in session')\n }\n\n const networks = await this.listNetworks()\n const network = networks.find((n) => n.chainId === chainId)\n if (!network) {\n throw new Error(`Network \"${chainId}\" not found`)\n }\n return network\n }\n\n async listNetworks(): Promise<Array<Network>> {\n return this.systemStorage.networks\n }\n\n async updateNetwork(network: Network): Promise<void> {\n this.assertConnected()\n this.removeNetwork(network.chainId) // Ensure no duplicates\n this.systemStorage.networks.push(network)\n }\n\n async addNetwork(network: Network): Promise<void> {\n const networkAlreadyExists = this.systemStorage.networks.find(\n (n) => n.chainId === network.chainId\n )\n if (networkAlreadyExists) {\n throw new Error(`Network ${network.chainId} already exists`)\n } else {\n this.systemStorage.networks.push(network)\n }\n }\n\n async removeNetwork(chainId: string): Promise<void> {\n this.assertConnected()\n this.systemStorage.networks = this.systemStorage.networks.filter(\n (n) => n.chainId !== chainId\n )\n }\n\n // Transaction methods\n async setTransaction(transaction: Transaction): Promise<void> {\n this.assertConnected()\n const storage = this.getStorage()\n\n storage.transactions.set(transaction.commandId, transaction)\n this.updateStorage(storage)\n }\n\n async getTransaction(commandId: string): Promise<Transaction | undefined> {\n this.assertConnected()\n const storage = this.getStorage()\n\n return storage.transactions.get(commandId)\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canton-network/core-wallet-store-inmemory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "In-memory implementation of the Store API",
|
|
6
6
|
"repository": "github:hyperledger-labs/splice-wallet-kernel",
|
|
@@ -10,17 +10,18 @@
|
|
|
10
10
|
"main": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc -
|
|
14
|
-
"dev": "tsc -
|
|
13
|
+
"build": "tsup && tsc -p tsconfig.types.json",
|
|
14
|
+
"dev": "tsup --watch --onSuccess \"tsc -p tsconfig.types.json\"",
|
|
15
15
|
"flatpack": "yarn pack --out \"$FLATPACK_OUTDIR\"",
|
|
16
16
|
"clean": "tsc -b --clean; rm -rf dist",
|
|
17
17
|
"test": "yarn node --experimental-vm-modules $(yarn bin jest)"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@canton-network/core-ledger-client": "",
|
|
21
|
-
"@canton-network/core-rpc-errors": "",
|
|
22
|
-
"@canton-network/core-
|
|
23
|
-
"@canton-network/core-wallet-
|
|
20
|
+
"@canton-network/core-ledger-client": "^0.16.0",
|
|
21
|
+
"@canton-network/core-rpc-errors": "^0.7.0",
|
|
22
|
+
"@canton-network/core-types": "^0.10.0",
|
|
23
|
+
"@canton-network/core-wallet-auth": "^0.11.0",
|
|
24
|
+
"@canton-network/core-wallet-store": "^0.10.0",
|
|
24
25
|
"pino": "^10.0.0",
|
|
25
26
|
"zod": "^3.25.64"
|
|
26
27
|
},
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
"pino-test": "^1.1.0",
|
|
34
35
|
"ts-jest": "^29.4.0",
|
|
35
36
|
"ts-jest-resolver": "^2.0.1",
|
|
37
|
+
"tsup": "^8.5.0",
|
|
36
38
|
"typescript": "^5.8.3"
|
|
37
39
|
},
|
|
38
40
|
"files": [
|
package/dist/Store.test.d.ts
DELETED
package/dist/Store.test.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Store.test.d.ts","sourceRoot":"","sources":["../src/Store.test.ts"],"names":[],"mappings":""}
|
package/dist/Store.test.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { beforeEach, describe, expect, test } from '@jest/globals';
|
|
4
|
-
import { StoreInternal } from './StoreInternal';
|
|
5
|
-
import { pino } from 'pino';
|
|
6
|
-
import { sink } from 'pino-test';
|
|
7
|
-
const authContextMock = {
|
|
8
|
-
userId: 'test-user-id',
|
|
9
|
-
accessToken: 'test-access-token',
|
|
10
|
-
};
|
|
11
|
-
const storeConfig = {
|
|
12
|
-
networks: [],
|
|
13
|
-
};
|
|
14
|
-
const implementations = [
|
|
15
|
-
['StoreInternal', StoreInternal],
|
|
16
|
-
];
|
|
17
|
-
implementations.forEach(([name, StoreImpl]) => {
|
|
18
|
-
describe(name, () => {
|
|
19
|
-
let store;
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
store = new StoreImpl(storeConfig, pino(sink()), authContextMock);
|
|
22
|
-
});
|
|
23
|
-
test('should add and retrieve wallets', async () => {
|
|
24
|
-
const wallet = {
|
|
25
|
-
primary: false,
|
|
26
|
-
partyId: 'party1',
|
|
27
|
-
hint: 'hint',
|
|
28
|
-
signingProviderId: 'internal',
|
|
29
|
-
publicKey: 'publicKey',
|
|
30
|
-
namespace: 'namespace',
|
|
31
|
-
chainId: 'network1',
|
|
32
|
-
};
|
|
33
|
-
await store.addWallet(wallet);
|
|
34
|
-
const wallets = await store.getWallets();
|
|
35
|
-
expect(wallets).toHaveLength(1);
|
|
36
|
-
});
|
|
37
|
-
test('should filter wallets', async () => {
|
|
38
|
-
const wallet1 = {
|
|
39
|
-
primary: false,
|
|
40
|
-
partyId: 'party1',
|
|
41
|
-
hint: 'hint1',
|
|
42
|
-
signingProviderId: 'internal1',
|
|
43
|
-
publicKey: 'publicKey',
|
|
44
|
-
namespace: 'namespace',
|
|
45
|
-
chainId: 'network1',
|
|
46
|
-
};
|
|
47
|
-
const wallet2 = {
|
|
48
|
-
primary: false,
|
|
49
|
-
partyId: 'party2',
|
|
50
|
-
hint: 'hint2',
|
|
51
|
-
signingProviderId: 'internal2',
|
|
52
|
-
publicKey: 'publicKey',
|
|
53
|
-
namespace: 'namespace',
|
|
54
|
-
chainId: 'network1',
|
|
55
|
-
};
|
|
56
|
-
const wallet3 = {
|
|
57
|
-
primary: false,
|
|
58
|
-
partyId: 'party3',
|
|
59
|
-
hint: 'hint3',
|
|
60
|
-
signingProviderId: 'internal2',
|
|
61
|
-
publicKey: 'publicKey',
|
|
62
|
-
namespace: 'namespace',
|
|
63
|
-
chainId: 'network2',
|
|
64
|
-
};
|
|
65
|
-
await store.addWallet(wallet1);
|
|
66
|
-
await store.addWallet(wallet2);
|
|
67
|
-
await store.addWallet(wallet3);
|
|
68
|
-
const getAllWallets = await store.getWallets();
|
|
69
|
-
const getWalletsByChainId = await store.getWallets({
|
|
70
|
-
chainIds: ['network1'],
|
|
71
|
-
});
|
|
72
|
-
const getWalletsBySigningProviderId = await store.getWallets({
|
|
73
|
-
signingProviderIds: ['internal2'],
|
|
74
|
-
});
|
|
75
|
-
const getWalletsByChainIdAndSigningProviderId = await store.getWallets({
|
|
76
|
-
chainIds: ['network1'],
|
|
77
|
-
signingProviderIds: ['internal2'],
|
|
78
|
-
});
|
|
79
|
-
expect(getAllWallets).toHaveLength(3);
|
|
80
|
-
expect(getWalletsByChainId).toHaveLength(2);
|
|
81
|
-
expect(getWalletsBySigningProviderId).toHaveLength(2);
|
|
82
|
-
expect(getWalletsByChainIdAndSigningProviderId).toHaveLength(1);
|
|
83
|
-
});
|
|
84
|
-
test('should set and get primary wallet', async () => {
|
|
85
|
-
const wallet1 = {
|
|
86
|
-
primary: false,
|
|
87
|
-
partyId: 'party1',
|
|
88
|
-
hint: 'hint1',
|
|
89
|
-
signingProviderId: 'internal',
|
|
90
|
-
publicKey: 'publicKey',
|
|
91
|
-
namespace: 'namespace',
|
|
92
|
-
chainId: 'network1',
|
|
93
|
-
};
|
|
94
|
-
const wallet2 = {
|
|
95
|
-
primary: false,
|
|
96
|
-
partyId: 'party2',
|
|
97
|
-
hint: 'hint2',
|
|
98
|
-
signingProviderId: 'internal',
|
|
99
|
-
publicKey: 'publicKey',
|
|
100
|
-
namespace: 'namespace',
|
|
101
|
-
chainId: 'network1',
|
|
102
|
-
};
|
|
103
|
-
await store.addWallet(wallet1);
|
|
104
|
-
await store.addWallet(wallet2);
|
|
105
|
-
await store.setPrimaryWallet('party2');
|
|
106
|
-
const primary = await store.getPrimaryWallet();
|
|
107
|
-
expect(primary?.partyId).toBe('party2');
|
|
108
|
-
expect(primary?.primary).toBe(true);
|
|
109
|
-
});
|
|
110
|
-
test('should set and get session', async () => {
|
|
111
|
-
const session = { network: 'net', accessToken: 'token' };
|
|
112
|
-
await store.setSession(session);
|
|
113
|
-
const result = await store.getSession();
|
|
114
|
-
expect(result).toEqual(session);
|
|
115
|
-
await store.removeSession();
|
|
116
|
-
const removed = await store.getSession();
|
|
117
|
-
expect(removed).toBeUndefined();
|
|
118
|
-
});
|
|
119
|
-
test('should add, list, get, update, and remove networks', async () => {
|
|
120
|
-
const ledgerApi = {
|
|
121
|
-
baseUrl: 'http://api',
|
|
122
|
-
};
|
|
123
|
-
const auth = {
|
|
124
|
-
identityProviderId: 'idp1',
|
|
125
|
-
type: 'password',
|
|
126
|
-
issuer: 'http://auth',
|
|
127
|
-
configUrl: 'http://auth/.well-known/openid-configuration',
|
|
128
|
-
tokenUrl: 'http://auth',
|
|
129
|
-
grantType: 'password',
|
|
130
|
-
clientId: 'cid',
|
|
131
|
-
scope: 'scope',
|
|
132
|
-
audience: 'aud',
|
|
133
|
-
};
|
|
134
|
-
const network = {
|
|
135
|
-
name: 'testnet',
|
|
136
|
-
chainId: 'network1',
|
|
137
|
-
synchronizerId: 'sync1::fingerprint',
|
|
138
|
-
description: 'Test Network',
|
|
139
|
-
ledgerApi,
|
|
140
|
-
auth,
|
|
141
|
-
};
|
|
142
|
-
await store.updateNetwork(network);
|
|
143
|
-
const listed = await store.listNetworks();
|
|
144
|
-
expect(listed).toHaveLength(1);
|
|
145
|
-
expect(listed[0].name).toBe('testnet');
|
|
146
|
-
const fetched = await store.getNetwork('network1');
|
|
147
|
-
expect(fetched.description).toBe('Test Network');
|
|
148
|
-
await store.removeNetwork('network1');
|
|
149
|
-
const afterRemove = await store.listNetworks();
|
|
150
|
-
expect(afterRemove).toHaveLength(0);
|
|
151
|
-
});
|
|
152
|
-
test('should throw when getting a non-existent network', async () => {
|
|
153
|
-
await expect(store.getNetwork('doesnotexist')).rejects.toThrow();
|
|
154
|
-
});
|
|
155
|
-
test('should throw when getting current network if none set', async () => {
|
|
156
|
-
await expect(store.getCurrentNetwork()).rejects.toThrow();
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
});
|
package/dist/StoreInternal.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { assertConnected, } from '@canton-network/core-wallet-auth';
|
|
4
|
-
import { LedgerClient } from '@canton-network/core-ledger-client';
|
|
5
|
-
import { defaultRetryableOptions } from '@canton-network/core-ledger-client/dist/ledger-api-utils';
|
|
6
|
-
// TODO: remove AuthAware and instead provide wrapper in clients
|
|
7
|
-
export class StoreInternal {
|
|
8
|
-
logger;
|
|
9
|
-
systemStorage;
|
|
10
|
-
userStorage;
|
|
11
|
-
authContext;
|
|
12
|
-
constructor(config, logger, authContext, userStorage) {
|
|
13
|
-
this.logger = logger.child({ component: 'StoreInternal' });
|
|
14
|
-
this.systemStorage = config;
|
|
15
|
-
this.authContext = authContext;
|
|
16
|
-
this.userStorage = userStorage || new Map();
|
|
17
|
-
this.syncWallets();
|
|
18
|
-
}
|
|
19
|
-
withAuthContext(context) {
|
|
20
|
-
return new StoreInternal(this.systemStorage, this.logger, context, this.userStorage);
|
|
21
|
-
}
|
|
22
|
-
static createStorage() {
|
|
23
|
-
return {
|
|
24
|
-
wallets: [],
|
|
25
|
-
transactions: new Map(),
|
|
26
|
-
session: undefined,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
assertConnected() {
|
|
30
|
-
return assertConnected(this.authContext).userId;
|
|
31
|
-
}
|
|
32
|
-
getStorage() {
|
|
33
|
-
const userId = this.assertConnected();
|
|
34
|
-
if (!this.userStorage.has(userId)) {
|
|
35
|
-
this.userStorage.set(userId, StoreInternal.createStorage());
|
|
36
|
-
}
|
|
37
|
-
return this.userStorage.get(userId);
|
|
38
|
-
}
|
|
39
|
-
updateStorage(storage) {
|
|
40
|
-
const userId = this.assertConnected();
|
|
41
|
-
this.userStorage.set(userId, storage);
|
|
42
|
-
}
|
|
43
|
-
// Wallet methods
|
|
44
|
-
async syncWallets() {
|
|
45
|
-
try {
|
|
46
|
-
const network = await this.getCurrentNetwork();
|
|
47
|
-
// Get existing parties from participant
|
|
48
|
-
const ledgerClient = new LedgerClient(new URL(network.ledgerApi.baseUrl), this.authContext.accessToken, this.logger);
|
|
49
|
-
const rights = await ledgerClient.getWithRetry('/v2/users/{user-id}/rights', defaultRetryableOptions, {
|
|
50
|
-
path: {
|
|
51
|
-
'user-id': this.authContext.userId,
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
const parties = rights.rights
|
|
55
|
-
?.filter((right) => 'CanActAs' in right.kind)
|
|
56
|
-
.map((right) => {
|
|
57
|
-
if ('CanActAs' in right.kind) {
|
|
58
|
-
return right.kind.CanActAs.value.party;
|
|
59
|
-
}
|
|
60
|
-
throw new Error('Unexpected right kind');
|
|
61
|
-
});
|
|
62
|
-
// Merge Wallets
|
|
63
|
-
const existingWallets = await this.getWallets();
|
|
64
|
-
const existingPartyIds = new Set(existingWallets.map((w) => w.partyId));
|
|
65
|
-
const participantWallets = parties
|
|
66
|
-
?.filter((party) => !existingPartyIds.has(party)
|
|
67
|
-
// todo: filter on idp id
|
|
68
|
-
)
|
|
69
|
-
.map((party) => {
|
|
70
|
-
const [hint, namespace] = party.split('::');
|
|
71
|
-
return {
|
|
72
|
-
primary: false,
|
|
73
|
-
partyId: party,
|
|
74
|
-
hint: hint,
|
|
75
|
-
publicKey: namespace,
|
|
76
|
-
namespace: namespace,
|
|
77
|
-
chainId: network.chainId,
|
|
78
|
-
signingProviderId: 'participant', // todo: determine based on partyDetails.isLocal
|
|
79
|
-
};
|
|
80
|
-
}) || [];
|
|
81
|
-
const storage = this.getStorage();
|
|
82
|
-
const wallets = [...storage.wallets, ...participantWallets];
|
|
83
|
-
// Set primary wallet if none exists
|
|
84
|
-
const hasPrimary = wallets.some((w) => w.primary);
|
|
85
|
-
if (!hasPrimary && wallets.length > 0) {
|
|
86
|
-
wallets[0].primary = true;
|
|
87
|
-
}
|
|
88
|
-
this.logger.debug(wallets, 'Wallets synchronized');
|
|
89
|
-
// Update storage with new wallets
|
|
90
|
-
storage.wallets = wallets;
|
|
91
|
-
this.updateStorage(storage);
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
async getWallets(filter = {}) {
|
|
98
|
-
const { chainIds, signingProviderIds } = filter;
|
|
99
|
-
const chainIdSet = chainIds ? new Set(chainIds) : null;
|
|
100
|
-
const signingProviderIdSet = signingProviderIds
|
|
101
|
-
? new Set(signingProviderIds)
|
|
102
|
-
: null;
|
|
103
|
-
return this.getStorage().wallets.filter((wallet) => {
|
|
104
|
-
const matchedChainIds = chainIdSet
|
|
105
|
-
? chainIdSet.has(wallet.chainId)
|
|
106
|
-
: true;
|
|
107
|
-
const matchedStorageProviderIdS = signingProviderIdSet
|
|
108
|
-
? signingProviderIdSet.has(wallet.signingProviderId)
|
|
109
|
-
: true;
|
|
110
|
-
return matchedChainIds && matchedStorageProviderIdS;
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
async getPrimaryWallet() {
|
|
114
|
-
const wallets = await this.getWallets();
|
|
115
|
-
return wallets.find((w) => w.primary === true);
|
|
116
|
-
}
|
|
117
|
-
async setPrimaryWallet(partyId) {
|
|
118
|
-
const storage = this.getStorage();
|
|
119
|
-
if (!storage.wallets.some((w) => w.partyId === partyId)) {
|
|
120
|
-
throw new Error(`Wallet with partyId "${partyId}" not found`);
|
|
121
|
-
}
|
|
122
|
-
const wallets = storage.wallets.map((w) => {
|
|
123
|
-
if (w.partyId === partyId) {
|
|
124
|
-
w.primary = true;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
w.primary = false;
|
|
128
|
-
}
|
|
129
|
-
return w;
|
|
130
|
-
});
|
|
131
|
-
storage.wallets = wallets;
|
|
132
|
-
this.updateStorage(storage);
|
|
133
|
-
}
|
|
134
|
-
async addWallet(wallet) {
|
|
135
|
-
const storage = this.getStorage();
|
|
136
|
-
if (storage.wallets.some((w) => w.partyId === wallet.partyId)) {
|
|
137
|
-
throw new Error(`Wallet with partyId "${wallet.partyId}" already exists`);
|
|
138
|
-
}
|
|
139
|
-
const wallets = await this.getWallets();
|
|
140
|
-
if (wallets.length === 0) {
|
|
141
|
-
// If this is the first wallet, set it as primary automatically
|
|
142
|
-
wallet.primary = true;
|
|
143
|
-
}
|
|
144
|
-
if (wallet.primary) {
|
|
145
|
-
// If the new wallet is primary, set all others to non-primary
|
|
146
|
-
storage.wallets.map((w) => (w.primary = false));
|
|
147
|
-
}
|
|
148
|
-
wallets.push(wallet);
|
|
149
|
-
storage.wallets = wallets;
|
|
150
|
-
this.updateStorage(storage);
|
|
151
|
-
}
|
|
152
|
-
// Session methods
|
|
153
|
-
async getSession() {
|
|
154
|
-
return this.getStorage().session;
|
|
155
|
-
}
|
|
156
|
-
async setSession(session) {
|
|
157
|
-
const storage = this.getStorage();
|
|
158
|
-
storage.session = session;
|
|
159
|
-
this.updateStorage(storage);
|
|
160
|
-
}
|
|
161
|
-
async removeSession() {
|
|
162
|
-
const storage = this.getStorage();
|
|
163
|
-
storage.session = undefined;
|
|
164
|
-
this.updateStorage(storage);
|
|
165
|
-
}
|
|
166
|
-
// Network methods
|
|
167
|
-
async getNetwork(chainId) {
|
|
168
|
-
this.assertConnected();
|
|
169
|
-
const networks = await this.listNetworks();
|
|
170
|
-
if (!networks)
|
|
171
|
-
throw new Error('No networks available');
|
|
172
|
-
const network = networks.find((n) => n.chainId === chainId);
|
|
173
|
-
if (!network)
|
|
174
|
-
throw new Error(`Network "${chainId}" not found`);
|
|
175
|
-
return network;
|
|
176
|
-
}
|
|
177
|
-
async getCurrentNetwork() {
|
|
178
|
-
const session = this.getStorage().session;
|
|
179
|
-
if (!session) {
|
|
180
|
-
throw new Error('No session found');
|
|
181
|
-
}
|
|
182
|
-
const chainId = session.network;
|
|
183
|
-
if (!chainId) {
|
|
184
|
-
throw new Error('No current network set in session');
|
|
185
|
-
}
|
|
186
|
-
const networks = await this.listNetworks();
|
|
187
|
-
const network = networks.find((n) => n.chainId === chainId);
|
|
188
|
-
if (!network) {
|
|
189
|
-
throw new Error(`Network "${chainId}" not found`);
|
|
190
|
-
}
|
|
191
|
-
return network;
|
|
192
|
-
}
|
|
193
|
-
async listNetworks() {
|
|
194
|
-
return this.systemStorage.networks;
|
|
195
|
-
}
|
|
196
|
-
async updateNetwork(network) {
|
|
197
|
-
this.assertConnected();
|
|
198
|
-
this.removeNetwork(network.chainId); // Ensure no duplicates
|
|
199
|
-
this.systemStorage.networks.push(network);
|
|
200
|
-
}
|
|
201
|
-
async addNetwork(network) {
|
|
202
|
-
const networkAlreadyExists = this.systemStorage.networks.find((n) => n.chainId === network.chainId);
|
|
203
|
-
if (networkAlreadyExists) {
|
|
204
|
-
throw new Error(`Network ${network.chainId} already exists`);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
this.systemStorage.networks.push(network);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
async removeNetwork(chainId) {
|
|
211
|
-
this.assertConnected();
|
|
212
|
-
this.systemStorage.networks = this.systemStorage.networks.filter((n) => n.chainId !== chainId);
|
|
213
|
-
}
|
|
214
|
-
// Transaction methods
|
|
215
|
-
async setTransaction(transaction) {
|
|
216
|
-
this.assertConnected();
|
|
217
|
-
const storage = this.getStorage();
|
|
218
|
-
storage.transactions.set(transaction.commandId, transaction);
|
|
219
|
-
this.updateStorage(storage);
|
|
220
|
-
}
|
|
221
|
-
async getTransaction(commandId) {
|
|
222
|
-
this.assertConnected();
|
|
223
|
-
const storage = this.getStorage();
|
|
224
|
-
return storage.transactions.get(commandId);
|
|
225
|
-
}
|
|
226
|
-
}
|