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

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,7 +10,6 @@ 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');
14
13
  const { sign } = require('@arcblock/jwt');
15
14
  const sleep = require('@abtnode/util/lib/sleep');
16
15
  const getBlockletInfo = require('@blocklet/meta/lib/info');
@@ -102,7 +101,7 @@ const formatContext = require('@abtnode/util/lib/format-context');
102
101
  const md5 = require('@abtnode/util/lib/md5');
103
102
  const { callFederated } = require('@abtnode/auth/lib/util/federated');
104
103
  const pAll = require('p-all');
105
- const { consumeServerlessNFT, consumeLauncherSession } = require('../../util/launcher');
104
+ const launcher = require('../../util/launcher');
106
105
  const util = require('../../util');
107
106
  const {
108
107
  refresh: refreshAccessibleExternalNodeIp,
@@ -140,7 +139,6 @@ const {
140
139
  getProcessState,
141
140
  getBlockletStatus,
142
141
  shouldSkipComponent,
143
- exceedRedemptionPeriod,
144
142
  ensureAppPortsNotOccupied,
145
143
  getComponentNamesWithVersion,
146
144
  updateDidDocument: updateBlockletDocument,
@@ -264,6 +262,7 @@ class DiskBlockletManager extends BaseBlockletManager {
264
262
  backupQueue,
265
263
  restoreQueue,
266
264
  checkUpdateQueue,
265
+ reportComponentUsageQueue,
267
266
  daemon = false,
268
267
  teamManager,
269
268
  }) {
@@ -279,6 +278,7 @@ class DiskBlockletManager extends BaseBlockletManager {
279
278
  this.backupQueue = backupQueue;
280
279
  this.restoreQueue = restoreQueue;
281
280
  this.checkUpdateQueue = checkUpdateQueue;
281
+ this.reportComponentUsageQueue = reportComponentUsageQueue;
282
282
  this.teamManager = teamManager;
283
283
 
284
284
  if (isFunction(this.backupQueue.on)) {
@@ -1196,6 +1196,27 @@ 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
+
1199
1220
  await this._updateDependents(rootDid);
1200
1221
 
1201
1222
  // support edge case
@@ -2025,6 +2046,10 @@ class DiskBlockletManager extends BaseBlockletManager {
2025
2046
  if (job.action === 'autoCheckUpdate') {
2026
2047
  await this._onCheckForComponentUpdate(job);
2027
2048
  }
2049
+
2050
+ if (job.action === 'reportComponentUsage') {
2051
+ await this._reportComponentUsage(job);
2052
+ }
2028
2053
  }
2029
2054
  }
2030
2055
 
@@ -2069,7 +2094,7 @@ class DiskBlockletManager extends BaseBlockletManager {
2069
2094
  },
2070
2095
  {
2071
2096
  name: 'clean-expired-blocklet-data',
2072
- time: '0 */20 0 * * *', // 每天凌晨 0 点的每 20 分钟
2097
+ time: '0 10 0 * * *', // 每天凌晨 0:10
2073
2098
  options: { runOnInit: false },
2074
2099
  fn: () => this.cleanExpiredBlocklets(),
2075
2100
  },
@@ -2526,6 +2551,23 @@ class DiskBlockletManager extends BaseBlockletManager {
2526
2551
  context,
2527
2552
  action: postAction,
2528
2553
  });
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
+ }
2529
2571
  } catch (err) {
2530
2572
  logger.error('blocklet onUpgrade error', { error: err });
2531
2573
  }
@@ -2925,6 +2967,25 @@ class DiskBlockletManager extends BaseBlockletManager {
2925
2967
  }
2926
2968
  }
2927
2969
 
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
+
2928
2989
  /**
2929
2990
  * @description send notification to multiple users, and send different notifications according to the user's own language
2930
2991
  * @param {{
@@ -3345,10 +3406,10 @@ class DiskBlockletManager extends BaseBlockletManager {
3345
3406
  if (blocklet.controller && process.env.NODE_ENV !== 'test') {
3346
3407
  let isNFTConsumed = false;
3347
3408
  if (blocklet.controller.launcherSessionId && blocklet.controller.launcherUrl) {
3348
- await consumeLauncherSession({ params: blocklet.controller, blocklet });
3409
+ await launcher.consumeLauncherSession({ params: blocklet.controller, blocklet });
3349
3410
  isNFTConsumed = true;
3350
3411
  } else if (blocklet.controller.nftId) {
3351
- await consumeServerlessNFT({ nftId: blocklet.controller.nftId, blocklet });
3412
+ await launcher.consumeServerlessNFT({ nftId: blocklet.controller.nftId, blocklet });
3352
3413
  isNFTConsumed = true;
3353
3414
  }
3354
3415
 
@@ -3920,8 +3981,8 @@ class DiskBlockletManager extends BaseBlockletManager {
3920
3981
  continue;
3921
3982
  }
3922
3983
 
3923
- const assetState = await util.getNFTState(data.controller.chainHost, data.controller.nftId);
3924
- const isExpired = isNFTExpired(assetState);
3984
+ const isExpired = await launcher.isBlockletExpired(data.did, data.controller);
3985
+
3925
3986
  if (isExpired === false) {
3926
3987
  logger.info('blocklet is renewed', { did: data.did });
3927
3988
  await states.blockletExtras.updateByDid(data.did, {
@@ -3955,24 +4016,21 @@ class DiskBlockletManager extends BaseBlockletManager {
3955
4016
  );
3956
4017
 
3957
4018
  if (blockletExtras.length === 0) {
3958
- logger.info('no expired blocklet');
4019
+ logger.info('no serverless blocklet');
3959
4020
  return;
3960
4021
  }
3961
4022
 
3962
- logger.info('expired blocklet count', { count: blockletExtras.length });
4023
+ logger.info('serverless blocklet count', { count: blockletExtras.length });
3963
4024
 
3964
4025
  for (const data of blockletExtras) {
3965
4026
  try {
3966
4027
  const { did } = data;
3967
- const assetState = await util.getNFTState(data.controller.chainHost, data.controller.nftId);
3968
- const isExpired = isNFTExpired(assetState);
4028
+ const isExpired = await launcher.isBlockletExpired(did, data.controller);
3969
4029
 
3970
4030
  if (isExpired) {
3971
- const expiredAt = getNftExpirationDate(assetState);
3972
4031
  logger.info('the blocklet already expired and will be stopped', {
3973
4032
  blockletDid: did,
3974
4033
  nftId: data.controller.nftId,
3975
- expiredAt,
3976
4034
  });
3977
4035
 
3978
4036
  // 如果 Blocklet 没停止, 先停止
@@ -4028,13 +4086,11 @@ class DiskBlockletManager extends BaseBlockletManager {
4028
4086
  for (const data of blockletExtras) {
4029
4087
  try {
4030
4088
  const { did } = data;
4031
- const assetState = await util.getNFTState(data.controller.chainHost, data.controller.nftId);
4032
- const expiredAt = getNftExpirationDate(assetState);
4089
+ const isTerminated = await launcher.isBlockletTerminated(did, data.controller);
4033
4090
 
4034
- if (!exceedRedemptionPeriod(expiredAt)) {
4035
- logger.error('skip cleaning the non-exceed redemption blocklet', {
4091
+ if (!isTerminated) {
4092
+ logger.info('skip cleaning the non-exceed redemption blocklet', {
4036
4093
  blockletDid: did,
4037
- expiredAt,
4038
4094
  });
4039
4095
  // eslint-disable-next-line no-continue
4040
4096
  continue;
@@ -4043,7 +4099,6 @@ class DiskBlockletManager extends BaseBlockletManager {
4043
4099
  logger.info('the blocklet already exceed redemption and will be deleted', {
4044
4100
  blockletDid: did,
4045
4101
  nftId: data.controller.nftId,
4046
- expiredAt,
4047
4102
  });
4048
4103
 
4049
4104
  // TODO: 如果绑定了 DID Space 备份到 DID Space
@@ -4274,9 +4329,9 @@ class DiskBlockletManager extends BaseBlockletManager {
4274
4329
  return;
4275
4330
  }
4276
4331
 
4277
- const assetState = await util.getNFTState(blocklet.controller?.chainHost, blocklet.controller?.nftId);
4332
+ const isExpired = await launcher.isBlockletExpired(blocklet.meta.did, blocklet.controller);
4278
4333
 
4279
- if (isNFTExpired(assetState)) {
4334
+ if (isExpired) {
4280
4335
  logger.error(`try to ${action} an expired blocklet`, {
4281
4336
  did: blocklet.meta.did,
4282
4337
  nftId: blocklet.controller?.nftId,
@@ -53,16 +53,6 @@ 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
-
66
56
  let blockletWalletType;
67
57
 
68
58
  // create component
package/lib/index.js CHANGED
@@ -189,6 +189,26 @@ 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
+
192
212
  const certManager = new Cert({
193
213
  maintainerEmail: DEFAULT_CERTIFICATE_EMAIL,
194
214
  dataDir: dataDirs.certManagerModule,
@@ -216,6 +236,7 @@ function ABTNode(options) {
216
236
  backupQueue,
217
237
  restoreQueue,
218
238
  checkUpdateQueue,
239
+ reportComponentUsageQueue,
219
240
  daemon: options.daemon,
220
241
  teamManager,
221
242
  });
@@ -2,7 +2,6 @@
2
2
 
3
3
  const fs = require('fs-extra');
4
4
  const path = require('path');
5
- const dayjs = require('@abtnode/util/lib/dayjs');
6
5
  const shelljs = require('shelljs');
7
6
  const os = require('os');
8
7
  const tar = require('tar');
@@ -38,7 +37,6 @@ const {
38
37
  BLOCKLET_MAX_MEM_LIMIT_IN_MB,
39
38
  BLOCKLET_INSTALL_TYPE,
40
39
  APP_STRUCT_VERSION,
41
- EXPIRED_BLOCKLET_DATA_RETENTION_DAYS,
42
40
  NODE_MODES,
43
41
  } = require('@abtnode/constant');
44
42
  const {
@@ -1801,10 +1799,6 @@ const shouldSkipComponent = (componentDid, whiteList) => {
1801
1799
  return !arr.includes(componentDid);
1802
1800
  };
1803
1801
 
1804
- const exceedRedemptionPeriod = (expirationDate) => {
1805
- return dayjs().diff(dayjs(expirationDate), 'day') > EXPIRED_BLOCKLET_DATA_RETENTION_DAYS;
1806
- };
1807
-
1808
1802
  const ensureAppPortsNotOccupied = async ({
1809
1803
  blocklet,
1810
1804
  componentDids: inputDids,
@@ -1858,7 +1852,7 @@ const getComponentNamesWithVersion = (app = {}, componentDids = []) => {
1858
1852
  };
1859
1853
 
1860
1854
  const shouldEnableSlpDomain = ({ mode, launcher }) => {
1861
- if (process.env.NODE_ENV === 'development' && process.env.ABT_NODE_ENABLE_SLP_DOMAIN === 'true') {
1855
+ if (process.env.ABT_NODE_ENABLE_SLP_DOMAIN === 'true') {
1862
1856
  return true;
1863
1857
  }
1864
1858
 
@@ -2045,7 +2039,6 @@ module.exports = {
2045
2039
  getBlockletStatus,
2046
2040
  shouldSkipComponent,
2047
2041
  getBlockletURLForLauncher,
2048
- exceedRedemptionPeriod,
2049
2042
  ensureAppPortsNotOccupied,
2050
2043
  getComponentNamesWithVersion,
2051
2044
  updateDidDocument,
@@ -2,6 +2,7 @@ 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');
5
6
  const isEmpty = require('lodash/isEmpty');
6
7
  const {
7
8
  getUserAvatarUrl,
@@ -24,6 +25,7 @@ const {
24
25
  NODE_DATA_DIR_NAME,
25
26
  USER_AVATAR_URL_PREFIX,
26
27
  ROLES,
28
+ LAUNCH_SESSION_STATUS,
27
29
  } = require('@abtnode/constant');
28
30
 
29
31
  const logger = require('@abtnode/logger')('@abtnode/core:util:launcher');
@@ -58,16 +60,58 @@ const consumeServerlessNFT = async ({ nftId, blocklet }) => {
58
60
  }
59
61
  };
60
62
 
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
+
61
96
  const consumeLauncherSession = async ({ params, blocklet }) => {
62
97
  try {
63
98
  const info = await states.node.read();
64
99
  const { name } = getBlockletInfo(blocklet, info.sk);
65
100
  const appUrl = getBlockletURLForLauncher({ blocklet, nodeInfo: info });
66
101
 
102
+ let componentDids = blocklet.children.map((x) => x.meta.did);
103
+ componentDids = uniq(componentDids);
104
+
67
105
  const result = await doRequest(info.sk, {
68
106
  launcherUrl: params.launcherUrl,
69
107
  pathname: `/api/launches/${params.launcherSessionId}/installed`,
70
- payload: { appDid: blocklet.appPid, appUrl, appName: name, ownerDid: params.ownerDid },
108
+ payload: {
109
+ appDid: blocklet.appPid,
110
+ appUrl,
111
+ appName: name,
112
+ ownerDid: params.ownerDid,
113
+ componentDids,
114
+ },
71
115
  method: 'post',
72
116
  });
73
117
 
@@ -213,7 +257,14 @@ const getLauncherSession = async ({ launcherUrl, launcherSessionId, external = t
213
257
 
214
258
  // strip sensitive data if call from external
215
259
  if (external && result.launcherSession) {
216
- result.launcherSession = pick(result.launcherSession, ['_id', 'status']);
260
+ result.launcherSession = pick(result.launcherSession, [
261
+ '_id',
262
+ 'status',
263
+ 'statusText',
264
+ 'subscription',
265
+ 'expirationDate',
266
+ 'reservedUntil',
267
+ ]);
217
268
  }
218
269
 
219
270
  return result;
@@ -240,10 +291,42 @@ const isLauncherSessionConsumed = async (params) => {
240
291
  return consumed;
241
292
  };
242
293
 
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
+
243
323
  module.exports = {
244
324
  consumeServerlessNFT,
245
325
  consumeLauncherSession,
326
+ reportComponentsEvent,
246
327
  setupAppOwner,
247
328
  getLauncherSession,
248
329
  isLauncherSessionConsumed,
330
+ isBlockletExpired,
331
+ isBlockletTerminated,
249
332
  };
@@ -14,7 +14,6 @@ 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),
18
17
  launcherUrl: Joi.string().uri().optional(),
19
18
  launcherSessionId: Joi.string().optional(),
20
19
  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-be3a37f4",
6
+ "version": "1.16.25-next-0ba03ffc",
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-be3a37f4",
23
- "@abtnode/auth": "1.16.25-next-be3a37f4",
24
- "@abtnode/certificate-manager": "1.16.25-next-be3a37f4",
25
- "@abtnode/constant": "1.16.25-next-be3a37f4",
26
- "@abtnode/cron": "1.16.25-next-be3a37f4",
27
- "@abtnode/logger": "1.16.25-next-be3a37f4",
28
- "@abtnode/models": "1.16.25-next-be3a37f4",
29
- "@abtnode/queue": "1.16.25-next-be3a37f4",
30
- "@abtnode/rbac": "1.16.25-next-be3a37f4",
31
- "@abtnode/router-provider": "1.16.25-next-be3a37f4",
32
- "@abtnode/static-server": "1.16.25-next-be3a37f4",
33
- "@abtnode/timemachine": "1.16.25-next-be3a37f4",
34
- "@abtnode/util": "1.16.25-next-be3a37f4",
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",
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-be3a37f4",
46
- "@blocklet/env": "1.16.25-next-be3a37f4",
47
- "@blocklet/meta": "1.16.25-next-be3a37f4",
48
- "@blocklet/resolver": "1.16.25-next-be3a37f4",
49
- "@blocklet/sdk": "1.16.25-next-be3a37f4",
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",
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": "908fb6a1dbf4f815474f02879990e5888c3e8577"
105
+ "gitHead": "4003cb3e4d32c47cdf097b00b551959db4d5d31a"
106
106
  }