@ledgerhq/vault-common 2.1.1 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +19 -59
- package/CHANGELOG.md +12 -0
- package/lib/{chunk-GAKIXPAF.js → chunk-65DEEXP4.js} +1 -1
- package/lib/chunk-65DEEXP4.js.map +1 -0
- package/lib/createHSMBridge.d.ts +1 -1
- package/lib/{index-Cm_O9VIx.d.ts → index-BpLhb-bQ.d.ts} +11 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/recipeManifest.d.ts +1 -1
- package/lib/reviewAPIRequest.d.ts +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.js +2 -2
- package/lib/utils.d.ts +1 -1
- package/package.json +8 -9
- package/tsup.config.ts +1 -1
- package/lib/chunk-54MXA3ZY.mjs +0 -14
- package/lib/chunk-54MXA3ZY.mjs.map +0 -1
- package/lib/chunk-6TT6A6YA.mjs +0 -1176
- package/lib/chunk-6TT6A6YA.mjs.map +0 -1
- package/lib/chunk-GAKIXPAF.js.map +0 -1
- package/lib/chunk-HU7O2ZFW.mjs +0 -249
- package/lib/chunk-HU7O2ZFW.mjs.map +0 -1
- package/lib/chunk-J5LGTIGS.mjs +0 -10
- package/lib/chunk-J5LGTIGS.mjs.map +0 -1
- package/lib/chunk-MNUHUKY3.mjs +0 -503
- package/lib/chunk-MNUHUKY3.mjs.map +0 -1
- package/lib/chunk-QNNV5GBH.mjs +0 -1261
- package/lib/chunk-QNNV5GBH.mjs.map +0 -1
- package/lib/chunk-VOB7PA3G.mjs +0 -97
- package/lib/chunk-VOB7PA3G.mjs.map +0 -1
- package/lib/chunk-ZJCMYPBL.mjs +0 -83
- package/lib/chunk-ZJCMYPBL.mjs.map +0 -1
- package/lib/createHSMBridge.d.mts +0 -27
- package/lib/createHSMBridge.mjs +0 -10
- package/lib/createHSMBridge.mjs.map +0 -1
- package/lib/crypto/utils.d.mts +0 -14
- package/lib/crypto/utils.mjs +0 -12
- package/lib/crypto/utils.mjs.map +0 -1
- package/lib/index-Cm_O9VIx.d.mts +0 -2010
- package/lib/index.d.mts +0 -161
- package/lib/index.mjs +0 -3252
- package/lib/index.mjs.map +0 -1
- package/lib/recipeManifest.d.mts +0 -6
- package/lib/recipeManifest.mjs +0 -11
- package/lib/recipeManifest.mjs.map +0 -1
- package/lib/reviewAPIRequest.d.mts +0 -20
- package/lib/reviewAPIRequest.mjs +0 -11
- package/lib/reviewAPIRequest.mjs.map +0 -1
- package/lib/types/index.d.mts +0 -6
- package/lib/types/index.mjs +0 -10
- package/lib/types/index.mjs.map +0 -1
- package/lib/utils.d.mts +0 -29
- package/lib/utils.mjs +0 -38
- package/lib/utils.mjs.map +0 -1
package/lib/chunk-6TT6A6YA.mjs
DELETED
|
@@ -1,1176 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createNetwork
|
|
3
|
-
} from "./chunk-VOB7PA3G.mjs";
|
|
4
|
-
import {
|
|
5
|
-
getAccountTypeByCurrency,
|
|
6
|
-
getAccountUnit,
|
|
7
|
-
getCurrencyUnit,
|
|
8
|
-
getWorkspaceFromGate,
|
|
9
|
-
serializeUnitValue,
|
|
10
|
-
unwrapConnection,
|
|
11
|
-
wait
|
|
12
|
-
} from "./chunk-QNNV5GBH.mjs";
|
|
13
|
-
import {
|
|
14
|
-
decodeData,
|
|
15
|
-
genKeys,
|
|
16
|
-
sign
|
|
17
|
-
} from "./chunk-HU7O2ZFW.mjs";
|
|
18
|
-
|
|
19
|
-
// src/reviewAPIRequest.ts
|
|
20
|
-
import { SILENT_LOGGER as SILENT_LOGGER2 } from "@ledgerhq/vault-utils";
|
|
21
|
-
|
|
22
|
-
// src/apiUser/index.ts
|
|
23
|
-
import chalk from "chalk";
|
|
24
|
-
|
|
25
|
-
// src/createDefaultRunner.ts
|
|
26
|
-
import { SILENT_LOGGER } from "@ledgerhq/vault-utils";
|
|
27
|
-
import invariant2 from "invariant";
|
|
28
|
-
import { v4 as uuidv4 } from "uuid";
|
|
29
|
-
|
|
30
|
-
// src/prepareRequest.ts
|
|
31
|
-
import invariant from "invariant";
|
|
32
|
-
var prepareUserCreation = ({ data }) => {
|
|
33
|
-
const { role, name, userID } = data;
|
|
34
|
-
return {
|
|
35
|
-
type: role === "operator" ? "CREATE_OPERATOR" : "CREATE_ADMIN",
|
|
36
|
-
username: name,
|
|
37
|
-
user_id: userID
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
var prepareAPIUserCreation = ({ data }) => {
|
|
41
|
-
const { publicKey, name, role } = data;
|
|
42
|
-
return {
|
|
43
|
-
type: "CREATE_API_USER",
|
|
44
|
-
user_data: {
|
|
45
|
-
username: name,
|
|
46
|
-
public_key: publicKey,
|
|
47
|
-
role
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
var prepareAPIUserAccessCreation = ({ data }) => {
|
|
52
|
-
const { name } = data;
|
|
53
|
-
return {
|
|
54
|
-
type: "CREATE_API_USER_ACCESS",
|
|
55
|
-
user_data: {
|
|
56
|
-
username: name
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
var prepareAccountCreation = ({ type, data }) => {
|
|
61
|
-
const {
|
|
62
|
-
account,
|
|
63
|
-
usersByDevice,
|
|
64
|
-
whitelistsIDsByName,
|
|
65
|
-
groupsIDsByName,
|
|
66
|
-
accountsByName,
|
|
67
|
-
hsmCustodiansIDsByName,
|
|
68
|
-
hsmAssetManagersIDsByName,
|
|
69
|
-
hsmExchangesIDsByName,
|
|
70
|
-
usersByName,
|
|
71
|
-
tokens
|
|
72
|
-
} = data;
|
|
73
|
-
const allAccounts = Object.keys(accountsByName).map((key) => accountsByName[key]);
|
|
74
|
-
const token = "contractAddress" in account ? tokens.find((t) => t.contract_address === account.contractAddress) : null;
|
|
75
|
-
if ("contractAddress" in account && !token) {
|
|
76
|
-
throw new Error(`Can't find token with contract address ${account.contractAddress}`);
|
|
77
|
-
}
|
|
78
|
-
let account_type = null;
|
|
79
|
-
if (token?.family === "ethereum") {
|
|
80
|
-
if (token.parent_currency === "bsc") {
|
|
81
|
-
account_type = "Bep20";
|
|
82
|
-
} else {
|
|
83
|
-
account_type = "Erc20";
|
|
84
|
-
}
|
|
85
|
-
} else if ("accountType" in account) {
|
|
86
|
-
account_type = account.accountType;
|
|
87
|
-
} else if ("currency" in account) {
|
|
88
|
-
account_type = getAccountTypeByCurrency(account.currency);
|
|
89
|
-
}
|
|
90
|
-
if (!account_type) {
|
|
91
|
-
throw new Error(`Can't determine account type`);
|
|
92
|
-
}
|
|
93
|
-
const unit = getAccountUnit(account, tokens);
|
|
94
|
-
const governance_rules = "tradelink_data" in account && !!account.tradelink_data ? null : transformManifestRules({
|
|
95
|
-
rules: account.rules,
|
|
96
|
-
unit,
|
|
97
|
-
usersByDevice,
|
|
98
|
-
usersByName,
|
|
99
|
-
whitelistsIDsByName,
|
|
100
|
-
groupsIDsByName,
|
|
101
|
-
// VG-18120 accounts *must* enforce having a tx-filter rule of type SEND for rules that are
|
|
102
|
-
// not SCI and not "any-other-type-of-filter".
|
|
103
|
-
enforceSendTxFilter: true
|
|
104
|
-
});
|
|
105
|
-
const account_data = {
|
|
106
|
-
name: account.name,
|
|
107
|
-
...governance_rules ? { governance_rules } : {}
|
|
108
|
-
};
|
|
109
|
-
if ("readOnly" in account && !!account.readOnly) {
|
|
110
|
-
Object.assign(account_data, {
|
|
111
|
-
xpub: account.readOnly.xpub,
|
|
112
|
-
extended_public_key: {
|
|
113
|
-
public_key: account.readOnly.publicKey,
|
|
114
|
-
chain_code: account.readOnly.chainCode
|
|
115
|
-
},
|
|
116
|
-
address: account.readOnly.address
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
if ("contractAddress" in account && token) {
|
|
120
|
-
const currencyName = token.parent_currency;
|
|
121
|
-
const parentAccountName = account.parentAccount;
|
|
122
|
-
const parent_account = parentAccountName ? (() => {
|
|
123
|
-
let parentAccountID = null;
|
|
124
|
-
const existingParentAccount = allAccounts.find(
|
|
125
|
-
(a) => !!a && a.name === parentAccountName
|
|
126
|
-
);
|
|
127
|
-
if (existingParentAccount) {
|
|
128
|
-
parentAccountID = existingParentAccount.id;
|
|
129
|
-
} else {
|
|
130
|
-
const createdParentAccount = accountsByName[parentAccountName];
|
|
131
|
-
if (!createdParentAccount) {
|
|
132
|
-
return { name: parentAccountName };
|
|
133
|
-
}
|
|
134
|
-
parentAccountID = createdParentAccount.id;
|
|
135
|
-
}
|
|
136
|
-
return { id: parentAccountID };
|
|
137
|
-
})() : null;
|
|
138
|
-
if (process.env.LEGACY_TOKENS) {
|
|
139
|
-
const erc20 = {
|
|
140
|
-
ticker: token.ticker,
|
|
141
|
-
address: token.contract_address,
|
|
142
|
-
decimals: token.units[0].magnitude,
|
|
143
|
-
hsm_account_parameters: token.__legacy_hsm_account_parameters,
|
|
144
|
-
hsm_signature: token.__legacy_hsm_signature
|
|
145
|
-
};
|
|
146
|
-
Object.assign(account_data, { erc20 });
|
|
147
|
-
} else {
|
|
148
|
-
Object.assign(account_data, {
|
|
149
|
-
token: { type: token.token_type, address: token.contract_address }
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
Object.assign(account_data, {
|
|
153
|
-
currency: { name: currencyName },
|
|
154
|
-
parent_account
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
if ("currency" in account) {
|
|
158
|
-
Object.assign(account_data, {
|
|
159
|
-
currency: {
|
|
160
|
-
name: account.currency
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
if ("derivationMode" in account) {
|
|
164
|
-
Object.assign(account_data, {
|
|
165
|
-
derivation_mode: account.derivationMode
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
let tradelinkData;
|
|
170
|
-
if ("tradelink_data" in account && !!account.tradelink_data) {
|
|
171
|
-
const custodianID = hsmCustodiansIDsByName[account.tradelink_data.custodian.name];
|
|
172
|
-
if (typeof custodianID === "undefined")
|
|
173
|
-
throw new Error(`Invalid custodian name ${account.tradelink_data.custodian.name}`);
|
|
174
|
-
const assetManagerID = hsmAssetManagersIDsByName[account.tradelink_data.asset_manager.name];
|
|
175
|
-
if (typeof assetManagerID === "undefined")
|
|
176
|
-
throw new Error(`Invalid asset manager name ${account.tradelink_data.asset_manager.name}`);
|
|
177
|
-
tradelinkData = {
|
|
178
|
-
currency: account.tradelink_data.currency,
|
|
179
|
-
custodian: custodianID,
|
|
180
|
-
asset_manager: assetManagerID,
|
|
181
|
-
exchanges: account.tradelink_data.exchanges.map((exchange) => {
|
|
182
|
-
const exchangeID = hsmExchangesIDsByName[exchange.name];
|
|
183
|
-
if (typeof exchangeID === "undefined")
|
|
184
|
-
throw new Error(`Invalid exchange name ${exchange.name}`);
|
|
185
|
-
return {
|
|
186
|
-
auto_repledge_enabled: exchange.auto_repledge_enabled,
|
|
187
|
-
requires_pre_approval: exchange.requires_pre_approval,
|
|
188
|
-
id: exchangeID
|
|
189
|
-
};
|
|
190
|
-
})
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
return {
|
|
194
|
-
type,
|
|
195
|
-
...account.index !== void 0 ? { index: account.index } : {},
|
|
196
|
-
...tradelinkData ? { tradelink_data: tradelinkData } : {},
|
|
197
|
-
account_type,
|
|
198
|
-
account_data
|
|
199
|
-
};
|
|
200
|
-
};
|
|
201
|
-
var prepareAccountEdition = ({ type, data }) => {
|
|
202
|
-
const {
|
|
203
|
-
account,
|
|
204
|
-
existingAccount,
|
|
205
|
-
usersByDevice,
|
|
206
|
-
usersByName,
|
|
207
|
-
whitelistsIDsByName,
|
|
208
|
-
groupsIDsByName,
|
|
209
|
-
tokens
|
|
210
|
-
} = data;
|
|
211
|
-
if (!existingAccount) {
|
|
212
|
-
throw new Error("No existingAccount given");
|
|
213
|
-
}
|
|
214
|
-
const unit = getAccountUnit(account, tokens);
|
|
215
|
-
const governance_rules = transformManifestRules({
|
|
216
|
-
rules: account.rules,
|
|
217
|
-
unit,
|
|
218
|
-
usersByDevice,
|
|
219
|
-
usersByName,
|
|
220
|
-
whitelistsIDsByName,
|
|
221
|
-
groupsIDsByName,
|
|
222
|
-
enforceSendTxFilter: true
|
|
223
|
-
});
|
|
224
|
-
const edit_data = {
|
|
225
|
-
name: account.name,
|
|
226
|
-
governance_rules
|
|
227
|
-
};
|
|
228
|
-
if ("contractAddress" in account) {
|
|
229
|
-
const token = tokens.find((t) => t.contract_address === account.contractAddress);
|
|
230
|
-
if (!token) {
|
|
231
|
-
throw new Error(`Can't find token with contract address ${account.contractAddress}`);
|
|
232
|
-
}
|
|
233
|
-
if (process.env.LEGACY_TOKENS) {
|
|
234
|
-
const erc20 = {
|
|
235
|
-
ticker: token.ticker,
|
|
236
|
-
address: token.contract_address,
|
|
237
|
-
decimals: token.units[0].magnitude,
|
|
238
|
-
hsm_account_parameters: token.__legacy_hsm_account_parameters,
|
|
239
|
-
hsm_signature: token.__legacy_hsm_signature
|
|
240
|
-
};
|
|
241
|
-
Object.assign(edit_data, { erc20 });
|
|
242
|
-
} else {
|
|
243
|
-
Object.assign(edit_data, {
|
|
244
|
-
token: { type: "erc20", address: token.contract_address }
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return {
|
|
249
|
-
type,
|
|
250
|
-
account_id: existingAccount.id,
|
|
251
|
-
edit_data
|
|
252
|
-
};
|
|
253
|
-
};
|
|
254
|
-
var serializeGroupMembers = (groupUsers, { usersByDevice, usersByName }) => {
|
|
255
|
-
return groupUsers.map((device) => {
|
|
256
|
-
if (typeof device === "number") {
|
|
257
|
-
const u = usersByDevice[device];
|
|
258
|
-
if (!u) throw new Error(`Invalid device ${device}`);
|
|
259
|
-
return u.id;
|
|
260
|
-
} else {
|
|
261
|
-
const u = usersByName[device];
|
|
262
|
-
if (!u) throw new Error(`Invalid user name ${device}`);
|
|
263
|
-
return u.id;
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
var prepareGroupCreation = ({ type, data }) => {
|
|
268
|
-
const { group } = data;
|
|
269
|
-
const members = serializeGroupMembers(group.users, data);
|
|
270
|
-
return {
|
|
271
|
-
type,
|
|
272
|
-
name: group.name,
|
|
273
|
-
description: group.description || "",
|
|
274
|
-
members
|
|
275
|
-
};
|
|
276
|
-
};
|
|
277
|
-
var prepareGroupEdition = ({ type, data }) => {
|
|
278
|
-
const { group, existingGroup } = data;
|
|
279
|
-
if (!existingGroup) {
|
|
280
|
-
throw new Error("No existingGroup given");
|
|
281
|
-
}
|
|
282
|
-
const members = serializeGroupMembers(group.users, data);
|
|
283
|
-
return {
|
|
284
|
-
type,
|
|
285
|
-
name: group.name,
|
|
286
|
-
description: group.description || "",
|
|
287
|
-
group_id: existingGroup.id,
|
|
288
|
-
edit_data: {
|
|
289
|
-
name: group.name,
|
|
290
|
-
members
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
};
|
|
294
|
-
var serializeVaultEntityAccounts = (vaultEntityAccounts, { accountsByName }) => {
|
|
295
|
-
return vaultEntityAccounts.map((accountName) => {
|
|
296
|
-
const a = accountsByName[accountName];
|
|
297
|
-
if (!a) throw new Error(`Invalid account ${accountName}`);
|
|
298
|
-
return a.id;
|
|
299
|
-
});
|
|
300
|
-
};
|
|
301
|
-
var prepareVaultEntityCreation = ({ type, data }) => {
|
|
302
|
-
const {
|
|
303
|
-
vaultEntity: { name, accounts }
|
|
304
|
-
} = data;
|
|
305
|
-
return {
|
|
306
|
-
type,
|
|
307
|
-
name,
|
|
308
|
-
accounts: accounts ? serializeVaultEntityAccounts(accounts, data) : []
|
|
309
|
-
};
|
|
310
|
-
};
|
|
311
|
-
var prepareVaultEntityEdition = ({ type, data }) => {
|
|
312
|
-
const { vaultEntity, existingVaultEntity } = data;
|
|
313
|
-
if (!existingVaultEntity) {
|
|
314
|
-
throw new Error("No existing VaultEntity given");
|
|
315
|
-
}
|
|
316
|
-
return {
|
|
317
|
-
type,
|
|
318
|
-
entity_id: existingVaultEntity.id,
|
|
319
|
-
edit_data: {
|
|
320
|
-
name: vaultEntity.name,
|
|
321
|
-
accounts: vaultEntity.accounts ? serializeVaultEntityAccounts(vaultEntity.accounts, data) : []
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
};
|
|
325
|
-
var prepareWhitelistCreation = ({ type, data }) => {
|
|
326
|
-
const { whitelist } = data;
|
|
327
|
-
const addresses = whitelist.addresses.map((a, i) => ({
|
|
328
|
-
...a,
|
|
329
|
-
name: a.name || `${a.currency}-${i + 1}`
|
|
330
|
-
}));
|
|
331
|
-
return {
|
|
332
|
-
type,
|
|
333
|
-
name: whitelist.name,
|
|
334
|
-
description: whitelist.description || "",
|
|
335
|
-
addresses,
|
|
336
|
-
...whitelist.type && { whitelist_type: whitelist.type }
|
|
337
|
-
};
|
|
338
|
-
};
|
|
339
|
-
var prepareWhitelistEdition = ({ type, data }) => {
|
|
340
|
-
const { whitelist, existingWhitelist } = data;
|
|
341
|
-
if (!existingWhitelist) {
|
|
342
|
-
throw new Error(`No existingWhitelist given`);
|
|
343
|
-
}
|
|
344
|
-
const addresses = whitelist.addresses.map((a, i) => ({
|
|
345
|
-
...a,
|
|
346
|
-
name: a.name || `${a.currency}-${i + 1}`
|
|
347
|
-
}));
|
|
348
|
-
return {
|
|
349
|
-
type,
|
|
350
|
-
name: whitelist.name,
|
|
351
|
-
description: "",
|
|
352
|
-
whitelist_id: existingWhitelist.id,
|
|
353
|
-
edit_data: {
|
|
354
|
-
name: whitelist.name,
|
|
355
|
-
addresses
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
};
|
|
359
|
-
var prepareExchangeCreation = ({ type, data }) => {
|
|
360
|
-
const { exchange, usersByDevice, usersByName, groupsIDsByName } = data;
|
|
361
|
-
const governance_rules = exchange.rules ? transformManifestRules({ rules: exchange.rules, usersByDevice, usersByName, groupsIDsByName }) : [];
|
|
362
|
-
return {
|
|
363
|
-
type,
|
|
364
|
-
exchange_data: {
|
|
365
|
-
name: exchange.name,
|
|
366
|
-
governance_rules,
|
|
367
|
-
platform: exchange.platform,
|
|
368
|
-
credentials: {
|
|
369
|
-
apiKey: exchange.configuration.apiKey,
|
|
370
|
-
secret: exchange.configuration.apiSecret
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
};
|
|
375
|
-
var preparePolicyCreation = ({ type, data }) => {
|
|
376
|
-
const { policy, usersByName, usersByDevice, groupsIDsByName, whitelistsIDsByName } = data;
|
|
377
|
-
const unit = getCurrencyUnit(data.policy.currency);
|
|
378
|
-
const governance_rules = transformManifestRules({
|
|
379
|
-
rules: policy.rules,
|
|
380
|
-
unit,
|
|
381
|
-
usersByDevice,
|
|
382
|
-
usersByName,
|
|
383
|
-
groupsIDsByName,
|
|
384
|
-
whitelistsIDsByName
|
|
385
|
-
});
|
|
386
|
-
return {
|
|
387
|
-
type,
|
|
388
|
-
policy_data: {
|
|
389
|
-
name: policy.name,
|
|
390
|
-
governance_rules,
|
|
391
|
-
currency: {
|
|
392
|
-
name: policy.currency
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
};
|
|
397
|
-
var prepareQuorumEdition = ({ data }) => {
|
|
398
|
-
return {
|
|
399
|
-
type: "UPDATE_QUORUM",
|
|
400
|
-
quorum: data.quorum
|
|
401
|
-
};
|
|
402
|
-
};
|
|
403
|
-
var prepareRequest = (data) => {
|
|
404
|
-
if (data.type === "EDIT_GROUP") {
|
|
405
|
-
return prepareGroupEdition(data);
|
|
406
|
-
}
|
|
407
|
-
if (data.type === "CREATE_GROUP") {
|
|
408
|
-
return prepareGroupCreation(data);
|
|
409
|
-
}
|
|
410
|
-
if (data.type === "EDIT_WHITELIST") {
|
|
411
|
-
return prepareWhitelistEdition(data);
|
|
412
|
-
}
|
|
413
|
-
if (data.type === "CREATE_WHITELIST") {
|
|
414
|
-
return prepareWhitelistCreation(data);
|
|
415
|
-
}
|
|
416
|
-
if (data.type === "CREATE_ACCOUNT") {
|
|
417
|
-
return prepareAccountCreation(data);
|
|
418
|
-
}
|
|
419
|
-
if (data.type === "EDIT_ACCOUNT") {
|
|
420
|
-
return prepareAccountEdition(data);
|
|
421
|
-
}
|
|
422
|
-
if (data.type === "CREATE_ENTITY") {
|
|
423
|
-
return prepareVaultEntityCreation(data);
|
|
424
|
-
}
|
|
425
|
-
if (data.type === "EDIT_ENTITY") {
|
|
426
|
-
return prepareVaultEntityEdition(data);
|
|
427
|
-
}
|
|
428
|
-
if (data.type === "CREATE_ADMIN" || data.type === "CREATE_OPERATOR") {
|
|
429
|
-
return prepareUserCreation(data);
|
|
430
|
-
}
|
|
431
|
-
if (data.type === "CREATE_API_USER") {
|
|
432
|
-
return prepareAPIUserCreation(data);
|
|
433
|
-
}
|
|
434
|
-
if (data.type === "CREATE_API_USER_ACCESS") {
|
|
435
|
-
return prepareAPIUserAccessCreation(data);
|
|
436
|
-
}
|
|
437
|
-
if (data.type === "UPDATE_QUORUM") {
|
|
438
|
-
return prepareQuorumEdition(data);
|
|
439
|
-
}
|
|
440
|
-
if (data.type === "IMPORT_EXCHANGE") {
|
|
441
|
-
return prepareExchangeCreation(data);
|
|
442
|
-
}
|
|
443
|
-
if (data.type === "CREATE_POLICY") {
|
|
444
|
-
return preparePolicyCreation(data);
|
|
445
|
-
}
|
|
446
|
-
throw new Error(`Unhandled request type ${data.type}`);
|
|
447
|
-
};
|
|
448
|
-
var getGroupID = (groupsIDsByName, groupName) => {
|
|
449
|
-
const groupID = groupsIDsByName[groupName];
|
|
450
|
-
if (typeof groupID === "undefined") throw new Error(`Invalid group name ${groupName}`);
|
|
451
|
-
return groupID;
|
|
452
|
-
};
|
|
453
|
-
var transformMultiAuthRuleFromManifest = (rule, groupsIDsByName, usersByDevice, usersByName) => {
|
|
454
|
-
return {
|
|
455
|
-
type: rule.type,
|
|
456
|
-
data: rule.steps.map((step) => {
|
|
457
|
-
return {
|
|
458
|
-
quorum: step.quorum,
|
|
459
|
-
..."group" in step ? { group_id: getGroupID(groupsIDsByName, step.group) } : {
|
|
460
|
-
users: step.users.map((d) => {
|
|
461
|
-
if (typeof d === "number") {
|
|
462
|
-
const user2 = usersByDevice[d];
|
|
463
|
-
if (!user2) throw new Error(`Invalid device ${d}`);
|
|
464
|
-
return user2.id;
|
|
465
|
-
}
|
|
466
|
-
const user = usersByName[d];
|
|
467
|
-
if (!user) throw new Error(`Invalid name ${d}`);
|
|
468
|
-
return user.id;
|
|
469
|
-
})
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
})
|
|
473
|
-
};
|
|
474
|
-
};
|
|
475
|
-
var transformWhitelistRuleFromManifest = (rule, whitelistsIDsByName) => {
|
|
476
|
-
return {
|
|
477
|
-
type: rule.type,
|
|
478
|
-
data: rule.whitelists.map((w) => {
|
|
479
|
-
const whitelistID = whitelistsIDsByName[w];
|
|
480
|
-
if (typeof whitelistID === "undefined") throw new Error(`Invalid whitelist name ${w}`);
|
|
481
|
-
return whitelistID;
|
|
482
|
-
})
|
|
483
|
-
};
|
|
484
|
-
};
|
|
485
|
-
var transformSCIRuleFromManifest = (rule) => {
|
|
486
|
-
return {
|
|
487
|
-
type: rule.type,
|
|
488
|
-
data: [
|
|
489
|
-
{
|
|
490
|
-
enabled: rule.enabled
|
|
491
|
-
}
|
|
492
|
-
]
|
|
493
|
-
};
|
|
494
|
-
};
|
|
495
|
-
var transformTezosDelegationRuleFromManifest = () => {
|
|
496
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "TEZOS_DELEGATION" } };
|
|
497
|
-
};
|
|
498
|
-
var transformPolkadotStakingRuleFromManifest = () => {
|
|
499
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "POLKADOT_STAKING" } };
|
|
500
|
-
};
|
|
501
|
-
var transformSolanaStakingRuleFromManifest = () => {
|
|
502
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "SOLANA_STAKING" } };
|
|
503
|
-
};
|
|
504
|
-
var transformMessageSigningRuleFromManifest = () => {
|
|
505
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "MESSAGE_SIGNING" } };
|
|
506
|
-
};
|
|
507
|
-
var transformCreateSplTokenAccountRuleFromManifest = () => {
|
|
508
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "CREATE_SPL_TOKEN_ACCOUNT" } };
|
|
509
|
-
};
|
|
510
|
-
var transformCardanoStakingRuleFromManifest = () => {
|
|
511
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "CARDANO_STAKING" } };
|
|
512
|
-
};
|
|
513
|
-
var transformRawTransactionRuleFromManifest = () => {
|
|
514
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "RAW_SIGNING" } };
|
|
515
|
-
};
|
|
516
|
-
var transformSendTransactionRuleFromManifest = () => {
|
|
517
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "SEND" } };
|
|
518
|
-
};
|
|
519
|
-
var transformSmartContractDeploymentFromManifest = () => {
|
|
520
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "DEPLOY_CONTRACT" } };
|
|
521
|
-
};
|
|
522
|
-
var transformStakeTransactionRuleFromManifest = () => {
|
|
523
|
-
return { type: "TRANSACTION_FILTER", data: { preset: "STAKE" } };
|
|
524
|
-
};
|
|
525
|
-
var transformThresholdRuleFromManifest = (rule, unit) => {
|
|
526
|
-
return {
|
|
527
|
-
type: rule.type,
|
|
528
|
-
data: [
|
|
529
|
-
{
|
|
530
|
-
currency_type: "CRYPTO",
|
|
531
|
-
...rule.max ? { max: serializeUnitValue(unit, rule.max) } : {},
|
|
532
|
-
min: serializeUnitValue(unit, rule.min || 0)
|
|
533
|
-
}
|
|
534
|
-
]
|
|
535
|
-
};
|
|
536
|
-
};
|
|
537
|
-
var transformManifestRules = ({
|
|
538
|
-
rules,
|
|
539
|
-
unit,
|
|
540
|
-
usersByDevice,
|
|
541
|
-
usersByName,
|
|
542
|
-
whitelistsIDsByName,
|
|
543
|
-
groupsIDsByName,
|
|
544
|
-
enforceSendTxFilter
|
|
545
|
-
}) => {
|
|
546
|
-
const governance_rules = rules && rules.length ? rules.map((rules2, i) => {
|
|
547
|
-
return {
|
|
548
|
-
name: `Rule ${i + 1}`,
|
|
549
|
-
rules: rules2.map((rule) => {
|
|
550
|
-
if (rule.type === "MULTI_AUTHORIZATIONS") {
|
|
551
|
-
return transformMultiAuthRuleFromManifest(
|
|
552
|
-
rule,
|
|
553
|
-
groupsIDsByName,
|
|
554
|
-
usersByDevice,
|
|
555
|
-
usersByName
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
if (rule.type === "WHITELIST") {
|
|
559
|
-
invariant(
|
|
560
|
-
whitelistsIDsByName,
|
|
561
|
-
"WHITELIST rule configured outside of account context"
|
|
562
|
-
);
|
|
563
|
-
return transformWhitelistRuleFromManifest(rule, whitelistsIDsByName);
|
|
564
|
-
}
|
|
565
|
-
if (rule.type === "THRESHOLD") {
|
|
566
|
-
invariant(unit, "THRESHOLD: no unit provided");
|
|
567
|
-
return transformThresholdRuleFromManifest(rule, unit);
|
|
568
|
-
}
|
|
569
|
-
if (rule.type === "SMART_CONTRACT_INTERACTION") {
|
|
570
|
-
return transformSCIRuleFromManifest(rule);
|
|
571
|
-
}
|
|
572
|
-
if (rule.type === "DEPLOY_CONTRACT") {
|
|
573
|
-
return transformSmartContractDeploymentFromManifest();
|
|
574
|
-
}
|
|
575
|
-
if (rule.type === "TEZOS_DELEGATION") {
|
|
576
|
-
return transformTezosDelegationRuleFromManifest();
|
|
577
|
-
}
|
|
578
|
-
if (rule.type === "POLKADOT_STAKING") {
|
|
579
|
-
return transformPolkadotStakingRuleFromManifest();
|
|
580
|
-
}
|
|
581
|
-
if (rule.type === "SOLANA_STAKING") {
|
|
582
|
-
return transformSolanaStakingRuleFromManifest();
|
|
583
|
-
}
|
|
584
|
-
if (rule.type === "CARDANO_STAKING") {
|
|
585
|
-
return transformCardanoStakingRuleFromManifest();
|
|
586
|
-
}
|
|
587
|
-
if (rule.type === "RAW_SIGNING") {
|
|
588
|
-
return transformRawTransactionRuleFromManifest();
|
|
589
|
-
}
|
|
590
|
-
if (rule.type === "SEND") {
|
|
591
|
-
return transformSendTransactionRuleFromManifest();
|
|
592
|
-
}
|
|
593
|
-
if (rule.type === "STAKE") {
|
|
594
|
-
return transformStakeTransactionRuleFromManifest();
|
|
595
|
-
}
|
|
596
|
-
if (rule.type === "MESSAGE_SIGNING") {
|
|
597
|
-
return transformMessageSigningRuleFromManifest();
|
|
598
|
-
}
|
|
599
|
-
if (rule.type === "CREATE_SPL_TOKEN_ACCOUNT") {
|
|
600
|
-
return transformCreateSplTokenAccountRuleFromManifest();
|
|
601
|
-
}
|
|
602
|
-
throw new Error(`Unhandled rule type ${rule.type}`);
|
|
603
|
-
})
|
|
604
|
-
};
|
|
605
|
-
}) : getDefaultRule(usersByDevice);
|
|
606
|
-
if (enforceSendTxFilter) {
|
|
607
|
-
governance_rules.forEach((rulesSet) => {
|
|
608
|
-
const hasTxFilterRule = !!rulesSet.rules.find((r) => r.type === "TRANSACTION_FILTER");
|
|
609
|
-
const hasSCIRule = !!rulesSet.rules.find((r) => r.type === "SMART_CONTRACT_INTERACTION");
|
|
610
|
-
if (!hasTxFilterRule && !hasSCIRule) {
|
|
611
|
-
rulesSet.rules.unshift({ type: "TRANSACTION_FILTER", data: { preset: "SEND" } });
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
return governance_rules;
|
|
616
|
-
};
|
|
617
|
-
var getDefaultRule = (usersByDevice) => {
|
|
618
|
-
const operatorsDevices = Object.keys(usersByDevice).filter((key) => {
|
|
619
|
-
const u = usersByDevice[key];
|
|
620
|
-
if (!u) throw new Error(`Invalid device ${key}`);
|
|
621
|
-
return u.role === "OPERATOR";
|
|
622
|
-
});
|
|
623
|
-
const lastCreatedOperatorDevice = operatorsDevices[0];
|
|
624
|
-
if (!lastCreatedOperatorDevice) {
|
|
625
|
-
throw new Error(`Can't get the last created operator device`);
|
|
626
|
-
}
|
|
627
|
-
const lastCreatedOperator = usersByDevice[lastCreatedOperatorDevice];
|
|
628
|
-
if (!lastCreatedOperator) {
|
|
629
|
-
throw new Error(`Can't get the last created operator`);
|
|
630
|
-
}
|
|
631
|
-
return [
|
|
632
|
-
{
|
|
633
|
-
name: "Rule 1",
|
|
634
|
-
rules: [
|
|
635
|
-
{
|
|
636
|
-
type: "MULTI_AUTHORIZATIONS",
|
|
637
|
-
data: [
|
|
638
|
-
{
|
|
639
|
-
quorum: 1,
|
|
640
|
-
users: [lastCreatedOperator.id]
|
|
641
|
-
}
|
|
642
|
-
]
|
|
643
|
-
}
|
|
644
|
-
]
|
|
645
|
-
}
|
|
646
|
-
];
|
|
647
|
-
};
|
|
648
|
-
var TWO_STEPS_CREATION_REQUESTS = [
|
|
649
|
-
"CREATE_ACCOUNT",
|
|
650
|
-
"CREATE_GROUP",
|
|
651
|
-
"CREATE_TRANSACTION",
|
|
652
|
-
"CREATE_WHITELIST",
|
|
653
|
-
"EDIT_ACCOUNT",
|
|
654
|
-
"EDIT_GROUP",
|
|
655
|
-
"EDIT_WHITELIST",
|
|
656
|
-
"REVOKE_USER",
|
|
657
|
-
"UPDATE_QUORUM"
|
|
658
|
-
];
|
|
659
|
-
var performRequest = async (payload, pool, options) => {
|
|
660
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
661
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
662
|
-
let request = options?.existingRequest;
|
|
663
|
-
if (!request) {
|
|
664
|
-
const enableTwoStepsCreation = options?.twoStepsRequest && TWO_STEPS_CREATION_REQUESTS.includes(payload.type);
|
|
665
|
-
if (enableTwoStepsCreation) {
|
|
666
|
-
Object.assign(payload, { enable_two_step_request_creation: true });
|
|
667
|
-
}
|
|
668
|
-
const r = await admin.post("/requests", payload);
|
|
669
|
-
request = r;
|
|
670
|
-
if (enableTwoStepsCreation) {
|
|
671
|
-
const pingChallenge = async () => {
|
|
672
|
-
try {
|
|
673
|
-
await admin.post(`/requests/${r.id}/post-create`, {});
|
|
674
|
-
} catch (err) {
|
|
675
|
-
await pingChallenge();
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
|
-
await pingChallenge();
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
if (!options || !options.noApproval) {
|
|
682
|
-
await pool.runWithQuorum(
|
|
683
|
-
(admin2) => options?.withoutHSM ? admin2.approveRequestWithoutHSM(request) : admin2.approveRequest(request)
|
|
684
|
-
);
|
|
685
|
-
}
|
|
686
|
-
return request;
|
|
687
|
-
};
|
|
688
|
-
var prepareRequest_default = prepareRequest;
|
|
689
|
-
|
|
690
|
-
// src/createDefaultRunner.ts
|
|
691
|
-
var createDefaultRunner = (pool, options) => {
|
|
692
|
-
const { twoStepsRequest } = options;
|
|
693
|
-
const basicHandler = (type, options2) => {
|
|
694
|
-
return async (params) => {
|
|
695
|
-
const { data, existingRequest, noApproval } = params;
|
|
696
|
-
const payload = prepareRequest_default({ type, data });
|
|
697
|
-
const extra = { noApproval, existingRequest, twoStepsRequest, ...options2 };
|
|
698
|
-
return performRequest(payload, pool, extra);
|
|
699
|
-
};
|
|
700
|
-
};
|
|
701
|
-
const createAccount = async (params) => {
|
|
702
|
-
const { account, data, tradelinkAM } = params;
|
|
703
|
-
if ("readOnly" in account && account.readOnly) {
|
|
704
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
705
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
706
|
-
const payload = prepareRequest_default({ type: "CREATE_ACCOUNT", data });
|
|
707
|
-
return admin.post("/dev/accounts", payload);
|
|
708
|
-
}
|
|
709
|
-
let res;
|
|
710
|
-
try {
|
|
711
|
-
res = await basicHandler("CREATE_ACCOUNT")(params);
|
|
712
|
-
if (tradelinkAM) {
|
|
713
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
714
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
715
|
-
const reqResp = await admin.get(
|
|
716
|
-
`/requests?page=1&type=ACTIVATE&target_id=${res.account.id}`
|
|
717
|
-
);
|
|
718
|
-
const requests = unwrapConnection(reqResp);
|
|
719
|
-
const activationRequest = requests[0];
|
|
720
|
-
if (!activationRequest) {
|
|
721
|
-
throw new Error(`No account activation request found for account ${res.account.name}`);
|
|
722
|
-
}
|
|
723
|
-
if (!pool.apiGateway) {
|
|
724
|
-
throw new Error("apiGateway URL is not set");
|
|
725
|
-
}
|
|
726
|
-
await reviewAPIRequest_default(
|
|
727
|
-
{
|
|
728
|
-
pool,
|
|
729
|
-
requestID: activationRequest.id,
|
|
730
|
-
apiUser: tradelinkAM,
|
|
731
|
-
gate: pool.gate,
|
|
732
|
-
apiGateway: pool.apiGateway,
|
|
733
|
-
reviewType: "APPROVE"
|
|
734
|
-
},
|
|
735
|
-
{ logger: SILENT_LOGGER }
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
} catch (err) {
|
|
739
|
-
if (err instanceof Error && err.name === "ACCOUNT_CHILD_ALREADY_EXISTED_EXCEPTION" && "contractAddress" in account && !!account.parentAccount) {
|
|
740
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
741
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
742
|
-
const parentAccountsConnection = await admin.network(
|
|
743
|
-
"GET",
|
|
744
|
-
`/accounts?name=${account.parentAccount}`
|
|
745
|
-
);
|
|
746
|
-
const parentAccountEdge = parentAccountsConnection.edges.find(
|
|
747
|
-
(e) => e.node.name === account.parentAccount
|
|
748
|
-
);
|
|
749
|
-
invariant2(parentAccountEdge, `Parent account not found for ${account.name}`);
|
|
750
|
-
const parentAccount = parentAccountEdge.node;
|
|
751
|
-
const rawCurrencyQuery = `${parentAccount.currency}:${account.contractAddress}`;
|
|
752
|
-
const currencyQuery = encodeURIComponent(rawCurrencyQuery);
|
|
753
|
-
const potentialAccounts = await admin.network(
|
|
754
|
-
"GET",
|
|
755
|
-
`/accounts?currency=${currencyQuery}&index=${parentAccount.index}`
|
|
756
|
-
);
|
|
757
|
-
invariant2(
|
|
758
|
-
potentialAccounts.edges.length === 1,
|
|
759
|
-
`We should have one matching token account for ${currencyQuery} (index: ${parentAccount.index})`
|
|
760
|
-
);
|
|
761
|
-
const existingAccount = potentialAccounts.edges[0].node;
|
|
762
|
-
const editParams = {
|
|
763
|
-
...params,
|
|
764
|
-
data: { ...params.data, existingAccount }
|
|
765
|
-
};
|
|
766
|
-
res = await basicHandler("EDIT_ACCOUNT")(editParams);
|
|
767
|
-
} else {
|
|
768
|
-
throw err;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
if (params.waitForActive) {
|
|
772
|
-
const accountId = res.target_id;
|
|
773
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
774
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
775
|
-
for (let i = 0; i < 60; i++) {
|
|
776
|
-
const account2 = await admin.get(`/accounts/${accountId}`);
|
|
777
|
-
if (account2.status === "ACTIVE") {
|
|
778
|
-
res.account = account2;
|
|
779
|
-
break;
|
|
780
|
-
}
|
|
781
|
-
await wait(3e3);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
return res;
|
|
785
|
-
};
|
|
786
|
-
const createUser = async (params) => {
|
|
787
|
-
const { role, userID, name, device } = params;
|
|
788
|
-
const type = role === "operator" ? "CREATE_OPERATOR" : "CREATE_ADMIN";
|
|
789
|
-
const data = { userID, role, name };
|
|
790
|
-
const payload = prepareRequest_default({ type, data });
|
|
791
|
-
const extra = { noApproval: true };
|
|
792
|
-
const req = await performRequest(payload, pool, extra);
|
|
793
|
-
const res = await pool.registerDevice(device, req);
|
|
794
|
-
req.user.pub_key = res.u2f_key.pubKey;
|
|
795
|
-
if (!options.noApproval) {
|
|
796
|
-
await pool.runWithQuorum((admin) => admin.approveRequest(req));
|
|
797
|
-
}
|
|
798
|
-
return req;
|
|
799
|
-
};
|
|
800
|
-
const createAPIUser = async (params, manifestFromGate) => {
|
|
801
|
-
const { user, name, userID } = params;
|
|
802
|
-
let request = manifestFromGate.rawData.pendingUserRequests.find((e) => e.user.username === name) || null;
|
|
803
|
-
if (!request) {
|
|
804
|
-
request = await performRequest(
|
|
805
|
-
{
|
|
806
|
-
type: "CREATE_OPERATOR",
|
|
807
|
-
username: name,
|
|
808
|
-
user_id: userID,
|
|
809
|
-
is_api: true,
|
|
810
|
-
view_all_override: user.viewAll
|
|
811
|
-
},
|
|
812
|
-
pool,
|
|
813
|
-
{ noApproval: true }
|
|
814
|
-
);
|
|
815
|
-
}
|
|
816
|
-
if (request.status != "PENDING_APPROVAL")
|
|
817
|
-
await pool.lamAPI.registerUser(name, request.url_id);
|
|
818
|
-
if (!options.noApproval) {
|
|
819
|
-
await pool.runWithQuorum((admin) => admin.approveRequest(request));
|
|
820
|
-
}
|
|
821
|
-
return request;
|
|
822
|
-
};
|
|
823
|
-
const createAPIV2User = async (params) => {
|
|
824
|
-
const { name, publicKey, role } = params;
|
|
825
|
-
const type = "CREATE_API_USER";
|
|
826
|
-
const data = { publicKey, name, role };
|
|
827
|
-
const payload = prepareRequest_default({ type, data });
|
|
828
|
-
const extra = { noApproval: true };
|
|
829
|
-
const req = await performRequest(payload, pool, extra);
|
|
830
|
-
if (!options.noApproval) {
|
|
831
|
-
await pool.runWithQuorum((admin) => admin.approveRequest(req));
|
|
832
|
-
}
|
|
833
|
-
return req;
|
|
834
|
-
};
|
|
835
|
-
const createAPIV2UserAccess = async (params) => {
|
|
836
|
-
const { name } = params;
|
|
837
|
-
const type = "CREATE_API_USER_ACCESS";
|
|
838
|
-
const data = { name };
|
|
839
|
-
const payload = prepareRequest_default({ type, data });
|
|
840
|
-
const extra = { noApproval: true };
|
|
841
|
-
return await performRequest(payload, pool, extra);
|
|
842
|
-
};
|
|
843
|
-
const createTradelinkEntity = async (params) => {
|
|
844
|
-
const { tradelinkEntity, type } = params;
|
|
845
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
846
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
847
|
-
const data = {
|
|
848
|
-
id: tradelinkEntity.id,
|
|
849
|
-
name: tradelinkEntity.name,
|
|
850
|
-
code: tradelinkEntity.code,
|
|
851
|
-
logo_url: tradelinkEntity.logoUrl
|
|
852
|
-
};
|
|
853
|
-
return await admin.post(`/tradelink/${type}`, data);
|
|
854
|
-
};
|
|
855
|
-
const createTradelinkNetwork = async (params) => {
|
|
856
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
857
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
858
|
-
const data = {
|
|
859
|
-
id: uuidv4(),
|
|
860
|
-
custodian: params.custodians[0],
|
|
861
|
-
exchanges: params.exchanges,
|
|
862
|
-
asset_managers: params.assetManagers
|
|
863
|
-
};
|
|
864
|
-
await admin.network("DELETE", "/tradelink/network").catch(
|
|
865
|
-
/* istanbul ignore next */
|
|
866
|
-
(error) => {
|
|
867
|
-
if (error.message.includes("404")) {
|
|
868
|
-
} else {
|
|
869
|
-
throw error;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
);
|
|
873
|
-
return await admin.post(`/tradelink/network`, data);
|
|
874
|
-
};
|
|
875
|
-
const createTradelink = async (params) => {
|
|
876
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
877
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
878
|
-
const request = await admin.post(`/requests`, params);
|
|
879
|
-
await pool.runWithQuorum((admin2) => admin2.approveRequest(request));
|
|
880
|
-
return request;
|
|
881
|
-
};
|
|
882
|
-
const onboardTradelinkEntity = async (params) => {
|
|
883
|
-
const { tradelinkEntity, type, tradelinkEntityApprover } = params;
|
|
884
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
885
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
886
|
-
let data = {};
|
|
887
|
-
let request;
|
|
888
|
-
if (type === "exchanges") {
|
|
889
|
-
data = {
|
|
890
|
-
type: "CREATE_TRADELINK_EXCHANGE",
|
|
891
|
-
exchange_name: tradelinkEntity.name,
|
|
892
|
-
operators: tradelinkEntity.operators,
|
|
893
|
-
addresses: tradelinkEntity.addresses
|
|
894
|
-
};
|
|
895
|
-
request = await admin.post(`/requests`, data);
|
|
896
|
-
} else {
|
|
897
|
-
data = {
|
|
898
|
-
type: "CREATE_TRADELINK_ASSET_MANAGER",
|
|
899
|
-
asset_manager_name: tradelinkEntity.name,
|
|
900
|
-
operators: tradelinkEntity.operators,
|
|
901
|
-
addresses: tradelinkEntity.addresses
|
|
902
|
-
};
|
|
903
|
-
request = await admin.post(`/requests`, data);
|
|
904
|
-
}
|
|
905
|
-
await pool.runWithQuorum((admin2) => admin2.approveRequest(request));
|
|
906
|
-
if (!pool.apiGateway) {
|
|
907
|
-
throw new Error("apiGateway URL is not set");
|
|
908
|
-
}
|
|
909
|
-
await reviewAPIRequest_default(
|
|
910
|
-
{
|
|
911
|
-
pool,
|
|
912
|
-
requestID: request.id,
|
|
913
|
-
apiUser: tradelinkEntityApprover,
|
|
914
|
-
gate: pool.gate,
|
|
915
|
-
apiGateway: pool.apiGateway,
|
|
916
|
-
reviewType: "APPROVE"
|
|
917
|
-
},
|
|
918
|
-
{ logger: SILENT_LOGGER }
|
|
919
|
-
);
|
|
920
|
-
return request;
|
|
921
|
-
};
|
|
922
|
-
const editQuorum = async (params) => {
|
|
923
|
-
const { quorum } = params;
|
|
924
|
-
const payload = prepareRequest_default({
|
|
925
|
-
type: "UPDATE_QUORUM",
|
|
926
|
-
data: { quorum }
|
|
927
|
-
});
|
|
928
|
-
await performRequest(payload, pool);
|
|
929
|
-
};
|
|
930
|
-
const editWorkspaceRule = async (params) => {
|
|
931
|
-
const { rule, usersByName } = params;
|
|
932
|
-
const payload = {
|
|
933
|
-
type: "EDIT_WORKSPACE_RULE",
|
|
934
|
-
permission: rule.permission,
|
|
935
|
-
edit_data: {
|
|
936
|
-
steps: rule.steps.map((s) => {
|
|
937
|
-
return {
|
|
938
|
-
quorum: s.quorum,
|
|
939
|
-
users: s.users.map((username) => {
|
|
940
|
-
const user = usersByName[username];
|
|
941
|
-
invariant2(user, `No user with name ${username}`);
|
|
942
|
-
return user.pub_key;
|
|
943
|
-
})
|
|
944
|
-
};
|
|
945
|
-
})
|
|
946
|
-
}
|
|
947
|
-
};
|
|
948
|
-
await performRequest(payload, pool);
|
|
949
|
-
};
|
|
950
|
-
const runner = {
|
|
951
|
-
editQuorum,
|
|
952
|
-
editWorkspaceRule,
|
|
953
|
-
createUser,
|
|
954
|
-
createAPIUser,
|
|
955
|
-
createAPIV2User,
|
|
956
|
-
createAPIV2UserAccess,
|
|
957
|
-
createGroup: basicHandler("CREATE_GROUP"),
|
|
958
|
-
editGroup: basicHandler("EDIT_GROUP"),
|
|
959
|
-
createAccount,
|
|
960
|
-
editAccount: basicHandler("EDIT_ACCOUNT"),
|
|
961
|
-
createWhitelist: basicHandler("CREATE_WHITELIST"),
|
|
962
|
-
editWhitelist: basicHandler("EDIT_WHITELIST"),
|
|
963
|
-
createVaultEntity: basicHandler("CREATE_ENTITY", {
|
|
964
|
-
withoutHSM: true
|
|
965
|
-
}),
|
|
966
|
-
editVaultEntity: basicHandler("EDIT_ENTITY", {
|
|
967
|
-
withoutHSM: true
|
|
968
|
-
}),
|
|
969
|
-
createExchange: basicHandler("IMPORT_EXCHANGE", {
|
|
970
|
-
withoutHSM: true
|
|
971
|
-
}),
|
|
972
|
-
editExchange: basicHandler("IMPORT_EXCHANGE", {
|
|
973
|
-
withoutHSM: true
|
|
974
|
-
}),
|
|
975
|
-
createPolicy: basicHandler("CREATE_POLICY"),
|
|
976
|
-
createTradelink,
|
|
977
|
-
createTradelinkEntity,
|
|
978
|
-
onboardTradelinkEntity,
|
|
979
|
-
createTradelinkNetwork
|
|
980
|
-
};
|
|
981
|
-
return runner;
|
|
982
|
-
};
|
|
983
|
-
var createDefaultRunner_default = createDefaultRunner;
|
|
984
|
-
|
|
985
|
-
// src/apiUser/index.ts
|
|
986
|
-
function getAPIHeader(bearerToken, workspace) {
|
|
987
|
-
return {
|
|
988
|
-
headers: {
|
|
989
|
-
"X-Ledger-Workspace": workspace,
|
|
990
|
-
"Content-Type": "application/json",
|
|
991
|
-
Authorization: `Bearer ${bearerToken}`
|
|
992
|
-
}
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
async function regenerateCredentials(pool, apiNetwork, workspace, apiUser, logger) {
|
|
996
|
-
const runner = createDefaultRunner_default(pool, {});
|
|
997
|
-
const postApiUserAccess = {
|
|
998
|
-
user: apiUser,
|
|
999
|
-
publicKey: genKeys(apiUser.name).hexPubKey,
|
|
1000
|
-
role: apiUser.role,
|
|
1001
|
-
name: apiUser.name
|
|
1002
|
-
};
|
|
1003
|
-
const userAccessRequest = await runner.createAPIV2UserAccess(postApiUserAccess);
|
|
1004
|
-
const apiUserAuth = {
|
|
1005
|
-
api_key_id: userAccessRequest.api_key_id,
|
|
1006
|
-
api_key_secret: userAccessRequest.api_key_secret
|
|
1007
|
-
};
|
|
1008
|
-
logger.info(
|
|
1009
|
-
chalk`{red.bold IMPORTANT:} {red The API user credentials will not be displayed again so note them somewhere}`
|
|
1010
|
-
);
|
|
1011
|
-
logger.info(
|
|
1012
|
-
JSON.stringify({
|
|
1013
|
-
api_key_id: userAccessRequest.api_key_id,
|
|
1014
|
-
api_key_secret: userAccessRequest.api_key_secret
|
|
1015
|
-
})
|
|
1016
|
-
);
|
|
1017
|
-
return apiUserAuth;
|
|
1018
|
-
}
|
|
1019
|
-
async function getAuthTokens(apiNetwork, workspace, apiUserAuth) {
|
|
1020
|
-
return await apiNetwork("POST", "/auth/token", apiUserAuth, {
|
|
1021
|
-
headers: { "X-Ledger-Workspace": workspace }
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
async function authenticate(pool, apiNetwork, workspace, apiUser, logger) {
|
|
1025
|
-
const apiUserAuth = await regenerateCredentials(pool, apiNetwork, workspace, apiUser, logger);
|
|
1026
|
-
const bearerResp = await getAuthTokens(apiNetwork, workspace, apiUserAuth);
|
|
1027
|
-
return bearerResp.access_token;
|
|
1028
|
-
}
|
|
1029
|
-
async function decodeChallenge({
|
|
1030
|
-
apiNetwork,
|
|
1031
|
-
workspace,
|
|
1032
|
-
bearerToken,
|
|
1033
|
-
requestID,
|
|
1034
|
-
reviewType
|
|
1035
|
-
}) {
|
|
1036
|
-
let challengeUrl = `/requests/${requestID}/challenge`;
|
|
1037
|
-
if (reviewType === "REJECT") {
|
|
1038
|
-
challengeUrl = `${challengeUrl}/reject`;
|
|
1039
|
-
}
|
|
1040
|
-
const challengeResp = await apiNetwork(
|
|
1041
|
-
"GET",
|
|
1042
|
-
challengeUrl,
|
|
1043
|
-
{},
|
|
1044
|
-
getAPIHeader(bearerToken, workspace)
|
|
1045
|
-
).catch((error) => {
|
|
1046
|
-
if (error.message.includes("Get abort challenge is only available for tradelink settlement")) {
|
|
1047
|
-
return { challenge: "" };
|
|
1048
|
-
}
|
|
1049
|
-
throw error;
|
|
1050
|
-
});
|
|
1051
|
-
if (challengeResp.challenge === "") {
|
|
1052
|
-
return {
|
|
1053
|
-
challenge: "",
|
|
1054
|
-
decodedChallenge: ""
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
return {
|
|
1058
|
-
challenge: challengeResp.challenge,
|
|
1059
|
-
decodedChallenge: decodeData(challengeResp.challenge)
|
|
1060
|
-
};
|
|
1061
|
-
}
|
|
1062
|
-
async function signAndApprove({
|
|
1063
|
-
apiNetwork,
|
|
1064
|
-
workspace,
|
|
1065
|
-
bearerToken,
|
|
1066
|
-
requestID,
|
|
1067
|
-
apiUser,
|
|
1068
|
-
challenge,
|
|
1069
|
-
reviewType
|
|
1070
|
-
}) {
|
|
1071
|
-
const keys = genKeys(apiUser.name);
|
|
1072
|
-
let jws = "";
|
|
1073
|
-
if (challenge !== "") {
|
|
1074
|
-
jws = sign(String(keys.privateKey), challenge);
|
|
1075
|
-
}
|
|
1076
|
-
return await apiNetwork(
|
|
1077
|
-
"POST",
|
|
1078
|
-
`/requests/${requestID}/${reviewType.toLowerCase()}`,
|
|
1079
|
-
{ jws },
|
|
1080
|
-
getAPIHeader(bearerToken, workspace)
|
|
1081
|
-
);
|
|
1082
|
-
}
|
|
1083
|
-
async function getTradelinkPledge({
|
|
1084
|
-
apiNetwork,
|
|
1085
|
-
workspace,
|
|
1086
|
-
gateAccount,
|
|
1087
|
-
bearerToken,
|
|
1088
|
-
exchange
|
|
1089
|
-
}) {
|
|
1090
|
-
const pledgesResp = await apiNetwork(
|
|
1091
|
-
"GET",
|
|
1092
|
-
`/pledges?account_id=${gateAccount.id}`,
|
|
1093
|
-
{},
|
|
1094
|
-
getAPIHeader(bearerToken, workspace)
|
|
1095
|
-
);
|
|
1096
|
-
const pledgeResp = pledgesResp.edges.find((p) => p.node.exchange.name == exchange);
|
|
1097
|
-
if (!pledgeResp) {
|
|
1098
|
-
throw new Error(`Exchange '${exchange}' not found`);
|
|
1099
|
-
}
|
|
1100
|
-
return pledgeResp.node;
|
|
1101
|
-
}
|
|
1102
|
-
async function getTradelinkRecipient({
|
|
1103
|
-
pool,
|
|
1104
|
-
gateAccount,
|
|
1105
|
-
pledge
|
|
1106
|
-
}) {
|
|
1107
|
-
const exchangeWLId = pledge.exchange.whitelist_id;
|
|
1108
|
-
const adminDevices = await pool.getOnboardingAdminDevices();
|
|
1109
|
-
const admin = await pool.login(adminDevices[0][1]);
|
|
1110
|
-
const wlResp = await admin.network(
|
|
1111
|
-
"GET",
|
|
1112
|
-
`/whitelists?id=${exchangeWLId}`
|
|
1113
|
-
);
|
|
1114
|
-
const wlAddress = wlResp.edges[0]?.node.addresses.find(
|
|
1115
|
-
(a) => a.currency === gateAccount.currency
|
|
1116
|
-
)?.address;
|
|
1117
|
-
return String(wlAddress);
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
// src/reviewAPIRequest.ts
|
|
1121
|
-
async function reviewAPIRequest({
|
|
1122
|
-
pool,
|
|
1123
|
-
requestID,
|
|
1124
|
-
apiUser,
|
|
1125
|
-
gate,
|
|
1126
|
-
apiGateway,
|
|
1127
|
-
reviewType,
|
|
1128
|
-
skipDecodeChallenge = false
|
|
1129
|
-
}, { logger = SILENT_LOGGER2 }) {
|
|
1130
|
-
const workspace = getWorkspaceFromGate(gate);
|
|
1131
|
-
const apiNetwork = createNetwork({
|
|
1132
|
-
baseURL: apiGateway
|
|
1133
|
-
});
|
|
1134
|
-
logger.info(`Authenticate for ${apiUser.name}`);
|
|
1135
|
-
const bearerToken = await authenticate(pool, apiNetwork, workspace, apiUser, logger);
|
|
1136
|
-
let apiChallenge = {
|
|
1137
|
-
challenge: "",
|
|
1138
|
-
decodedChallenge: ""
|
|
1139
|
-
};
|
|
1140
|
-
if (skipDecodeChallenge === false) {
|
|
1141
|
-
logger.info("Decode challenge");
|
|
1142
|
-
apiChallenge = await decodeChallenge({
|
|
1143
|
-
apiNetwork,
|
|
1144
|
-
workspace,
|
|
1145
|
-
bearerToken,
|
|
1146
|
-
requestID,
|
|
1147
|
-
reviewType
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
logger.info(apiChallenge.decodedChallenge);
|
|
1151
|
-
logger.info("Sign and approve");
|
|
1152
|
-
return signAndApprove({
|
|
1153
|
-
apiNetwork,
|
|
1154
|
-
workspace,
|
|
1155
|
-
bearerToken,
|
|
1156
|
-
requestID,
|
|
1157
|
-
apiUser,
|
|
1158
|
-
challenge: apiChallenge.challenge,
|
|
1159
|
-
reviewType
|
|
1160
|
-
});
|
|
1161
|
-
}
|
|
1162
|
-
var reviewAPIRequest_default = reviewAPIRequest;
|
|
1163
|
-
|
|
1164
|
-
export {
|
|
1165
|
-
performRequest,
|
|
1166
|
-
prepareRequest_default,
|
|
1167
|
-
reviewAPIRequest_default,
|
|
1168
|
-
createDefaultRunner_default,
|
|
1169
|
-
getAuthTokens,
|
|
1170
|
-
authenticate,
|
|
1171
|
-
decodeChallenge,
|
|
1172
|
-
signAndApprove,
|
|
1173
|
-
getTradelinkPledge,
|
|
1174
|
-
getTradelinkRecipient
|
|
1175
|
-
};
|
|
1176
|
-
//# sourceMappingURL=chunk-6TT6A6YA.mjs.map
|