@abtnode/core 1.16.25-next-0ba03ffc → 1.16.25-next-44800645

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.
@@ -10,6 +10,7 @@ const merge = require('lodash/merge');
10
10
  const pick = require('lodash/pick');
11
11
  const isEmpty = require('lodash/isEmpty');
12
12
  const cloneDeep = require('lodash/cloneDeep');
13
+ const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
13
14
  const { sign } = require('@arcblock/jwt');
14
15
  const sleep = require('@abtnode/util/lib/sleep');
15
16
  const getBlockletInfo = require('@blocklet/meta/lib/info');
@@ -101,7 +102,7 @@ const formatContext = require('@abtnode/util/lib/format-context');
101
102
  const md5 = require('@abtnode/util/lib/md5');
102
103
  const { callFederated } = require('@abtnode/auth/lib/util/federated');
103
104
  const pAll = require('p-all');
104
- const launcher = require('../../util/launcher');
105
+ const { consumeServerlessNFT, consumeLauncherSession } = require('../../util/launcher');
105
106
  const util = require('../../util');
106
107
  const {
107
108
  refresh: refreshAccessibleExternalNodeIp,
@@ -139,6 +140,7 @@ const {
139
140
  getProcessState,
140
141
  getBlockletStatus,
141
142
  shouldSkipComponent,
143
+ exceedRedemptionPeriod,
142
144
  ensureAppPortsNotOccupied,
143
145
  getComponentNamesWithVersion,
144
146
  updateDidDocument: updateBlockletDocument,
@@ -262,7 +264,6 @@ class DiskBlockletManager extends BaseBlockletManager {
262
264
  backupQueue,
263
265
  restoreQueue,
264
266
  checkUpdateQueue,
265
- reportComponentUsageQueue,
266
267
  daemon = false,
267
268
  teamManager,
268
269
  }) {
@@ -278,7 +279,6 @@ class DiskBlockletManager extends BaseBlockletManager {
278
279
  this.backupQueue = backupQueue;
279
280
  this.restoreQueue = restoreQueue;
280
281
  this.checkUpdateQueue = checkUpdateQueue;
281
- this.reportComponentUsageQueue = reportComponentUsageQueue;
282
282
  this.teamManager = teamManager;
283
283
 
284
284
  if (isFunction(this.backupQueue.on)) {
@@ -1196,27 +1196,6 @@ class DiskBlockletManager extends BaseBlockletManager {
1196
1196
 
1197
1197
  const newBlocklet = await this.getBlocklet(rootDid);
1198
1198
 
1199
- if (newBlocklet.controller) {
1200
- const componentDids = [did];
1201
- const eventType = 'uninstall';
1202
-
1203
- this.reportComponentUsageQueue.push({
1204
- entity: 'blocklet',
1205
- action: 'reportComponentUsage',
1206
- did: newBlocklet.meta.did,
1207
- time: new Date().toISOString(),
1208
- componentDids,
1209
- eventType,
1210
- context,
1211
- });
1212
-
1213
- logger.info('pushed reporting uninstall components event job to queue', {
1214
- did: newBlocklet.meta.did,
1215
- componentDids,
1216
- eventType,
1217
- });
1218
- }
1219
-
1220
1199
  await this._updateDependents(rootDid);
1221
1200
 
1222
1201
  // support edge case
@@ -2046,10 +2025,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2046
2025
  if (job.action === 'autoCheckUpdate') {
2047
2026
  await this._onCheckForComponentUpdate(job);
2048
2027
  }
2049
-
2050
- if (job.action === 'reportComponentUsage') {
2051
- await this._reportComponentUsage(job);
2052
- }
2053
2028
  }
2054
2029
  }
2055
2030
 
@@ -2094,7 +2069,7 @@ class DiskBlockletManager extends BaseBlockletManager {
2094
2069
  },
2095
2070
  {
2096
2071
  name: 'clean-expired-blocklet-data',
2097
- time: '0 10 0 * * *', // 每天凌晨 0:10
2072
+ time: '0 */20 0 * * *', // 每天凌晨 0 点的每 20 分钟
2098
2073
  options: { runOnInit: false },
2099
2074
  fn: () => this.cleanExpiredBlocklets(),
2100
2075
  },
@@ -2551,23 +2526,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2551
2526
  context,
2552
2527
  action: postAction,
2553
2528
  });
2554
-
2555
- const newBlocklet = await this.getBlocklet(did);
2556
- if (newBlocklet.controller) {
2557
- const eventType = 'install';
2558
-
2559
- this.reportComponentUsageQueue.push({
2560
- entity: 'blocklet',
2561
- action: 'reportComponentUsage',
2562
- time: new Date().toISOString(),
2563
- did,
2564
- componentDids,
2565
- eventType: 'install',
2566
- context,
2567
- });
2568
-
2569
- logger.info('pushed reporting install components event job to queue', { did, componentDids, eventType });
2570
- }
2571
2529
  } catch (err) {
2572
2530
  logger.error('blocklet onUpgrade error', { error: err });
2573
2531
  }
@@ -2967,25 +2925,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2967
2925
  }
2968
2926
  }
2969
2927
 
2970
- async _reportComponentUsage({ did, componentDids, eventType, time }) {
2971
- try {
2972
- logger.info('start report component usage', { did, componentDids, eventType });
2973
-
2974
- const blocklet = await this.getBlocklet(did);
2975
- await launcher.reportComponentsEvent({
2976
- blocklet,
2977
- dids: componentDids,
2978
- type: eventType,
2979
- time: time || new Date().toISOString(),
2980
- });
2981
-
2982
- logger.info('report component usage success', { did, componentDids, eventType });
2983
- } catch (error) {
2984
- logger.error('report component usage failed', { did, componentDids, eventType, error });
2985
- throw error; // 一定要 throw 出去,否则会导致队列任务不会重试
2986
- }
2987
- }
2988
-
2989
2928
  /**
2990
2929
  * @description send notification to multiple users, and send different notifications according to the user's own language
2991
2930
  * @param {{
@@ -3406,10 +3345,10 @@ class DiskBlockletManager extends BaseBlockletManager {
3406
3345
  if (blocklet.controller && process.env.NODE_ENV !== 'test') {
3407
3346
  let isNFTConsumed = false;
3408
3347
  if (blocklet.controller.launcherSessionId && blocklet.controller.launcherUrl) {
3409
- await launcher.consumeLauncherSession({ params: blocklet.controller, blocklet });
3348
+ await consumeLauncherSession({ params: blocklet.controller, blocklet });
3410
3349
  isNFTConsumed = true;
3411
3350
  } else if (blocklet.controller.nftId) {
3412
- await launcher.consumeServerlessNFT({ nftId: blocklet.controller.nftId, blocklet });
3351
+ await consumeServerlessNFT({ nftId: blocklet.controller.nftId, blocklet });
3413
3352
  isNFTConsumed = true;
3414
3353
  }
3415
3354
 
@@ -3981,8 +3920,8 @@ class DiskBlockletManager extends BaseBlockletManager {
3981
3920
  continue;
3982
3921
  }
3983
3922
 
3984
- const isExpired = await launcher.isBlockletExpired(data.did, data.controller);
3985
-
3923
+ const assetState = await util.getNFTState(data.controller.chainHost, data.controller.nftId);
3924
+ const isExpired = isNFTExpired(assetState);
3986
3925
  if (isExpired === false) {
3987
3926
  logger.info('blocklet is renewed', { did: data.did });
3988
3927
  await states.blockletExtras.updateByDid(data.did, {
@@ -4016,21 +3955,24 @@ class DiskBlockletManager extends BaseBlockletManager {
4016
3955
  );
4017
3956
 
4018
3957
  if (blockletExtras.length === 0) {
4019
- logger.info('no serverless blocklet');
3958
+ logger.info('no expired blocklet');
4020
3959
  return;
4021
3960
  }
4022
3961
 
4023
- logger.info('serverless blocklet count', { count: blockletExtras.length });
3962
+ logger.info('expired blocklet count', { count: blockletExtras.length });
4024
3963
 
4025
3964
  for (const data of blockletExtras) {
4026
3965
  try {
4027
3966
  const { did } = data;
4028
- const isExpired = await launcher.isBlockletExpired(did, data.controller);
3967
+ const assetState = await util.getNFTState(data.controller.chainHost, data.controller.nftId);
3968
+ const isExpired = isNFTExpired(assetState);
4029
3969
 
4030
3970
  if (isExpired) {
3971
+ const expiredAt = getNftExpirationDate(assetState);
4031
3972
  logger.info('the blocklet already expired and will be stopped', {
4032
3973
  blockletDid: did,
4033
3974
  nftId: data.controller.nftId,
3975
+ expiredAt,
4034
3976
  });
4035
3977
 
4036
3978
  // 如果 Blocklet 没停止, 先停止
@@ -4086,11 +4028,13 @@ class DiskBlockletManager extends BaseBlockletManager {
4086
4028
  for (const data of blockletExtras) {
4087
4029
  try {
4088
4030
  const { did } = data;
4089
- const isTerminated = await launcher.isBlockletTerminated(did, data.controller);
4031
+ const assetState = await util.getNFTState(data.controller.chainHost, data.controller.nftId);
4032
+ const expiredAt = getNftExpirationDate(assetState);
4090
4033
 
4091
- if (!isTerminated) {
4092
- logger.info('skip cleaning the non-exceed redemption blocklet', {
4034
+ if (!exceedRedemptionPeriod(expiredAt)) {
4035
+ logger.error('skip cleaning the non-exceed redemption blocklet', {
4093
4036
  blockletDid: did,
4037
+ expiredAt,
4094
4038
  });
4095
4039
  // eslint-disable-next-line no-continue
4096
4040
  continue;
@@ -4099,6 +4043,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4099
4043
  logger.info('the blocklet already exceed redemption and will be deleted', {
4100
4044
  blockletDid: did,
4101
4045
  nftId: data.controller.nftId,
4046
+ expiredAt,
4102
4047
  });
4103
4048
 
4104
4049
  // TODO: 如果绑定了 DID Space 备份到 DID Space
@@ -4329,9 +4274,9 @@ class DiskBlockletManager extends BaseBlockletManager {
4329
4274
  return;
4330
4275
  }
4331
4276
 
4332
- const isExpired = await launcher.isBlockletExpired(blocklet.meta.did, blocklet.controller);
4277
+ const assetState = await util.getNFTState(blocklet.controller?.chainHost, blocklet.controller?.nftId);
4333
4278
 
4334
- if (isExpired) {
4279
+ if (isNFTExpired(assetState)) {
4335
4280
  logger.error(`try to ${action} an expired blocklet`, {
4336
4281
  did: blocklet.meta.did,
4337
4282
  nftId: blocklet.controller?.nftId,
@@ -53,6 +53,16 @@ const installApplicationFromGeneral = async ({
53
53
  throw new Error(`Should not be here: unknown type ${type}`);
54
54
  }
55
55
 
56
+ // check install count
57
+ if (controller?.nftId) {
58
+ const installedCount = await states.blockletExtras.count({ 'controller.nftId': controller.nftId });
59
+ if (installedCount >= (controller.appMaxCount || 1)) {
60
+ throw new Error(
61
+ `You can only install ${controller.appMaxCount} blocklet with this credential: ${controller.nftId}`
62
+ );
63
+ }
64
+ }
65
+
56
66
  let blockletWalletType;
57
67
 
58
68
  // create component
package/lib/index.js CHANGED
@@ -189,26 +189,6 @@ function ABTNode(options) {
189
189
  },
190
190
  });
191
191
 
192
- const reportComponentUsageQueue = createQueue({
193
- daemon: options.daemon,
194
- model: states.job,
195
- name: 'report_component_usage_queue',
196
- onJob: async (job) => {
197
- /* eslint-disable no-use-before-define */
198
-
199
- if (typeof blockletManager.onJob === 'function') {
200
- await blockletManager.onJob(job);
201
- }
202
- },
203
- options: {
204
- concurrency,
205
- maxRetries: 30,
206
- retryDelay: 60 * 1000, // retry after 1 minute
207
- maxTimeout: 60 * 1000 * 30, // throw timeout error after 15 minutes
208
- id: (job) => (job ? md5(`${job.entity}-${job.action}-${job.id}`) : ''),
209
- },
210
- });
211
-
212
192
  const certManager = new Cert({
213
193
  maintainerEmail: DEFAULT_CERTIFICATE_EMAIL,
214
194
  dataDir: dataDirs.certManagerModule,
@@ -236,7 +216,6 @@ function ABTNode(options) {
236
216
  backupQueue,
237
217
  restoreQueue,
238
218
  checkUpdateQueue,
239
- reportComponentUsageQueue,
240
219
  daemon: options.daemon,
241
220
  teamManager,
242
221
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs-extra');
4
4
  const path = require('path');
5
+ const dayjs = require('@abtnode/util/lib/dayjs');
5
6
  const shelljs = require('shelljs');
6
7
  const os = require('os');
7
8
  const tar = require('tar');
@@ -37,6 +38,7 @@ const {
37
38
  BLOCKLET_MAX_MEM_LIMIT_IN_MB,
38
39
  BLOCKLET_INSTALL_TYPE,
39
40
  APP_STRUCT_VERSION,
41
+ EXPIRED_BLOCKLET_DATA_RETENTION_DAYS,
40
42
  NODE_MODES,
41
43
  } = require('@abtnode/constant');
42
44
  const {
@@ -1799,6 +1801,10 @@ const shouldSkipComponent = (componentDid, whiteList) => {
1799
1801
  return !arr.includes(componentDid);
1800
1802
  };
1801
1803
 
1804
+ const exceedRedemptionPeriod = (expirationDate) => {
1805
+ return dayjs().diff(dayjs(expirationDate), 'day') > EXPIRED_BLOCKLET_DATA_RETENTION_DAYS;
1806
+ };
1807
+
1802
1808
  const ensureAppPortsNotOccupied = async ({
1803
1809
  blocklet,
1804
1810
  componentDids: inputDids,
@@ -1852,7 +1858,7 @@ const getComponentNamesWithVersion = (app = {}, componentDids = []) => {
1852
1858
  };
1853
1859
 
1854
1860
  const shouldEnableSlpDomain = ({ mode, launcher }) => {
1855
- if (process.env.ABT_NODE_ENABLE_SLP_DOMAIN === 'true') {
1861
+ if (process.env.NODE_ENV === 'development' && process.env.ABT_NODE_ENABLE_SLP_DOMAIN === 'true') {
1856
1862
  return true;
1857
1863
  }
1858
1864
 
@@ -2039,6 +2045,7 @@ module.exports = {
2039
2045
  getBlockletStatus,
2040
2046
  shouldSkipComponent,
2041
2047
  getBlockletURLForLauncher,
2048
+ exceedRedemptionPeriod,
2042
2049
  ensureAppPortsNotOccupied,
2043
2050
  getComponentNamesWithVersion,
2044
2051
  updateDidDocument,
@@ -2,7 +2,6 @@ const path = require('path');
2
2
  const fs = require('fs-extra');
3
3
  const joinUrl = require('url-join');
4
4
  const pick = require('lodash/pick');
5
- const uniq = require('lodash/uniq');
6
5
  const isEmpty = require('lodash/isEmpty');
7
6
  const {
8
7
  getUserAvatarUrl,
@@ -25,7 +24,6 @@ const {
25
24
  NODE_DATA_DIR_NAME,
26
25
  USER_AVATAR_URL_PREFIX,
27
26
  ROLES,
28
- LAUNCH_SESSION_STATUS,
29
27
  } = require('@abtnode/constant');
30
28
 
31
29
  const logger = require('@abtnode/logger')('@abtnode/core:util:launcher');
@@ -60,58 +58,16 @@ const consumeServerlessNFT = async ({ nftId, blocklet }) => {
60
58
  }
61
59
  };
62
60
 
63
- const reportComponentsEvent = async ({ blocklet, dids, type, time }) => {
64
- const { controller } = blocklet;
65
- const componentDids = uniq(dids);
66
-
67
- const payload = {
68
- componentDids,
69
- type,
70
- time,
71
- };
72
-
73
- try {
74
- const info = await states.node.read();
75
-
76
- const result = await doRequest(info.sk, {
77
- launcherUrl: controller.launcherUrl,
78
- pathname: `/api/launches/${controller.launcherSessionId}/events`,
79
- payload,
80
- method: 'post',
81
- });
82
-
83
- logger.info(`reported components event ${type}`, {
84
- controller,
85
- blockletPid: blocklet.appPid,
86
- componentDids,
87
- type,
88
- result,
89
- });
90
- } catch (error) {
91
- logger.error('report components event failed', { controller, blockletPid: blocklet.appPid, componentDids, type });
92
- throw new Error(`report components event failed of blocklet ${blocklet.appPid}`);
93
- }
94
- };
95
-
96
61
  const consumeLauncherSession = async ({ params, blocklet }) => {
97
62
  try {
98
63
  const info = await states.node.read();
99
64
  const { name } = getBlockletInfo(blocklet, info.sk);
100
65
  const appUrl = getBlockletURLForLauncher({ blocklet, nodeInfo: info });
101
66
 
102
- let componentDids = blocklet.children.map((x) => x.meta.did);
103
- componentDids = uniq(componentDids);
104
-
105
67
  const result = await doRequest(info.sk, {
106
68
  launcherUrl: params.launcherUrl,
107
69
  pathname: `/api/launches/${params.launcherSessionId}/installed`,
108
- payload: {
109
- appDid: blocklet.appPid,
110
- appUrl,
111
- appName: name,
112
- ownerDid: params.ownerDid,
113
- componentDids,
114
- },
70
+ payload: { appDid: blocklet.appPid, appUrl, appName: name, ownerDid: params.ownerDid },
115
71
  method: 'post',
116
72
  });
117
73
 
@@ -257,14 +213,7 @@ const getLauncherSession = async ({ launcherUrl, launcherSessionId, external = t
257
213
 
258
214
  // strip sensitive data if call from external
259
215
  if (external && result.launcherSession) {
260
- result.launcherSession = pick(result.launcherSession, [
261
- '_id',
262
- 'status',
263
- 'statusText',
264
- 'subscription',
265
- 'expirationDate',
266
- 'reservedUntil',
267
- ]);
216
+ result.launcherSession = pick(result.launcherSession, ['_id', 'status']);
268
217
  }
269
218
 
270
219
  return result;
@@ -291,42 +240,10 @@ const isLauncherSessionConsumed = async (params) => {
291
240
  return consumed;
292
241
  };
293
242
 
294
- const getLaunchSessionStatus = async (blockletDid, controller) => {
295
- logger.info('checking blocklet status', { blockletDid, controller });
296
-
297
- const { launcherSessionId } = controller;
298
- // 新版都通过 Launcher 判断过期状态
299
- const { error, launcherSession } = await getLauncherSession({
300
- launcherSessionId,
301
- launcherUrl: controller.launcherUrl || 'https://launcher.arcblock.io/',
302
- });
303
-
304
- if (error) {
305
- logger.error('get launcher session failed', { error, blockletDid, controller });
306
- throw new Error(error);
307
- }
308
-
309
- logger.info('get launcher session success', { launcherSessionId, launcherSession });
310
- return launcherSession.status;
311
- };
312
-
313
- const isBlockletExpired = async (blockletDid, controller) => {
314
- const status = await getLaunchSessionStatus(blockletDid, controller);
315
- return [LAUNCH_SESSION_STATUS.expired, LAUNCH_SESSION_STATUS.terminated].includes(status);
316
- };
317
-
318
- const isBlockletTerminated = async (blockletDid, controller) => {
319
- const status = await getLaunchSessionStatus(blockletDid, controller);
320
- return status === LAUNCH_SESSION_STATUS.terminated;
321
- };
322
-
323
243
  module.exports = {
324
244
  consumeServerlessNFT,
325
245
  consumeLauncherSession,
326
- reportComponentsEvent,
327
246
  setupAppOwner,
328
247
  getLauncherSession,
329
248
  isLauncherSessionConsumed,
330
- isBlockletExpired,
331
- isBlockletTerminated,
332
249
  };
@@ -71,7 +71,11 @@ const ruleSchema = {
71
71
  interfaceName: Joi.string() // root interface
72
72
  .label('interface name')
73
73
  .when('type', { is: ROUTING_RULE_TYPES.BLOCKLET, then: Joi.required() }),
74
- response: Joi.object({ status: Joi.number().required(), contentType: Joi.string(), body: Joi.string().required() })
74
+ response: Joi.object({
75
+ status: Joi.number().required(),
76
+ contentType: Joi.string(),
77
+ body: Joi.string().max(4096).required(),
78
+ })
75
79
  .label('response')
76
80
  .when('type', {
77
81
  is: ROUTING_RULE_TYPES.DIRECT_RESPONSE,
@@ -14,6 +14,7 @@ const blockletController = Joi.object({
14
14
  nftId: Joi.DID().required(),
15
15
  nftOwner: Joi.DID().required(),
16
16
  chainHost: Joi.string().uri().required(),
17
+ appMaxCount: Joi.number().required().min(1),
17
18
  launcherUrl: Joi.string().uri().optional(),
18
19
  launcherSessionId: Joi.string().optional(),
19
20
  ownerDid: Joi.DID().optional(),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.25-next-0ba03ffc",
6
+ "version": "1.16.25-next-44800645",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,19 +19,19 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.25-next-0ba03ffc",
23
- "@abtnode/auth": "1.16.25-next-0ba03ffc",
24
- "@abtnode/certificate-manager": "1.16.25-next-0ba03ffc",
25
- "@abtnode/constant": "1.16.25-next-0ba03ffc",
26
- "@abtnode/cron": "1.16.25-next-0ba03ffc",
27
- "@abtnode/logger": "1.16.25-next-0ba03ffc",
28
- "@abtnode/models": "1.16.25-next-0ba03ffc",
29
- "@abtnode/queue": "1.16.25-next-0ba03ffc",
30
- "@abtnode/rbac": "1.16.25-next-0ba03ffc",
31
- "@abtnode/router-provider": "1.16.25-next-0ba03ffc",
32
- "@abtnode/static-server": "1.16.25-next-0ba03ffc",
33
- "@abtnode/timemachine": "1.16.25-next-0ba03ffc",
34
- "@abtnode/util": "1.16.25-next-0ba03ffc",
22
+ "@abtnode/analytics": "1.16.25-next-44800645",
23
+ "@abtnode/auth": "1.16.25-next-44800645",
24
+ "@abtnode/certificate-manager": "1.16.25-next-44800645",
25
+ "@abtnode/constant": "1.16.25-next-44800645",
26
+ "@abtnode/cron": "1.16.25-next-44800645",
27
+ "@abtnode/logger": "1.16.25-next-44800645",
28
+ "@abtnode/models": "1.16.25-next-44800645",
29
+ "@abtnode/queue": "1.16.25-next-44800645",
30
+ "@abtnode/rbac": "1.16.25-next-44800645",
31
+ "@abtnode/router-provider": "1.16.25-next-44800645",
32
+ "@abtnode/static-server": "1.16.25-next-44800645",
33
+ "@abtnode/timemachine": "1.16.25-next-44800645",
34
+ "@abtnode/util": "1.16.25-next-44800645",
35
35
  "@arcblock/did": "1.18.113",
36
36
  "@arcblock/did-auth": "1.18.113",
37
37
  "@arcblock/did-ext": "^1.18.113",
@@ -42,11 +42,11 @@
42
42
  "@arcblock/pm2-events": "^0.0.5",
43
43
  "@arcblock/validator": "^1.18.113",
44
44
  "@arcblock/vc": "1.18.113",
45
- "@blocklet/constant": "1.16.25-next-0ba03ffc",
46
- "@blocklet/env": "1.16.25-next-0ba03ffc",
47
- "@blocklet/meta": "1.16.25-next-0ba03ffc",
48
- "@blocklet/resolver": "1.16.25-next-0ba03ffc",
49
- "@blocklet/sdk": "1.16.25-next-0ba03ffc",
45
+ "@blocklet/constant": "1.16.25-next-44800645",
46
+ "@blocklet/env": "1.16.25-next-44800645",
47
+ "@blocklet/meta": "1.16.25-next-44800645",
48
+ "@blocklet/resolver": "1.16.25-next-44800645",
49
+ "@blocklet/sdk": "1.16.25-next-44800645",
50
50
  "@did-space/client": "^0.3.69",
51
51
  "@fidm/x509": "^1.2.1",
52
52
  "@ocap/mcrypto": "1.18.113",
@@ -102,5 +102,5 @@
102
102
  "jest": "^29.7.0",
103
103
  "unzipper": "^0.10.11"
104
104
  },
105
- "gitHead": "4003cb3e4d32c47cdf097b00b551959db4d5d31a"
105
+ "gitHead": "7d09cee17eb88bcfe6a4b298a0394c5945aa5f2e"
106
106
  }