@abtnode/core 1.8.2 → 1.8.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.
@@ -22,8 +22,7 @@ const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
22
22
  const downloadFile = require('@abtnode/util/lib/download-file');
23
23
  const Lock = require('@abtnode/util/lib/lock');
24
24
  const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
25
- const handleInstanceInStore = require('@abtnode/util/lib/public-to-store');
26
- const { VC_TYPE_BLOCKLET_PURCHASE } = require('@abtnode/constant');
25
+ const { VC_TYPE_BLOCKLET_PURCHASE, WHO_CAN_ACCESS } = require('@abtnode/constant');
27
26
 
28
27
  const getBlockletEngine = require('@blocklet/meta/lib/engine');
29
28
  const {
@@ -116,6 +115,7 @@ const { getFactoryState } = require('../../util/chain');
116
115
  const runMigrationScripts = require('../migration');
117
116
  const hooks = require('../hooks');
118
117
  const { formatName } = require('../../util/get-domain-for-blocklet');
118
+ const handleInstanceInStore = require('../../util/public-to-store');
119
119
 
120
120
  const {
121
121
  isInProgress,
@@ -234,7 +234,9 @@ class BlockletManager extends BaseBlockletManager {
234
234
  context.headers = Object.assign(context?.headers || {}, {
235
235
  'x-server-did': info.did,
236
236
  'x-download-token': params.downloadToken,
237
+ // FIXME: 先保证兼容性,后续删除
237
238
  'x-server-publick-key': info.pk,
239
+ 'x-server-public-key': info.pk,
238
240
  'x-server-signature': sign(info.did, info.sk, {
239
241
  exp: (Date.now() + 5 * 60 * 1000) / 1000,
240
242
  }),
@@ -880,6 +882,25 @@ class BlockletManager extends BaseBlockletManager {
880
882
  return newState;
881
883
  }
882
884
 
885
+ async updateWhoCanAccess({ did, whoCanAccess }) {
886
+ if (!(await this.hasBlocklet({ did }))) {
887
+ throw new Error('The blocklet does not exist');
888
+ }
889
+
890
+ if (!Object.values(WHO_CAN_ACCESS).includes(whoCanAccess)) {
891
+ logger.error(`The value of whoCanAccess is invalid: ${whoCanAccess}`);
892
+ throw new Error('the value is invalid');
893
+ }
894
+
895
+ await states.blockletExtras.setSettings(did, { whoCanAccess });
896
+
897
+ const blocklet = await this.ensureBlocklet(did);
898
+
899
+ this.emit(BlockletEvents.updated, { meta: { did: blocklet.meta.did } });
900
+
901
+ return blocklet;
902
+ }
903
+
883
904
  /**
884
905
  * upgrade blocklet from registry
885
906
  */
@@ -1838,7 +1859,9 @@ class BlockletManager extends BaseBlockletManager {
1838
1859
  headers: {
1839
1860
  'x-server-did': info.did,
1840
1861
  'x-download-token': downloadToken,
1862
+ // FIXME: 先保证兼容性,后续删除
1841
1863
  'x-server-publick-key': info.pk,
1864
+ 'x-server-public-key': info.pk,
1842
1865
  'x-server-signature': sign(info.did, info.sk, {
1843
1866
  exp: (Date.now() + 5 * 60 * 1000) / 1000,
1844
1867
  }),
@@ -2406,7 +2429,9 @@ class BlockletManager extends BaseBlockletManager {
2406
2429
  headers: {
2407
2430
  'x-server-did': info.did,
2408
2431
  'x-download-token': blocklet?.tokens?.paidBlockletDownloadToken,
2432
+ // FIXME: 先保证兼容性,后续删除
2409
2433
  'x-server-publick-key': info.pk,
2434
+ 'x-server-public-key': info.pk,
2410
2435
  'x-server-signature': sign(info.did, info.sk, {
2411
2436
  exp: (Date.now() + 5 * 60 * 1000) / 1000,
2412
2437
  }),
@@ -2440,7 +2465,11 @@ class BlockletManager extends BaseBlockletManager {
2440
2465
  ticket.on('failed', async (err) => {
2441
2466
  logger.error('queue failed', { entity: 'blocklet', action, did, version, name, error: err });
2442
2467
  await this._rollback(action, did, oldBlocklet);
2443
- this.emit(`blocklet.${action}.failed`, { did, version, err });
2468
+ const eventNames = {
2469
+ upgrade: BlockletEvents.upgradeFailed,
2470
+ downgrade: BlockletEvents.downgradeFailed,
2471
+ };
2472
+ this.emit(eventNames[action], { blocklet: oldBlocklet, context });
2444
2473
  states.notification.create({
2445
2474
  title: `Blocklet ${capitalize(action)} Failed`,
2446
2475
  description: `Blocklet ${name}@${version} ${action} failed with error: ${err.message || 'queue exception'}`,
@@ -2811,7 +2840,15 @@ class BlockletManager extends BaseBlockletManager {
2811
2840
  } catch (err) {
2812
2841
  const b = await this._rollback(action, did, oldBlocklet);
2813
2842
  logger.error(`failed to ${action} blocklet`, { did, version, name, error: err });
2843
+
2814
2844
  this.emit(BlockletEvents.updated, b);
2845
+
2846
+ const eventNames = {
2847
+ upgrade: BlockletEvents.upgradeFailed,
2848
+ downgrade: BlockletEvents.downgradeFailed,
2849
+ };
2850
+ this.emit(eventNames[action], { blocklet: oldBlocklet, context });
2851
+
2815
2852
  states.notification.create({
2816
2853
  title: `Blocklet ${capitalize(action)} Failed`,
2817
2854
  description: `Blocklet ${name}@${version} ${action} failed with error: ${err.message}`,
package/lib/event.js CHANGED
@@ -5,7 +5,7 @@ const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
5
5
  const logger = require('@abtnode/logger')('@abtnode/core:event');
6
6
  const { BLOCKLET_MODES, BlockletStatus, BlockletSource, BlockletEvents } = require('@blocklet/meta/lib/constants');
7
7
  const { EVENTS } = require('@abtnode/constant');
8
- const handleInstanceInStore = require('@abtnode/util/lib/public-to-store');
8
+ const handleInstanceInStore = require('./util/public-to-store');
9
9
 
10
10
  const eventHub =
11
11
  process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
@@ -27,6 +27,7 @@ module.exports = ({
27
27
  domainStatus,
28
28
  teamAPI,
29
29
  certManager,
30
+ node,
30
31
  }) => {
31
32
  const notificationState = states.notification;
32
33
  const nodeState = states.node;
@@ -155,22 +156,65 @@ module.exports = ({
155
156
  };
156
157
 
157
158
  const handleBlockletEvent = async (eventName, payload) => {
159
+ const blocklet = payload.blocklet || payload;
160
+
158
161
  if ([BlockletEvents.deployed, BlockletEvents.installed].includes(eventName)) {
159
162
  await handleBlockletAdd(eventName, payload);
163
+
164
+ try {
165
+ await node.createAuditLog({
166
+ action: 'installBlocklet',
167
+ args: {
168
+ did: blocklet.meta.did,
169
+ },
170
+ context: payload.context || {},
171
+ result: blocklet,
172
+ });
173
+ } catch (error) {
174
+ logger.error('Failed to createAuditLog for installBlocklet', { error });
175
+ }
160
176
  } else if ([BlockletEvents.upgraded, BlockletEvents.downgraded].includes(eventName)) {
161
177
  await handleBlockletUpgrade(eventName, payload);
178
+
179
+ try {
180
+ await node.createAuditLog({
181
+ action: 'upgradeBlocklet',
182
+ args: {
183
+ did: blocklet.meta.did,
184
+ },
185
+ context: payload.context || {},
186
+ result: blocklet,
187
+ });
188
+ } catch (error) {
189
+ logger.error('Failed to createAuditLog for upgradeBlocklet', { error });
190
+ }
162
191
  } else if ([BlockletEvents.removed].includes(eventName)) {
163
192
  await handleBlockletRemove(eventName, payload);
164
193
  } else if ([BlockletEvents.started].includes(eventName)) {
165
194
  try {
166
- const blocklet = await blockletManager.ensureBlocklet(payload.meta.did);
167
- const { publicToStore } = blocklet.settings;
195
+ const { publicToStore } = blocklet.settings || {};
168
196
  // 如果一个 blocklet 没有设置 publicToStore,启动成功后不应给 store 发请求
169
197
  if (publicToStore) {
170
198
  await handleInstanceInStore(blocklet, { publicToStore });
171
199
  }
172
200
  } catch (error) {
173
- logger.error('BlockletEvents started failed', { error });
201
+ logger.error('handleInstanceInStore failed', { error });
202
+ }
203
+ } else if ([BlockletEvents.upgradeFailed, BlockletEvents.downgradeFailed].includes(eventName)) {
204
+ try {
205
+ await node.createAuditLog({
206
+ action: 'upgradeBlocklet',
207
+ args: {
208
+ did: blocklet.meta.did,
209
+ },
210
+ context: payload.context || {},
211
+ result: {
212
+ ...blocklet,
213
+ resultStatus: 'failed',
214
+ },
215
+ });
216
+ } catch (error) {
217
+ logger.error('Failed to createAuditLog for upgradeBlocklet failed', { error });
174
218
  }
175
219
  }
176
220
 
package/lib/index.js CHANGED
@@ -174,19 +174,6 @@ function ABTNode(options) {
174
174
  onStatesReady(createStateReadyHandler(routingSnapshot));
175
175
  const domainStatus = new DomainStatus(routerManager);
176
176
 
177
- const events = createEvents({
178
- blockletManager,
179
- blockletRegistry,
180
- ensureBlockletRouting,
181
- ensureBlockletRoutingForUpgrade,
182
- removeBlockletRouting,
183
- takeRoutingSnapshot,
184
- handleRouting,
185
- domainStatus,
186
- teamAPI,
187
- certManager,
188
- });
189
-
190
177
  const isInitialized = async () => {
191
178
  const state = await states.node.read();
192
179
  return states.node.isInitialized(state);
@@ -226,9 +213,9 @@ function ABTNode(options) {
226
213
  getLatestBlockletVersion: blockletManager.getLatestBlockletVersion.bind(blockletManager),
227
214
  getBlockletMetaFromUrl: blockletManager.getMetaFromUrl.bind(blockletManager),
228
215
  resetBlocklet: blockletManager.reset.bind(blockletManager),
229
- configPublicToStore: blockletManager.configPublicToStore.bind(blockletManager),
230
-
231
216
  deleteBlockletProcess: blockletManager.deleteProcess.bind(blockletManager),
217
+ configPublicToStore: blockletManager.configPublicToStore.bind(blockletManager),
218
+ updateWhoCanAccess: blockletManager.updateWhoCanAccess.bind(blockletManager),
232
219
 
233
220
  // For diagnose purpose
234
221
  syncBlockletStatus: blockletManager.status.bind(blockletManager),
@@ -319,7 +306,6 @@ function ABTNode(options) {
319
306
  processPassportIssuance: teamAPI.processPassportIssuance.bind(teamAPI),
320
307
  configTrustedPassports: teamAPI.configTrustedPassports.bind(teamAPI),
321
308
  configPassportIssuance: teamAPI.configPassportIssuance.bind(teamAPI),
322
- configWhoCanAccess: teamAPI.configWhoCanAccess.bind(teamAPI),
323
309
 
324
310
  // Challenge
325
311
  generateChallenge: states.challenge.generate.bind(states.challenge),
@@ -405,6 +391,20 @@ function ABTNode(options) {
405
391
  getRouterProvider,
406
392
  };
407
393
 
394
+ const events = createEvents({
395
+ blockletManager,
396
+ blockletRegistry,
397
+ ensureBlockletRouting,
398
+ ensureBlockletRoutingForUpgrade,
399
+ removeBlockletRouting,
400
+ takeRoutingSnapshot,
401
+ handleRouting,
402
+ domainStatus,
403
+ teamAPI,
404
+ certManager,
405
+ node: instance,
406
+ });
407
+
408
408
  const webhook = WebHook({ events, dataDirs, instance });
409
409
 
410
410
  const initCron = () => {
@@ -111,6 +111,9 @@ const getLogContent = async (action, args, context, result, info, node) => {
111
111
  case 'configBlocklet':
112
112
  return `updated following config for blocklet ${getBlockletInfo(result, info)}:\n${args.configs.map(x => `- ${x.key}: ${x.value}\n`)}`; // prettier-ignore
113
113
  case 'upgradeBlocklet':
114
+ if (result.resultStatus === 'failed') {
115
+ return `upgrade blocklet failed: ${getBlockletInfo(result, info)}`;
116
+ }
114
117
  return `upgraded blocklet ${getBlockletInfo(result, info)} to v${result.meta.version}`;
115
118
  case 'updateChildBlocklets':
116
119
  return `upgraded components for blocklet ${getBlockletInfo(result, info)}`;
@@ -141,7 +144,7 @@ const getLogContent = async (action, args, context, result, info, node) => {
141
144
  return `switched passport to ${args.passport.name} for ${team}`;
142
145
  case 'login':
143
146
  return `${user} logged in to ${team} with passport ${args.passport.name}`;
144
- case 'configWhoCanAccess':
147
+ case 'updateWhoCanAccess':
145
148
  return `updated access control policy to **${args.value}** for ${team} when ${args.reason}`;
146
149
  case 'configPassportIssuance':
147
150
  return `${args.enabled ? 'enabled' : 'disabled'} passport issuance for ${team}`;
@@ -214,6 +217,14 @@ const getLogContent = async (action, args, context, result, info, node) => {
214
217
  return `added extra domain **${args.domainAlias}** to ${site}`; // prettier-ignore
215
218
  case 'deleteDomainAlias':
216
219
  return `removed extra domain **${args.domainAlias}** from ${site}`; // prettier-ignore
220
+ case 'updateRoutingSite':
221
+ return `updated site from ${site}`; // prettier-ignore
222
+ case 'addRoutingRule':
223
+ return `added routing rule **${args.rule?.from?.pathPrefix}** from ${site}`; // prettier-ignore
224
+ case 'updateRoutingRule':
225
+ return `updated routing rule **${args.rule?.from?.pathPrefix}** from ${site}`; // prettier-ignore
226
+ case 'deleteRoutingRule':
227
+ return `deleted routing rule from ${site}`; // prettier-ignore
217
228
  case 'updateGateway': {
218
229
  let message = args.requestLimit.enabled ? `status: enabled, rate: ${args.requestLimit.rate}` : 'status: disabled';
219
230
  message = `update gateway. ${message}`;
@@ -312,16 +323,21 @@ const getScope = (args = {}) => {
312
323
  return args.teamDid;
313
324
  }
314
325
 
326
+ // this param usually means mutating an blockle application
327
+ if (args.did) {
328
+ // this param usually means mutating a nested child component
329
+ if (Array.isArray(args.did)) {
330
+ return args.did[0];
331
+ }
332
+
333
+ return args.did;
334
+ }
335
+
315
336
  // this param usually means mutating a child component
316
337
  if (args.rootDid) {
317
338
  return args.rootDid;
318
339
  }
319
340
 
320
- // this param usually means mutating a nested child component
321
- if (Array.isArray(args.did)) {
322
- return args.did[0];
323
- }
324
-
325
341
  return null;
326
342
  };
327
343
 
@@ -283,6 +283,14 @@ class NodeState extends BaseState {
283
283
  return this.updateNodeInfo({ previousMode: '', mode: info.previousMode });
284
284
  }
285
285
 
286
+ async setMode(mode) {
287
+ if (Object.values(NODE_MODES).includes(mode) === false) {
288
+ throw new Error(`Can not update server to unsupported mode: ${mode}`);
289
+ }
290
+
291
+ return this.updateNodeInfo({ previousMode: '', mode });
292
+ }
293
+
286
294
  async getEnvironments() {
287
295
  return this.read().then((info) => ({
288
296
  ABT_NODE: info.version,
@@ -312,6 +312,7 @@ const getComponentSystemEnvironments = (blocklet) => {
312
312
 
313
313
  return {
314
314
  BLOCKLET_REAL_DID: blocklet.env.id,
315
+ BLOCKLET_REAL_NAME: blocklet.env.name,
315
316
  BLOCKLET_DATA_DIR: blocklet.env.dataDir,
316
317
  BLOCKLET_LOG_DIR: blocklet.env.logsDir,
317
318
  BLOCKLET_CACHE_DIR: blocklet.env.cacheDir,
@@ -337,11 +338,21 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
337
338
  }
338
339
  : {};
339
340
 
341
+ const root = (ancestors || [])[0] || blocklet;
342
+ const ports = {};
343
+ forEachBlockletSync(root, (x) => {
344
+ const webInterface = findWebInterface(x);
345
+ if (webInterface && x.environmentObj[webInterface.port]) {
346
+ ports[x.environmentObj.BLOCKLET_REAL_NAME] = x.environmentObj[webInterface.port];
347
+ }
348
+ });
349
+
340
350
  return {
341
351
  ...blocklet.configObj,
342
352
  ...getSharedConfigObj(blocklet, ancestors),
343
353
  ...blocklet.environmentObj,
344
354
  ...devEnvironments,
355
+ BLOCKLET_WEB_PORTS: JSON.stringify(ports),
345
356
  ...nodeEnvironments,
346
357
  ...safeNodeEnvironments,
347
358
  };
@@ -415,7 +426,7 @@ const getBlockletMetaFromUrls = async (urls) => {
415
426
  const meta = await any(urls.map(getBlockletMetaFromUrl));
416
427
  return meta;
417
428
  } catch (err) {
418
- logger.error('failed get blocklet meta', { urls });
429
+ logger.error('failed get blocklet meta', { urls, error: err });
419
430
  throw new Error('Failed get blocklet meta');
420
431
  }
421
432
  };
@@ -0,0 +1,85 @@
1
+ const { sign } = require('@arcblock/jwt');
2
+ const { BlockletSource } = require('@blocklet/meta/lib/constants');
3
+ const { WHO_CAN_ACCESS } = require('@abtnode/constant');
4
+ const logger = require('@abtnode/logger')('@abtnode/util:public-to-store');
5
+
6
+ const getWallet = require('@abtnode/util/lib/get-app-wallet');
7
+ const axios = require('@abtnode/util/lib/axios');
8
+
9
+ const getAppToken = (blocklet) =>
10
+ sign(blocklet.environmentObj?.BLOCKLET_APP_ID, blocklet.environmentObj?.BLOCKLET_APP_SK);
11
+
12
+ const getAppId = (blocklet) => blocklet.environmentObj?.BLOCKLET_APP_ID;
13
+
14
+ const getAppSK = (blocklet) => blocklet.environmentObj?.BLOCKLET_APP_SK;
15
+
16
+ const getBlockletDid = (blocklet) => blocklet.meta?.bundleDid;
17
+
18
+ const getAppUrl = (blocklet) => blocklet.environmentObj?.BLOCKLET_APP_URL;
19
+
20
+ /**
21
+ * verify manages the permissions of blocklet public instance
22
+ * @param {*} blocklet
23
+ * @returns bool
24
+ */
25
+ const verifyPublicInstance = (blocklet) => {
26
+ const { whoCanAccess = WHO_CAN_ACCESS.ALL } = blocklet.settings;
27
+ return blocklet.source === BlockletSource.registry && whoCanAccess === WHO_CAN_ACCESS.ALL;
28
+ };
29
+
30
+ /**
31
+ *
32
+ * @param {*} blocklet
33
+ * @param {*} {userDid publicToStore}
34
+ * @returns bool
35
+ */
36
+ async function handleInstanceInStore(blocklet, { userDid = null, publicToStore = false } = {}) {
37
+ if (!blocklet) {
38
+ logger.error('blocklet argument is required');
39
+ throw new Error('blocklet argument is required');
40
+ }
41
+
42
+ const ownerDid = userDid || blocklet.settings?.owner?.did;
43
+ if (!ownerDid) {
44
+ return false;
45
+ }
46
+
47
+ if (!verifyPublicInstance(blocklet)) {
48
+ logger.error('no permission to set publicInstance');
49
+ throw new Error('no permission to set publicInstance');
50
+ }
51
+
52
+ const appToken = getAppToken(blocklet);
53
+ const blockletDid = getBlockletDid(blocklet);
54
+ const appId = getAppId(blocklet);
55
+ const appSK = getAppSK(blocklet);
56
+ const wallet = getWallet(appSK);
57
+ const body = {
58
+ appToken,
59
+ appId,
60
+ appPK: wallet.publicKey,
61
+ ownerDid,
62
+ appUrl: getAppUrl(blocklet),
63
+ blockletDid,
64
+ };
65
+
66
+ const api = axios.create({ baseURL: blocklet.deployedFrom, timeout: 1000 * 10 });
67
+ if (!publicToStore) {
68
+ try {
69
+ await api.delete(`/api/blocklet-instances/${appId}`, { data: body });
70
+ } catch (error) {
71
+ logger.error('failed to delete blocklet instance', { error });
72
+ throw new Error('failed to delete blocklet instance');
73
+ }
74
+ } else {
75
+ try {
76
+ await api.put(`/api/blocklet-instances/${appId}`, body);
77
+ } catch (error) {
78
+ logger.error('failed to update blocklet instance', { error });
79
+ throw new Error('failed to delete blocklet instance');
80
+ }
81
+ }
82
+ return true;
83
+ }
84
+
85
+ module.exports = handleInstanceInStore;
@@ -126,7 +126,7 @@ const updateSite = Joi.object({
126
126
  )
127
127
  .optional()
128
128
  .messages(domainMessages),
129
- });
129
+ }).unknown();
130
130
 
131
131
  const addRuleSchema = Joi.object({
132
132
  id: Joi.string().required(),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.2",
6
+ "version": "1.8.3",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,31 +19,31 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/certificate-manager": "1.8.2",
23
- "@abtnode/constant": "1.8.2",
24
- "@abtnode/cron": "1.8.2",
25
- "@abtnode/db": "1.8.2",
26
- "@abtnode/logger": "1.8.2",
27
- "@abtnode/queue": "1.8.2",
28
- "@abtnode/rbac": "1.8.2",
29
- "@abtnode/router-provider": "1.8.2",
30
- "@abtnode/static-server": "1.8.2",
31
- "@abtnode/timemachine": "1.8.2",
32
- "@abtnode/util": "1.8.2",
33
- "@arcblock/did": "1.17.2",
22
+ "@abtnode/certificate-manager": "1.8.3",
23
+ "@abtnode/constant": "1.8.3",
24
+ "@abtnode/cron": "1.8.3",
25
+ "@abtnode/db": "1.8.3",
26
+ "@abtnode/logger": "1.8.3",
27
+ "@abtnode/queue": "1.8.3",
28
+ "@abtnode/rbac": "1.8.3",
29
+ "@abtnode/router-provider": "1.8.3",
30
+ "@abtnode/static-server": "1.8.3",
31
+ "@abtnode/timemachine": "1.8.3",
32
+ "@abtnode/util": "1.8.3",
33
+ "@arcblock/did": "1.17.5",
34
34
  "@arcblock/did-motif": "^1.1.10",
35
- "@arcblock/did-util": "1.17.2",
36
- "@arcblock/event-hub": "1.17.2",
37
- "@arcblock/jwt": "^1.17.2",
35
+ "@arcblock/did-util": "1.17.5",
36
+ "@arcblock/event-hub": "1.17.5",
37
+ "@arcblock/jwt": "^1.17.5",
38
38
  "@arcblock/pm2-events": "^0.0.5",
39
- "@arcblock/vc": "1.17.2",
40
- "@blocklet/meta": "1.8.2",
39
+ "@arcblock/vc": "1.17.5",
40
+ "@blocklet/meta": "1.8.3",
41
41
  "@fidm/x509": "^1.2.1",
42
42
  "@nedb/core": "^1.3.1",
43
43
  "@nedb/multi": "^1.3.1",
44
- "@ocap/mcrypto": "1.17.2",
45
- "@ocap/util": "1.17.2",
46
- "@ocap/wallet": "1.17.2",
44
+ "@ocap/mcrypto": "1.17.5",
45
+ "@ocap/util": "1.17.5",
46
+ "@ocap/wallet": "1.17.5",
47
47
  "@slack/webhook": "^5.0.3",
48
48
  "axios": "^0.27.2",
49
49
  "axon": "^2.0.3",
@@ -81,5 +81,5 @@
81
81
  "express": "^4.17.1",
82
82
  "jest": "^27.4.5"
83
83
  },
84
- "gitHead": "fcbe3c97f3825c507ee16714f49bbf8f58c5b59f"
84
+ "gitHead": "c734aca7bf1fc03378c3b082d0622b6a540a8bd3"
85
85
  }