@ledgerhq/revault-sdk 0.25.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/lib/bake.cjs +1214 -1359
  2. package/lib/bake.cjs.map +1 -1
  3. package/lib/bake.d.cts +564 -562
  4. package/lib/bake.d.ts +564 -562
  5. package/lib/bake.js +1204 -1359
  6. package/lib/bake.js.map +1 -1
  7. package/lib/chunk-CKQMccvm.cjs +28 -0
  8. package/lib/crypto-BDBF_rfw.cjs +268 -0
  9. package/lib/crypto-BDBF_rfw.cjs.map +1 -0
  10. package/lib/crypto-CPCBrCSZ.js +245 -0
  11. package/lib/crypto-CPCBrCSZ.js.map +1 -0
  12. package/lib/crypto.cjs +5 -11
  13. package/lib/crypto.d.cts +10 -7
  14. package/lib/crypto.d.ts +10 -7
  15. package/lib/crypto.js +2 -11
  16. package/lib/device-0lcfYGHr.cjs +793 -0
  17. package/lib/device-0lcfYGHr.cjs.map +1 -0
  18. package/lib/device-B8Fww8_6.js +719 -0
  19. package/lib/device-B8Fww8_6.js.map +1 -0
  20. package/lib/device.cjs +6 -13
  21. package/lib/device.d.cts +2 -50
  22. package/lib/device.d.ts +2 -50
  23. package/lib/device.js +2 -13
  24. package/lib/engine.cjs +835 -886
  25. package/lib/engine.cjs.map +1 -1
  26. package/lib/engine.d.cts +3 -25
  27. package/lib/engine.d.ts +3 -25
  28. package/lib/engine.js +828 -885
  29. package/lib/engine.js.map +1 -1
  30. package/lib/index--fscLDTT.d.ts +237 -0
  31. package/lib/index-BE7oUpCb.d.cts +237 -0
  32. package/lib/index-C4Xjiv0k.d.cts +23 -0
  33. package/lib/index-CVjhPoZh.d.ts +23 -0
  34. package/lib/index.cjs +0 -1
  35. package/lib/index.d.cts +10 -5
  36. package/lib/index.d.ts +10 -5
  37. package/lib/index.js +1 -1
  38. package/lib/logger-Cme0iL1f.d.cts +10 -0
  39. package/lib/logger-DWLViq7U.d.ts +10 -0
  40. package/lib/onboarding.cjs +179 -181
  41. package/lib/onboarding.cjs.map +1 -1
  42. package/lib/onboarding.d.cts +1751 -1722
  43. package/lib/onboarding.d.ts +1751 -1722
  44. package/lib/onboarding.js +175 -181
  45. package/lib/onboarding.js.map +1 -1
  46. package/lib/trpc-CWGPr8Ox.d.ts +20 -0
  47. package/lib/trpc-C_dUOB1u.d.cts +20 -0
  48. package/lib/types-4CfR5--z.d.ts +203 -0
  49. package/lib/types-Byf9V35t.d.cts +203 -0
  50. package/lib/types-CQROu0nu.d.cts +6 -0
  51. package/lib/types-_QeBv1U4.d.ts +6 -0
  52. package/lib/types.cjs +0 -1
  53. package/lib/types.d.cts +3 -4
  54. package/lib/types.d.ts +3 -4
  55. package/lib/types.js +1 -1
  56. package/lib/utils-BGbdjOP9.js +61 -0
  57. package/lib/utils-BGbdjOP9.js.map +1 -0
  58. package/lib/utils-DbSFXp4c.cjs +86 -0
  59. package/lib/utils-DbSFXp4c.cjs.map +1 -0
  60. package/package.json +6 -6
  61. package/lib/chunk-2WGM7EWA.cjs +0 -282
  62. package/lib/chunk-2WGM7EWA.cjs.map +0 -1
  63. package/lib/chunk-AXI72NFY.js +0 -50
  64. package/lib/chunk-AXI72NFY.js.map +0 -1
  65. package/lib/chunk-DRMYBKL3.cjs +0 -820
  66. package/lib/chunk-DRMYBKL3.cjs.map +0 -1
  67. package/lib/chunk-KV5FO7N5.js +0 -282
  68. package/lib/chunk-KV5FO7N5.js.map +0 -1
  69. package/lib/chunk-LH4QQXUH.cjs +0 -50
  70. package/lib/chunk-LH4QQXUH.cjs.map +0 -1
  71. package/lib/chunk-PFZIW6UP.js +0 -820
  72. package/lib/chunk-PFZIW6UP.js.map +0 -1
  73. package/lib/crypto.cjs.map +0 -1
  74. package/lib/crypto.js.map +0 -1
  75. package/lib/device.cjs.map +0 -1
  76. package/lib/device.js.map +0 -1
  77. package/lib/index.cjs.map +0 -1
  78. package/lib/index.js.map +0 -1
  79. package/lib/logger-C-TPbnjv.d.cts +0 -9
  80. package/lib/logger-C-TPbnjv.d.ts +0 -9
  81. package/lib/types-C-ngtI5m.d.ts +0 -202
  82. package/lib/types-CpGEbAxh.d.cts +0 -19
  83. package/lib/types-CpGEbAxh.d.ts +0 -19
  84. package/lib/types-CryvY9pW.d.cts +0 -202
  85. package/lib/types-DJfbanPz.d.cts +0 -167
  86. package/lib/types-DJfbanPz.d.ts +0 -167
  87. package/lib/types.cjs.map +0 -1
  88. package/lib/types.js.map +0 -1
package/lib/bake.cjs CHANGED
@@ -1,1418 +1,1273 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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 _chunkLH4QQXUHcjs = require('./chunk-LH4QQXUH.cjs');
5
-
6
-
7
- var _chunk2WGM7EWAcjs = require('./chunk-2WGM7EWA.cjs');
8
-
9
- // src/bake/index.ts
10
- var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant);
11
-
12
- // src/bake/bake-pledge.ts
13
-
14
-
15
- // src/bake/utils.ts
16
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_chunk = require("./chunk-CKQMccvm.cjs");
3
+ const require_utils = require("./utils-DbSFXp4c.cjs");
4
+ const require_crypto = require("./crypto-BDBF_rfw.cjs");
5
+ let invariant = require("invariant");
6
+ invariant = require_chunk.__toESM(invariant);
7
+ let lodash = require("lodash");
8
+ lodash = require_chunk.__toESM(lodash);
9
+ let ts_pattern = require("ts-pattern");
10
+ let zod = require("zod");
11
+ zod = require_chunk.__toESM(zod);
12
+ //#region src/bake/utils.ts
17
13
  function createBakeLogHelpers(logger) {
18
- return {
19
- logTitle(title) {
20
- logger.info(`:: ${title} ::`);
21
- },
22
- logStep(msg) {
23
- logger.info(`=> ${msg}`);
24
- },
25
- logSubStep(msg) {
26
- logger.info(` -> ${msg}`);
27
- }
28
- };
14
+ return {
15
+ logTitle(title) {
16
+ logger.info(`:: ${title} ::`);
17
+ },
18
+ logStep(msg) {
19
+ logger.info(`=> ${msg}`);
20
+ },
21
+ logSubStep(msg) {
22
+ logger.info(` -> ${msg}`);
23
+ }
24
+ };
29
25
  }
30
- var IS_REQUEST_STATE_END_STATE = {
31
- // end states:
32
- ABORTED: true,
33
- BLOCKED: true,
34
- EXECUTED: true,
35
- EXPIRED: true,
36
- FAILED: true,
37
- STUCK: true,
38
- // not end states:
39
- EXECUTING: false,
40
- INITIAL: false,
41
- PENDING_APPROVAL: false
26
+ const IS_REQUEST_STATE_END_STATE = {
27
+ ABORTED: true,
28
+ BLOCKED: true,
29
+ EXECUTED: true,
30
+ EXPIRED: true,
31
+ FAILED: true,
32
+ STUCK: true,
33
+ EXECUTING: false,
34
+ INITIAL: false,
35
+ PENDING_APPROVAL: false
42
36
  };
43
- var isEndState = (state) => IS_REQUEST_STATE_END_STATE[state];
44
- var DEFAULT_POLL_INTERVAL_MS = 250;
45
- var DEFAULT_TIMEOUT_MS = 6e4;
46
- var wait = (ms) => {
47
- return new Promise((resolve) => setTimeout(resolve, ms));
37
+ const isEndState = (state) => IS_REQUEST_STATE_END_STATE[state];
38
+ const DEFAULT_POLL_INTERVAL_MS = 250;
39
+ const DEFAULT_TIMEOUT_MS = 6e4;
40
+ const wait = (ms) => {
41
+ return new Promise((resolve) => setTimeout(resolve, ms));
48
42
  };
43
+ /**
44
+ * Poll a request until its inflight field is false, indicating it has been processed by the system.
45
+ * Returns the updated request once inflight is false.
46
+ * Throws if the timeout is exceeded before inflight becomes false.
47
+ */
49
48
  async function waitForRequestInflightDone(client, request, logger, options) {
50
- const { logSubStep } = createBakeLogHelpers(logger);
51
- if (request.inflight === void 0) {
52
- return request;
53
- }
54
- logSubStep(`Waiting for inflight request to be processed...`);
55
- const timeoutMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _3 => _3.timeoutMs]), () => ( DEFAULT_TIMEOUT_MS));
56
- const deadline = Date.now() + timeoutMs;
57
- const pollIntervalMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _4 => _4.pollIntervalMs]), () => ( DEFAULT_POLL_INTERVAL_MS));
58
- let updated = request;
59
- while (Date.now() < deadline) {
60
- await wait(pollIntervalMs);
61
- updated = await client.requests.findById.query({ id: request.id });
62
- if (updated.inflight === void 0) {
63
- return updated;
64
- }
65
- }
66
- throw new Error(
67
- `Timed out waiting for request ${request.id} inflight to be processed (last inflight: ${JSON.stringify(
68
- updated.inflight
69
- )})`
70
- );
49
+ const { logSubStep } = createBakeLogHelpers(logger);
50
+ if (request.inflight === void 0) return request;
51
+ logSubStep(`Waiting for inflight request to be processed...`);
52
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
53
+ const deadline = Date.now() + timeoutMs;
54
+ const pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
55
+ let updated = request;
56
+ while (Date.now() < deadline) {
57
+ await wait(pollIntervalMs);
58
+ updated = await client.requests.findById.query({ id: request.id });
59
+ if (updated.inflight === void 0) return updated;
60
+ }
61
+ throw new Error(`Timed out waiting for request ${request.id} inflight to be processed (last inflight: ${JSON.stringify(updated.inflight)})`);
71
62
  }
63
+ /**
64
+ * Poll a request until it reaches a terminal state (EXECUTED, FAILED, etc.).
65
+ *
66
+ * Returns the request once it is no longer in EXECUTING/STUCK state.
67
+ * Throws if the request reaches FAILED or STUCK state, or if the timeout is exceeded.
68
+ */
72
69
  async function waitForRequestExecuted(client, request, logger, options) {
73
- const { logSubStep } = createBakeLogHelpers(logger);
74
- if (isEndState(request.state)) {
75
- if (request.state === "EXECUTED") {
76
- return request;
77
- }
78
- throw new Error(`Request is in error state ${request.state}`);
79
- }
80
- const pollIntervalMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.pollIntervalMs]), () => ( DEFAULT_POLL_INTERVAL_MS));
81
- const timeoutMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.timeoutMs]), () => ( DEFAULT_TIMEOUT_MS));
82
- const deadline = Date.now() + timeoutMs;
83
- logSubStep(`Waiting for request to be executed...`);
84
- let updated = request;
85
- while (Date.now() < deadline) {
86
- await wait(pollIntervalMs);
87
- updated = await client.requests.findById.query({ id: request.id });
88
- if (isEndState(updated.state)) {
89
- if (updated.state === "EXECUTED") {
90
- return updated;
91
- }
92
- throw new Error(`Request is in error state ${updated.state}`);
93
- }
94
- }
95
- throw new Error(
96
- `Timed out waiting for request ${request.id} to reach a terminal state (last state: ${updated.state})`
97
- );
70
+ const { logSubStep } = createBakeLogHelpers(logger);
71
+ if (isEndState(request.state)) {
72
+ if (request.state === "EXECUTED") return request;
73
+ throw new Error(`Request is in error state ${request.state}`);
74
+ }
75
+ const pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
76
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
77
+ const deadline = Date.now() + timeoutMs;
78
+ logSubStep(`Waiting for request to be executed...`);
79
+ let updated = request;
80
+ while (Date.now() < deadline) {
81
+ await wait(pollIntervalMs);
82
+ updated = await client.requests.findById.query({ id: request.id });
83
+ if (isEndState(updated.state)) {
84
+ if (updated.state === "EXECUTED") return updated;
85
+ throw new Error(`Request is in error state ${updated.state}`);
86
+ }
87
+ }
88
+ throw new Error(`Timed out waiting for request ${request.id} to reach a terminal state (last state: ${updated.state})`);
98
89
  }
99
90
  async function approveRequest(request, approvers, logger) {
100
- const { logSubStep } = createBakeLogHelpers(logger);
101
- for (let i = 0; i < approvers.length; i++) {
102
- logSubStep(`Collecting approval (${i + 1}/${approvers.length})...`);
103
- const approver = approvers[i];
104
- request = await approver.approve(request);
105
- request = await waitForRequestInflightDone(approver.client, request, logger);
106
- }
107
- return waitForRequestExecuted(approvers[0].client, request, logger);
91
+ const { logSubStep } = createBakeLogHelpers(logger);
92
+ for (let i = 0; i < approvers.length; i++) {
93
+ logSubStep(`Collecting approval (${i + 1}/${approvers.length})...`);
94
+ const approver = approvers[i];
95
+ request = await approver.approve(request);
96
+ request = await waitForRequestInflightDone(approver.client, request, logger);
97
+ }
98
+ return waitForRequestExecuted(approvers[0].client, request, logger);
108
99
  }
109
100
  async function createAndApproveRequest(input, approvers, logger) {
110
- const { logSubStep } = createBakeLogHelpers(logger);
111
- const creator = approvers[0];
112
- _invariant2.default.call(void 0, creator, "Need at least 1 user to create a request");
113
- logSubStep(`Creating request of type ${input.type}...`);
114
- const request = await creator.client.requests.create.mutate({ request: input });
115
- return approveRequest(request, approvers, logger);
101
+ const { logSubStep } = createBakeLogHelpers(logger);
102
+ const creator = approvers[0];
103
+ (0, invariant.default)(creator, "Need at least 1 user to create a request");
104
+ logSubStep(`Creating request of type ${input.type}...`);
105
+ return approveRequest(await creator.client.requests.create.mutate({ request: input }), approvers, logger);
116
106
  }
117
107
  function stripUndefinedDeep(obj) {
118
- if (Array.isArray(obj)) {
119
- return obj.map(stripUndefinedDeep);
120
- }
121
- if (obj && typeof obj === "object") {
122
- return Object.fromEntries(
123
- Object.entries(obj).filter(([_2, v]) => v !== void 0).map(([k, v]) => [k, stripUndefinedDeep(v)])
124
- );
125
- }
126
- return obj;
108
+ if (Array.isArray(obj)) return obj.map(stripUndefinedDeep);
109
+ if (obj && typeof obj === "object") return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== void 0).map(([k, v]) => [k, stripUndefinedDeep(v)]));
110
+ return obj;
127
111
  }
128
-
129
- // src/bake/bake-pledge.ts
130
- var flattenApprovers = (groups) => {
131
- return groups.reduce((acc, cur) => {
132
- acc.push(...cur.userIds.slice(0, cur.quorum));
133
- return acc;
134
- }, []);
112
+ //#endregion
113
+ //#region src/bake/bake-pledge.ts
114
+ const flattenApprovers = (groups) => {
115
+ return groups.reduce((acc, cur) => {
116
+ acc.push(...cur.userIds.slice(0, cur.quorum));
117
+ return acc;
118
+ }, []);
135
119
  };
136
120
  async function bakePledgeAdjustment(options, logger) {
137
- const { pledgeAdjustment, engine } = options;
138
- const getDeviceIndex = _chunkLH4QQXUHcjs.createDeviceIndexResolver.call(void 0, engine);
139
- logger.info("Logging in with admin...");
140
- const admin = await engine.withDeviceIndex(4).login();
141
- logger.info("Fetching account, tradelink blueprint and network...");
142
- const [matchingAccounts, blueprint, network] = await Promise.all([
143
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.accounts.list.query, { name: pledgeAdjustment.account }),
144
- admin.client.tradelink.getNetworkBlueprint.query(),
145
- admin.client.tradelink.getNetwork.query()
146
- ]);
147
- const account = matchingAccounts.find((account2) => account2.name === pledgeAdjustment.account);
148
- _invariant2.default.call(void 0, account, `Account ${pledgeAdjustment.account} not found`);
149
- _invariant2.default.call(void 0, blueprint, "Tradelink blueprint is not created yet");
150
- _invariant2.default.call(void 0, network, "Tradelink network is not created yet");
151
- const exchange = network.exchanges.find((exchange2) => {
152
- const blueprintExchange = blueprint.exchanges.find(
153
- (blueprintExchange2) => blueprintExchange2.tradelinkId === exchange2.tradelinkId
154
- );
155
- _invariant2.default.call(void 0, blueprintExchange, `Exchange ${exchange2.tradelinkId} not found in blueprint`);
156
- return blueprintExchange.name === pledgeAdjustment.exchange;
157
- });
158
- _invariant2.default.call(void 0, exchange, `Exchange ${pledgeAdjustment.exchange} not found in network`);
159
- const governance = account.governance;
160
- _invariant2.default.call(void 0, governance.type === "TRADELINK", "Account governance is not TRADELINK");
161
- const assetManager = network.assetManagers.find((am) => am.id === governance.assetManagerId);
162
- _invariant2.default.call(void 0, assetManager, `Asset manager ${governance.assetManagerId} not found in network`);
163
- const exchangeIsConfiguredForAccount = !!governance.exchangeConfigs.find(
164
- (e) => e.exchangeId === exchange.id
165
- );
166
- _invariant2.default.call(void 0,
167
- exchangeIsConfiguredForAccount,
168
- `Exchange ${exchange.id} is not configured for account ${account.id}`
169
- );
170
- const approverIds = [
171
- ...flattenApprovers(assetManager.groups),
172
- ...flattenApprovers(exchange.groups)
173
- ];
174
- const approvers = await Promise.all(
175
- approverIds.map(
176
- (id) => admin.client.users.findById.query({ id }).then((user) => getDeviceIndex(user.deviceUserId)).then((index) => engine.withDeviceIndex(index).login())
177
- )
178
- );
179
- await createAndApproveRequest(
180
- {
181
- type: "TRADELINK_ADJUST_PLEDGE",
182
- data: {
183
- accountId: account.id,
184
- exchangeId: exchange.id,
185
- amount: pledgeAdjustment.amount
186
- }
187
- },
188
- approvers,
189
- logger
190
- );
191
- logger.info(
192
- `Successfully adjusted pledge for account ${pledgeAdjustment.account} on exchange ${pledgeAdjustment.exchange}`
193
- );
121
+ const { pledgeAdjustment, engine } = options;
122
+ const getDeviceIndex = require_utils.createDeviceIndexResolver(engine);
123
+ logger.info("Logging in with admin...");
124
+ const admin = await engine.withDeviceIndex(4).login();
125
+ logger.info("Fetching account, tradelink blueprint and network...");
126
+ const [matchingAccounts, blueprint, network] = await Promise.all([
127
+ require_utils.fetchAll(admin.client.accounts.list.query, { name: pledgeAdjustment.account }),
128
+ admin.client.tradelink.getNetworkBlueprint.query(),
129
+ admin.client.tradelink.getNetwork.query()
130
+ ]);
131
+ const account = matchingAccounts.find((account) => account.name === pledgeAdjustment.account);
132
+ (0, invariant.default)(account, `Account ${pledgeAdjustment.account} not found`);
133
+ (0, invariant.default)(blueprint, "Tradelink blueprint is not created yet");
134
+ (0, invariant.default)(network, "Tradelink network is not created yet");
135
+ const exchange = network.exchanges.find((exchange) => {
136
+ const blueprintExchange = blueprint.exchanges.find((blueprintExchange) => blueprintExchange.tradelinkId === exchange.tradelinkId);
137
+ (0, invariant.default)(blueprintExchange, `Exchange ${exchange.tradelinkId} not found in blueprint`);
138
+ return blueprintExchange.name === pledgeAdjustment.exchange;
139
+ });
140
+ (0, invariant.default)(exchange, `Exchange ${pledgeAdjustment.exchange} not found in network`);
141
+ const governance = account.governance;
142
+ (0, invariant.default)(governance.type === "TRADELINK", "Account governance is not TRADELINK");
143
+ const assetManager = network.assetManagers.find((am) => am.id === governance.assetManagerId);
144
+ (0, invariant.default)(assetManager, `Asset manager ${governance.assetManagerId} not found in network`);
145
+ (0, invariant.default)(!!governance.exchangeConfigs.find((e) => e.exchangeId === exchange.id), `Exchange ${exchange.id} is not configured for account ${account.id}`);
146
+ const approverIds = [...flattenApprovers(assetManager.groups), ...flattenApprovers(exchange.groups)];
147
+ const approvers = await Promise.all(approverIds.map((id) => admin.client.users.findById.query({ id }).then((user) => getDeviceIndex(user.deviceUserId)).then((index) => engine.withDeviceIndex(index).login())));
148
+ await createAndApproveRequest({
149
+ type: "TRADELINK_ADJUST_PLEDGE",
150
+ data: {
151
+ accountId: account.id,
152
+ exchangeId: exchange.id,
153
+ amount: pledgeAdjustment.amount
154
+ }
155
+ }, approvers, logger);
156
+ logger.info(`Successfully adjusted pledge for account ${pledgeAdjustment.account} on exchange ${pledgeAdjustment.exchange}`);
194
157
  }
195
-
196
- // src/bake/bake-tradelink-organization.ts
158
+ //#endregion
159
+ //#region src/bake/bake-tradelink-organization.ts
197
160
  async function bakeTradelinkOrganization(options, logger) {
198
- const { tradelink, engine, rootAuthToken, networkBlueprint } = options;
199
- const { logStep } = createBakeLogHelpers(logger);
200
- const rootClient = engine.createClient({ rootAuthToken });
201
- if (tradelink.exchanges) {
202
- logStep("Creating Tradelink organization exchanges...");
203
- const existingOrgExchanges = await rootClient.tradelink.root.listOrgExchanges.query();
204
- for (const orgExchange of tradelink.exchanges) {
205
- const existingOrgExchange = existingOrgExchanges.find((e) => e.name === orgExchange.name);
206
- if (existingOrgExchange) {
207
- logger.info(
208
- `[SKIPPED] Organization exchange ${existingOrgExchange.name} (${existingOrgExchange.code}) already exists`
209
- );
210
- } else {
211
- await rootClient.tradelink.root.createOrgExchange.mutate({
212
- code: orgExchange.code,
213
- name: orgExchange.name,
214
- logoUrl: orgExchange.logo
215
- });
216
- logger.info(`Created organization exchange ${orgExchange.name} (${orgExchange.code})`);
217
- }
218
- }
219
- }
220
- if (tradelink.assetManagers) {
221
- logStep("Creating Tradelink organization asset managers...");
222
- const existingAssetManagers = await rootClient.tradelink.root.listOrgAssetManagers.query();
223
- for (const orgAssetManager of tradelink.assetManagers) {
224
- const existingOrgAssetManager = existingAssetManagers.find(
225
- (e) => e.name === orgAssetManager.name
226
- );
227
- if (existingOrgAssetManager) {
228
- logger.info(
229
- `[SKIPPED] Organization asset manager ${existingOrgAssetManager.name} (${existingOrgAssetManager.code}) already exists`
230
- );
231
- } else {
232
- await rootClient.tradelink.root.createOrgAssetManager.mutate({
233
- code: orgAssetManager.code,
234
- name: orgAssetManager.name,
235
- logoUrl: orgAssetManager.logo
236
- });
237
- logger.info(
238
- `Created organization asset manager ${orgAssetManager.name} (${orgAssetManager.code})`
239
- );
240
- }
241
- }
242
- }
243
- if (tradelink.custodians) {
244
- logStep("Creating Tradelink organization custodians...");
245
- const existingCustodians = await rootClient.tradelink.root.listOrgCustodians.query();
246
- for (const orgCustodian of tradelink.custodians) {
247
- const existingOrgCustodian = existingCustodians.find((e) => e.name === orgCustodian.name);
248
- if (existingOrgCustodian) {
249
- logger.info(
250
- `[SKIPPED] Organization custodian ${existingOrgCustodian.name} (${existingOrgCustodian.code}) already exists`
251
- );
252
- } else {
253
- await rootClient.tradelink.root.createOrgCustodian.mutate({
254
- code: orgCustodian.code,
255
- name: orgCustodian.name,
256
- logoUrl: orgCustodian.logo
257
- });
258
- logger.info(`Created organization custodian ${orgCustodian.name} (${orgCustodian.code})`);
259
- }
260
- }
261
- }
262
- if (networkBlueprint) {
263
- logStep("Creating Tradelink network blueprint...");
264
- const { workspaceName, blueprint } = networkBlueprint;
265
- const existingBlueprints = await rootClient.tradelink.root.listNetworkBlueprints.query();
266
- const existingBlueprint = existingBlueprints.find((e) => e.workspaceName === workspaceName);
267
- if (existingBlueprint) {
268
- logger.info(`[SKIPPED] Network blueprint for ${workspaceName} workspace already exists`);
269
- } else {
270
- await rootClient.tradelink.root.createNetworkBlueprint.mutate({
271
- workspaceName,
272
- custodian: { name: blueprint.custodian },
273
- exchanges: blueprint.exchanges.map((_2) => ({ name: _2 })),
274
- assetManagers: blueprint.assetManagers.map((_2) => ({ name: _2 }))
275
- });
276
- logger.info(`Created network blueprint for ${networkBlueprint.workspaceName} workspace`);
277
- }
278
- }
161
+ const { tradelink, engine, rootAuthToken, networkBlueprint } = options;
162
+ const { logStep } = createBakeLogHelpers(logger);
163
+ const rootClient = engine.createClient({ rootAuthToken });
164
+ /* v8 ignore else - TODO bake empty tradelink org -- @preserve */
165
+ if (tradelink.exchanges) {
166
+ logStep("Creating Tradelink organization exchanges...");
167
+ const existingOrgExchanges = await rootClient.tradelink.root.listOrgExchanges.query();
168
+ for (const orgExchange of tradelink.exchanges) {
169
+ const existingOrgExchange = existingOrgExchanges.find((e) => e.name === orgExchange.name);
170
+ if (existingOrgExchange) logger.info(`[SKIPPED] Organization exchange ${existingOrgExchange.name} (${existingOrgExchange.code}) already exists`);
171
+ else {
172
+ await rootClient.tradelink.root.createOrgExchange.mutate({
173
+ code: orgExchange.code,
174
+ name: orgExchange.name,
175
+ logoUrl: orgExchange.logo
176
+ });
177
+ logger.info(`Created organization exchange ${orgExchange.name} (${orgExchange.code})`);
178
+ }
179
+ }
180
+ }
181
+ /* v8 ignore else -- @preserve */
182
+ if (tradelink.assetManagers) {
183
+ logStep("Creating Tradelink organization asset managers...");
184
+ const existingAssetManagers = await rootClient.tradelink.root.listOrgAssetManagers.query();
185
+ for (const orgAssetManager of tradelink.assetManagers) {
186
+ const existingOrgAssetManager = existingAssetManagers.find((e) => e.name === orgAssetManager.name);
187
+ if (existingOrgAssetManager) logger.info(`[SKIPPED] Organization asset manager ${existingOrgAssetManager.name} (${existingOrgAssetManager.code}) already exists`);
188
+ else {
189
+ await rootClient.tradelink.root.createOrgAssetManager.mutate({
190
+ code: orgAssetManager.code,
191
+ name: orgAssetManager.name,
192
+ logoUrl: orgAssetManager.logo
193
+ });
194
+ logger.info(`Created organization asset manager ${orgAssetManager.name} (${orgAssetManager.code})`);
195
+ }
196
+ }
197
+ }
198
+ /* v8 ignore else -- @preserve */
199
+ if (tradelink.custodians) {
200
+ logStep("Creating Tradelink organization custodians...");
201
+ const existingCustodians = await rootClient.tradelink.root.listOrgCustodians.query();
202
+ for (const orgCustodian of tradelink.custodians) {
203
+ const existingOrgCustodian = existingCustodians.find((e) => e.name === orgCustodian.name);
204
+ if (existingOrgCustodian) logger.info(`[SKIPPED] Organization custodian ${existingOrgCustodian.name} (${existingOrgCustodian.code}) already exists`);
205
+ else {
206
+ await rootClient.tradelink.root.createOrgCustodian.mutate({
207
+ code: orgCustodian.code,
208
+ name: orgCustodian.name,
209
+ logoUrl: orgCustodian.logo
210
+ });
211
+ logger.info(`Created organization custodian ${orgCustodian.name} (${orgCustodian.code})`);
212
+ }
213
+ }
214
+ }
215
+ /* v8 ignore else -- @preserve */
216
+ if (networkBlueprint) {
217
+ logStep("Creating Tradelink network blueprint...");
218
+ const { workspaceName, blueprint } = networkBlueprint;
219
+ if ((await rootClient.tradelink.root.listNetworkBlueprints.query()).find((e) => e.workspaceName === workspaceName)) logger.info(`[SKIPPED] Network blueprint for ${workspaceName} workspace already exists`);
220
+ else {
221
+ await rootClient.tradelink.root.createNetworkBlueprint.mutate({
222
+ workspaceName,
223
+ custodian: { name: blueprint.custodian },
224
+ exchanges: blueprint.exchanges.map((_) => ({ name: _ })),
225
+ assetManagers: blueprint.assetManagers.map((_) => ({ name: _ }))
226
+ });
227
+ logger.info(`Created network blueprint for ${networkBlueprint.workspaceName} workspace`);
228
+ }
229
+ }
279
230
  }
280
-
281
- // src/bake/bake-workspace.ts
282
-
283
- var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash);
284
- var _tspattern = require('ts-pattern');
231
+ //#endregion
232
+ //#region src/bake/bake-workspace.ts
285
233
  async function bakeWorkspace(options, logger) {
286
- const { workspace, engine, workspaceName } = options;
287
- const workspaceEngine = engine.withWorkspace(workspaceName);
288
- const { logTitle, logStep, logSubStep } = createBakeLogHelpers(logger);
289
- const findDeviceIndex = _chunkLH4QQXUHcjs.createDeviceIndexResolver.call(void 0, workspaceEngine);
290
- logger.info("Authenticating with two admins...");
291
- const [admin1, admin2] = await Promise.all([
292
- workspaceEngine.withDeviceIndex(4).login(),
293
- workspaceEngine.withDeviceIndex(5).login()
294
- ]);
295
- logger.info("Fetching existing data...");
296
- const [
297
- existingUsers,
298
- existingGroups,
299
- existingWhitelists,
300
- existingPolicies,
301
- existingAccounts,
302
- existingEntities,
303
- tradelinkNetworkBlueprint
304
- ] = await Promise.all([
305
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin1.client.users.list.query, { status: "ACTIVE" }),
306
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin1.client.groups.list.query, { status: "ACTIVE" }),
307
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin1.client.whitelists.list.query, { status: "ACTIVE" }),
308
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin1.client.policies.list.query, { isPrivate: false }),
309
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin1.client.accounts.list.query, { status: "ACTIVE" }),
310
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin1.client.entities.list.query, { status: "ACTIVE" }),
311
- admin1.client.tradelink.getNetworkBlueprint.query()
312
- ]);
313
- const tradelinkOrgExchangesByName = _lodash2.default.keyBy(_optionalChain([tradelinkNetworkBlueprint, 'optionalAccess', _7 => _7.exchanges]), "name");
314
- const tradelinkOrgAssetManagersByName = _lodash2.default.keyBy(_optionalChain([tradelinkNetworkBlueprint, 'optionalAccess', _8 => _8.assetManagers]), "name");
315
- let existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
316
- const existingPsdUsers = existingUsers.filter((user) => user.deviceType === "PSD");
317
- const existingApiUsers = existingUsers.filter((user) => user.deviceType === "API");
318
- const usersWithDeviceIndex = await resolveDevicesIndexes(existingPsdUsers);
319
- if (workspace.users) {
320
- logTitle("Users");
321
- if (workspace.users.admins) {
322
- for (const deviceIndex of workspace.users.admins) {
323
- await createUser("ADMIN", deviceIndex);
324
- }
325
- }
326
- if (workspace.users.operators) {
327
- for (const deviceIndex of workspace.users.operators) {
328
- await createUser("OPERATOR", deviceIndex);
329
- }
330
- }
331
- if (workspace.users.api) {
332
- for (const apiUser of workspace.users.api) {
333
- await createApiUser(apiUser);
334
- }
335
- }
336
- }
337
- if (workspace.workspaceRules) {
338
- logTitle("Workspace Rules");
339
- for (const workspaceRule of workspace.workspaceRules) {
340
- await createWorkspaceRule(workspaceRule);
341
- }
342
- }
343
- if (workspace.groups) {
344
- logTitle("Groups");
345
- for (const group of workspace.groups) {
346
- await createGroup(group);
347
- }
348
- }
349
- if (workspace.whitelists) {
350
- logTitle("Whitelists");
351
- await createWhitelists(workspace.whitelists);
352
- }
353
- if (workspace.policies) {
354
- logTitle("Policies");
355
- for (const policy of workspace.policies) {
356
- await createPolicy(policy);
357
- }
358
- }
359
- if (workspace.tradelink) {
360
- logTitle("Tradelink");
361
- await createTradelink(workspace.tradelink);
362
- }
363
- if (workspace.accounts) {
364
- logTitle("Accounts");
365
- for (const account of workspace.accounts) {
366
- await createAccount(account, workspace);
367
- }
368
- }
369
- if (workspace.entities) {
370
- logTitle("Entities");
371
- for (const entity of workspace.entities) {
372
- await createEntity(entity);
373
- }
374
- }
375
- async function editDomainObjectIfNeeded(params) {
376
- const previousRequests = await admin1.client.requests.list.query({
377
- type: params.requestTypes,
378
- targetId: params.existingId,
379
- state: "EXECUTED",
380
- sortBy: "createdAt",
381
- sortOrder: "desc",
382
- pageSize: 1
383
- });
384
- if (_optionalChain([previousRequests, 'optionalAccess', _9 => _9.results]) && previousRequests.results.length > 0) {
385
- const stateRequest = previousRequests.results[0];
386
- _invariant2.default.call(void 0,
387
- stateRequest && params.requestTypes.includes(stateRequest.type),
388
- `State request should be a ${params.requestTypes[0]} or ${params.requestTypes[1]} request`
389
- );
390
- const lastData = params.extractLastData(stateRequest.data);
391
- if (_lodash2.default.isEqual(stripUndefinedDeep(params.editData), stripUndefinedDeep(lastData))) {
392
- logger.info(`[SKIPPED] ${params.entityType} "${params.entityName}" has not changed`);
393
- return "skipped";
394
- }
395
- }
396
- logStep(`Editing ${params.entityType.toLowerCase()} "${params.entityName}"...`);
397
- await createAndApproveRequest(params.editInput, [admin1, admin2], logger);
398
- logger.info(`[EDITED] ${params.entityType} "${params.entityName}" has been edited`);
399
- return "edited";
400
- }
401
- async function createWhitelists(whitelists) {
402
- for (const whitelist of whitelists) {
403
- await createWhitelist(whitelist);
404
- }
405
- async function createWhitelist(whitelist) {
406
- const existing = existingWhitelists.find((w) => w.name === whitelist.name);
407
- const normalizeAddresses = (addresses) => addresses.map(({ destinationTags, ...rest }) => ({
408
- ...rest,
409
- ..._optionalChain([destinationTags, 'optionalAccess', _10 => _10.length]) ? { destinationTags } : {}
410
- }));
411
- const whitelistEditData = {
412
- name: whitelist.name,
413
- addresses: normalizeAddresses(whitelist.addresses)
414
- };
415
- if (existing) {
416
- await editDomainObjectIfNeeded({
417
- entityType: "Whitelist",
418
- entityName: whitelist.name,
419
- existingId: existing.id,
420
- editInput: {
421
- type: "EDIT_WHITELIST",
422
- targetId: existing.id,
423
- data: { name: whitelist.name, addresses: whitelist.addresses }
424
- },
425
- editData: whitelistEditData,
426
- requestTypes: ["CREATE_WHITELIST", "EDIT_WHITELIST"],
427
- extractLastData: (data) => ({
428
- name: data.name,
429
- addresses: normalizeAddresses(data.addresses)
430
- })
431
- });
432
- return;
433
- }
434
- const input = {
435
- type: "CREATE_WHITELIST",
436
- data: { ...whitelist, description: _nullishCoalesce(whitelist.description, () => ( null)) }
437
- };
438
- const req = await createAndApproveRequest(input, [admin1, admin2], logger);
439
- logSubStep(`Whitelist "${whitelist.name}" has been created`);
440
- const createdWhitelist = await admin1.client.whitelists.findById.query({ id: req.targetId });
441
- existingWhitelists.push(createdWhitelist);
442
- }
443
- }
444
- function govRuleFromManifest(rule) {
445
- return {
446
- operationType: rule.type,
447
- reviewSteps: rule.steps.map((step) => {
448
- if ("group" in step) {
449
- return {
450
- quorum: step.quorum,
451
- groupId: groupIdFromName(step.group)
452
- };
453
- }
454
- return {
455
- quorum: step.quorum,
456
- userIds: step.members.map(userIdFromDeviceIndexOrName)
457
- };
458
- }),
459
- threshold: rule.threshold,
460
- whitelistIds: _optionalChain([rule, 'access', _11 => _11.whitelistNames, 'optionalAccess', _12 => _12.map, 'call', _13 => _13(whitelistIdFromName)])
461
- };
462
- }
463
- function rawSigningRuleFromManifest(rule) {
464
- return {
465
- operationType: rule.type,
466
- // RAW_SIGNING only supports steps with userIds (no groups)
467
- reviewSteps: rule.steps.map((step) => ({
468
- quorum: step.quorum,
469
- userIds: step.members.map(userIdFromDeviceIndexOrName)
470
- }))
471
- };
472
- }
473
- async function createAccount(account, workspace2) {
474
- const existing = existingAccounts.find(
475
- (a) => a.currency === account.currency && a.index === account.index && (_nullishCoalesce(a.contractAddress, () => ( null))) === (_nullishCoalesce(account.contractAddress, () => ( null)))
476
- );
477
- const governance = _tspattern.match.call(void 0, account.governance).with({ type: "TRADELINK" }, (gov) => ({
478
- type: "TRADELINK",
479
- assetManagerId: assetManagerIdFromName(gov.assetManager),
480
- exchangeConfigs: gov.exchanges.map((exchangeConfig) => ({
481
- exchangeId: exchangeIdFromName(exchangeConfig.name),
482
- repledgeAuthorized: exchangeConfig.repledgeAuthorized === true,
483
- needsAssetManagerApprovalForSettlements: exchangeConfig.needsAssetManagerApprovalForSettlements === true
484
- }))
485
- })).with({ type: "RAW_SIGNING" }, (gov) => ({
486
- type: "RAW_SIGNING",
487
- policy: { rules: gov.rules.map(rawSigningRuleFromManifest) }
488
- })).with({ type: "CLASSIC" }, (gov) => ({
489
- type: "CLASSIC",
490
- policy: { rules: gov.rules.map(govRuleFromManifest) }
491
- })).with({ type: "POLICY" }, (gov) => ({
492
- type: "CLASSIC",
493
- policy: { policyId: policyIdFromName(gov.policy) }
494
- })).exhaustive();
495
- const accountData = {
496
- name: account.name,
497
- currency: account.currency,
498
- contractAddress: _nullishCoalesce(account.contractAddress, () => ( null)),
499
- tokenIdentifier: _nullishCoalesce(account.tokenIdentifier, () => ( null)),
500
- index: account.index,
501
- governance
502
- };
503
- if (existing) {
504
- const editData = { name: accountData.name, governance };
505
- const result = await editDomainObjectIfNeeded({
506
- entityType: "Account",
507
- entityName: account.name,
508
- existingId: existing.id,
509
- editInput: { type: "EDIT_ACCOUNT", targetId: existing.id, data: editData },
510
- editData,
511
- requestTypes: ["CREATE_ACCOUNT", "EDIT_ACCOUNT"],
512
- extractLastData: (data) => ({ name: data.name, governance: data.governance })
513
- });
514
- if (result === "skipped") {
515
- await activateHederaAccount(account, workspace2, existing.id);
516
- }
517
- return;
518
- }
519
- logStep(`Creating account "${account.name}"`);
520
- const createInput = {
521
- type: "CREATE_ACCOUNT",
522
- data: accountData
523
- };
524
- const req = await createAndApproveRequest(createInput, [admin1, admin2], logger);
525
- const createdAccount = await admin1.client.accounts.findById.query({ id: req.targetId });
526
- existingAccounts.push(createdAccount);
527
- if (account.governance.type === "TRADELINK") {
528
- logStep(`Activating tradelink account "${account.name}"`);
529
- const assetManagerId = assetManagerIdFromName(account.governance.assetManager);
530
- const assetManager = _optionalChain([existingTradelinkNetwork, 'optionalAccess', _14 => _14.assetManagers, 'access', _15 => _15.find, 'call', _16 => _16(
531
- (assetManager2) => assetManager2.id === assetManagerId
532
- )]);
533
- _invariant2.default.call(void 0, assetManager, `Asset manager for account exists`);
534
- const loggedAssetManagerOperators = await Promise.all(
535
- assetManager.groups.flatMap(
536
- ({ quorum, userIds }) => userIds.slice(0, quorum).map((userId) => {
537
- const deviceIndex = _optionalChain([usersWithDeviceIndex, 'access', _17 => _17.find, 'call', _18 => _18((o) => o.user.id === userId), 'optionalAccess', _19 => _19.deviceIndex]);
538
- return workspaceEngine.withDeviceIndex(deviceIndex).login();
539
- })
540
- )
541
- );
542
- await createAndApproveRequest(
543
- { type: "TRADELINK_ACTIVATE_ACCOUNT", targetId: req.targetId, data: null },
544
- loggedAssetManagerOperators,
545
- logger
546
- );
547
- }
548
- if (req.targetId) {
549
- await activateHederaAccount(account, workspace2, req.targetId);
550
- }
551
- logSubStep(`Account ${account.name} has been created`);
552
- }
553
- async function activateHederaAccount(account, workspace2, accountId) {
554
- if (account.currency === "hedera" && account.contractAddress === void 0 && workspace2.hederaData && accountId) {
555
- const salt = engine.__options.salt;
556
- const hederaAccountsForSalt = workspace2.hederaData[salt];
557
- const hederaAccountData = _optionalChain([hederaAccountsForSalt, 'optionalAccess', _20 => _20.find, 'call', _21 => _21(
558
- (h) => h.index === account.index && h.activate
559
- )]);
560
- if (hederaAccountData) {
561
- try {
562
- await admin1.client.accounts.hedera.activateAccount.mutate({
563
- id: accountId,
564
- onchainId: hederaAccountData.onChainId
565
- });
566
- logSubStep(`Hedera account "${account.name}" has been activated`);
567
- } catch (error) {
568
- logger.warning(`Activation for "${account.name}" failed: ${error}`);
569
- }
570
- }
571
- }
572
- }
573
- async function createUser(role, deviceIndex) {
574
- const userEngine = workspaceEngine.withDeviceIndex(deviceIndex);
575
- const deviceId = await userEngine.device.getDeviceUserId();
576
- const existing = existingUsers.find((user) => user.deviceUserId === deviceId);
577
- if (existing) {
578
- logger.info(`[SKIPPED] User with device index ${deviceIndex} already exists`);
579
- return;
580
- }
581
- const name = `${role === "ADMIN" ? "Admin" : "Operator"} ${deviceIndex}`;
582
- logStep(`Creating ${name}`);
583
- logSubStep("Creating invitation...");
584
- let registration = await admin1.client.userRegistrations.invite.mutate({
585
- name,
586
- role,
587
- deviceUserId: deviceId,
588
- psdModel: "STAX"
589
- });
590
- logSubStep("Completing registration...");
591
- registration = await userEngine.register(registration);
592
- logSubStep("Creating request...");
593
- let req = await admin1.client.requests.create.mutate({
594
- request: {
595
- type: "CREATE_PSD_USER",
596
- data: { registrationId: registration.id }
597
- }
598
- });
599
- req = await approveRequest(req, [admin1, admin2], logger);
600
- logSubStep(`${name} has been created`);
601
- const createdUser = await admin1.client.users.findById.query({ id: req.targetId });
602
- existingUsers.push(createdUser);
603
- usersWithDeviceIndex.push({ user: createdUser, deviceIndex });
604
- }
605
- async function createApiUser(apiUser) {
606
- const pubKey = _nullishCoalesce(apiUser.pubKey, () => ( _chunk2WGM7EWAcjs.genKeys.call(void 0, apiUser.name).hexPubKey));
607
- const existing = existingApiUsers.find(
608
- (user) => user.pubKey === pubKey || user.name === apiUser.name
609
- );
610
- if (existing) {
611
- logger.info(
612
- `[SKIPPED] API user already exists with name "${apiUser.name}" or public key "${pubKey}"`
613
- );
614
- return;
615
- }
616
- logStep(`Creating API user "${apiUser.name}"...`);
617
- logSubStep("Creating request...");
618
- let req = await admin1.client.requests.create.mutate({
619
- request: {
620
- type: "CREATE_API_USER",
621
- data: {
622
- name: apiUser.name,
623
- role: apiUser.role,
624
- pubKey,
625
- viewAll: apiUser.viewAll
626
- }
627
- }
628
- });
629
- req = await approveRequest(req, [admin1, admin2], logger);
630
- logSubStep(`API user "${apiUser.name}" has been created`);
631
- logSubStep("Generating credentials...");
632
- const credentials = await admin1.client.users.resetApiUserCredentials.mutate({
633
- id: req.targetId
634
- });
635
- logSubStep(
636
- `API user "${apiUser.name}" credentials have been generated: apiKeyId=${credentials.apiKeyId}, apiKeySecret=${credentials.apiKeySecret}`
637
- );
638
- const createdUser = await admin1.client.users.findById.query({ id: req.targetId });
639
- existingApiUsers.push(createdUser);
640
- }
641
- async function createGroup(group) {
642
- const existing = existingGroups.find((g) => g.name === group.name);
643
- const members = group.members.map(userIdFromDeviceIndexOrName);
644
- const groupData = {
645
- name: group.name,
646
- description: "",
647
- members
648
- };
649
- if (existing) {
650
- await editDomainObjectIfNeeded({
651
- entityType: "Group",
652
- entityName: group.name,
653
- existingId: existing.id,
654
- editInput: { type: "EDIT_GROUP", targetId: existing.id, data: groupData },
655
- editData: groupData,
656
- requestTypes: ["CREATE_GROUP", "EDIT_GROUP"],
657
- extractLastData: (data) => ({ ...data, description: _nullishCoalesce(data.description, () => ( "")) })
658
- });
659
- return;
660
- }
661
- logStep(`Creating group ${group.name}...`);
662
- logSubStep("Creating request...");
663
- let request = await admin1.client.requests.create.mutate({
664
- request: {
665
- type: "CREATE_GROUP",
666
- data: groupData
667
- }
668
- });
669
- request = await approveRequest(request, [admin1, admin2], logger);
670
- logSubStep(`${group.name} has been created`);
671
- const createdGroup = await admin1.client.groups.findById.query({ id: request.targetId });
672
- existingGroups.push(createdGroup);
673
- }
674
- async function createPolicy(policy) {
675
- const existing = existingPolicies.find((p) => p.name === policy.name);
676
- const policyEditData = {
677
- name: policy.name,
678
- description: "",
679
- govRules: policy.rules.map(govRuleFromManifest)
680
- };
681
- if (existing) {
682
- await editDomainObjectIfNeeded({
683
- entityType: "Policy",
684
- entityName: policy.name,
685
- existingId: existing.id,
686
- editInput: { type: "EDIT_POLICY", targetId: existing.id, data: policyEditData },
687
- editData: policyEditData,
688
- requestTypes: ["CREATE_POLICY", "EDIT_POLICY"],
689
- extractLastData: (data) => ({
690
- name: data.name,
691
- description: _nullishCoalesce(data.description, () => ( "")),
692
- govRules: data.govRules
693
- })
694
- });
695
- return;
696
- }
697
- logStep(`Creating policy ${policy.name}...`);
698
- logSubStep("Creating request...");
699
- let request = await admin1.client.requests.create.mutate({
700
- request: {
701
- type: "CREATE_POLICY",
702
- data: {
703
- ...policyEditData,
704
- currency: policy.currency
705
- }
706
- }
707
- });
708
- request = await approveRequest(request, [admin1, admin2], logger);
709
- logSubStep(`${policy.name} has been created`);
710
- const createdPolicy = await admin1.client.policies.findById.query({ id: request.targetId });
711
- existingPolicies.push(createdPolicy);
712
- }
713
- async function createWorkspaceRule(workspaceRule) {
714
- const { permission, quorum, members } = workspaceRule;
715
- logStep(`Editing workspace rule for ${permission}...`);
716
- const userIds = members.map(userIdFromDeviceIndexOrName);
717
- logSubStep("Creating request...");
718
- const input = {
719
- type: "EDIT_WORKSPACE_RULE",
720
- data: {
721
- permission,
722
- reviewConfig: [{ quorum, userIds }]
723
- }
724
- };
725
- await createAndApproveRequest(input, [admin1, admin2], logger);
726
- logSubStep(`Workspace rule for "${permission}" has been edited`);
727
- }
728
- async function createEntity(entity) {
729
- const existing = existingEntities.find((e) => e.name === entity.name);
730
- const accountIds = (_nullishCoalesce(entity.accounts, () => ( []))).map(accountIdFromName);
731
- const memberIds = (_nullishCoalesce(entity.members, () => ( []))).map(userIdFromUserName);
732
- const entityEditData = { name: entity.name, accountIds, memberIds };
733
- if (existing) {
734
- await editDomainObjectIfNeeded({
735
- entityType: "Entity",
736
- entityName: entity.name,
737
- existingId: existing.id,
738
- editInput: { type: "EDIT_ENTITY", targetId: existing.id, data: entityEditData },
739
- editData: entityEditData,
740
- requestTypes: ["CREATE_ENTITY", "EDIT_ENTITY"],
741
- extractLastData: (data) => ({
742
- name: data.name,
743
- accountIds: data.accountIds,
744
- memberIds: data.memberIds
745
- })
746
- });
747
- return;
748
- }
749
- logStep(`Creating entity "${entity.name}"...`);
750
- const input = {
751
- type: "CREATE_ENTITY",
752
- data: entityEditData
753
- };
754
- const request = await createAndApproveRequest(input, [admin1, admin2], logger);
755
- logSubStep(`Entity "${entity.name}" has been created`);
756
- const createdEntity = await admin1.client.entities.findById.query({ id: request.targetId });
757
- existingEntities.push(createdEntity);
758
- }
759
- async function createTradelink(tradelink) {
760
- if (tradelink.custodian) {
761
- if (existingTradelinkNetwork === null) {
762
- logStep("Creating custodian config...");
763
- const { settlement, withdraw, arbitration } = tradelink.custodian;
764
- const data = {
765
- settlement: settlement.map(tradelinkReviewStepFromManifest),
766
- withdraw: withdraw.map(tradelinkReviewStepFromManifest),
767
- arbitration: arbitration.map(tradelinkReviewStepFromManifest)
768
- };
769
- logSubStep("Creating request...");
770
- const request = await admin1.client.requests.create.mutate({
771
- request: {
772
- type: "TRADELINK_CREATE_CUSTODIAN",
773
- data
774
- }
775
- });
776
- await approveRequest(request, [admin1, admin2], logger);
777
- logSubStep("Tradelink custodian config has been created");
778
- existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
779
- } else {
780
- logger.info("[SKIPPED] Custodian config already exists");
781
- }
782
- const networkBlueprint = await admin1.client.tradelink.getNetworkBlueprint.query();
783
- if (networkBlueprint !== null) {
784
- if (tradelink.exchanges !== void 0) {
785
- await createTradelinkExchanges(networkBlueprint, tradelink.exchanges);
786
- }
787
- if (tradelink.assetManagers !== void 0) {
788
- await createTradelinkAssetManagers(networkBlueprint, tradelink.assetManagers);
789
- }
790
- } else {
791
- logger.error(
792
- "Will not create exchanges and asset managers because there is no network blueprint for current workspace"
793
- );
794
- }
795
- }
796
- }
797
- async function createTradelinkExchanges(networkBlueprint, exchanges) {
798
- _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Network should exist");
799
- const blueprintExchanges = networkBlueprint.exchanges;
800
- for (const exchange of exchanges) {
801
- const blueprintExchange = blueprintExchanges.find(({ name }) => name === exchange.name);
802
- _invariant2.default.call(void 0,
803
- blueprintExchange !== void 0,
804
- `Exchange ${exchange.name} does not exist in network blueprint`
805
- );
806
- const exchangeId = blueprintExchange.tradelinkId;
807
- logStep(`Creating exchange ${exchange.name}...`);
808
- if (existingTradelinkNetwork.exchanges.find(({ tradelinkId }) => tradelinkId === exchangeId) !== void 0) {
809
- logger.info(`[SKIPPED] Exchange "${exchange.name}" already exists`);
810
- continue;
811
- }
812
- logSubStep("Creating request...");
813
- const request = await admin1.client.requests.create.mutate({
814
- request: {
815
- type: "TRADELINK_CREATE_EXCHANGE",
816
- data: {
817
- tradelinkId: exchangeId,
818
- groups: exchange.groups.map(tradelinkReviewStepFromManifest),
819
- whitelist: exchange.whitelist
820
- }
821
- }
822
- });
823
- const loggedExchangeOperators = await Promise.all(
824
- exchange.groups.flatMap(
825
- ({ quorum, members }) => members.slice(0, quorum).map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login())
826
- )
827
- );
828
- await approveRequest(request, [admin1, admin2, ...loggedExchangeOperators], logger);
829
- existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
830
- _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Tradelink network exists");
831
- }
832
- }
833
- async function createTradelinkAssetManagers(networkBlueprint, assetManagers) {
834
- _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Network should exist");
835
- const blueprintAssetManagers = networkBlueprint.assetManagers;
836
- for (const assetManager of assetManagers) {
837
- const blueprintAssetManager = blueprintAssetManagers.find(
838
- ({ name }) => name === assetManager.name
839
- );
840
- _invariant2.default.call(void 0,
841
- blueprintAssetManager !== void 0,
842
- `AssetManager ${assetManager.name} does not exist in network blueprint`
843
- );
844
- const assetManagerId = blueprintAssetManager.tradelinkId;
845
- logStep(`Creating assetManager ${assetManager.name}...`);
846
- if (existingTradelinkNetwork.assetManagers.find(
847
- ({ tradelinkId }) => tradelinkId === assetManagerId
848
- ) !== void 0) {
849
- logger.info(`[SKIPPED] Asset manager "${assetManager.name}" already exists`);
850
- continue;
851
- }
852
- logSubStep("Creating request...");
853
- const request = await admin1.client.requests.create.mutate({
854
- request: {
855
- type: "TRADELINK_CREATE_ASSET_MANAGER",
856
- data: {
857
- tradelinkId: assetManagerId,
858
- groups: assetManager.groups.map(tradelinkReviewStepFromManifest),
859
- whitelist: assetManager.whitelist
860
- }
861
- }
862
- });
863
- const loggedAssetManagerOperators = await Promise.all(
864
- assetManager.groups.flatMap(
865
- ({ quorum, members }) => members.slice(0, quorum).map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login())
866
- )
867
- );
868
- await approveRequest(request, [admin1, admin2, ...loggedAssetManagerOperators], logger);
869
- existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
870
- _invariant2.default.call(void 0, existingTradelinkNetwork !== null, "Tradelink network exists");
871
- }
872
- }
873
- async function resolveDevicesIndexes(users) {
874
- const usersWithDeviceIndex2 = await users.reduce(
875
- (acc, cur) => acc.then(async (acc2) => {
876
- acc2.push(await withDeviceIndex(cur));
877
- return acc2;
878
- }),
879
- Promise.resolve([])
880
- );
881
- return usersWithDeviceIndex2;
882
- }
883
- async function withDeviceIndex(user) {
884
- _invariant2.default.call(void 0, user.deviceUserId, `User ${user.id} does not have any device user id`);
885
- const deviceIndex = await findDeviceIndex(user.deviceUserId);
886
- return { user, deviceIndex };
887
- }
888
- function userIdFromDeviceIndex(deviceIndex) {
889
- const corresponding = usersWithDeviceIndex.find((o) => o.deviceIndex === deviceIndex);
890
- _invariant2.default.call(void 0, corresponding, `No user with device index ${deviceIndex}`);
891
- return corresponding.user.id;
892
- }
893
- function userIdFromUserName(name) {
894
- const user = existingApiUsers.find((u) => u.name === name);
895
- _invariant2.default.call(void 0, user, `User ${name} not found`);
896
- return user.id;
897
- }
898
- function userIdFromDeviceIndexOrName(identifier) {
899
- if (typeof identifier === "number") {
900
- return userIdFromDeviceIndex(identifier);
901
- }
902
- return userIdFromUserName(identifier);
903
- }
904
- function groupIdFromName(groupName) {
905
- const group = existingGroups.find((g) => g.name === groupName);
906
- _invariant2.default.call(void 0, group, `Group ${groupName} not found`);
907
- return group.id;
908
- }
909
- function policyIdFromName(policyName) {
910
- const policy = existingPolicies.find((g) => g.name === policyName);
911
- _invariant2.default.call(void 0, policy, `Policy ${policyName} not found`);
912
- return policy.id;
913
- }
914
- function whitelistIdFromName(whitelistName) {
915
- const whitelist = existingWhitelists.find((w) => w.name === whitelistName);
916
- _invariant2.default.call(void 0, whitelist, `Whitelist ${whitelistName} not found`);
917
- return whitelist.id;
918
- }
919
- function accountIdFromName(accountName) {
920
- const account = existingAccounts.find((a) => a.name === accountName);
921
- _invariant2.default.call(void 0, account, `Account "${accountName}" not found`);
922
- return account.id;
923
- }
924
- function assetManagerIdFromName(assetManagerName) {
925
- const orgAssetManager = tradelinkOrgAssetManagersByName[assetManagerName];
926
- _invariant2.default.call(void 0,
927
- orgAssetManager,
928
- `Can't find Tradelink organization asset manager ${assetManagerName}`
929
- );
930
- const assetManager = _optionalChain([existingTradelinkNetwork, 'optionalAccess', _22 => _22.assetManagers, 'access', _23 => _23.find, 'call', _24 => _24(
931
- (assetManager2) => assetManager2.tradelinkId === orgAssetManager.tradelinkId
932
- )]);
933
- _invariant2.default.call(void 0, assetManager, `Can't find Tradelink assetManager ${assetManagerName}`);
934
- return assetManager.id;
935
- }
936
- function exchangeIdFromName(exchangeName) {
937
- const exchange = _optionalChain([existingTradelinkNetwork, 'optionalAccess', _25 => _25.exchanges, 'access', _26 => _26.find, 'call', _27 => _27((exchange2) => {
938
- const orgExchange = tradelinkOrgExchangesByName[exchangeName];
939
- _invariant2.default.call(void 0, orgExchange, `Can't find Tradelink organization exchange ${exchange2.tradelinkId}`);
940
- return orgExchange.name === exchangeName;
941
- })]);
942
- _invariant2.default.call(void 0, exchange, `Can't find Tradelink exchange ${exchangeName}`);
943
- return exchange.id;
944
- }
945
- function tradelinkReviewStepFromManifest({
946
- members,
947
- quorum
948
- }) {
949
- return {
950
- userIds: members.map(userIdFromDeviceIndex),
951
- quorum
952
- };
953
- }
234
+ const { workspace, engine, workspaceName } = options;
235
+ const workspaceEngine = engine.withWorkspace(workspaceName);
236
+ const { logTitle, logStep, logSubStep } = createBakeLogHelpers(logger);
237
+ const findDeviceIndex = require_utils.createDeviceIndexResolver(workspaceEngine);
238
+ logger.info("Authenticating with two admins...");
239
+ const [admin1, admin2] = await Promise.all([workspaceEngine.withDeviceIndex(4).login(), workspaceEngine.withDeviceIndex(5).login()]);
240
+ logger.info("Fetching existing data...");
241
+ const [existingUsers, existingGroups, existingWhitelists, existingPolicies, existingAccounts, existingEntities, tradelinkNetworkBlueprint] = await Promise.all([
242
+ require_utils.fetchAll(admin1.client.users.list.query, { status: "ACTIVE" }),
243
+ require_utils.fetchAll(admin1.client.groups.list.query, { status: "ACTIVE" }),
244
+ require_utils.fetchAll(admin1.client.whitelists.list.query, { status: "ACTIVE" }),
245
+ require_utils.fetchAll(admin1.client.policies.list.query, { isPrivate: false }),
246
+ require_utils.fetchAll(admin1.client.accounts.list.query, { status: "ACTIVE" }),
247
+ require_utils.fetchAll(admin1.client.entities.list.query, { status: "ACTIVE" }),
248
+ admin1.client.tradelink.getNetworkBlueprint.query()
249
+ ]);
250
+ const tradelinkOrgExchangesByName = lodash.default.keyBy(tradelinkNetworkBlueprint?.exchanges, "name");
251
+ const tradelinkOrgAssetManagersByName = lodash.default.keyBy(tradelinkNetworkBlueprint?.assetManagers, "name");
252
+ let existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
253
+ const existingPsdUsers = existingUsers.filter((user) => user.deviceType === "PSD");
254
+ const existingApiUsers = existingUsers.filter((user) => user.deviceType === "API");
255
+ const usersWithDeviceIndex = await resolveDevicesIndexes(existingPsdUsers);
256
+ if (workspace.users) {
257
+ logTitle("Users");
258
+ if (workspace.users.admins) for (const deviceIndex of workspace.users.admins) await createUser("ADMIN", deviceIndex);
259
+ /* v8 ignore else -- @preserve */
260
+ if (workspace.users.operators) for (const deviceIndex of workspace.users.operators) await createUser("OPERATOR", deviceIndex);
261
+ if (workspace.users.api) for (const apiUser of workspace.users.api) await createApiUser(apiUser);
262
+ }
263
+ if (workspace.workspaceRules) {
264
+ logTitle("Workspace Rules");
265
+ for (const workspaceRule of workspace.workspaceRules) await createWorkspaceRule(workspaceRule);
266
+ }
267
+ if (workspace.groups) {
268
+ logTitle("Groups");
269
+ for (const group of workspace.groups) await createGroup(group);
270
+ }
271
+ if (workspace.whitelists) {
272
+ logTitle("Whitelists");
273
+ await createWhitelists(workspace.whitelists);
274
+ }
275
+ if (workspace.policies) {
276
+ logTitle("Policies");
277
+ for (const policy of workspace.policies) await createPolicy(policy);
278
+ }
279
+ if (workspace.tradelink) {
280
+ logTitle("Tradelink");
281
+ await createTradelink(workspace.tradelink);
282
+ }
283
+ if (workspace.accounts) {
284
+ logTitle("Accounts");
285
+ for (const account of workspace.accounts) await createAccount(account, workspace);
286
+ }
287
+ if (workspace.entities) {
288
+ logTitle("Entities");
289
+ for (const entity of workspace.entities) await createEntity(entity);
290
+ }
291
+ async function editDomainObjectIfNeeded(params) {
292
+ const previousRequests = await admin1.client.requests.list.query({
293
+ type: params.requestTypes,
294
+ targetId: params.existingId,
295
+ state: "EXECUTED",
296
+ sortBy: "createdAt",
297
+ sortOrder: "desc",
298
+ pageSize: 1
299
+ });
300
+ if (previousRequests?.results && previousRequests.results.length > 0) {
301
+ const stateRequest = previousRequests.results[0];
302
+ (0, invariant.default)(stateRequest && params.requestTypes.includes(stateRequest.type), `State request should be a ${params.requestTypes[0]} or ${params.requestTypes[1]} request`);
303
+ const lastData = params.extractLastData(stateRequest.data);
304
+ if (lodash.default.isEqual(stripUndefinedDeep(params.editData), stripUndefinedDeep(lastData))) {
305
+ logger.info(`[SKIPPED] ${params.entityType} "${params.entityName}" has not changed`);
306
+ return "skipped";
307
+ }
308
+ }
309
+ logStep(`Editing ${params.entityType.toLowerCase()} "${params.entityName}"...`);
310
+ await createAndApproveRequest(params.editInput, [admin1, admin2], logger);
311
+ logger.info(`[EDITED] ${params.entityType} "${params.entityName}" has been edited`);
312
+ return "edited";
313
+ }
314
+ async function createWhitelists(whitelists) {
315
+ for (const whitelist of whitelists) await createWhitelist(whitelist);
316
+ async function createWhitelist(whitelist) {
317
+ const existing = existingWhitelists.find((w) => w.name === whitelist.name);
318
+ const normalizeAddresses = (addresses) => addresses.map(({ destinationTags, ...rest }) => ({
319
+ ...rest,
320
+ ...destinationTags?.length ? { destinationTags } : {}
321
+ }));
322
+ const whitelistEditData = {
323
+ name: whitelist.name,
324
+ addresses: normalizeAddresses(whitelist.addresses)
325
+ };
326
+ if (existing) {
327
+ await editDomainObjectIfNeeded({
328
+ entityType: "Whitelist",
329
+ entityName: whitelist.name,
330
+ existingId: existing.id,
331
+ editInput: {
332
+ type: "EDIT_WHITELIST",
333
+ targetId: existing.id,
334
+ data: {
335
+ name: whitelist.name,
336
+ addresses: whitelist.addresses
337
+ }
338
+ },
339
+ editData: whitelistEditData,
340
+ requestTypes: ["CREATE_WHITELIST", "EDIT_WHITELIST"],
341
+ extractLastData: (data) => ({
342
+ name: data.name,
343
+ addresses: normalizeAddresses(data.addresses)
344
+ })
345
+ });
346
+ return;
347
+ }
348
+ const req = await createAndApproveRequest({
349
+ type: "CREATE_WHITELIST",
350
+ data: {
351
+ ...whitelist,
352
+ description: whitelist.description ?? null
353
+ }
354
+ }, [admin1, admin2], logger);
355
+ logSubStep(`Whitelist "${whitelist.name}" has been created`);
356
+ const createdWhitelist = await admin1.client.whitelists.findById.query({ id: req.targetId });
357
+ existingWhitelists.push(createdWhitelist);
358
+ }
359
+ }
360
+ function govRuleFromManifest(rule) {
361
+ return {
362
+ operationType: rule.type,
363
+ reviewSteps: rule.steps.map((step) => {
364
+ if ("group" in step) return {
365
+ quorum: step.quorum,
366
+ groupId: groupIdFromName(step.group)
367
+ };
368
+ return {
369
+ quorum: step.quorum,
370
+ userIds: step.members.map(userIdFromDeviceIndexOrName)
371
+ };
372
+ }),
373
+ threshold: rule.threshold,
374
+ whitelistIds: rule.whitelistNames?.map(whitelistIdFromName)
375
+ };
376
+ }
377
+ function rawSigningRuleFromManifest(rule) {
378
+ return {
379
+ operationType: rule.type,
380
+ reviewSteps: rule.steps.map((step) => ({
381
+ quorum: step.quorum,
382
+ userIds: step.members.map(userIdFromDeviceIndexOrName)
383
+ }))
384
+ };
385
+ }
386
+ async function createAccount(account, workspace) {
387
+ const existing = existingAccounts.find((a) => a.currency === account.currency && a.index === account.index && (a.contractAddress ?? null) === (account.contractAddress ?? null));
388
+ const governance = (0, ts_pattern.match)(account.governance).with({ type: "TRADELINK" }, (gov) => ({
389
+ type: "TRADELINK",
390
+ assetManagerId: assetManagerIdFromName(gov.assetManager),
391
+ exchangeConfigs: gov.exchanges.map((exchangeConfig) => ({
392
+ exchangeId: exchangeIdFromName(exchangeConfig.name),
393
+ repledgeAuthorized: exchangeConfig.repledgeAuthorized === true,
394
+ needsAssetManagerApprovalForSettlements: exchangeConfig.needsAssetManagerApprovalForSettlements === true
395
+ }))
396
+ })).with({ type: "RAW_SIGNING" }, (gov) => ({
397
+ type: "RAW_SIGNING",
398
+ policy: { rules: gov.rules.map(rawSigningRuleFromManifest) }
399
+ })).with({ type: "CLASSIC" }, (gov) => ({
400
+ type: "CLASSIC",
401
+ policy: { rules: gov.rules.map(govRuleFromManifest) }
402
+ })).with({ type: "POLICY" }, (gov) => ({
403
+ type: "CLASSIC",
404
+ policy: { policyId: policyIdFromName(gov.policy) }
405
+ })).exhaustive();
406
+ const accountData = {
407
+ name: account.name,
408
+ currency: account.currency,
409
+ contractAddress: account.contractAddress ?? null,
410
+ tokenIdentifier: account.tokenIdentifier ?? null,
411
+ index: account.index,
412
+ governance
413
+ };
414
+ if (existing) {
415
+ const editData = {
416
+ name: accountData.name,
417
+ governance
418
+ };
419
+ if (await editDomainObjectIfNeeded({
420
+ entityType: "Account",
421
+ entityName: account.name,
422
+ existingId: existing.id,
423
+ editInput: {
424
+ type: "EDIT_ACCOUNT",
425
+ targetId: existing.id,
426
+ data: editData
427
+ },
428
+ editData,
429
+ requestTypes: ["CREATE_ACCOUNT", "EDIT_ACCOUNT"],
430
+ extractLastData: (data) => ({
431
+ name: data.name,
432
+ governance: data.governance
433
+ })
434
+ }) === "skipped") await activateHederaAccount(account, workspace, existing.id);
435
+ return;
436
+ }
437
+ logStep(`Creating account "${account.name}"`);
438
+ const req = await createAndApproveRequest({
439
+ type: "CREATE_ACCOUNT",
440
+ data: accountData
441
+ }, [admin1, admin2], logger);
442
+ const createdAccount = await admin1.client.accounts.findById.query({ id: req.targetId });
443
+ existingAccounts.push(createdAccount);
444
+ if (account.governance.type === "TRADELINK") {
445
+ logStep(`Activating tradelink account "${account.name}"`);
446
+ const assetManagerId = assetManagerIdFromName(account.governance.assetManager);
447
+ const assetManager = existingTradelinkNetwork?.assetManagers.find((assetManager) => assetManager.id === assetManagerId);
448
+ (0, invariant.default)(assetManager, `Asset manager for account exists`);
449
+ const loggedAssetManagerOperators = await Promise.all(assetManager.groups.flatMap(({ quorum, userIds }) => userIds.slice(0, quorum).map((userId) => {
450
+ const deviceIndex = usersWithDeviceIndex.find((o) => o.user.id === userId)?.deviceIndex;
451
+ return workspaceEngine.withDeviceIndex(deviceIndex).login();
452
+ })));
453
+ await createAndApproveRequest({
454
+ type: "TRADELINK_ACTIVATE_ACCOUNT",
455
+ targetId: req.targetId,
456
+ data: null
457
+ }, loggedAssetManagerOperators, logger);
458
+ }
459
+ if (req.targetId) await activateHederaAccount(account, workspace, req.targetId);
460
+ logSubStep(`Account ${account.name} has been created`);
461
+ }
462
+ async function activateHederaAccount(account, workspace, accountId) {
463
+ if (account.currency === "hedera" && account.contractAddress === void 0 && workspace.hederaData && accountId) {
464
+ const salt = engine.__options.salt;
465
+ const hederaAccountData = workspace.hederaData[salt]?.find((h) => h.index === account.index && h.activate);
466
+ if (hederaAccountData) try {
467
+ await admin1.client.accounts.hedera.activateAccount.mutate({
468
+ id: accountId,
469
+ onchainId: hederaAccountData.onChainId
470
+ });
471
+ logSubStep(`Hedera account "${account.name}" has been activated`);
472
+ } catch (error) {
473
+ logger.warning(`Activation for "${account.name}" failed: ${error}`);
474
+ }
475
+ }
476
+ }
477
+ async function createUser(role, deviceIndex) {
478
+ const userEngine = workspaceEngine.withDeviceIndex(deviceIndex);
479
+ const deviceId = await userEngine.device.getDeviceUserId();
480
+ if (existingUsers.find((user) => user.deviceUserId === deviceId)) {
481
+ logger.info(`[SKIPPED] User with device index ${deviceIndex} already exists`);
482
+ return;
483
+ }
484
+ const name = `${role === "ADMIN" ? "Admin" : "Operator"} ${deviceIndex}`;
485
+ logStep(`Creating ${name}`);
486
+ logSubStep("Creating invitation...");
487
+ let registration = await admin1.client.userRegistrations.invite.mutate({
488
+ name,
489
+ role,
490
+ deviceUserId: deviceId,
491
+ psdModel: "STAX"
492
+ });
493
+ logSubStep("Completing registration...");
494
+ registration = await userEngine.register(registration);
495
+ logSubStep("Creating request...");
496
+ let req = await admin1.client.requests.create.mutate({ request: {
497
+ type: "CREATE_PSD_USER",
498
+ data: { registrationId: registration.id }
499
+ } });
500
+ req = await approveRequest(req, [admin1, admin2], logger);
501
+ logSubStep(`${name} has been created`);
502
+ const createdUser = await admin1.client.users.findById.query({ id: req.targetId });
503
+ existingUsers.push(createdUser);
504
+ usersWithDeviceIndex.push({
505
+ user: createdUser,
506
+ deviceIndex
507
+ });
508
+ }
509
+ async function createApiUser(apiUser) {
510
+ const pubKey = apiUser.pubKey ?? require_crypto.genKeys(apiUser.name).hexPubKey;
511
+ if (existingApiUsers.find((user) => user.pubKey === pubKey || user.name === apiUser.name)) {
512
+ logger.info(`[SKIPPED] API user already exists with name "${apiUser.name}" or public key "${pubKey}"`);
513
+ return;
514
+ }
515
+ logStep(`Creating API user "${apiUser.name}"...`);
516
+ logSubStep("Creating request...");
517
+ let req = await admin1.client.requests.create.mutate({ request: {
518
+ type: "CREATE_API_USER",
519
+ data: {
520
+ name: apiUser.name,
521
+ role: apiUser.role,
522
+ pubKey,
523
+ viewAll: apiUser.viewAll
524
+ }
525
+ } });
526
+ req = await approveRequest(req, [admin1, admin2], logger);
527
+ logSubStep(`API user "${apiUser.name}" has been created`);
528
+ logSubStep("Generating credentials...");
529
+ const credentials = await admin1.client.users.resetApiUserCredentials.mutate({ id: req.targetId });
530
+ logSubStep(`API user "${apiUser.name}" credentials have been generated: apiKeyId=${credentials.apiKeyId}, apiKeySecret=${credentials.apiKeySecret}`);
531
+ const createdUser = await admin1.client.users.findById.query({ id: req.targetId });
532
+ existingApiUsers.push(createdUser);
533
+ }
534
+ async function createGroup(group) {
535
+ const existing = existingGroups.find((g) => g.name === group.name);
536
+ const members = group.members.map(userIdFromDeviceIndexOrName);
537
+ const groupData = {
538
+ name: group.name,
539
+ description: "",
540
+ members
541
+ };
542
+ if (existing) {
543
+ await editDomainObjectIfNeeded({
544
+ entityType: "Group",
545
+ entityName: group.name,
546
+ existingId: existing.id,
547
+ editInput: {
548
+ type: "EDIT_GROUP",
549
+ targetId: existing.id,
550
+ data: groupData
551
+ },
552
+ editData: groupData,
553
+ requestTypes: ["CREATE_GROUP", "EDIT_GROUP"],
554
+ extractLastData: (data) => ({
555
+ ...data,
556
+ description: data.description ?? ""
557
+ })
558
+ });
559
+ return;
560
+ }
561
+ logStep(`Creating group ${group.name}...`);
562
+ logSubStep("Creating request...");
563
+ let request = await admin1.client.requests.create.mutate({ request: {
564
+ type: "CREATE_GROUP",
565
+ data: groupData
566
+ } });
567
+ request = await approveRequest(request, [admin1, admin2], logger);
568
+ logSubStep(`${group.name} has been created`);
569
+ const createdGroup = await admin1.client.groups.findById.query({ id: request.targetId });
570
+ existingGroups.push(createdGroup);
571
+ }
572
+ async function createPolicy(policy) {
573
+ const existing = existingPolicies.find((p) => p.name === policy.name);
574
+ const policyEditData = {
575
+ name: policy.name,
576
+ description: "",
577
+ govRules: policy.rules.map(govRuleFromManifest)
578
+ };
579
+ if (existing) {
580
+ await editDomainObjectIfNeeded({
581
+ entityType: "Policy",
582
+ entityName: policy.name,
583
+ existingId: existing.id,
584
+ editInput: {
585
+ type: "EDIT_POLICY",
586
+ targetId: existing.id,
587
+ data: policyEditData
588
+ },
589
+ editData: policyEditData,
590
+ requestTypes: ["CREATE_POLICY", "EDIT_POLICY"],
591
+ extractLastData: (data) => ({
592
+ name: data.name,
593
+ description: data.description ?? "",
594
+ govRules: data.govRules
595
+ })
596
+ });
597
+ return;
598
+ }
599
+ logStep(`Creating policy ${policy.name}...`);
600
+ logSubStep("Creating request...");
601
+ let request = await admin1.client.requests.create.mutate({ request: {
602
+ type: "CREATE_POLICY",
603
+ data: {
604
+ ...policyEditData,
605
+ currency: policy.currency
606
+ }
607
+ } });
608
+ request = await approveRequest(request, [admin1, admin2], logger);
609
+ logSubStep(`${policy.name} has been created`);
610
+ const createdPolicy = await admin1.client.policies.findById.query({ id: request.targetId });
611
+ existingPolicies.push(createdPolicy);
612
+ }
613
+ async function createWorkspaceRule(workspaceRule) {
614
+ const { permission, quorum, members } = workspaceRule;
615
+ logStep(`Editing workspace rule for ${permission}...`);
616
+ const userIds = members.map(userIdFromDeviceIndexOrName);
617
+ logSubStep("Creating request...");
618
+ await createAndApproveRequest({
619
+ type: "EDIT_WORKSPACE_RULE",
620
+ data: {
621
+ permission,
622
+ reviewConfig: [{
623
+ quorum,
624
+ userIds
625
+ }]
626
+ }
627
+ }, [admin1, admin2], logger);
628
+ logSubStep(`Workspace rule for "${permission}" has been edited`);
629
+ }
630
+ async function createEntity(entity) {
631
+ const existing = existingEntities.find((e) => e.name === entity.name);
632
+ const accountIds = (entity.accounts ?? []).map(accountIdFromName);
633
+ const memberIds = (entity.members ?? []).map(userIdFromUserName);
634
+ const entityEditData = {
635
+ name: entity.name,
636
+ accountIds,
637
+ memberIds
638
+ };
639
+ if (existing) {
640
+ await editDomainObjectIfNeeded({
641
+ entityType: "Entity",
642
+ entityName: entity.name,
643
+ existingId: existing.id,
644
+ editInput: {
645
+ type: "EDIT_ENTITY",
646
+ targetId: existing.id,
647
+ data: entityEditData
648
+ },
649
+ editData: entityEditData,
650
+ requestTypes: ["CREATE_ENTITY", "EDIT_ENTITY"],
651
+ extractLastData: (data) => ({
652
+ name: data.name,
653
+ accountIds: data.accountIds,
654
+ memberIds: data.memberIds
655
+ })
656
+ });
657
+ return;
658
+ }
659
+ logStep(`Creating entity "${entity.name}"...`);
660
+ const request = await createAndApproveRequest({
661
+ type: "CREATE_ENTITY",
662
+ data: entityEditData
663
+ }, [admin1, admin2], logger);
664
+ logSubStep(`Entity "${entity.name}" has been created`);
665
+ const createdEntity = await admin1.client.entities.findById.query({ id: request.targetId });
666
+ existingEntities.push(createdEntity);
667
+ }
668
+ async function createTradelink(tradelink) {
669
+ /* v8 ignore else -- @preserve */
670
+ if (tradelink.custodian) {
671
+ if (existingTradelinkNetwork === null) {
672
+ logStep("Creating custodian config...");
673
+ const { settlement, withdraw, arbitration } = tradelink.custodian;
674
+ const data = {
675
+ settlement: settlement.map(tradelinkReviewStepFromManifest),
676
+ withdraw: withdraw.map(tradelinkReviewStepFromManifest),
677
+ arbitration: arbitration.map(tradelinkReviewStepFromManifest)
678
+ };
679
+ logSubStep("Creating request...");
680
+ await approveRequest(await admin1.client.requests.create.mutate({ request: {
681
+ type: "TRADELINK_CREATE_CUSTODIAN",
682
+ data
683
+ } }), [admin1, admin2], logger);
684
+ logSubStep("Tradelink custodian config has been created");
685
+ existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
686
+ } else logger.info("[SKIPPED] Custodian config already exists");
687
+ const networkBlueprint = await admin1.client.tradelink.getNetworkBlueprint.query();
688
+ if (networkBlueprint !== null) {
689
+ /* v8 ignore else -- @preserve */
690
+ if (tradelink.exchanges !== void 0) await createTradelinkExchanges(networkBlueprint, tradelink.exchanges);
691
+ /* v8 ignore else -- @preserve */
692
+ if (tradelink.assetManagers !== void 0) await createTradelinkAssetManagers(networkBlueprint, tradelink.assetManagers);
693
+ } else logger.error("Will not create exchanges and asset managers because there is no network blueprint for current workspace");
694
+ }
695
+ }
696
+ async function createTradelinkExchanges(networkBlueprint, exchanges) {
697
+ (0, invariant.default)(existingTradelinkNetwork !== null, "Network should exist");
698
+ const blueprintExchanges = networkBlueprint.exchanges;
699
+ for (const exchange of exchanges) {
700
+ const blueprintExchange = blueprintExchanges.find(({ name }) => name === exchange.name);
701
+ (0, invariant.default)(blueprintExchange !== void 0, `Exchange ${exchange.name} does not exist in network blueprint`);
702
+ const exchangeId = blueprintExchange.tradelinkId;
703
+ logStep(`Creating exchange ${exchange.name}...`);
704
+ if (existingTradelinkNetwork.exchanges.find(({ tradelinkId }) => tradelinkId === exchangeId) !== void 0) {
705
+ logger.info(`[SKIPPED] Exchange "${exchange.name}" already exists`);
706
+ continue;
707
+ }
708
+ logSubStep("Creating request...");
709
+ await approveRequest(await admin1.client.requests.create.mutate({ request: {
710
+ type: "TRADELINK_CREATE_EXCHANGE",
711
+ data: {
712
+ tradelinkId: exchangeId,
713
+ groups: exchange.groups.map(tradelinkReviewStepFromManifest),
714
+ whitelist: exchange.whitelist
715
+ }
716
+ } }), [
717
+ admin1,
718
+ admin2,
719
+ ...await Promise.all(exchange.groups.flatMap(({ quorum, members }) => members.slice(0, quorum).map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login())))
720
+ ], logger);
721
+ existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
722
+ (0, invariant.default)(existingTradelinkNetwork !== null, "Tradelink network exists");
723
+ }
724
+ }
725
+ async function createTradelinkAssetManagers(networkBlueprint, assetManagers) {
726
+ (0, invariant.default)(existingTradelinkNetwork !== null, "Network should exist");
727
+ const blueprintAssetManagers = networkBlueprint.assetManagers;
728
+ for (const assetManager of assetManagers) {
729
+ const blueprintAssetManager = blueprintAssetManagers.find(({ name }) => name === assetManager.name);
730
+ (0, invariant.default)(blueprintAssetManager !== void 0, `AssetManager ${assetManager.name} does not exist in network blueprint`);
731
+ const assetManagerId = blueprintAssetManager.tradelinkId;
732
+ logStep(`Creating assetManager ${assetManager.name}...`);
733
+ if (existingTradelinkNetwork.assetManagers.find(({ tradelinkId }) => tradelinkId === assetManagerId) !== void 0) {
734
+ logger.info(`[SKIPPED] Asset manager "${assetManager.name}" already exists`);
735
+ continue;
736
+ }
737
+ logSubStep("Creating request...");
738
+ await approveRequest(await admin1.client.requests.create.mutate({ request: {
739
+ type: "TRADELINK_CREATE_ASSET_MANAGER",
740
+ data: {
741
+ tradelinkId: assetManagerId,
742
+ groups: assetManager.groups.map(tradelinkReviewStepFromManifest),
743
+ whitelist: assetManager.whitelist
744
+ }
745
+ } }), [
746
+ admin1,
747
+ admin2,
748
+ ...await Promise.all(assetManager.groups.flatMap(({ quorum, members }) => members.slice(0, quorum).map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login())))
749
+ ], logger);
750
+ existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();
751
+ (0, invariant.default)(existingTradelinkNetwork !== null, "Tradelink network exists");
752
+ }
753
+ }
754
+ async function resolveDevicesIndexes(users) {
755
+ return await users.reduce((acc, cur) => acc.then(async (acc) => {
756
+ acc.push(await withDeviceIndex(cur));
757
+ return acc;
758
+ }), Promise.resolve([]));
759
+ }
760
+ async function withDeviceIndex(user) {
761
+ (0, invariant.default)(user.deviceUserId, `User ${user.id} does not have any device user id`);
762
+ return {
763
+ user,
764
+ deviceIndex: await findDeviceIndex(user.deviceUserId)
765
+ };
766
+ }
767
+ function userIdFromDeviceIndex(deviceIndex) {
768
+ const corresponding = usersWithDeviceIndex.find((o) => o.deviceIndex === deviceIndex);
769
+ (0, invariant.default)(corresponding, `No user with device index ${deviceIndex}`);
770
+ return corresponding.user.id;
771
+ }
772
+ function userIdFromUserName(name) {
773
+ const user = existingApiUsers.find((u) => u.name === name);
774
+ (0, invariant.default)(user, `User ${name} not found`);
775
+ return user.id;
776
+ }
777
+ function userIdFromDeviceIndexOrName(identifier) {
778
+ if (typeof identifier === "number") return userIdFromDeviceIndex(identifier);
779
+ return userIdFromUserName(identifier);
780
+ }
781
+ function groupIdFromName(groupName) {
782
+ const group = existingGroups.find((g) => g.name === groupName);
783
+ (0, invariant.default)(group, `Group ${groupName} not found`);
784
+ return group.id;
785
+ }
786
+ function policyIdFromName(policyName) {
787
+ const policy = existingPolicies.find((g) => g.name === policyName);
788
+ (0, invariant.default)(policy, `Policy ${policyName} not found`);
789
+ return policy.id;
790
+ }
791
+ function whitelistIdFromName(whitelistName) {
792
+ const whitelist = existingWhitelists.find((w) => w.name === whitelistName);
793
+ (0, invariant.default)(whitelist, `Whitelist ${whitelistName} not found`);
794
+ return whitelist.id;
795
+ }
796
+ function accountIdFromName(accountName) {
797
+ const account = existingAccounts.find((a) => a.name === accountName);
798
+ (0, invariant.default)(account, `Account "${accountName}" not found`);
799
+ return account.id;
800
+ }
801
+ function assetManagerIdFromName(assetManagerName) {
802
+ const orgAssetManager = tradelinkOrgAssetManagersByName[assetManagerName];
803
+ (0, invariant.default)(orgAssetManager, `Can't find Tradelink organization asset manager ${assetManagerName}`);
804
+ const assetManager = existingTradelinkNetwork?.assetManagers.find((assetManager) => assetManager.tradelinkId === orgAssetManager.tradelinkId);
805
+ (0, invariant.default)(assetManager, `Can't find Tradelink assetManager ${assetManagerName}`);
806
+ return assetManager.id;
807
+ }
808
+ function exchangeIdFromName(exchangeName) {
809
+ const exchange = existingTradelinkNetwork?.exchanges.find((exchange) => {
810
+ const orgExchange = tradelinkOrgExchangesByName[exchangeName];
811
+ (0, invariant.default)(orgExchange, `Can't find Tradelink organization exchange ${exchange.tradelinkId}`);
812
+ return orgExchange.name === exchangeName;
813
+ });
814
+ (0, invariant.default)(exchange, `Can't find Tradelink exchange ${exchangeName}`);
815
+ return exchange.id;
816
+ }
817
+ function tradelinkReviewStepFromManifest({ members, quorum }) {
818
+ return {
819
+ userIds: members.map(userIdFromDeviceIndex),
820
+ quorum
821
+ };
822
+ }
954
823
  }
955
-
956
- // src/bake/recipe-workspace.ts
957
-
958
-
824
+ //#endregion
825
+ //#region src/bake/recipe-workspace.ts
959
826
  async function recipeWorkspace(options, logger) {
960
- const { engine, workspaceName } = options;
961
- const workspaceEngine = engine.withWorkspace(workspaceName);
962
- const findDeviceIndex = _chunkLH4QQXUHcjs.createDeviceIndexResolver.call(void 0, workspaceEngine);
963
- logger.info("Authenticating with admin...");
964
- const admin = await workspaceEngine.withDeviceIndex(4).login();
965
- logger.info("Fetching existing data...");
966
- const [
967
- existingUsers,
968
- existingGroups,
969
- existingWhitelists,
970
- publicPolicies,
971
- privatePolicies,
972
- existingAccounts,
973
- existingEntities,
974
- existingWorkspaceRules
975
- ] = await Promise.all([
976
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.users.list.query, { status: "ACTIVE" }),
977
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.groups.list.query, { status: "ACTIVE" }),
978
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.whitelists.list.query, { status: "ACTIVE" }),
979
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.policies.list.query, { isPrivate: false }),
980
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.policies.list.query, { isPrivate: true }),
981
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.accounts.list.query, { status: "ACTIVE" }),
982
- _chunkLH4QQXUHcjs.fetchAll.call(void 0, admin.client.entities.list.query, { status: "ACTIVE" }),
983
- admin.client.governance.listWorkspaceRules.query()
984
- ]);
985
- const existingPolicies = [...publicPolicies, ...privatePolicies];
986
- const existingPsdUsers = existingUsers.filter((user) => user.deviceType === "PSD");
987
- const existingApiUsers = existingUsers.filter((user) => user.deviceType === "API");
988
- logger.info("Resolving device indexes...");
989
- const psdUsersWithIndex = await resolveDevicesIndexes(existingPsdUsers);
990
- logger.info("Reading users...");
991
- const adminIndexes = psdUsersWithIndex.filter((u) => u.user.role === "ADMIN").map((u) => u.deviceIndex);
992
- const operatorIndexes = psdUsersWithIndex.filter((u) => u.user.role === "OPERATOR").map((u) => u.deviceIndex);
993
- const apiUsers = existingApiUsers.map((user) => {
994
- const role = _tspattern.match.call(void 0, user.role).with("ADMIN", "OPERATOR", (role2) => role2).with("READ_ONLY_API_KEY", (role2) => {
995
- throw new Error(`Unexpected API user role "${role2}" for user ${user.name}`);
996
- }).exhaustive();
997
- return {
998
- name: user.name,
999
- role,
1000
- pubKey: user.pubKey,
1001
- viewAll: user.legacyViewAll
1002
- };
1003
- });
1004
- logger.info("Reading groups...");
1005
- const groups = existingGroups.map((group) => ({
1006
- name: group.name,
1007
- members: group.members.map((member) => resolveUserIdentifier(member.id))
1008
- }));
1009
- logger.info("Reading whitelists...");
1010
- const whitelists = existingWhitelists.map((whitelist) => ({
1011
- name: whitelist.name,
1012
- description: _nullishCoalesce(whitelist.description, () => ( void 0)),
1013
- type: "TRANSACTION",
1014
- addresses: whitelist.addresses.map((addr) => ({
1015
- name: addr.name,
1016
- currency: addr.currency,
1017
- address: addr.address,
1018
- ..._optionalChain([addr, 'access', _28 => _28.destinationTags, 'optionalAccess', _29 => _29.length]) ? { destinationTags: addr.destinationTags } : {}
1019
- }))
1020
- }));
1021
- logger.info("Reading policies...");
1022
- const policies = publicPolicies.map((policy) => ({
1023
- name: policy.name,
1024
- currency: policy.currency,
1025
- rules: policy.rules.map(govRuleToManifest)
1026
- }));
1027
- logger.info("Reading accounts...");
1028
- const accounts = existingAccounts.map((account) => {
1029
- const governance = _tspattern.match.call(void 0, account.governance).with({ type: "CLASSIC" }, (gov) => {
1030
- const policy = existingPolicies.find((p) => p.id === gov.policyId);
1031
- _invariant2.default.call(void 0, policy, `Policy ${gov.policyId} not found for account ${account.name}`);
1032
- return policy.isPrivate ? {
1033
- type: "CLASSIC",
1034
- rules: policy.rules.map(govRuleToManifest)
1035
- } : {
1036
- type: "POLICY",
1037
- policy: policy.name
1038
- };
1039
- }).with({ type: "RAW_SIGNING" }, (gov) => {
1040
- const policy = existingPolicies.find((p) => p.id === gov.policyId);
1041
- _invariant2.default.call(void 0, policy, `Policy ${gov.policyId} not found for account ${account.name}`);
1042
- return {
1043
- type: "RAW_SIGNING",
1044
- rules: policy.rules.map((rule) => ({
1045
- type: "SIGN_DIGESTS",
1046
- steps: rule.reviewSteps.map((step) => {
1047
- _invariant2.default.call(void 0, "userIds" in step, "RAW_SIGNING rules only support user steps");
1048
- return {
1049
- quorum: step.quorum,
1050
- members: step.userIds.map(resolveUserToDeviceIndexOrName)
1051
- };
1052
- })
1053
- }))
1054
- };
1055
- }).with({ type: "TRADELINK" }, (gov) => ({
1056
- type: "TRADELINK",
1057
- assetManager: resolveAssetManagerName(gov.assetManagerId),
1058
- exchanges: gov.exchangeConfigs.map((exchangeConfig) => ({
1059
- name: resolveExchangeName(exchangeConfig.exchangeId),
1060
- ...exchangeConfig.repledgeAuthorized ? { repledgeAuthorized: true } : {},
1061
- ...exchangeConfig.needsAssetManagerApprovalForSettlements ? { needsAssetManagerApprovalForSettlements: true } : {}
1062
- }))
1063
- })).exhaustive();
1064
- return {
1065
- name: account.name,
1066
- currency: account.currency,
1067
- index: account.index,
1068
- ...account.contractAddress ? { contractAddress: account.contractAddress } : {},
1069
- ...account.tokenIdentifier ? { tokenIdentifier: account.tokenIdentifier } : {},
1070
- governance
1071
- };
1072
- });
1073
- logger.info("Reading entities...");
1074
- const entities = existingEntities.map((entity) => ({
1075
- name: entity.name,
1076
- ...entity.accountIds.length > 0 ? { accounts: entity.accountIds.map(accountNameFromId) } : {},
1077
- ...entity.memberIds.length > 0 ? { members: entity.memberIds.map(userNameFromId) } : {}
1078
- }));
1079
- logger.info("Reading workspace rules...");
1080
- const workspaceRules = existingWorkspaceRules.results.filter((rule) => rule.permission !== "ROOT").map((rule) => {
1081
- _invariant2.default.call(void 0,
1082
- rule.reviewSteps.length === 1,
1083
- "Only one review step supported for workspace rules in manifest"
1084
- );
1085
- const step = rule.reviewSteps[0];
1086
- const quorum = step.quorum;
1087
- _invariant2.default.call(void 0, rule.permission !== "ROOT", "filtered out");
1088
- return {
1089
- permission: rule.permission,
1090
- quorum,
1091
- members: step.userIds.map(resolveUserToDeviceIndexOrName)
1092
- };
1093
- });
1094
- const workspace = {
1095
- users: {
1096
- ...adminIndexes.length > 0 ? { admins: adminIndexes } : {},
1097
- ...operatorIndexes.length > 0 ? { operators: operatorIndexes } : {},
1098
- ...apiUsers.length > 0 ? { api: apiUsers } : {}
1099
- },
1100
- ...groups.length > 0 ? { groups } : {},
1101
- ...whitelists.length > 0 ? { whitelists } : {},
1102
- ...policies.length > 0 ? { policies } : {},
1103
- ...accounts.length > 0 ? { accounts } : {},
1104
- ...entities.length > 0 ? { entities } : {},
1105
- ...workspaceRules.length > 0 ? { workspaceRules } : {}
1106
- };
1107
- logger.info("Recipe completed");
1108
- return workspace;
1109
- async function resolveDevicesIndexes(users) {
1110
- const result = [];
1111
- for (const user of users) {
1112
- _invariant2.default.call(void 0, user.deviceUserId, `User ${user.id} does not have any device user id`);
1113
- const deviceIndex = await findDeviceIndex(user.deviceUserId);
1114
- result.push({ user, deviceIndex });
1115
- }
1116
- return result;
1117
- }
1118
- function resolveUserIdentifier(userId) {
1119
- const psdUser = psdUsersWithIndex.find((u) => u.user.id === userId);
1120
- if (psdUser) return psdUser.deviceIndex;
1121
- const apiUser = existingApiUsers.find((u) => u.id === userId);
1122
- if (apiUser) return apiUser.name;
1123
- throw new Error(`User ${userId} not found`);
1124
- }
1125
- function resolveUserToDeviceIndexOrName(userId) {
1126
- return resolveUserIdentifier(userId);
1127
- }
1128
- function validateGovernanceRuleType(value) {
1129
- _invariant2.default.call(void 0,
1130
- ["SEND", "STAKE", "DEPLOY_CONTRACT", "EXECUTE_CONTRACT", "SIGN_MESSAGE", "RECEIVE"].includes(
1131
- value
1132
- ),
1133
- "Unexpected governance rule type: " + value
1134
- );
1135
- return value;
1136
- }
1137
- function govRuleToManifest(rule) {
1138
- const operationType = validateGovernanceRuleType(rule.operationType);
1139
- const threshold = rule.threshold !== void 0 && (rule.threshold.min !== null || rule.threshold.max !== null) ? { threshold: { min: rule.threshold.min, max: rule.threshold.max } } : {};
1140
- return {
1141
- type: operationType,
1142
- steps: rule.reviewSteps.map((step) => {
1143
- if ("groupId" in step) {
1144
- const group = existingGroups.find((g) => g.id === step.groupId);
1145
- _invariant2.default.call(void 0, group, `Group ${step.groupId} not found`);
1146
- return { quorum: step.quorum, group: group.name };
1147
- }
1148
- return {
1149
- quorum: step.quorum,
1150
- members: step.userIds.map(resolveUserToDeviceIndexOrName)
1151
- };
1152
- }),
1153
- ...threshold,
1154
- ...rule.whitelistIds && rule.whitelistIds.length > 0 ? { whitelistNames: rule.whitelistIds.map(whitelistNameFromId) } : {}
1155
- };
1156
- }
1157
- function whitelistNameFromId(whitelistId) {
1158
- const whitelist = existingWhitelists.find((w) => w.id === whitelistId);
1159
- _invariant2.default.call(void 0, whitelist, `Whitelist ${whitelistId} not found`);
1160
- return whitelist.name;
1161
- }
1162
- function accountNameFromId(accountId) {
1163
- const account = existingAccounts.find((a) => a.id === accountId);
1164
- _invariant2.default.call(void 0, account, `Account ${accountId} not found`);
1165
- return account.name;
1166
- }
1167
- function userNameFromId(userId) {
1168
- const user = existingApiUsers.find((u) => u.id === userId);
1169
- _invariant2.default.call(void 0, user, `API user ${userId} not found`);
1170
- return user.name;
1171
- }
1172
- function resolveAssetManagerName(assetManagerId) {
1173
- return assetManagerId;
1174
- }
1175
- function resolveExchangeName(exchangeId) {
1176
- return exchangeId;
1177
- }
827
+ const { engine, workspaceName } = options;
828
+ const workspaceEngine = engine.withWorkspace(workspaceName);
829
+ const findDeviceIndex = require_utils.createDeviceIndexResolver(workspaceEngine);
830
+ logger.info("Authenticating with admin...");
831
+ const admin = await workspaceEngine.withDeviceIndex(4).login();
832
+ logger.info("Fetching existing data...");
833
+ const [existingUsers, existingGroups, existingWhitelists, publicPolicies, privatePolicies, existingAccounts, existingEntities, existingWorkspaceRules] = await Promise.all([
834
+ require_utils.fetchAll(admin.client.users.list.query, { status: "ACTIVE" }),
835
+ require_utils.fetchAll(admin.client.groups.list.query, { status: "ACTIVE" }),
836
+ require_utils.fetchAll(admin.client.whitelists.list.query, { status: "ACTIVE" }),
837
+ require_utils.fetchAll(admin.client.policies.list.query, { isPrivate: false }),
838
+ require_utils.fetchAll(admin.client.policies.list.query, { isPrivate: true }),
839
+ require_utils.fetchAll(admin.client.accounts.list.query, { status: "ACTIVE" }),
840
+ require_utils.fetchAll(admin.client.entities.list.query, { status: "ACTIVE" }),
841
+ admin.client.governance.listWorkspaceRules.query()
842
+ ]);
843
+ const existingPolicies = [...publicPolicies, ...privatePolicies];
844
+ const existingPsdUsers = existingUsers.filter((user) => user.deviceType === "PSD");
845
+ const existingApiUsers = existingUsers.filter((user) => user.deviceType === "API");
846
+ logger.info("Resolving device indexes...");
847
+ const psdUsersWithIndex = await resolveDevicesIndexes(existingPsdUsers);
848
+ logger.info("Reading users...");
849
+ const adminIndexes = psdUsersWithIndex.filter((u) => u.user.role === "ADMIN").map((u) => u.deviceIndex);
850
+ const operatorIndexes = psdUsersWithIndex.filter((u) => u.user.role === "OPERATOR").map((u) => u.deviceIndex);
851
+ const apiUsers = existingApiUsers.map((user) => {
852
+ const role = (0, ts_pattern.match)(user.role).with("ADMIN", "OPERATOR", (role) => role).with("READ_ONLY_API_KEY", (role) => {
853
+ throw new Error(`Unexpected API user role "${role}" for user ${user.name}`);
854
+ }).exhaustive();
855
+ return {
856
+ name: user.name,
857
+ role,
858
+ pubKey: user.pubKey,
859
+ viewAll: user.legacyViewAll
860
+ };
861
+ });
862
+ logger.info("Reading groups...");
863
+ const groups = existingGroups.map((group) => ({
864
+ name: group.name,
865
+ members: group.members.map((member) => resolveUserIdentifier(member.id))
866
+ }));
867
+ logger.info("Reading whitelists...");
868
+ const whitelists = existingWhitelists.map((whitelist) => ({
869
+ name: whitelist.name,
870
+ description: whitelist.description ?? void 0,
871
+ type: "TRANSACTION",
872
+ addresses: whitelist.addresses.map((addr) => ({
873
+ name: addr.name,
874
+ currency: addr.currency,
875
+ address: addr.address,
876
+ ...addr.destinationTags?.length ? { destinationTags: addr.destinationTags } : {}
877
+ }))
878
+ }));
879
+ logger.info("Reading policies...");
880
+ const policies = publicPolicies.map((policy) => ({
881
+ name: policy.name,
882
+ currency: policy.currency,
883
+ rules: policy.rules.map(govRuleToManifest)
884
+ }));
885
+ logger.info("Reading accounts...");
886
+ const accounts = existingAccounts.map((account) => {
887
+ const governance = (0, ts_pattern.match)(account.governance).with({ type: "CLASSIC" }, (gov) => {
888
+ const policy = existingPolicies.find((p) => p.id === gov.policyId);
889
+ (0, invariant.default)(policy, `Policy ${gov.policyId} not found for account ${account.name}`);
890
+ return policy.isPrivate ? {
891
+ type: "CLASSIC",
892
+ rules: policy.rules.map(govRuleToManifest)
893
+ } : {
894
+ type: "POLICY",
895
+ policy: policy.name
896
+ };
897
+ }).with({ type: "RAW_SIGNING" }, (gov) => {
898
+ const policy = existingPolicies.find((p) => p.id === gov.policyId);
899
+ (0, invariant.default)(policy, `Policy ${gov.policyId} not found for account ${account.name}`);
900
+ return {
901
+ type: "RAW_SIGNING",
902
+ rules: policy.rules.map((rule) => ({
903
+ type: "SIGN_DIGESTS",
904
+ steps: rule.reviewSteps.map((step) => {
905
+ (0, invariant.default)("userIds" in step, "RAW_SIGNING rules only support user steps");
906
+ return {
907
+ quorum: step.quorum,
908
+ members: step.userIds.map(resolveUserToDeviceIndexOrName)
909
+ };
910
+ })
911
+ }))
912
+ };
913
+ }).with({ type: "TRADELINK" }, (gov) => ({
914
+ type: "TRADELINK",
915
+ assetManager: resolveAssetManagerName(gov.assetManagerId),
916
+ exchanges: gov.exchangeConfigs.map((exchangeConfig) => ({
917
+ name: resolveExchangeName(exchangeConfig.exchangeId),
918
+ ...exchangeConfig.repledgeAuthorized ? { repledgeAuthorized: true } : {},
919
+ ...exchangeConfig.needsAssetManagerApprovalForSettlements ? { needsAssetManagerApprovalForSettlements: true } : {}
920
+ }))
921
+ })).exhaustive();
922
+ return {
923
+ name: account.name,
924
+ currency: account.currency,
925
+ index: account.index,
926
+ ...account.contractAddress ? { contractAddress: account.contractAddress } : {},
927
+ ...account.tokenIdentifier ? { tokenIdentifier: account.tokenIdentifier } : {},
928
+ governance
929
+ };
930
+ });
931
+ logger.info("Reading entities...");
932
+ const entities = existingEntities.map((entity) => ({
933
+ name: entity.name,
934
+ ...entity.accountIds.length > 0 ? { accounts: entity.accountIds.map(accountNameFromId) } : {},
935
+ ...entity.memberIds.length > 0 ? { members: entity.memberIds.map(userNameFromId) } : {}
936
+ }));
937
+ logger.info("Reading workspace rules...");
938
+ const workspaceRules = existingWorkspaceRules.results.filter((rule) => rule.permission !== "ROOT").map((rule) => {
939
+ (0, invariant.default)(rule.reviewSteps.length === 1, "Only one review step supported for workspace rules in manifest");
940
+ const step = rule.reviewSteps[0];
941
+ const quorum = step.quorum;
942
+ (0, invariant.default)(rule.permission !== "ROOT", "filtered out");
943
+ return {
944
+ permission: rule.permission,
945
+ quorum,
946
+ members: step.userIds.map(resolveUserToDeviceIndexOrName)
947
+ };
948
+ });
949
+ const workspace = {
950
+ users: {
951
+ ...adminIndexes.length > 0 ? { admins: adminIndexes } : {},
952
+ ...operatorIndexes.length > 0 ? { operators: operatorIndexes } : {},
953
+ ...apiUsers.length > 0 ? { api: apiUsers } : {}
954
+ },
955
+ ...groups.length > 0 ? { groups } : {},
956
+ ...whitelists.length > 0 ? { whitelists } : {},
957
+ ...policies.length > 0 ? { policies } : {},
958
+ ...accounts.length > 0 ? { accounts } : {},
959
+ ...entities.length > 0 ? { entities } : {},
960
+ ...workspaceRules.length > 0 ? { workspaceRules } : {}
961
+ };
962
+ logger.info("Recipe completed");
963
+ return workspace;
964
+ async function resolveDevicesIndexes(users) {
965
+ const result = [];
966
+ for (const user of users) {
967
+ (0, invariant.default)(user.deviceUserId, `User ${user.id} does not have any device user id`);
968
+ const deviceIndex = await findDeviceIndex(user.deviceUserId);
969
+ result.push({
970
+ user,
971
+ deviceIndex
972
+ });
973
+ }
974
+ return result;
975
+ }
976
+ function resolveUserIdentifier(userId) {
977
+ const psdUser = psdUsersWithIndex.find((u) => u.user.id === userId);
978
+ if (psdUser) return psdUser.deviceIndex;
979
+ const apiUser = existingApiUsers.find((u) => u.id === userId);
980
+ if (apiUser) return apiUser.name;
981
+ throw new Error(`User ${userId} not found`);
982
+ }
983
+ function resolveUserToDeviceIndexOrName(userId) {
984
+ return resolveUserIdentifier(userId);
985
+ }
986
+ function validateGovernanceRuleType(value) {
987
+ (0, invariant.default)([
988
+ "SEND",
989
+ "STAKE",
990
+ "DEPLOY_CONTRACT",
991
+ "EXECUTE_CONTRACT",
992
+ "SIGN_MESSAGE",
993
+ "RECEIVE"
994
+ ].includes(value), "Unexpected governance rule type: " + value);
995
+ return value;
996
+ }
997
+ function govRuleToManifest(rule) {
998
+ const operationType = validateGovernanceRuleType(rule.operationType);
999
+ const threshold = rule.threshold !== void 0 && (rule.threshold.min !== null || rule.threshold.max !== null) ? { threshold: {
1000
+ min: rule.threshold.min,
1001
+ max: rule.threshold.max
1002
+ } } : {};
1003
+ return {
1004
+ type: operationType,
1005
+ steps: rule.reviewSteps.map((step) => {
1006
+ if ("groupId" in step) {
1007
+ const group = existingGroups.find((g) => g.id === step.groupId);
1008
+ (0, invariant.default)(group, `Group ${step.groupId} not found`);
1009
+ return {
1010
+ quorum: step.quorum,
1011
+ group: group.name
1012
+ };
1013
+ }
1014
+ return {
1015
+ quorum: step.quorum,
1016
+ members: step.userIds.map(resolveUserToDeviceIndexOrName)
1017
+ };
1018
+ }),
1019
+ ...threshold,
1020
+ ...rule.whitelistIds && rule.whitelistIds.length > 0 ? { whitelistNames: rule.whitelistIds.map(whitelistNameFromId) } : {}
1021
+ };
1022
+ }
1023
+ function whitelistNameFromId(whitelistId) {
1024
+ const whitelist = existingWhitelists.find((w) => w.id === whitelistId);
1025
+ (0, invariant.default)(whitelist, `Whitelist ${whitelistId} not found`);
1026
+ return whitelist.name;
1027
+ }
1028
+ function accountNameFromId(accountId) {
1029
+ const account = existingAccounts.find((a) => a.id === accountId);
1030
+ (0, invariant.default)(account, `Account ${accountId} not found`);
1031
+ return account.name;
1032
+ }
1033
+ function userNameFromId(userId) {
1034
+ const user = existingApiUsers.find((u) => u.id === userId);
1035
+ (0, invariant.default)(user, `API user ${userId} not found`);
1036
+ return user.name;
1037
+ }
1038
+ function resolveAssetManagerName(assetManagerId) {
1039
+ return assetManagerId;
1040
+ }
1041
+ function resolveExchangeName(exchangeId) {
1042
+ return exchangeId;
1043
+ }
1178
1044
  }
1179
-
1180
- // src/bake/recipe.ts
1045
+ //#endregion
1046
+ //#region src/bake/recipe.ts
1181
1047
  async function recipeManifest(options, logger) {
1182
- const workspace = await recipeWorkspace(options, logger);
1183
- return {
1184
- manifestVersion: 2,
1185
- workspace
1186
- };
1048
+ return {
1049
+ manifestVersion: 2,
1050
+ workspace: await recipeWorkspace(options, logger)
1051
+ };
1187
1052
  }
1188
-
1189
- // src/bake/types.ts
1190
- var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod);
1191
- var zManifestUser = _zod2.default.number().meta({ description: "User device index" });
1192
- var zManifestUserName = _zod2.default.string().meta({ description: "User name" });
1193
- var zManifestApiUser = _zod2.default.object({
1194
- name: _zod2.default.string().meta({ description: "API user name" }),
1195
- role: _zod2.default.enum(["ADMIN", "OPERATOR"]).meta({ description: "API user role" }).default("OPERATOR"),
1196
- pubKey: _zod2.default.string().meta({
1197
- description: "API user public key. If not provided, one will be generated using the name as entropy"
1198
- }).optional(),
1199
- viewAll: _zod2.default.boolean().meta({ description: "Whether the API user can view all accounts" })
1053
+ //#endregion
1054
+ //#region src/bake/types.ts
1055
+ const zManifestUser = zod.default.number().meta({ description: "User device index" });
1056
+ const zManifestUserName = zod.default.string().meta({ description: "User name" });
1057
+ const zManifestApiUser = zod.default.object({
1058
+ name: zod.default.string().meta({ description: "API user name" }),
1059
+ role: zod.default.enum(["ADMIN", "OPERATOR"]).meta({ description: "API user role" }).default("OPERATOR"),
1060
+ pubKey: zod.default.string().meta({ description: "API user public key. If not provided, one will be generated using the name as entropy" }).optional(),
1061
+ viewAll: zod.default.boolean().meta({ description: "Whether the API user can view all accounts" })
1200
1062
  });
1201
- var zManifestGroup = _zod2.default.object({
1202
- name: _zod2.default.string().meta({ description: "Group name" }),
1203
- members: _zod2.default.array(_zod2.default.union([zManifestUser, zManifestUserName])).meta({ description: "Group members" })
1063
+ const zManifestGroup = zod.default.object({
1064
+ name: zod.default.string().meta({ description: "Group name" }),
1065
+ members: zod.default.array(zod.default.union([zManifestUser, zManifestUserName])).meta({ description: "Group members" })
1204
1066
  }).strict().meta({ description: "Operators group" });
1205
- var zManifestWhitelistAddress = _zod2.default.object({
1206
- name: _zod2.default.string().meta({ description: "Whitelist address name" }),
1207
- currency: _zod2.default.string().meta({ description: "Whitelist address currency" }),
1208
- address: _zod2.default.string().meta({ description: "Whitelist address" }),
1209
- destinationTags: _zod2.default.array(_zod2.default.string()).optional().meta({ description: "List of destination tags (applicable for Ripple currency)" })
1067
+ const zManifestWhitelistAddress = zod.default.object({
1068
+ name: zod.default.string().meta({ description: "Whitelist address name" }),
1069
+ currency: zod.default.string().meta({ description: "Whitelist address currency" }),
1070
+ address: zod.default.string().meta({ description: "Whitelist address" }),
1071
+ destinationTags: zod.default.array(zod.default.string()).optional().meta({ description: "List of destination tags (applicable for Ripple currency)" })
1210
1072
  }).strict();
1211
- var zManifestWhitelist = _zod2.default.object({
1212
- name: _zod2.default.string().meta({ description: "Whitelist name" }),
1213
- description: _zod2.default.string().optional().meta({ description: "Whitelist description" }),
1214
- type: _zod2.default.enum(["TRANSACTION", "SMART_CONTRACT"]).optional().default("TRANSACTION").meta({ description: "Whitelist type" }),
1215
- addresses: _zod2.default.array(zManifestWhitelistAddress).meta({ description: "Whitelist addresses" })
1073
+ const zManifestWhitelist = zod.default.object({
1074
+ name: zod.default.string().meta({ description: "Whitelist name" }),
1075
+ description: zod.default.string().optional().meta({ description: "Whitelist description" }),
1076
+ type: zod.default.enum(["TRANSACTION", "SMART_CONTRACT"]).optional().default("TRANSACTION").meta({ description: "Whitelist type" }),
1077
+ addresses: zod.default.array(zManifestWhitelistAddress).meta({ description: "Whitelist addresses" })
1216
1078
  }).strict().meta({ description: "Whitelist" });
1217
- var zManifestGovernanceStepWithUsers = _zod2.default.object({
1218
- quorum: _zod2.default.number(),
1219
- members: _zod2.default.array(_zod2.default.union([zManifestUser, zManifestUserName]))
1079
+ const zManifestGovernanceStepWithUsers = zod.default.object({
1080
+ quorum: zod.default.number(),
1081
+ members: zod.default.array(zod.default.union([zManifestUser, zManifestUserName]))
1220
1082
  }).strict();
1221
- var zManifestGovernanceStepWithGroup = _zod2.default.object({
1222
- quorum: _zod2.default.number(),
1223
- group: _zod2.default.string()
1083
+ const zManifestGovernanceStepWithGroup = zod.default.object({
1084
+ quorum: zod.default.number(),
1085
+ group: zod.default.string()
1224
1086
  }).strict();
1225
- var zManifestGovernanceStep = _zod2.default.union([
1226
- zManifestGovernanceStepWithUsers,
1227
- zManifestGovernanceStepWithGroup
1228
- ]);
1229
- var zManifestGovernanceRule = _zod2.default.object({
1230
- // TODO see if there is a way to import this from `api` package
1231
- // (the challenge there is that enums are not transpiled)
1232
- type: _zod2.default.enum([
1233
- "SEND",
1234
- "STAKE",
1235
- "DEPLOY_CONTRACT",
1236
- "EXECUTE_CONTRACT",
1237
- "SIGN_MESSAGE",
1238
- "RECEIVE"
1239
- ]),
1240
- steps: _zod2.default.array(zManifestGovernanceStep).min(1),
1241
- threshold: _zod2.default.object({
1242
- min: _zod2.default.string().nullable(),
1243
- max: _zod2.default.string().nullable()
1244
- }).optional(),
1245
- whitelistNames: _zod2.default.array(_zod2.default.string()).optional()
1087
+ const zManifestGovernanceStep = zod.default.union([zManifestGovernanceStepWithUsers, zManifestGovernanceStepWithGroup]);
1088
+ const zManifestGovernanceRule = zod.default.object({
1089
+ type: zod.default.enum([
1090
+ "SEND",
1091
+ "STAKE",
1092
+ "DEPLOY_CONTRACT",
1093
+ "EXECUTE_CONTRACT",
1094
+ "SIGN_MESSAGE",
1095
+ "RECEIVE"
1096
+ ]),
1097
+ steps: zod.default.array(zManifestGovernanceStep).min(1),
1098
+ threshold: zod.default.object({
1099
+ min: zod.default.string().nullable(),
1100
+ max: zod.default.string().nullable()
1101
+ }).optional(),
1102
+ whitelistNames: zod.default.array(zod.default.string()).optional()
1246
1103
  }).strict();
1247
- var zManifestPolicy = _zod2.default.object({
1248
- name: _zod2.default.string(),
1249
- currency: _zod2.default.string().nullable(),
1250
- rules: _zod2.default.array(zManifestGovernanceRule)
1104
+ const zManifestPolicy = zod.default.object({
1105
+ name: zod.default.string(),
1106
+ currency: zod.default.string().nullable(),
1107
+ rules: zod.default.array(zManifestGovernanceRule)
1251
1108
  }).strict();
1252
- var zManifestClassicAccountGovernance = _zod2.default.object({
1253
- type: _zod2.default.literal("CLASSIC"),
1254
- rules: _zod2.default.array(zManifestGovernanceRule)
1109
+ const zManifestClassicAccountGovernance = zod.default.object({
1110
+ type: zod.default.literal("CLASSIC"),
1111
+ rules: zod.default.array(zManifestGovernanceRule)
1255
1112
  }).strict();
1256
- var zManifestClassicAccountGovernanceWithPolicy = _zod2.default.object({
1257
- type: _zod2.default.literal("POLICY"),
1258
- policy: _zod2.default.string()
1113
+ const zManifestClassicAccountGovernanceWithPolicy = zod.default.object({
1114
+ type: zod.default.literal("POLICY"),
1115
+ policy: zod.default.string()
1259
1116
  }).strict();
1260
- var zManifestTradelinkExchangeConfig = _zod2.default.object({
1261
- name: _zod2.default.string().meta({ description: "Exchange name" }),
1262
- repledgeAuthorized: _zod2.default.boolean().optional().meta({ description: "Whether repledge is authorized" }),
1263
- needsAssetManagerApprovalForSettlements: _zod2.default.boolean().optional().meta({ description: "Whether asset manager pre approval is needed" })
1117
+ const zManifestTradelinkExchangeConfig = zod.default.object({
1118
+ name: zod.default.string().meta({ description: "Exchange name" }),
1119
+ repledgeAuthorized: zod.default.boolean().optional().meta({ description: "Whether repledge is authorized" }),
1120
+ needsAssetManagerApprovalForSettlements: zod.default.boolean().optional().meta({ description: "Whether asset manager pre approval is needed" })
1264
1121
  }).strict();
1265
- var zManifestTradelinkAccountGovernance = _zod2.default.object({
1266
- type: _zod2.default.literal("TRADELINK"),
1267
- assetManager: _zod2.default.string().meta({ description: "Asset manager name" }),
1268
- exchanges: _zod2.default.array(zManifestTradelinkExchangeConfig)
1122
+ const zManifestTradelinkAccountGovernance = zod.default.object({
1123
+ type: zod.default.literal("TRADELINK"),
1124
+ assetManager: zod.default.string().meta({ description: "Asset manager name" }),
1125
+ exchanges: zod.default.array(zManifestTradelinkExchangeConfig)
1269
1126
  }).strict();
1270
- var zManifestRawSigningGovernanceRule = _zod2.default.object({
1271
- type: _zod2.default.literal("SIGN_DIGESTS"),
1272
- steps: _zod2.default.array(zManifestGovernanceStepWithUsers).min(1)
1127
+ const zManifestRawSigningGovernanceRule = zod.default.object({
1128
+ type: zod.default.literal("SIGN_DIGESTS"),
1129
+ steps: zod.default.array(zManifestGovernanceStepWithUsers).min(1)
1273
1130
  }).strict();
1274
- var zManifestRawSigningAccountGovernance = _zod2.default.object({
1275
- type: _zod2.default.literal("RAW_SIGNING"),
1276
- rules: _zod2.default.array(zManifestRawSigningGovernanceRule)
1131
+ const zManifestRawSigningAccountGovernance = zod.default.object({
1132
+ type: zod.default.literal("RAW_SIGNING"),
1133
+ rules: zod.default.array(zManifestRawSigningGovernanceRule)
1277
1134
  }).strict();
1278
- var zManifestAccountGovernance = _zod2.default.discriminatedUnion("type", [
1279
- zManifestClassicAccountGovernance,
1280
- zManifestTradelinkAccountGovernance,
1281
- zManifestRawSigningAccountGovernance,
1282
- zManifestClassicAccountGovernanceWithPolicy
1135
+ const zManifestAccountGovernance = zod.default.discriminatedUnion("type", [
1136
+ zManifestClassicAccountGovernance,
1137
+ zManifestTradelinkAccountGovernance,
1138
+ zManifestRawSigningAccountGovernance,
1139
+ zManifestClassicAccountGovernanceWithPolicy
1283
1140
  ]);
1284
- var zManifestAccount = _zod2.default.object({
1285
- name: _zod2.default.string(),
1286
- currency: _zod2.default.string(),
1287
- index: _zod2.default.number().nonnegative(),
1288
- contractAddress: _zod2.default.string().optional(),
1289
- tokenIdentifier: _zod2.default.string().optional(),
1290
- governance: zManifestAccountGovernance
1141
+ const zManifestAccount = zod.default.object({
1142
+ name: zod.default.string(),
1143
+ currency: zod.default.string(),
1144
+ index: zod.default.number().nonnegative(),
1145
+ contractAddress: zod.default.string().optional(),
1146
+ tokenIdentifier: zod.default.string().optional(),
1147
+ governance: zManifestAccountGovernance
1291
1148
  }).strict();
1292
- var zManifestEntity = _zod2.default.object({
1293
- name: _zod2.default.string().min(1).max(19).meta({ description: "Entity name" }),
1294
- accounts: _zod2.default.array(_zod2.default.string()).optional().meta({ description: "Account names to include in this entity" }),
1295
- members: _zod2.default.array(_zod2.default.string()).optional().meta({ description: "API operator names to include in this entity" })
1149
+ const zManifestEntity = zod.default.object({
1150
+ name: zod.default.string().min(1).max(19).meta({ description: "Entity name" }),
1151
+ accounts: zod.default.array(zod.default.string()).optional().meta({ description: "Account names to include in this entity" }),
1152
+ members: zod.default.array(zod.default.string()).optional().meta({ description: "API operator names to include in this entity" })
1296
1153
  }).strict().meta({ description: "Entity" });
1297
- var zManifestHederaData = _zod2.default.object({
1298
- index: _zod2.default.number(),
1299
- onChainId: _zod2.default.string(),
1300
- activate: _zod2.default.boolean().default(true)
1154
+ const zManifestHederaData = zod.default.object({
1155
+ index: zod.default.number(),
1156
+ onChainId: zod.default.string(),
1157
+ activate: zod.default.boolean().default(true)
1301
1158
  }).strict();
1302
- var zManifestPledgeAdjustment = _zod2.default.object({
1303
- account: _zod2.default.string(),
1304
- exchange: _zod2.default.string(),
1305
- amount: _zod2.default.string()
1159
+ const zManifestPledgeAdjustment = zod.default.object({
1160
+ account: zod.default.string(),
1161
+ exchange: zod.default.string(),
1162
+ amount: zod.default.string()
1306
1163
  }).strict();
1307
- var zManifestTradelinkGroup = _zod2.default.object({
1308
- members: _zod2.default.array(zManifestUser),
1309
- quorum: _zod2.default.number()
1164
+ const zManifestTradelinkGroup = zod.default.object({
1165
+ members: zod.default.array(zManifestUser),
1166
+ quorum: zod.default.number()
1310
1167
  }).strict().meta({ description: "Tradelink group" });
1311
- var zManifestTradelinkGroups = _zod2.default.array(zManifestTradelinkGroup);
1312
- var zManifestTradelinkWhitelistAddress = _zod2.default.object({
1313
- name: _zod2.default.string().min(1),
1314
- currency: _zod2.default.string().min(1),
1315
- address: _zod2.default.string().min(1)
1168
+ const zManifestTradelinkGroups = zod.default.array(zManifestTradelinkGroup);
1169
+ const zManifestTradelinkWhitelistAddress = zod.default.object({
1170
+ name: zod.default.string().min(1),
1171
+ currency: zod.default.string().min(1),
1172
+ address: zod.default.string().min(1)
1316
1173
  }).strict().meta({ description: "Tradelink whitelist address" });
1317
- var zManifestTradelinkWhitelist = _zod2.default.array(zManifestTradelinkWhitelistAddress).meta({ description: "Tradelink whitelist" });
1318
- var zManifestTradelinkEntity = _zod2.default.object({
1319
- name: _zod2.default.string(),
1320
- groups: zManifestTradelinkGroups,
1321
- whitelist: zManifestTradelinkWhitelist
1174
+ const zManifestTradelinkWhitelist = zod.default.array(zManifestTradelinkWhitelistAddress).meta({ description: "Tradelink whitelist" });
1175
+ const zManifestTradelinkEntity = zod.default.object({
1176
+ name: zod.default.string(),
1177
+ groups: zManifestTradelinkGroups,
1178
+ whitelist: zManifestTradelinkWhitelist
1322
1179
  }).strict();
1323
- var zManifestTradelinkCustodian = _zod2.default.object({
1324
- settlement: zManifestTradelinkGroups,
1325
- withdraw: zManifestTradelinkGroups,
1326
- arbitration: zManifestTradelinkGroups
1180
+ const zManifestTradelinkCustodian = zod.default.object({
1181
+ settlement: zManifestTradelinkGroups,
1182
+ withdraw: zManifestTradelinkGroups,
1183
+ arbitration: zManifestTradelinkGroups
1327
1184
  }).strict();
1328
- var zManifestTradelinkNetworkBlueprint = _zod2.default.object({
1329
- custodian: _zod2.default.string(),
1330
- exchanges: _zod2.default.array(_zod2.default.string()),
1331
- assetManagers: _zod2.default.array(_zod2.default.string())
1185
+ const zManifestTradelinkNetworkBlueprint = zod.default.object({
1186
+ custodian: zod.default.string(),
1187
+ exchanges: zod.default.array(zod.default.string()),
1188
+ assetManagers: zod.default.array(zod.default.string())
1332
1189
  }).strict();
1333
- var zManifestTradelinkNetwork = _zod2.default.object({
1334
- networkBlueprint: zManifestTradelinkNetworkBlueprint.optional(),
1335
- custodian: zManifestTradelinkCustodian.optional(),
1336
- exchanges: _zod2.default.array(zManifestTradelinkEntity).optional(),
1337
- assetManagers: _zod2.default.array(zManifestTradelinkEntity).optional()
1190
+ const zManifestTradelinkNetwork = zod.default.object({
1191
+ networkBlueprint: zManifestTradelinkNetworkBlueprint.optional(),
1192
+ custodian: zManifestTradelinkCustodian.optional(),
1193
+ exchanges: zod.default.array(zManifestTradelinkEntity).optional(),
1194
+ assetManagers: zod.default.array(zManifestTradelinkEntity).optional()
1338
1195
  }).strict().meta({ description: "Tradelink network configuration" });
1339
- var zManifestWorkspaceRule = _zod2.default.object({
1340
- permission: _zod2.default.enum(["CREATE_ACCOUNT_WITH_POLICY"]),
1341
- quorum: _zod2.default.number().min(1),
1342
- members: _zod2.default.array(_zod2.default.union([zManifestUser, zManifestUserName]))
1196
+ const zManifestWorkspaceRule = zod.default.object({
1197
+ permission: zod.default.enum(["CREATE_ACCOUNT_WITH_POLICY"]),
1198
+ quorum: zod.default.number().min(1),
1199
+ members: zod.default.array(zod.default.union([zManifestUser, zManifestUserName]))
1343
1200
  }).strict().meta({ description: "Workspace rule for granting permissions" });
1344
- var zManifestWorkspace = _zod2.default.object({
1345
- tradelink: zManifestTradelinkNetwork.optional(),
1346
- users: _zod2.default.object({
1347
- admins: _zod2.default.array(zManifestUser).optional(),
1348
- operators: _zod2.default.array(zManifestUser).optional(),
1349
- api: _zod2.default.array(zManifestApiUser).optional()
1350
- }).optional(),
1351
- groups: _zod2.default.array(zManifestGroup).optional(),
1352
- whitelists: _zod2.default.array(zManifestWhitelist).optional(),
1353
- policies: _zod2.default.array(zManifestPolicy).optional(),
1354
- accounts: _zod2.default.array(zManifestAccount).optional(),
1355
- entities: _zod2.default.array(zManifestEntity).optional(),
1356
- hederaData: _zod2.default.record(_zod2.default.string(), _zod2.default.array(zManifestHederaData)).optional(),
1357
- pledges: _zod2.default.array(zManifestPledgeAdjustment).optional(),
1358
- workspaceRules: _zod2.default.array(zManifestWorkspaceRule).optional()
1201
+ const zManifestWorkspace = zod.default.object({
1202
+ tradelink: zManifestTradelinkNetwork.optional(),
1203
+ users: zod.default.object({
1204
+ admins: zod.default.array(zManifestUser).optional(),
1205
+ operators: zod.default.array(zManifestUser).optional(),
1206
+ api: zod.default.array(zManifestApiUser).optional()
1207
+ }).optional(),
1208
+ groups: zod.default.array(zManifestGroup).optional(),
1209
+ whitelists: zod.default.array(zManifestWhitelist).optional(),
1210
+ policies: zod.default.array(zManifestPolicy).optional(),
1211
+ accounts: zod.default.array(zManifestAccount).optional(),
1212
+ entities: zod.default.array(zManifestEntity).optional(),
1213
+ hederaData: zod.default.record(zod.default.string(), zod.default.array(zManifestHederaData)).optional(),
1214
+ pledges: zod.default.array(zManifestPledgeAdjustment).optional(),
1215
+ workspaceRules: zod.default.array(zManifestWorkspaceRule).optional()
1359
1216
  }).strict().meta({ description: "Workspace configuration" });
1360
- var zManifestTradelinkOrgEntity = _zod2.default.object({
1361
- name: _zod2.default.string(),
1362
- code: _zod2.default.string(),
1363
- logo: _zod2.default.string()
1217
+ const zManifestTradelinkOrgEntity = zod.default.object({
1218
+ name: zod.default.string(),
1219
+ code: zod.default.string(),
1220
+ logo: zod.default.string()
1364
1221
  }).strict().meta({ description: "Tradelink organization entity" });
1365
- var zManifestTradelinkOrg = _zod2.default.object({
1366
- exchanges: _zod2.default.array(zManifestTradelinkOrgEntity).optional(),
1367
- assetManagers: _zod2.default.array(zManifestTradelinkOrgEntity).optional(),
1368
- custodians: _zod2.default.array(zManifestTradelinkOrgEntity).optional()
1222
+ const zManifestTradelinkOrg = zod.default.object({
1223
+ exchanges: zod.default.array(zManifestTradelinkOrgEntity).optional(),
1224
+ assetManagers: zod.default.array(zManifestTradelinkOrgEntity).optional(),
1225
+ custodians: zod.default.array(zManifestTradelinkOrgEntity).optional()
1369
1226
  }).strict().meta({ description: "Tradelink organization configuration" });
1370
- var zManifest = _zod2.default.object({
1371
- manifestVersion: _zod2.default.literal(2),
1372
- tradelink: zManifestTradelinkOrg.optional(),
1373
- workspace: zManifestWorkspace.optional()
1227
+ const zManifest = zod.default.object({
1228
+ manifestVersion: zod.default.literal(2),
1229
+ tradelink: zManifestTradelinkOrg.optional(),
1230
+ workspace: zManifestWorkspace.optional()
1374
1231
  }).strict();
1375
-
1376
- // src/bake/index.ts
1232
+ //#endregion
1233
+ //#region src/bake/index.ts
1377
1234
  async function bakeManifest(options, logger) {
1378
- const {
1379
- engine,
1380
- workspaceName,
1381
- rootAuthToken,
1382
- manifest: { tradelink, workspace }
1383
- } = options;
1384
- if (tradelink) {
1385
- _invariant2.default.call(void 0, rootAuthToken, `rootAuthToken is required to create Tradelink org entities`);
1386
- await bakeTradelinkOrganization(
1387
- {
1388
- engine,
1389
- tradelink,
1390
- rootAuthToken,
1391
- ..._optionalChain([workspace, 'optionalAccess', _30 => _30.tradelink, 'optionalAccess', _31 => _31.networkBlueprint]) && workspaceName ? { networkBlueprint: { blueprint: workspace.tradelink.networkBlueprint, workspaceName } } : {}
1392
- },
1393
- logger
1394
- );
1395
- }
1396
- if (workspace) {
1397
- _invariant2.default.call(void 0, workspaceName, `Can't bake workspace without specifying a workspace name`);
1398
- await bakeWorkspace({ engine, workspace, workspaceName }, logger);
1399
- if (workspace.pledges) {
1400
- const engineWithWorkspace = engine.withWorkspace(workspaceName);
1401
- for (const pledgeAdjustment of workspace.pledges) {
1402
- await bakePledgeAdjustment({ engine: engineWithWorkspace, pledgeAdjustment }, logger);
1403
- }
1404
- }
1405
- }
1406
- logger.info("Successfully baked");
1235
+ const { engine, workspaceName, rootAuthToken, manifest: { tradelink, workspace } } = options;
1236
+ if (tradelink) {
1237
+ (0, invariant.default)(rootAuthToken, `rootAuthToken is required to create Tradelink org entities`);
1238
+ await bakeTradelinkOrganization({
1239
+ engine,
1240
+ tradelink,
1241
+ rootAuthToken,
1242
+ ...workspace?.tradelink?.networkBlueprint && workspaceName ? { networkBlueprint: {
1243
+ blueprint: workspace.tradelink.networkBlueprint,
1244
+ workspaceName
1245
+ } } : {}
1246
+ }, logger);
1247
+ }
1248
+ if (workspace) {
1249
+ (0, invariant.default)(workspaceName, `Can't bake workspace without specifying a workspace name`);
1250
+ await bakeWorkspace({
1251
+ engine,
1252
+ workspace,
1253
+ workspaceName
1254
+ }, logger);
1255
+ if (workspace.pledges) {
1256
+ const engineWithWorkspace = engine.withWorkspace(workspaceName);
1257
+ for (const pledgeAdjustment of workspace.pledges) await bakePledgeAdjustment({
1258
+ engine: engineWithWorkspace,
1259
+ pledgeAdjustment
1260
+ }, logger);
1261
+ }
1262
+ }
1263
+ logger.info("Successfully baked");
1407
1264
  }
1265
+ //#endregion
1266
+ exports.bakeManifest = bakeManifest;
1267
+ exports.bakePledgeAdjustment = bakePledgeAdjustment;
1268
+ exports.createAndApproveRequest = createAndApproveRequest;
1269
+ exports.recipeManifest = recipeManifest;
1270
+ exports.zManifest = zManifest;
1271
+ exports.zManifestPolicy = zManifestPolicy;
1408
1272
 
1409
-
1410
-
1411
-
1412
-
1413
-
1414
-
1415
- exports.bakeManifest = bakeManifest; exports.bakePledgeAdjustment = bakePledgeAdjustment; exports.createAndApproveRequest = createAndApproveRequest; exports.recipeManifest = recipeManifest; exports.zManifest = zManifest; exports.zManifestPolicy = zManifestPolicy;
1416
- /* v8 ignore else - TODO bake empty tradelink org -- @preserve */
1417
- /* v8 ignore else -- @preserve */
1418
1273
  //# sourceMappingURL=bake.cjs.map