@ledgerhq/revault-sdk 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.
Files changed (45) hide show
  1. package/LICENSE.md +202 -0
  2. package/README.md +18 -0
  3. package/lib/bake.cjs +812 -0
  4. package/lib/bake.cjs.map +1 -0
  5. package/lib/bake.d.cts +2659 -0
  6. package/lib/bake.d.ts +2659 -0
  7. package/lib/bake.js +812 -0
  8. package/lib/bake.js.map +1 -0
  9. package/lib/chunk-DPHEFR6E.js +493 -0
  10. package/lib/chunk-DPHEFR6E.js.map +1 -0
  11. package/lib/chunk-QOP5LA3E.cjs +35 -0
  12. package/lib/chunk-QOP5LA3E.cjs.map +1 -0
  13. package/lib/chunk-VCAQTGQE.cjs +493 -0
  14. package/lib/chunk-VCAQTGQE.cjs.map +1 -0
  15. package/lib/chunk-VHZJP75X.js +35 -0
  16. package/lib/chunk-VHZJP75X.js.map +1 -0
  17. package/lib/device.cjs +13 -0
  18. package/lib/device.cjs.map +1 -0
  19. package/lib/device.d.cts +50 -0
  20. package/lib/device.d.ts +50 -0
  21. package/lib/device.js +13 -0
  22. package/lib/device.js.map +1 -0
  23. package/lib/engine.cjs +704 -0
  24. package/lib/engine.cjs.map +1 -0
  25. package/lib/engine.d.cts +18 -0
  26. package/lib/engine.d.ts +18 -0
  27. package/lib/engine.js +704 -0
  28. package/lib/engine.js.map +1 -0
  29. package/lib/index.cjs +1 -0
  30. package/lib/index.cjs.map +1 -0
  31. package/lib/index.d.cts +13 -0
  32. package/lib/index.d.ts +13 -0
  33. package/lib/index.js +1 -0
  34. package/lib/index.js.map +1 -0
  35. package/lib/onboarding.cjs +160 -0
  36. package/lib/onboarding.cjs.map +1 -0
  37. package/lib/onboarding.d.cts +1735 -0
  38. package/lib/onboarding.d.ts +1735 -0
  39. package/lib/onboarding.js +160 -0
  40. package/lib/onboarding.js.map +1 -0
  41. package/lib/types-BYNH6EdK.d.cts +199 -0
  42. package/lib/types-CsvE9Mlb.d.cts +159 -0
  43. package/lib/types-CsvE9Mlb.d.ts +159 -0
  44. package/lib/types-DHZzeq9X.d.ts +199 -0
  45. package/package.json +75 -0
package/lib/bake.cjs ADDED
@@ -0,0 +1,812 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+ var _chunkQOP5LA3Ecjs = require('./chunk-QOP5LA3E.cjs');
5
+
6
+ // src/bake/index.ts
7
+ var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant);
8
+
9
+ // src/bake/bake-pledge.ts
10
+
11
+
12
+ // src/bake/utils.ts
13
+
14
+ function createBakeLogHelpers(logger) {
15
+ return {
16
+ logTitle(title) {
17
+ logger.info(`:: ${title} ::`);
18
+ },
19
+ logStep(msg) {
20
+ logger.info(`=> ${msg}`);
21
+ },
22
+ logSubStep(msg) {
23
+ logger.info(` -> ${msg}`);
24
+ }
25
+ };
26
+ }
27
+ async function approveRequest(request, approvers, logger) {
28
+ const { logSubStep } = createBakeLogHelpers(logger);
29
+ for (let i = 0; i < approvers.length; i++) {
30
+ logSubStep(`Collecting approval (${i + 1}/${approvers.length})...`);
31
+ const approver = approvers[i];
32
+ request = await approver.approve(request);
33
+ }
34
+ return request;
35
+ }
36
+ async function createAndApproveRequest(input, approvers, logger) {
37
+ const { logSubStep } = createBakeLogHelpers(logger);
38
+ const creator = approvers[0];
39
+ _invariant2.default.call(void 0, creator, "Need at least 1 user to create a request");
40
+ logSubStep(`Creating request of type ${input.type}...`);
41
+ const request = await creator.client.requests.create.mutate({ request: input });
42
+ return approveRequest(request, approvers, logger);
43
+ }
44
+
45
+ // src/bake/bake-pledge.ts
46
+ var flattenApprovers = (groups) => {
47
+ return groups.reduce((acc, cur) => {
48
+ acc.push(...cur.userIds.slice(0, cur.quorum));
49
+ return acc;
50
+ }, []);
51
+ };
52
+ async function bakePledgeAdjustment(options, logger) {
53
+ const { pledgeAdjustment, engine } = options;
54
+ const getDeviceIndex = _chunkQOP5LA3Ecjs.createDeviceIndexResolver.call(void 0, engine);
55
+ logger.info("Logging in with admin...");
56
+ const admin = await engine.withDeviceIndex(4).login();
57
+ logger.info("Fetching account, tradelink blueprint and network...");
58
+ const [matchingAccounts, blueprint, network] = await Promise.all([
59
+ _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin.client.accounts.list.query, { name: pledgeAdjustment.account }),
60
+ admin.client.tradelink.getNetworkBlueprint.query(),
61
+ admin.client.tradelink.getNetwork.query()
62
+ ]);
63
+ const account = matchingAccounts.find((account2) => account2.name === pledgeAdjustment.account);
64
+ _invariant2.default.call(void 0, account, `Account ${pledgeAdjustment.account} not found`);
65
+ _invariant2.default.call(void 0, blueprint, "Tradelink blueprint is not created yet");
66
+ _invariant2.default.call(void 0, network, "Tradelink network is not created yet");
67
+ const exchange = network.exchanges.find((exchange2) => {
68
+ const blueprintExchange = blueprint.exchanges.find(
69
+ (blueprintExchange2) => blueprintExchange2.tradelinkId === exchange2.tradelinkId
70
+ );
71
+ _invariant2.default.call(void 0, blueprintExchange, `Exchange ${exchange2.tradelinkId} not found in blueprint`);
72
+ return blueprintExchange.name === pledgeAdjustment.exchange;
73
+ });
74
+ _invariant2.default.call(void 0, exchange, `Exchange ${pledgeAdjustment.exchange} not found in network`);
75
+ const governance = account.governance;
76
+ _invariant2.default.call(void 0, governance.type === "TRADELINK", "Account governance is not TRADELINK");
77
+ const assetManager = network.assetManagers.find((am) => am.id === governance.assetManagerId);
78
+ _invariant2.default.call(void 0, assetManager, `Asset manager ${governance.assetManagerId} not found in network`);
79
+ const exchangeIsConfiguredForAccount = !!governance.exchangeConfigs.find(
80
+ (e) => e.exchangeId === exchange.id
81
+ );
82
+ _invariant2.default.call(void 0,
83
+ exchangeIsConfiguredForAccount,
84
+ `Exchange ${exchange.id} is not configured for account ${account.id}`
85
+ );
86
+ const approverIds = [
87
+ ...flattenApprovers(assetManager.groups),
88
+ ...flattenApprovers(exchange.groups)
89
+ ];
90
+ const approvers = await Promise.all(
91
+ approverIds.map(
92
+ (id) => admin.client.users.findById.query({ id }).then((user) => getDeviceIndex(user.deviceUserId)).then((index) => engine.withDeviceIndex(index).login())
93
+ )
94
+ );
95
+ await createAndApproveRequest(
96
+ {
97
+ type: "ADJUST_PLEDGE",
98
+ data: {
99
+ accountId: account.id,
100
+ exchangeId: exchange.id,
101
+ amount: pledgeAdjustment.amount
102
+ }
103
+ },
104
+ approvers,
105
+ logger
106
+ );
107
+ logger.info(
108
+ `Successfully adjusted pledge for account ${pledgeAdjustment.account} on exchange ${pledgeAdjustment.exchange}`
109
+ );
110
+ }
111
+
112
+ // src/bake/bake-tradelink-organization.ts
113
+ async function bakeTradelinkOrganization(options, logger) {
114
+ const { tradelink, engine, rootAuthToken, networkBlueprint } = options;
115
+ const { logStep } = createBakeLogHelpers(logger);
116
+ const rootClient = engine.createClient({ rootAuthToken });
117
+ if (tradelink.exchanges) {
118
+ logStep("Creating Tradelink organization exchanges...");
119
+ const existingOrgExchanges = await rootClient.tradelink.root.listOrgExchanges.query();
120
+ for (const orgExchange of tradelink.exchanges) {
121
+ const existingOrgExchange = existingOrgExchanges.find((e) => e.name === orgExchange.name);
122
+ if (existingOrgExchange) {
123
+ logger.info(
124
+ `[SKIPPED] Organization exchange ${existingOrgExchange.name} (${existingOrgExchange.code}) already exists`
125
+ );
126
+ } else {
127
+ await rootClient.tradelink.root.createOrgExchange.mutate({
128
+ code: orgExchange.code,
129
+ name: orgExchange.name,
130
+ logoUrl: orgExchange.logo
131
+ });
132
+ logger.info(`Created organization exchange ${orgExchange.name} (${orgExchange.code})`);
133
+ }
134
+ }
135
+ }
136
+ if (tradelink.assetManagers) {
137
+ logStep("Creating Tradelink organization asset managers...");
138
+ const existingAssetManagers = await rootClient.tradelink.root.listOrgAssetManagers.query();
139
+ for (const orgAssetManager of tradelink.assetManagers) {
140
+ const existingOrgAssetManager = existingAssetManagers.find(
141
+ (e) => e.name === orgAssetManager.name
142
+ );
143
+ if (existingOrgAssetManager) {
144
+ logger.info(
145
+ `[SKIPPED] Organization asset manager ${existingOrgAssetManager.name} (${existingOrgAssetManager.code}) already exists`
146
+ );
147
+ } else {
148
+ await rootClient.tradelink.root.createOrgAssetManager.mutate({
149
+ code: orgAssetManager.code,
150
+ name: orgAssetManager.name,
151
+ logoUrl: orgAssetManager.logo
152
+ });
153
+ logger.info(
154
+ `Created organization asset manager ${orgAssetManager.name} (${orgAssetManager.code})`
155
+ );
156
+ }
157
+ }
158
+ }
159
+ if (tradelink.custodians) {
160
+ logStep("Creating Tradelink organization custodians...");
161
+ const existingCustodians = await rootClient.tradelink.root.listOrgCustodians.query();
162
+ for (const orgCustodian of tradelink.custodians) {
163
+ const existingOrgCustodian = existingCustodians.find((e) => e.name === orgCustodian.name);
164
+ if (existingOrgCustodian) {
165
+ logger.info(
166
+ `[SKIPPED] Organization custodian ${existingOrgCustodian.name} (${existingOrgCustodian.code}) already exists`
167
+ );
168
+ } else {
169
+ await rootClient.tradelink.root.createOrgCustodian.mutate({
170
+ code: orgCustodian.code,
171
+ name: orgCustodian.name,
172
+ logoUrl: orgCustodian.logo
173
+ });
174
+ logger.info(`Created organization custodian ${orgCustodian.name} (${orgCustodian.code})`);
175
+ }
176
+ }
177
+ }
178
+ if (networkBlueprint) {
179
+ logStep("Creating Tradelink network blueprint...");
180
+ const { workspaceName, blueprint } = networkBlueprint;
181
+ const existingBlueprints = await rootClient.tradelink.root.listNetworkBlueprints.query();
182
+ const existingBlueprint = existingBlueprints.find((e) => e.workspaceName === workspaceName);
183
+ if (existingBlueprint) {
184
+ logger.info(`[SKIPPED] Network blueprint for ${workspaceName} workspace already exists`);
185
+ } else {
186
+ await rootClient.tradelink.root.createNetworkBlueprint.mutate({
187
+ workspaceName,
188
+ custodian: { name: blueprint.custodian },
189
+ exchanges: blueprint.exchanges.map((_2) => ({ name: _2 })),
190
+ assetManagers: blueprint.assetManagers.map((_2) => ({ name: _2 }))
191
+ });
192
+ logger.info(`Created network blueprint for ${networkBlueprint.workspaceName} workspace`);
193
+ }
194
+ }
195
+ }
196
+
197
+ // src/bake/bake-workspace.ts
198
+
199
+ var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash);
200
+ async function bakeWorkspace(options, logger) {
201
+ const { workspace, engine, workspaceName } = options;
202
+ const workspaceEngine = engine.withWorkspace(workspaceName);
203
+ const { logTitle, logStep, logSubStep } = createBakeLogHelpers(logger);
204
+ const findDeviceIndex = _chunkQOP5LA3Ecjs.createDeviceIndexResolver.call(void 0, workspaceEngine);
205
+ logger.info("Authenticating with two admins...");
206
+ const [admin1, admin2] = await Promise.all([
207
+ workspaceEngine.withDeviceIndex(4).login(),
208
+ workspaceEngine.withDeviceIndex(5).login()
209
+ ]);
210
+ logger.info("Fetching existing data...");
211
+ const [
212
+ existingAdmins,
213
+ existingOperators,
214
+ existingGroups,
215
+ existingPolicies,
216
+ existingAccounts,
217
+ tradelinkNetworkBlueprint
218
+ ] = await Promise.all([
219
+ _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin1.client.users.list.query, { status: "ACTIVE", role: "ADMIN" }),
220
+ _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin1.client.users.list.query, { status: "ACTIVE", role: "OPERATOR" }),
221
+ _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin1.client.groups.list.query, { status: "ACTIVE" }),
222
+ _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin1.client.policies.list.query, { isPrivate: false }),
223
+ _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin1.client.accounts.list.query, { status: "ACTIVE", skipLiveData: true }),
224
+ admin1.client.tradelink.getNetworkBlueprint.query()
225
+ ]);
226
+ const tradelinkOrgExchangesByName = _lodash2.default.keyBy(_optionalChain([tradelinkNetworkBlueprint, 'optionalAccess', _3 => _3.exchanges]), "name");
227
+ const tradelinkOrgAssetManagersByName = _lodash2.default.keyBy(_optionalChain([tradelinkNetworkBlueprint, 'optionalAccess', _4 => _4.assetManagers]), "name");
228
+ let existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
229
+ const existingUsers = [...existingAdmins, ...existingOperators];
230
+ const usersWithDeviceIndex = await resolveDevicesIndexes(existingUsers);
231
+ if (workspace.users) {
232
+ logTitle("Users");
233
+ if (workspace.users.admins) {
234
+ for (const deviceIndex of workspace.users.admins) {
235
+ await createUser("ADMIN", deviceIndex);
236
+ }
237
+ }
238
+ if (workspace.users.operators) {
239
+ for (const deviceIndex of workspace.users.operators) {
240
+ await createUser("OPERATOR", deviceIndex);
241
+ }
242
+ }
243
+ }
244
+ if (workspace.groups) {
245
+ logTitle("Groups");
246
+ for (const group of workspace.groups) {
247
+ await createGroup(group);
248
+ }
249
+ }
250
+ if (workspace.whitelists) {
251
+ logTitle("Whitelists");
252
+ await createWhitelists(workspace.whitelists);
253
+ }
254
+ if (workspace.policies) {
255
+ logTitle("Policies");
256
+ for (const policy of workspace.policies) {
257
+ await createPolicy(policy);
258
+ }
259
+ }
260
+ if (workspace.tradelink) {
261
+ logTitle("Tradelink");
262
+ await createTradelink(workspace.tradelink);
263
+ }
264
+ if (workspace.accounts) {
265
+ logTitle("Accounts");
266
+ for (const account of workspace.accounts) {
267
+ await createAccount(account);
268
+ }
269
+ }
270
+ async function createWhitelists(whitelists) {
271
+ const existingWhitelists = await _chunkQOP5LA3Ecjs.fetchAll.call(void 0, admin1.client.whitelists.list.query, {
272
+ status: "ACTIVE"
273
+ });
274
+ for (const whitelist of whitelists) {
275
+ await createWhitelist(whitelist);
276
+ }
277
+ async function createWhitelist(whitelist) {
278
+ const existing = existingWhitelists.find((w) => w.name === whitelist.name);
279
+ if (existing) {
280
+ logger.info(`[SKIPPED] Whitelist "${whitelist.name}" already exists`);
281
+ return;
282
+ }
283
+ const input = {
284
+ type: "CREATE_WHITELIST",
285
+ data: whitelist
286
+ };
287
+ await createAndApproveRequest(input, [admin1, admin2], logger);
288
+ logSubStep(`Whitelist "${whitelist.name}" has been created`);
289
+ }
290
+ }
291
+ function govRuleFromManifest(rule) {
292
+ return {
293
+ operationType: rule.type,
294
+ reviewSteps: rule.steps.map((step) => {
295
+ if ("group" in step) {
296
+ return {
297
+ quorum: step.quorum,
298
+ groupId: groupIdFromName(step.group)
299
+ };
300
+ }
301
+ return {
302
+ quorum: step.quorum,
303
+ userIds: step.members.map(userIdFromDeviceIndex)
304
+ };
305
+ })
306
+ };
307
+ }
308
+ async function createAccount(account) {
309
+ const existing = existingAccounts.find((a) => a.name === account.name);
310
+ if (existing) {
311
+ logger.info(`[SKIPPED] Account "${account.name}" already exists`);
312
+ return;
313
+ }
314
+ logStep(`Creating account "${account.name}"`);
315
+ logSubStep("Fetching account asset...");
316
+ const asset = await fetchAsset({
317
+ currency: account.currency,
318
+ contractAddress: account.contractAddress
319
+ });
320
+ const input = {
321
+ type: "CREATE_ACCOUNT",
322
+ data: {
323
+ // general fields
324
+ name: account.name,
325
+ // asset fields
326
+ type: asset.type,
327
+ currency: account.currency,
328
+ contractAddress: account.contractAddress,
329
+ // governance fields
330
+ governance: account.governance.type === "TRADELINK" ? {
331
+ type: "TRADELINK",
332
+ assetManagerId: assetManagerIdFromName(account.governance.assetManager),
333
+ exchangeConfigs: account.governance.exchanges.map((exchangeConfig) => ({
334
+ exchangeId: exchangeIdFromName(exchangeConfig.name),
335
+ repledgeAuthorized: exchangeConfig.repledgeAuthorized === true,
336
+ needsAssetManagerApprovalForSettlements: exchangeConfig.needsAssetManagerApprovalForSettlements === true
337
+ }))
338
+ } : {
339
+ type: "CLASSIC",
340
+ policy: {
341
+ type: "ACCOUNT_PRIVATE_POLICY",
342
+ rules: account.governance.rules.map(govRuleFromManifest)
343
+ }
344
+ }
345
+ }
346
+ };
347
+ const req = await createAndApproveRequest(input, [admin1, admin2], logger);
348
+ if (account.governance.type === "TRADELINK") {
349
+ logStep(`Activating tradelink account "${account.name}"`);
350
+ const assetManagerId = assetManagerIdFromName(account.governance.assetManager);
351
+ const assetManager = _optionalChain([existingTradelinkNetwork, 'optionalAccess', _5 => _5.assetManagers, 'access', _6 => _6.find, 'call', _7 => _7(
352
+ (assetManager2) => assetManager2.id === assetManagerId
353
+ )]);
354
+ _invariant2.default.call(void 0, assetManager, `Asset manager for account exists`);
355
+ const loggedAssetManagerOperators = await Promise.all(
356
+ assetManager.groups.flatMap(
357
+ ({ quorum, userIds }) => userIds.slice(0, quorum).map((userId) => {
358
+ const deviceIndex = _optionalChain([usersWithDeviceIndex, 'access', _8 => _8.find, 'call', _9 => _9((o) => o.user.id === userId), 'optionalAccess', _10 => _10.deviceIndex]);
359
+ return workspaceEngine.withDeviceIndex(deviceIndex).login();
360
+ })
361
+ )
362
+ );
363
+ await createAndApproveRequest(
364
+ { type: "ACTIVATE_TRADELINK_ACCOUNT", targetId: req.targetId, data: {} },
365
+ loggedAssetManagerOperators,
366
+ logger
367
+ );
368
+ }
369
+ logSubStep(`Account ${account.name} has been created`);
370
+ }
371
+ async function fetchAsset(params) {
372
+ const { currency, contractAddress } = params;
373
+ if (contractAddress) {
374
+ const tokens = await admin1.client.assets.tokens.query({ search: contractAddress });
375
+ const t = tokens.results.find(
376
+ (t2) => t2.contractAddress === contractAddress && t2.currency === currency
377
+ );
378
+ _invariant2.default.call(void 0, t, `Token ${contractAddress} (${currency}) not found`);
379
+ return t;
380
+ } else {
381
+ const currencies = await admin1.client.assets.currencies.query({ search: currency });
382
+ const c = currencies.results.find((c2) => c2.id === currency);
383
+ _invariant2.default.call(void 0, c, `Currency ${currency} not found`);
384
+ return c;
385
+ }
386
+ }
387
+ async function createUser(role, deviceIndex) {
388
+ const userEngine = workspaceEngine.withDeviceIndex(deviceIndex);
389
+ const deviceId = await userEngine.device.getDeviceUserId();
390
+ const existing = existingUsers.find((user) => user.deviceUserId === deviceId);
391
+ if (existing) {
392
+ logger.info(`[SKIPPED] User with device index ${deviceIndex} already exists`);
393
+ return;
394
+ }
395
+ const name = `${role === "ADMIN" ? "Admin" : "Operator"} ${deviceIndex}`;
396
+ logStep(`Creating ${name}`);
397
+ logSubStep("Creating request...");
398
+ let req = await admin1.client.requests.create.mutate({
399
+ request: {
400
+ type: role === "ADMIN" ? "CREATE_ADMIN" : "CREATE_OPERATOR",
401
+ data: {
402
+ deviceUserId: deviceId,
403
+ name,
404
+ deviceType: "PSD"
405
+ }
406
+ }
407
+ });
408
+ logSubStep("Registering user...");
409
+ req = await userEngine.register({ requestId: req.id, name, role });
410
+ req = await approveRequest(req, [admin1, admin2], logger);
411
+ logSubStep(`${name} has been created`);
412
+ const createdUser = await admin1.client.users.findById.query({ id: req.targetId });
413
+ existingUsers.push(createdUser);
414
+ usersWithDeviceIndex.push({ user: createdUser, deviceIndex });
415
+ }
416
+ async function createGroup(group) {
417
+ const existing = existingGroups.find((g) => g.name === group.name);
418
+ if (existing) {
419
+ logger.info(`[SKIPPED] Group "${group.name}" already exists`);
420
+ return;
421
+ }
422
+ logStep(`Creating group ${group.name}...`);
423
+ const members = group.members.map(userIdFromDeviceIndex);
424
+ logSubStep("Creating request...");
425
+ let request = await admin1.client.requests.create.mutate({
426
+ request: {
427
+ type: "CREATE_GROUP",
428
+ data: {
429
+ name: group.name,
430
+ description: "",
431
+ members
432
+ }
433
+ }
434
+ });
435
+ request = await approveRequest(request, [admin1, admin2], logger);
436
+ logSubStep(`${group.name} has been created`);
437
+ const createdGroup = await admin1.client.groups.findById.query({ id: request.targetId });
438
+ existingGroups.push(createdGroup);
439
+ }
440
+ async function createPolicy(policy) {
441
+ const existing = existingPolicies.find((p) => p.name === policy.name);
442
+ if (existing) {
443
+ logger.info(`[SKIPPED] Policy "${policy.name}" already exists`);
444
+ return;
445
+ }
446
+ logStep(`Creating policy ${policy.name}...`);
447
+ logSubStep("Creating request...");
448
+ let request = await admin1.client.requests.create.mutate({
449
+ request: {
450
+ type: "CREATE_POLICY",
451
+ data: {
452
+ name: policy.name,
453
+ currency: policy.currency,
454
+ description: "",
455
+ govRules: policy.rules.map(govRuleFromManifest)
456
+ }
457
+ }
458
+ });
459
+ request = await approveRequest(request, [admin1, admin2], logger);
460
+ logSubStep(`${policy.name} has been created`);
461
+ const createdPolicy = await admin1.client.policies.findById.query({ id: request.targetId });
462
+ existingPolicies.push(createdPolicy);
463
+ }
464
+ async function createTradelink(tradelink) {
465
+ if (tradelink.custodian) {
466
+ if (existingTradelinkNetwork === null) {
467
+ logStep("Creating custodian config...");
468
+ const { settlement, withdraw, arbitration } = tradelink.custodian;
469
+ const data = {
470
+ settlement: settlement.map(tradelinkReviewStepFromManifest),
471
+ withdraw: withdraw.map(tradelinkReviewStepFromManifest),
472
+ arbitration: arbitration.map(tradelinkReviewStepFromManifest)
473
+ };
474
+ logSubStep("Creating request...");
475
+ const request = await admin1.client.requests.create.mutate({
476
+ request: {
477
+ type: "CREATE_TRADELINK_CUSTODIAN",
478
+ data
479
+ }
480
+ });
481
+ await approveRequest(request, [admin1, admin2], logger);
482
+ logSubStep("Tradelink custodian config has been created");
483
+ existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
484
+ } else {
485
+ logger.info("[SKIPPED] Custodian config already exists");
486
+ }
487
+ const networkBlueprint = await admin1.client.tradelink.getNetworkBlueprint.query();
488
+ if (networkBlueprint !== null) {
489
+ if (tradelink.exchanges !== void 0) {
490
+ await createTradelinkExchanges(networkBlueprint, tradelink.exchanges);
491
+ }
492
+ if (tradelink.assetManagers !== void 0) {
493
+ await createTradelinkAssetManagers(networkBlueprint, tradelink.assetManagers);
494
+ }
495
+ } else {
496
+ logger.error(
497
+ "Will not create exchanges and asset managers because there is no network blueprint for current workspace"
498
+ );
499
+ }
500
+ }
501
+ }
502
+ async function createTradelinkExchanges(networkBlueprint, exchanges) {
503
+ _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Network should exist");
504
+ const blueprintExchanges = networkBlueprint.exchanges;
505
+ for (const exchange of exchanges) {
506
+ const blueprintExchange = blueprintExchanges.find(({ name }) => name === exchange.name);
507
+ _invariant2.default.call(void 0,
508
+ blueprintExchange !== void 0,
509
+ `Exchange ${exchange.name} does not exist in network blueprint`
510
+ );
511
+ const exchangeId = blueprintExchange.tradelinkId;
512
+ logStep(`Creating exchange ${exchange.name}...`);
513
+ if (existingTradelinkNetwork.exchanges.find(({ tradelinkId }) => tradelinkId === exchangeId) !== void 0) {
514
+ logger.info(`[SKIPPED] Exchange "${exchange.name}" already exists`);
515
+ continue;
516
+ }
517
+ logSubStep("Creating request...");
518
+ const request = await admin1.client.requests.create.mutate({
519
+ request: {
520
+ type: "CREATE_TRADELINK_EXCHANGE",
521
+ data: {
522
+ tradelinkId: exchangeId,
523
+ groups: exchange.groups.map(tradelinkReviewStepFromManifest),
524
+ whitelist: exchange.whitelist
525
+ }
526
+ }
527
+ });
528
+ const loggedExchangeOperators = await Promise.all(
529
+ exchange.groups.flatMap(
530
+ ({ quorum, members }) => members.slice(0, quorum).map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login())
531
+ )
532
+ );
533
+ await approveRequest(request, [admin1, admin2, ...loggedExchangeOperators], logger);
534
+ existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
535
+ _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Tradelink network exists");
536
+ }
537
+ }
538
+ async function createTradelinkAssetManagers(networkBlueprint, assetManagers) {
539
+ _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Network should exist");
540
+ const blueprintAssetManagers = networkBlueprint.assetManagers;
541
+ for (const assetManager of assetManagers) {
542
+ const blueprintAssetManager = blueprintAssetManagers.find(
543
+ ({ name }) => name === assetManager.name
544
+ );
545
+ _invariant2.default.call(void 0,
546
+ blueprintAssetManager !== void 0,
547
+ `AssetManager ${assetManager.name} does not exist in network blueprint`
548
+ );
549
+ const assetManagerId = blueprintAssetManager.tradelinkId;
550
+ logStep(`Creating assetManager ${assetManager.name}...`);
551
+ if (existingTradelinkNetwork.assetManagers.find(
552
+ ({ tradelinkId }) => tradelinkId === assetManagerId
553
+ ) !== void 0) {
554
+ logger.info(`[SKIPPED] Asset manager "${assetManager.name}" already exists`);
555
+ continue;
556
+ }
557
+ logSubStep("Creating request...");
558
+ const request = await admin1.client.requests.create.mutate({
559
+ request: {
560
+ type: "CREATE_TRADELINK_ASSET_MANAGER",
561
+ data: {
562
+ tradelinkId: assetManagerId,
563
+ groups: assetManager.groups.map(tradelinkReviewStepFromManifest),
564
+ whitelist: assetManager.whitelist
565
+ }
566
+ }
567
+ });
568
+ const loggedAssetManagerOperators = await Promise.all(
569
+ assetManager.groups.flatMap(
570
+ ({ quorum, members }) => members.slice(0, quorum).map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login())
571
+ )
572
+ );
573
+ await approveRequest(request, [admin1, admin2, ...loggedAssetManagerOperators], logger);
574
+ existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
575
+ _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Tradelink network exists");
576
+ }
577
+ }
578
+ async function resolveDevicesIndexes(users) {
579
+ const usersWithDeviceIndex2 = await users.reduce(
580
+ (acc, cur) => acc.then(async (acc2) => {
581
+ acc2.push(await withDeviceIndex(cur));
582
+ return acc2;
583
+ }),
584
+ Promise.resolve([])
585
+ );
586
+ return usersWithDeviceIndex2;
587
+ }
588
+ async function withDeviceIndex(user) {
589
+ _invariant2.default.call(void 0, user.deviceUserId, `User ${user.id} does not have any device user id`);
590
+ const deviceIndex = await findDeviceIndex(user.deviceUserId);
591
+ return { user, deviceIndex };
592
+ }
593
+ function userIdFromDeviceIndex(deviceIndex) {
594
+ const corresponding = usersWithDeviceIndex.find((o) => o.deviceIndex === deviceIndex);
595
+ _invariant2.default.call(void 0, corresponding, `No user with device index ${deviceIndex}`);
596
+ return corresponding.user.id;
597
+ }
598
+ function groupIdFromName(groupName) {
599
+ const group = existingGroups.find((g) => g.name === groupName);
600
+ _invariant2.default.call(void 0, group, `Group ${groupName} not found`);
601
+ return group.id;
602
+ }
603
+ function assetManagerIdFromName(assetManagerName) {
604
+ const orgAssetManager = tradelinkOrgAssetManagersByName[assetManagerName];
605
+ _invariant2.default.call(void 0,
606
+ orgAssetManager,
607
+ `Can't find Tradelink organization asset manager ${assetManagerName}`
608
+ );
609
+ const assetManager = _optionalChain([existingTradelinkNetwork, 'optionalAccess', _11 => _11.assetManagers, 'access', _12 => _12.find, 'call', _13 => _13(
610
+ (assetManager2) => assetManager2.tradelinkId === orgAssetManager.tradelinkId
611
+ )]);
612
+ _invariant2.default.call(void 0, assetManager, `Can't find Tradelink assetManager ${assetManagerName}`);
613
+ return assetManager.id;
614
+ }
615
+ function exchangeIdFromName(exchangeName) {
616
+ const exchange = _optionalChain([existingTradelinkNetwork, 'optionalAccess', _14 => _14.exchanges, 'access', _15 => _15.find, 'call', _16 => _16((exchange2) => {
617
+ const orgExchange = tradelinkOrgExchangesByName[exchangeName];
618
+ _invariant2.default.call(void 0, orgExchange, `Can't find Tradelink organization exchange ${exchange2.tradelinkId}`);
619
+ return orgExchange.name === exchangeName;
620
+ })]);
621
+ _invariant2.default.call(void 0, exchange, `Can't find Tradelink exchange ${exchangeName}`);
622
+ return exchange.id;
623
+ }
624
+ function tradelinkReviewStepFromManifest({
625
+ members,
626
+ quorum
627
+ }) {
628
+ return {
629
+ userIds: members.map(userIdFromDeviceIndex),
630
+ quorum
631
+ };
632
+ }
633
+ }
634
+
635
+ // src/bake/types.ts
636
+ var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod);
637
+ var zManifestUser = _zod2.default.number().describe("User device index");
638
+ var zManifestGroup = _zod2.default.object({
639
+ name: _zod2.default.string().describe("Group name"),
640
+ members: _zod2.default.array(zManifestUser).describe("Group members")
641
+ }).describe("Operators group");
642
+ var zManifestWhitelistAddress = _zod2.default.object({
643
+ name: _zod2.default.string().describe("Whitelist address name"),
644
+ currency: _zod2.default.string().describe("Whitelist address currency"),
645
+ address: _zod2.default.string().describe("Whitelist address"),
646
+ destinationTags: _zod2.default.array(_zod2.default.string()).optional().describe("List of destination tags (applicable for Ripple currency)")
647
+ });
648
+ var zManifestWhitelist = _zod2.default.object({
649
+ name: _zod2.default.string().describe("Whitelist name"),
650
+ description: _zod2.default.string().optional().default("").describe("Whitelist description"),
651
+ type: _zod2.default.enum(["TRANSACTION", "SMART_CONTRACT"]).optional().default("TRANSACTION").describe("Whitelist type"),
652
+ addresses: _zod2.default.array(zManifestWhitelistAddress).describe("Whitelist addresses")
653
+ }).describe("Whitelist");
654
+ var zManifestGovernanceStepWithUsers = _zod2.default.object({
655
+ quorum: _zod2.default.number(),
656
+ members: _zod2.default.array(zManifestUser)
657
+ });
658
+ var zManifestGovernanceStepWithGroup = _zod2.default.object({
659
+ quorum: _zod2.default.number(),
660
+ group: _zod2.default.string()
661
+ });
662
+ var zManifestGovernanceStep = _zod2.default.union([
663
+ zManifestGovernanceStepWithUsers,
664
+ zManifestGovernanceStepWithGroup
665
+ ]);
666
+ var zManifestGovernanceRule = _zod2.default.object({
667
+ // TODO see if there is a way to import this from `api` package
668
+ // (the challenge there is that enums are not transpiled)
669
+ type: _zod2.default.enum([
670
+ "SEND",
671
+ "STAKE",
672
+ "DEPLOY_CONTRACT",
673
+ "EXECUTE_CONTRACT",
674
+ "SIGN_DIGESTS",
675
+ "SIGN_MESSAGE"
676
+ ]),
677
+ steps: _zod2.default.array(zManifestGovernanceStep).min(1)
678
+ });
679
+ var zManifestPolicy = _zod2.default.object({
680
+ name: _zod2.default.string(),
681
+ currency: _zod2.default.string(),
682
+ rules: _zod2.default.array(zManifestGovernanceRule)
683
+ });
684
+ var zManifestClassicAccountGovernance = _zod2.default.object({
685
+ type: _zod2.default.literal("CLASSIC"),
686
+ rules: _zod2.default.array(zManifestGovernanceRule)
687
+ });
688
+ var zManifestTradelinkExchangeConfig = _zod2.default.object({
689
+ name: _zod2.default.string().describe("Exchange name"),
690
+ repledgeAuthorized: _zod2.default.boolean().optional().describe("Whether repledge is authorized"),
691
+ needsAssetManagerApprovalForSettlements: _zod2.default.boolean().optional().describe("Whether asset manager pre approval is needed")
692
+ });
693
+ var zManifestTradelinkAccountGovernance = _zod2.default.object({
694
+ type: _zod2.default.literal("TRADELINK"),
695
+ assetManager: _zod2.default.string().describe("Asset manager name"),
696
+ exchanges: _zod2.default.array(zManifestTradelinkExchangeConfig)
697
+ });
698
+ var zManifestAccountGovernance = _zod2.default.discriminatedUnion("type", [
699
+ zManifestClassicAccountGovernance,
700
+ zManifestTradelinkAccountGovernance
701
+ ]);
702
+ var zManifestAccount = _zod2.default.object({
703
+ name: _zod2.default.string(),
704
+ currency: _zod2.default.string(),
705
+ contractAddress: _zod2.default.string().optional(),
706
+ governance: zManifestAccountGovernance
707
+ });
708
+ var zManifestPledgeAdjustment = _zod2.default.object({
709
+ account: _zod2.default.string(),
710
+ exchange: _zod2.default.string(),
711
+ amount: _zod2.default.string()
712
+ });
713
+ var zManifestTradelinkGroup = _zod2.default.object({
714
+ members: _zod2.default.array(zManifestUser),
715
+ quorum: _zod2.default.number()
716
+ }).describe("Tradelink group");
717
+ var zManifestTradelinkGroups = _zod2.default.array(zManifestTradelinkGroup);
718
+ var zManifestTradelinkWhitelistAddress = _zod2.default.object({
719
+ name: _zod2.default.string().min(1),
720
+ currency: _zod2.default.string().min(1),
721
+ address: _zod2.default.string().min(1)
722
+ }).describe("Tradelink whitelist address");
723
+ var zManifestTradelinkWhitelist = _zod2.default.array(zManifestTradelinkWhitelistAddress).describe("Tradelink whitelist");
724
+ var zManifestTradelinkEntity = _zod2.default.object({
725
+ name: _zod2.default.string(),
726
+ groups: zManifestTradelinkGroups,
727
+ whitelist: zManifestTradelinkWhitelist
728
+ });
729
+ var zManifestTradelinkCustodian = _zod2.default.object({
730
+ settlement: zManifestTradelinkGroups,
731
+ withdraw: zManifestTradelinkGroups,
732
+ arbitration: zManifestTradelinkGroups
733
+ });
734
+ var zManifestTradelinkNetworkBlueprint = _zod2.default.object({
735
+ custodian: _zod2.default.string(),
736
+ exchanges: _zod2.default.array(_zod2.default.string()),
737
+ assetManagers: _zod2.default.array(_zod2.default.string())
738
+ });
739
+ var zManifestTradelinkNetwork = _zod2.default.object({
740
+ networkBlueprint: zManifestTradelinkNetworkBlueprint.optional(),
741
+ custodian: zManifestTradelinkCustodian.optional(),
742
+ exchanges: _zod2.default.array(zManifestTradelinkEntity).optional(),
743
+ assetManagers: _zod2.default.array(zManifestTradelinkEntity).optional()
744
+ }).describe("Tradelink network configuration");
745
+ var zManifestWorkspace = _zod2.default.object({
746
+ tradelink: zManifestTradelinkNetwork.optional(),
747
+ users: _zod2.default.object({
748
+ admins: _zod2.default.array(zManifestUser).optional(),
749
+ operators: _zod2.default.array(zManifestUser).optional()
750
+ }).optional(),
751
+ groups: _zod2.default.array(zManifestGroup).optional(),
752
+ whitelists: _zod2.default.array(zManifestWhitelist).optional(),
753
+ policies: _zod2.default.array(zManifestPolicy).optional(),
754
+ accounts: _zod2.default.array(zManifestAccount).optional(),
755
+ pledges: _zod2.default.array(zManifestPledgeAdjustment).optional()
756
+ }).describe("Workspace configuration");
757
+ var zManifestTradelinkOrgEntity = _zod2.default.object({
758
+ name: _zod2.default.string(),
759
+ code: _zod2.default.string(),
760
+ logo: _zod2.default.string()
761
+ }).describe("Tradelink organization entity");
762
+ var zManifestTradelinkOrg = _zod2.default.object({
763
+ exchanges: _zod2.default.array(zManifestTradelinkOrgEntity).optional(),
764
+ assetManagers: _zod2.default.array(zManifestTradelinkOrgEntity).optional(),
765
+ custodians: _zod2.default.array(zManifestTradelinkOrgEntity).optional()
766
+ }).describe("Tradelink organization configuration");
767
+ var zManifest = _zod2.default.object({
768
+ manifestVersion: _zod2.default.literal(2),
769
+ tradelink: zManifestTradelinkOrg.optional(),
770
+ workspace: zManifestWorkspace.optional()
771
+ });
772
+
773
+ // src/bake/index.ts
774
+ async function bakeManifest(options, logger) {
775
+ const {
776
+ engine,
777
+ workspaceName,
778
+ rootAuthToken,
779
+ manifest: { tradelink, workspace }
780
+ } = options;
781
+ if (tradelink) {
782
+ _invariant2.default.call(void 0, rootAuthToken, `rootAuthToken is required to create Tradelink org entities`);
783
+ await bakeTradelinkOrganization(
784
+ {
785
+ engine,
786
+ tradelink,
787
+ rootAuthToken,
788
+ ..._optionalChain([workspace, 'optionalAccess', _17 => _17.tradelink, 'optionalAccess', _18 => _18.networkBlueprint]) && workspaceName ? { networkBlueprint: { blueprint: workspace.tradelink.networkBlueprint, workspaceName } } : {}
789
+ },
790
+ logger
791
+ );
792
+ }
793
+ if (workspace) {
794
+ _invariant2.default.call(void 0, workspaceName, `Can't bake workspace without specifying a workspace name`);
795
+ await bakeWorkspace({ engine, workspace, workspaceName }, logger);
796
+ if (workspace.pledges) {
797
+ const engineWithWorkspace = engine.withWorkspace(workspaceName);
798
+ for (const pledgeAdjustment of workspace.pledges) {
799
+ await bakePledgeAdjustment({ engine: engineWithWorkspace, pledgeAdjustment }, logger);
800
+ }
801
+ }
802
+ }
803
+ logger.info("Successfully baked");
804
+ }
805
+
806
+
807
+
808
+
809
+
810
+
811
+ exports.bakeManifest = bakeManifest; exports.bakePledgeAdjustment = bakePledgeAdjustment; exports.createAndApproveRequest = createAndApproveRequest; exports.zManifest = zManifest; exports.zManifestPolicy = zManifestPolicy;
812
+ //# sourceMappingURL=bake.cjs.map