@abtnode/core 1.16.0-beta-8ee536d7 → 1.16.0-beta-62b42401

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/lib/api/team.js CHANGED
@@ -12,6 +12,7 @@ const {
12
12
  WELLKNOWN_SERVICE_PATH_PREFIX,
13
13
  MAX_USER_PAGE_SIZE,
14
14
  STORE_DETAIL_PAGE_PATH_PREFIX,
15
+ USER_TYPE,
15
16
  } = require('@abtnode/constant');
16
17
  const { isValid: isValidDid } = require('@arcblock/did');
17
18
  const { BlockletEvents } = require('@blocklet/constant');
@@ -182,6 +183,10 @@ class TeamAPI extends EventEmitter {
182
183
  'remark',
183
184
  'avatar',
184
185
  'locale',
186
+ // oauth relate fields
187
+ 'source',
188
+ 'derivedAccount',
189
+ 'connectedAccounts',
185
190
  ])
186
191
  // eslint-disable-next-line function-paren-newline
187
192
  ),
@@ -592,6 +597,13 @@ class TeamAPI extends EventEmitter {
592
597
 
593
598
  // Issue Passport
594
599
 
600
+ /**
601
+ * 为指定用户颁发 passport
602
+ * @param {string} param.teamDid - 应用的 did
603
+ * @param {string} param.ownerDid - 指定用户的 did
604
+ * @param {string} param.name - passport 的 role
605
+ * @returns {object} passport-info
606
+ */
595
607
  async createPassportIssuance({ teamDid, ownerDid, name }) {
596
608
  if (!name) {
597
609
  throw new Error('Passport cannot be empty');
@@ -613,6 +625,45 @@ class TeamAPI extends EventEmitter {
613
625
  const expireDate = Date.now() + this.memberInviteExpireTime;
614
626
 
615
627
  const state = await this.getSessionState(teamDid);
628
+
629
+ const currentUser = await this.getUser({ teamDid, user: { did: ownerDid } });
630
+ if (currentUser?.source === USER_TYPE.DERIVED) {
631
+ const userDid = currentUser.did;
632
+ const blocklet = await getBlocklet({ did: teamDid, states: this.states, dataDirs: this.dataDirs });
633
+ const nodeInfo = await this.node.read();
634
+ const blockletInfo = getBlockletInfo(blocklet, nodeInfo.sk);
635
+ const { wallet, passportColor, appUrl, name: issuerName } = blockletInfo;
636
+ const vc = createPassportVC({
637
+ issuerName,
638
+ issuerWallet: wallet,
639
+ ownerDid: userDid,
640
+ passport: await createPassport({
641
+ role,
642
+ }),
643
+ endpoint: getPassportStatusEndpoint({
644
+ baseUrl: joinUrl(appUrl, WELLKNOWN_SERVICE_PATH_PREFIX),
645
+ userDid,
646
+ teamDid,
647
+ }),
648
+ ownerProfile: {
649
+ ...currentUser,
650
+ // avatar: await parseUserAvatar(currentUser.avatar, { dataDir: blocklet.env.dataDir }),
651
+ },
652
+ preferredColor: passportColor,
653
+ });
654
+
655
+ // write passport to db
656
+ const passport = createUserPassport(vc, { role: role.name });
657
+ const passports = upsertToPassports(currentUser.passports || [], passport);
658
+ await this.updateUser({
659
+ teamDid,
660
+ user: {
661
+ did: ownerDid,
662
+ passports,
663
+ },
664
+ });
665
+ return undefined;
666
+ }
616
667
  const { id } = await state.start({
617
668
  type: 'passport-issuance',
618
669
  expireDate, // session expireDate
@@ -11,9 +11,11 @@ const cloneDeep = require('lodash/cloneDeep');
11
11
  const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
12
12
  const didDocument = require('@abtnode/util/lib/did-document');
13
13
  const { sign } = require('@arcblock/jwt');
14
+ const { isEthereumDid } = require('@arcblock/did');
14
15
  const { toSvg: createDidLogo } =
15
16
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
16
17
  const getBlockletInfo = require('@blocklet/meta/lib/info');
18
+ const { createBlockiesSvg } = require('@blocklet/meta/lib/blockies');
17
19
  const sleep = require('@abtnode/util/lib/sleep');
18
20
 
19
21
  const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
@@ -60,6 +62,7 @@ const {
60
62
  BLOCKLET_LATEST_SPEC_VERSION,
61
63
  BLOCKLET_META_FILE,
62
64
  BLOCKLET_CONFIGURABLE_KEY,
65
+ RESTORE_PROGRESS_STATUS,
63
66
  } = require('@blocklet/constant');
64
67
  const util = require('../../util');
65
68
  const {
@@ -109,7 +112,10 @@ const handleInstanceInStore = require('../../util/public-to-store');
109
112
  const { BlockletRuntimeMonitor } = require('../../monitor/blocklet-runtime-monitor');
110
113
  const getHistoryList = require('../../monitor/get-history-list');
111
114
  const { SpacesBackup } = require('../storage/backup/spaces');
115
+ const { DiskBackup } = require('../storage/backup/disk');
116
+ const { getBackupList, removeBackup } = require('../storage/utils/disk');
112
117
  const { SpacesRestore } = require('../storage/restore/spaces');
118
+ const { DiskRestore } = require('../storage/restore/disk');
113
119
  const { installApplicationFromGeneral } = require('./helper/install-application-from-general');
114
120
  const { installApplicationFromDev } = require('./helper/install-application-from-dev');
115
121
  const { installApplicationFromBackup } = require('./helper/install-application-from-backup');
@@ -566,51 +572,45 @@ class BlockletManager extends BaseBlockletManager {
566
572
  }
567
573
 
568
574
  /**
569
- * FIXME: @wangshijun create audit log for this
570
- * @param {import('@abtnode/client').RequestBackupToSpacesInput} input
575
+ * @param {import('@abtnode/client').RequestBackupBlockletInput} input
571
576
  * @memberof BlockletManager
572
577
  */
573
578
  // eslint-disable-next-line no-unused-vars
574
- async backupToSpaces({ appDid }, context) {
579
+ async backup({ appDid, to }, context) {
575
580
  const blocklet = await states.blocklet.getBlocklet(appDid);
576
581
  if (blocklet.structVersion !== APP_STRUCT_VERSION) {
577
582
  throw new Error('Only new version app can be backup to spaces, please migrate this app first');
578
583
  }
579
584
 
580
- const userDid = context.user.did;
581
- const { referrer } = context;
585
+ if (to === 'spaces') {
586
+ return this._backupToSpaces({ blocklet }, context);
587
+ }
582
588
 
583
- const spacesBackup = new SpacesBackup({ appDid, event: this, userDid, referrer });
584
- this.emit(BlockletEvents.backupProgress, { appDid, message: 'Start backup...', progress: 10, completed: false });
585
- await spacesBackup.backup();
586
- this.emit(BlockletEvents.backupProgress, { appDid, completed: true, progress: 100 });
589
+ if (to === 'disk') {
590
+ return this._backupToDisk({ blocklet }, context);
591
+ }
592
+
593
+ throw new Error('Can only backup to spaces or disk');
587
594
  }
588
595
 
589
596
  /**
590
597
  * FIXME: @linchen support cancel
591
598
  * FIXME: @wangshijun create audit log for this
592
- * @param {import('@abtnode/client').RequestRestoreFromSpacesInput} input
599
+ * @param {import('@abtnode/client').RequestRestoreBlockletInput} input
593
600
  * @memberof BlockletManager
594
601
  */
595
602
  // eslint-disable-next-line no-unused-vars
596
- async restoreFromSpaces(input, context) {
597
- this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, message: 'Start restore...', completed: false });
598
-
599
- const userDid = context.user.did;
600
-
601
- const spacesRestore = new SpacesRestore({ ...input, event: this, userDid, referrer: context.referrer });
602
- const params = await spacesRestore.restore();
603
+ async restore(input, context) {
604
+ const { from, ...param } = input;
605
+ if (from === 'spaces') {
606
+ return this._restoreFromSpaces(param, context);
607
+ }
603
608
 
604
- this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, message: 'Installing blocklet...' });
605
- await installApplicationFromBackup({
606
- url: `file://${spacesRestore.restoreDir}`,
607
- moveDir: true,
608
- ...merge(...params),
609
- manager: this,
610
- states,
611
- });
609
+ if (from === 'disk') {
610
+ return this._restoreFromDisk(param, context);
611
+ }
612
612
 
613
- this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, completed: true });
613
+ throw new Error('Can only restore from spaces or disk');
614
614
  }
615
615
 
616
616
  /**
@@ -982,6 +982,10 @@ class BlockletManager extends BaseBlockletManager {
982
982
  return blocklets;
983
983
  }
984
984
 
985
+ async listBackups() {
986
+ return getBackupList(this.dataDirs.data);
987
+ }
988
+
985
989
  // CAUTION: this method currently only support config by blocklet.meta.did
986
990
  // eslint-disable-next-line no-unused-vars
987
991
  async config({ did, configs: newConfigs, skipHook, skipDidDocument }, context) {
@@ -1150,6 +1154,15 @@ class BlockletManager extends BaseBlockletManager {
1150
1154
  return blocklet;
1151
1155
  }
1152
1156
 
1157
+ async configOAuth({ did, oauth = {} }) {
1158
+ const oldOAuth = await states.blockletExtras.getSettings(did, 'oauth', {});
1159
+ const mergeConfig = { ...oldOAuth, ...JSON.parse(oauth) };
1160
+ await states.blockletExtras.setSettings(did, { oauth: mergeConfig });
1161
+ const newState = await this.getBlocklet(did);
1162
+ this.emit(BlockletEvents.updated, newState);
1163
+ return newState;
1164
+ }
1165
+
1153
1166
  async updateComponentTitle({ did, rootDid: inputRootDid, title }) {
1154
1167
  await titleSchema.validateAsync(title);
1155
1168
 
@@ -1402,6 +1415,7 @@ class BlockletManager extends BaseBlockletManager {
1402
1415
  throwOnError,
1403
1416
  skipCheckStatusBeforeDownload,
1404
1417
  selectedComponentDids,
1418
+ skipCheckIntegrity,
1405
1419
  } = params;
1406
1420
  const { meta } = blocklet;
1407
1421
  const { name, did, version } = meta;
@@ -1443,7 +1457,10 @@ class BlockletManager extends BaseBlockletManager {
1443
1457
  return x;
1444
1458
  }),
1445
1459
  };
1446
- const { isCancelled } = await this._downloadBlocklet(blockletForDownload, context);
1460
+ const { isCancelled } = await this._downloadBlocklet(
1461
+ blockletForDownload,
1462
+ Object.assign({}, context, { skipCheckIntegrity })
1463
+ );
1447
1464
 
1448
1465
  if (isCancelled) {
1449
1466
  logger.info('Download was canceled', { name, did, version });
@@ -1869,7 +1886,11 @@ class BlockletManager extends BaseBlockletManager {
1869
1886
  await fs.copy(src, dist);
1870
1887
  }
1871
1888
 
1872
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
1889
+ if (isEthereumDid(blocklet.meta.did)) {
1890
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createBlockiesSvg(blocklet.meta.did));
1891
+ } else {
1892
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
1893
+ }
1873
1894
 
1874
1895
  // Init db
1875
1896
  await this.teamManager.initTeam(blocklet.meta.did);
@@ -1910,6 +1931,7 @@ class BlockletManager extends BaseBlockletManager {
1910
1931
  }
1911
1932
 
1912
1933
  await this._rollbackCache.remove({ did: blocklet.meta.did });
1934
+ removeBackup(this.dataDirs.data, blocklet.appDid);
1913
1935
  return blocklet;
1914
1936
  } catch (err) {
1915
1937
  const { meta } = await states.blocklet.getBlocklet(did);
@@ -2473,6 +2495,85 @@ class BlockletManager extends BaseBlockletManager {
2473
2495
 
2474
2496
  await states.blocklet.updateBlocklet(blocklet.meta.did, { children: blocklet.children });
2475
2497
  }
2498
+
2499
+ /**
2500
+ * FIXME: @wangshijun create audit log for this
2501
+ * @param {import('@abtnode/client').BlockletState} blocklet
2502
+ * @memberof BlockletManager
2503
+ */
2504
+ // eslint-disable-next-line no-unused-vars
2505
+ async _backupToSpaces({ blocklet }, context) {
2506
+ const userDid = context.user.did;
2507
+ const { referrer } = context;
2508
+ const { appDid } = blocklet;
2509
+
2510
+ const spacesBackup = new SpacesBackup({ appDid, event: this, userDid, referrer });
2511
+ this.emit(BlockletEvents.backupProgress, { appDid, message: 'Start backup...', progress: 10, completed: false });
2512
+ await spacesBackup.backup();
2513
+ this.emit(BlockletEvents.backupProgress, { appDid, completed: true, progress: 100 });
2514
+ }
2515
+
2516
+ /**
2517
+ * @param {import('@abtnode/client').BlockletState} blocklet
2518
+ */
2519
+ // eslint-disable-next-line no-unused-vars
2520
+ async _backupToDisk({ blocklet }, context) {
2521
+ const { appDid } = blocklet;
2522
+
2523
+ const diskBackup = new DiskBackup({ appDid, event: this });
2524
+ await diskBackup.backup();
2525
+ }
2526
+
2527
+ /**
2528
+ * FIXME: @linchen support cancel
2529
+ * FIXME: @wangshijun create audit log for this
2530
+ * @param {import('@abtnode/client').RequestRestoreBlockletInput} input
2531
+ * @memberof BlockletManager
2532
+ */
2533
+ // eslint-disable-next-line no-unused-vars
2534
+ async _restoreFromSpaces(input, context) {
2535
+ if (input.delay) {
2536
+ await sleep(input.delay);
2537
+ }
2538
+
2539
+ this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, status: RESTORE_PROGRESS_STATUS.start });
2540
+
2541
+ const userDid = context.user.did;
2542
+
2543
+ const spacesRestore = new SpacesRestore({ ...input, event: this, userDid, referrer: context.referrer });
2544
+ const params = await spacesRestore.restore();
2545
+
2546
+ this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, status: RESTORE_PROGRESS_STATUS.installing });
2547
+ await installApplicationFromBackup({
2548
+ url: `file://${spacesRestore.restoreDir}`,
2549
+ moveDir: true,
2550
+ ...merge(...params),
2551
+ manager: this,
2552
+ states,
2553
+ controller: input.controller,
2554
+ context: { ...context, startImmediately: true },
2555
+ });
2556
+
2557
+ this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, status: RESTORE_PROGRESS_STATUS.completed });
2558
+ }
2559
+
2560
+ async _restoreFromDisk(input) {
2561
+ if (input.delay) {
2562
+ await sleep(input.delay);
2563
+ }
2564
+
2565
+ const diskRestore = new DiskRestore({ ...input, event: this });
2566
+ const params = await diskRestore.restore();
2567
+
2568
+ await installApplicationFromBackup({
2569
+ url: `file://${diskRestore.restoreDir}`,
2570
+ ...merge(...params),
2571
+ manager: this,
2572
+ states,
2573
+ move: true,
2574
+ sync: false, // use queue to download and install application
2575
+ });
2576
+ }
2476
2577
  }
2477
2578
 
2478
2579
  module.exports = BlockletManager;
@@ -5,7 +5,7 @@ const omit = require('lodash/omit');
5
5
  const { forEachBlockletSync, getBlockletAppIdList } = require('@blocklet/meta/lib/util');
6
6
  const getBlockletInfo = require('@blocklet/meta/lib/info');
7
7
 
8
- const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
8
+ const { BLOCKLET_CONFIGURABLE_KEY, BlockletEvents, BlockletStatus } = require('@blocklet/constant');
9
9
 
10
10
  const logger = require('@abtnode/logger')('@abtnode/core:install-app-backup');
11
11
 
@@ -18,12 +18,21 @@ const { validateBlocklet, checkDuplicateAppSk, getAppDirs } = require('../../../
18
18
  * /blocklets/<name3>version>
19
19
  * /data
20
20
  * /blocklet.json
21
- * /blocklet_extras.json
21
+ * /blocklet-extras.json
22
22
  * @see Blocklet 端到端备份方案的设计与实现(一期) https://team.arcblock.io/comment/discussions/e62084d5-fafa-489e-91d5-defcd6e93223
23
23
  * @param {{ url: string, appSk: string, moveDir: boolean, manager: import('../disk'), states: import('../../../states/index'), context: Record<string, string> }}
24
24
  * @return {Promise<any>}
25
25
  */
26
- const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {}, states, manager } = {}) => {
26
+ const installApplicationFromBackup = async ({
27
+ url,
28
+ appSk,
29
+ moveDir,
30
+ context = {},
31
+ states,
32
+ manager,
33
+ sync = true,
34
+ controller,
35
+ } = {}) => {
27
36
  // TODO: support more url schema feature (http, did-spaces)
28
37
  if (!url.startsWith('file://')) {
29
38
  throw new Error('url must starts with file://');
@@ -41,7 +50,7 @@ const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {},
41
50
  const srcDataDir = path.join(dir, 'data');
42
51
 
43
52
  /** @type {import('@abtnode/client').BlockletState} */
44
- const state = omit(fs.readJSONSync(path.join(dir, 'blocklet.json')), [
53
+ const blockletState = omit(fs.readJSONSync(path.join(dir, 'blocklet.json')), [
45
54
  '_id',
46
55
  'createdAt',
47
56
  'updatedAt',
@@ -49,22 +58,24 @@ const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {},
49
58
  'startedAt',
50
59
  ]);
51
60
 
52
- if (!state.structVersion) {
61
+ if (!blockletState.structVersion) {
53
62
  throw new Error(
54
63
  'Only application of structVersion 2 can be restored on this server. Please migrate you application and re-backup your application on your previous server.'
55
64
  );
56
65
  }
57
66
 
58
- const { meta } = state;
67
+ const { meta } = blockletState;
59
68
  const { did, name: appName } = meta;
60
69
 
61
70
  const extra = omit(fs.readJSONSync(path.join(dir, 'blocklet-extras.json')), ['_id', 'createdAt', 'updatedAt']);
62
71
 
63
- if (state.meta.did !== extra.did) {
64
- throw new Error(`did does not match in blocklet.json (${state.meta.did}) and blocklet_extra.json ${extra.did}`);
72
+ if (blockletState.meta.did !== extra.did) {
73
+ throw new Error(
74
+ `did does not match in blocklet.json (${blockletState.meta.did}) and blocklet_extra.json ${extra.did}`
75
+ );
65
76
  }
66
77
 
67
- forEachBlockletSync(state, (component) => {
78
+ forEachBlockletSync(blockletState, (component) => {
68
79
  delete component.status;
69
80
  delete component.ports;
70
81
  delete component.environments;
@@ -98,8 +109,11 @@ const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {},
98
109
 
99
110
  // validate appDid
100
111
  const nodeInfo = await states.node.read();
101
- const appIdList = getBlockletAppIdList(state);
102
- const { wallet } = getBlockletInfo({ meta: state.meta, configs: extra.configs, environments: [] }, nodeInfo.sk);
112
+ const appIdList = getBlockletAppIdList(blockletState);
113
+ const { wallet } = getBlockletInfo(
114
+ { meta: blockletState.meta, configs: extra.configs, environments: [] },
115
+ nodeInfo.sk
116
+ );
103
117
  if (appIdList.includes(wallet.address) === false) {
104
118
  throw new Error('blocklet appDid is different from the previous one');
105
119
  }
@@ -117,11 +131,15 @@ const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {},
117
131
  logger.error('old extra state exists and will be force removed', { existExtra });
118
132
  await states.blockletExtras.remove({ did });
119
133
  }
134
+ if (controller) {
135
+ extra.controller = controller;
136
+ }
137
+
120
138
  await states.blockletExtras.insert(extra);
121
139
  logger.info('blocklet extra is copied successfully');
122
140
 
123
141
  // add blocklet
124
- await states.blocklet.addBlocklet(state);
142
+ await states.blocklet.addBlocklet(blockletState);
125
143
  logger.info('blocklet state is added successfully');
126
144
 
127
145
  // copy bundle
@@ -145,9 +163,8 @@ const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {},
145
163
  logger.info(`bundle is ${moveDir ? 'moved' : 'copied'} successfully`, { installDir });
146
164
  })
147
165
  );
148
- // 从 store 下载 blocklet
149
- await manager.blockletDownloader.download(state, { skipCheckIntegrity: true });
150
166
 
167
+ // copy data
151
168
  const dataDir = path.join(manager.dataDirs.data, appName);
152
169
  if (fs.existsSync(dataDir)) {
153
170
  logger.error('old data exists and will be force removed', { dataDir });
@@ -170,8 +187,76 @@ const installApplicationFromBackup = async ({ url, appSk, moveDir, context = {},
170
187
  throw error;
171
188
  }
172
189
 
173
- logger.info('start install blocklet', { did });
174
- return manager._installBlocklet({ did, context });
190
+ if (sync) {
191
+ try {
192
+ logger.info('start download blocklet', { did });
193
+ // 从 store 下载 blocklet
194
+ await manager.blockletDownloader.download(blockletState, { skipCheckIntegrity: true });
195
+ } catch (error) {
196
+ logger.error('download blocklet failed', { did, error });
197
+
198
+ await manager._rollback('install', did);
199
+
200
+ throw error;
201
+ }
202
+ logger.info('start install blocklet', { did });
203
+ return manager._installBlocklet({ did, context });
204
+ }
205
+
206
+ try {
207
+ const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
208
+ manager.emit(BlockletEvents.added, blocklet1);
209
+
210
+ const downloadParams = {
211
+ blocklet: { ...blocklet1 },
212
+ skipCheckIntegrity: true,
213
+ context,
214
+ postAction: 'install',
215
+ };
216
+
217
+ // backup rollback data
218
+ await manager._rollbackCache.backup({ did, action: 'install' });
219
+
220
+ const ticket = manager.installQueue.push(
221
+ {
222
+ entity: 'blocklet',
223
+ action: 'download',
224
+ id: did,
225
+ ...downloadParams,
226
+ },
227
+ did
228
+ );
229
+ ticket.on('failed', async (err) => {
230
+ logger.error('failed to install blocklet', { did, error: err });
231
+ try {
232
+ await manager._rollback('install', did, {});
233
+ } catch (e) {
234
+ logger.error('failed to remove blocklet on install error', { did, error: e });
235
+ }
236
+
237
+ manager._createNotification(did, {
238
+ title: 'Blocklet Install Failed',
239
+ description: `Blocklet ${blockletState?.meta?.title} install failed with error: ${
240
+ err.message || 'queue exception'
241
+ }`,
242
+ entityType: 'blocklet',
243
+ entityId: did,
244
+ severity: 'error',
245
+ });
246
+ });
247
+
248
+ return blocklet1;
249
+ } catch (err) {
250
+ logger.error('failed to install blocklet', { did, error: err });
251
+
252
+ try {
253
+ await manager._rollback('install', did, {});
254
+ } catch (e) {
255
+ logger.error('failed to remove blocklet on install error', { did, error: e });
256
+ }
257
+
258
+ throw err;
259
+ }
175
260
  };
176
261
 
177
262
  module.exports = { installApplicationFromBackup };
@@ -1,5 +1,7 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs-extra');
3
+ const { isEthereumDid } = require('@arcblock/did');
4
+ const { createBlockiesSvg } = require('@blocklet/meta/lib/blockies');
3
5
 
4
6
  const { toSvg: createDidLogo } =
5
7
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
@@ -86,7 +88,11 @@ const installApplicationFromDev = async ({ folder, meta, states, manager } = {})
86
88
 
87
89
  blocklet = await manager.getBlocklet(did);
88
90
 
89
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
91
+ if (isEthereumDid(blocklet.meta.did)) {
92
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createBlockiesSvg(blocklet.meta.did));
93
+ } else {
94
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
95
+ }
90
96
 
91
97
  return blocklet;
92
98
  };
@@ -63,28 +63,16 @@ const installApplicationFromGeneral = async ({
63
63
  }
64
64
  }
65
65
 
66
- // app wallet
67
- const wallet = getApplicationWallet(appSk);
68
- const did = wallet.address;
69
- const name = wallet.address;
70
-
71
- // check exist
72
- const exist = await states.blocklet.hasBlocklet(did);
73
- if (exist) {
74
- throw new Error(`blocklet ${did} already exists`);
75
- }
76
-
77
- // remove dirty data
78
- const oldExtraState = await states.blockletExtras.findOne({ did });
79
- if (oldExtraState) {
80
- logger.error('find dirty data in blocklet extra', { did });
81
- await states.blockletExtras.remove({ did });
82
- }
66
+ let blockletWalletType;
83
67
 
84
68
  // create component
85
69
  let component;
86
70
  if (componentSourceUrl) {
87
71
  const meta = await getBlockletMetaFromUrl(componentSourceUrl);
72
+ const blockletWalletTypeEnv = (meta.environments || []).find((x) => x.name === 'BLOCKLET_WALLET_TYPE');
73
+ if (blockletWalletTypeEnv) {
74
+ blockletWalletType = blockletWalletTypeEnv.default;
75
+ }
88
76
 
89
77
  if (nodeInfo.mode === NODE_MODES.SERVERLESS) {
90
78
  validateInServerless({ blockletMeta: meta });
@@ -97,6 +85,24 @@ const installApplicationFromGeneral = async ({
97
85
  };
98
86
  }
99
87
 
88
+ // app wallet
89
+ const wallet = getApplicationWallet(appSk, undefined, blockletWalletType);
90
+ const did = wallet.address;
91
+ const name = wallet.address;
92
+
93
+ // check exist
94
+ const exist = await states.blocklet.hasBlocklet(did);
95
+ if (exist) {
96
+ throw new Error(`blocklet ${did} already exists`);
97
+ }
98
+
99
+ // remove dirty data
100
+ const oldExtraState = await states.blockletExtras.findOne({ did });
101
+ if (oldExtraState) {
102
+ logger.error('find dirty data in blocklet extra', { did });
103
+ await states.blockletExtras.remove({ did });
104
+ }
105
+
100
106
  // create app
101
107
  const blocklet = await manager._addBlocklet({ component, name, did, title, description });
102
108
  logger.info('blocklet added to database', { did: blocklet.meta.did });
@@ -138,7 +138,7 @@ const diff = async ({ did, hashFiles: clientFiles, rootDid: inputRootDid, states
138
138
 
139
139
  const rootBlocklet = await states.blocklet.getBlocklet(rootDid);
140
140
  if (childDid && !rootBlocklet) {
141
- throw new Error('Root blocklet does not exist');
141
+ throw new Error(`Root blocklet does not exist: ${rootDid}`);
142
142
  }
143
143
 
144
144
  const state = childDid ? await (rootBlocklet.children || []).find((x) => x.meta.did === childDid) : rootBlocklet;