@abtnode/blocklet-services 1.16.6-beta-8be2fe37 → 1.16.6-beta-4ea1eb90
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/api/libs/connect/session.js +4 -4
- package/api/routes/oauth.js +1 -1
- package/api/services/auth/connect/bind-wallet.js +12 -2
- package/api/services/auth/connect/receive-transfer-app-owner.js +15 -8
- package/api/services/dashboard/index.js +1 -0
- package/api/socket/channel/app.js +2 -2
- package/api/socket/channel/did.js +2 -2
- package/api/socket/channel/relay.js +2 -2
- package/api/socket/util.js +2 -2
- package/build/asset-manifest.json +13 -13
- package/build/index.html +1 -1
- package/build/static/js/343.f30fdb24.chunk.js +2 -0
- package/build/static/js/573.fc22f41e.chunk.js +2 -0
- package/build/static/js/{61.20fc6264.chunk.js → 61.3c903dd8.chunk.js} +3 -3
- package/build/static/js/648.5eec48ea.chunk.js +3 -0
- package/build/static/js/{648.b5b229e5.chunk.js.LICENSE.txt → 648.5eec48ea.chunk.js.LICENSE.txt} +10 -0
- package/build/static/js/716.bcea7c98.chunk.js +2 -0
- package/build/static/js/main.00308947.js +3 -0
- package/package.json +34 -34
- package/build/static/js/343.54712c04.chunk.js +0 -2
- package/build/static/js/573.2052cb80.chunk.js +0 -2
- package/build/static/js/648.b5b229e5.chunk.js +0 -3
- package/build/static/js/716.874040d8.chunk.js +0 -2
- package/build/static/js/main.88eb4897.js +0 -3
- /package/build/static/js/{61.20fc6264.chunk.js.LICENSE.txt → 61.3c903dd8.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{main.88eb4897.js.LICENSE.txt → main.00308947.js.LICENSE.txt} +0 -0
|
@@ -616,7 +616,7 @@ module.exports = {
|
|
|
616
616
|
|
|
617
617
|
// 基本流程与 login 一致,但在创建更新用户信息的逻辑不一样
|
|
618
618
|
bindWallet: {
|
|
619
|
-
onConnect: async ({ node, request, userDid, locale, passportId = '', componentId }) => {
|
|
619
|
+
onConnect: async ({ node, request, userDid, locale, passportId = '', componentId, previousUserDid }) => {
|
|
620
620
|
const translations = {
|
|
621
621
|
en: {
|
|
622
622
|
notFound: "Can't get bind account information",
|
|
@@ -640,7 +640,7 @@ module.exports = {
|
|
|
640
640
|
}
|
|
641
641
|
|
|
642
642
|
const config = await request.getServiceConfig(NODE_SERVICES.AUTH, { componentId });
|
|
643
|
-
let oauthUser = await getRawUser(teamDid,
|
|
643
|
+
let oauthUser = await getRawUser(teamDid, previousUserDid, {
|
|
644
644
|
getUser: node.getUser,
|
|
645
645
|
getUsers: node.getUsers,
|
|
646
646
|
});
|
|
@@ -694,11 +694,11 @@ module.exports = {
|
|
|
694
694
|
|
|
695
695
|
return claims;
|
|
696
696
|
},
|
|
697
|
-
onApprove: async ({ node, request, locale, userDid, userPk, claims }) => {
|
|
697
|
+
onApprove: async ({ node, request, locale, userDid, userPk, claims, previousUserDid }) => {
|
|
698
698
|
const blocklet = await request.getBlocklet();
|
|
699
699
|
const { did: teamDid, wallet: blockletWallet } = await request.getBlockletInfo();
|
|
700
700
|
|
|
701
|
-
const oauthUser = await node.getUser({ teamDid, user: { did:
|
|
701
|
+
const oauthUser = await node.getUser({ teamDid, user: { did: previousUserDid } });
|
|
702
702
|
const nodeInfo = await request.getNodeInfo();
|
|
703
703
|
// Check user approved
|
|
704
704
|
let bindUser = await getRawUser(teamDid, userDid, {
|
package/api/routes/oauth.js
CHANGED
|
@@ -7,7 +7,7 @@ const { onConnect, onApprove } = bindWallet;
|
|
|
7
7
|
module.exports = function createRoutes(node, authenticator, createSessionToken) {
|
|
8
8
|
return {
|
|
9
9
|
action: 'bind-wallet',
|
|
10
|
-
onConnect: async ({ req, userDid, extraParams: { locale, passportId = '', componentId } }) => {
|
|
10
|
+
onConnect: async ({ req, userDid, extraParams: { locale, passportId = '', componentId, previousUserDid } }) => {
|
|
11
11
|
return onConnect({
|
|
12
12
|
node,
|
|
13
13
|
request: req,
|
|
@@ -15,10 +15,19 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
|
|
|
15
15
|
locale,
|
|
16
16
|
passportId,
|
|
17
17
|
componentId,
|
|
18
|
+
previousUserDid,
|
|
18
19
|
});
|
|
19
20
|
},
|
|
20
21
|
|
|
21
|
-
onAuth: async ({
|
|
22
|
+
onAuth: async ({
|
|
23
|
+
claims,
|
|
24
|
+
challenge,
|
|
25
|
+
userDid,
|
|
26
|
+
userPk,
|
|
27
|
+
extraParams: { locale, componentId, previousUserDid },
|
|
28
|
+
req,
|
|
29
|
+
baseUrl,
|
|
30
|
+
}) => {
|
|
22
31
|
try {
|
|
23
32
|
const result = await onApprove({
|
|
24
33
|
node,
|
|
@@ -31,6 +40,7 @@ module.exports = function createRoutes(node, authenticator, createSessionToken)
|
|
|
31
40
|
claims,
|
|
32
41
|
createSessionToken,
|
|
33
42
|
componentId,
|
|
43
|
+
previousUserDid,
|
|
34
44
|
});
|
|
35
45
|
|
|
36
46
|
return result;
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
getRoleFromLocalPassport,
|
|
16
16
|
} = require('@abtnode/auth/lib/passport');
|
|
17
17
|
const getBlockletWallet = require('@blocklet/meta/lib/wallet');
|
|
18
|
-
const { getBlockletChainInfo, isInProgress
|
|
18
|
+
const { getBlockletChainInfo, isInProgress } = require('@blocklet/meta/lib/util');
|
|
19
19
|
const { ROLES } = require('@abtnode/constant');
|
|
20
20
|
const logger = require('@abtnode/logger')('blocklet-service:transfer-blocklet-owner');
|
|
21
21
|
|
|
@@ -127,8 +127,8 @@ module.exports = function createRoutes(node, _, createSessionToken) {
|
|
|
127
127
|
|
|
128
128
|
const blocklet = await getBlocklet(appDid);
|
|
129
129
|
|
|
130
|
-
if (isInProgress(blocklet.status)
|
|
131
|
-
throw new Error(messages.
|
|
130
|
+
if (isInProgress(blocklet.status)) {
|
|
131
|
+
throw new Error(messages.appIsInProgress[locale]);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
return getKeyPairClaim(node, { title: blocklet.meta.title, declare: false })(opts);
|
|
@@ -188,9 +188,6 @@ module.exports = function createRoutes(node, _, createSessionToken) {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
const oldOwnerDid = blocklet.settings?.owner?.did;
|
|
191
|
-
if (userDid === oldOwnerDid) {
|
|
192
|
-
throw new Error(messages.notAllowedTransferToSelf[locale]);
|
|
193
|
-
}
|
|
194
191
|
|
|
195
192
|
const { appPid } = blocklet;
|
|
196
193
|
|
|
@@ -257,7 +254,7 @@ module.exports = function createRoutes(node, _, createSessionToken) {
|
|
|
257
254
|
locale,
|
|
258
255
|
lastLoginIp: get(req, 'headers[x-real-ip]') || '',
|
|
259
256
|
lastUsedPassport: passport,
|
|
260
|
-
connectedAccount: { provider: 'wallet' },
|
|
257
|
+
connectedAccount: { provider: 'wallet', did: userDid },
|
|
261
258
|
}),
|
|
262
259
|
...profile,
|
|
263
260
|
avatar,
|
|
@@ -324,7 +321,7 @@ module.exports = function createRoutes(node, _, createSessionToken) {
|
|
|
324
321
|
);
|
|
325
322
|
|
|
326
323
|
try {
|
|
327
|
-
if (oldOwnerDid) {
|
|
324
|
+
if (oldOwnerDid && oldOwnerDid !== userDid) {
|
|
328
325
|
const oldOwner = await getUser(node, appPid, oldOwnerDid);
|
|
329
326
|
if (oldOwner) {
|
|
330
327
|
const filteredPassports = (oldOwner.passports || []).filter((p) => p.role !== ROLES.OWNER);
|
|
@@ -366,6 +363,16 @@ module.exports = function createRoutes(node, _, createSessionToken) {
|
|
|
366
363
|
logger.error('migrateAppOnChain failed', { error });
|
|
367
364
|
});
|
|
368
365
|
|
|
366
|
+
// restart blocklet (not use queue)
|
|
367
|
+
node
|
|
368
|
+
.stopBlocklet({ did: appPid })
|
|
369
|
+
.then(() => {
|
|
370
|
+
return node.startBlocklet({ did: appPid });
|
|
371
|
+
})
|
|
372
|
+
.catch((error) => {
|
|
373
|
+
logger.error('restart blocklet failed', { appPid, error });
|
|
374
|
+
});
|
|
375
|
+
|
|
369
376
|
await sleep(3000);
|
|
370
377
|
logger.info('transfer ownership success', { userDid });
|
|
371
378
|
|
|
@@ -58,6 +58,7 @@ function createWebsocketServer(node, ensureWsUser) {
|
|
|
58
58
|
// blocklet events
|
|
59
59
|
Object.values(BlockletEvents).forEach((name) => {
|
|
60
60
|
eventHub.on(name, (data) => {
|
|
61
|
+
// 注意,此处的 did 指的是 appPid
|
|
61
62
|
const did = get(data, 'meta.did');
|
|
62
63
|
const eventName = `${did}/${name}`;
|
|
63
64
|
wsServer.broadcast(eventName, eventName, data, { noCluster: true });
|
|
@@ -4,7 +4,7 @@ const { CHANNEL_TYPE, parseChannel, getAppPublicChannel } = require('@blocklet/m
|
|
|
4
4
|
const { validateNotification } = require('@blocklet/sdk/lib/validators/notification');
|
|
5
5
|
const { NODE_MODES } = require('@abtnode/constant');
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const { ensureSenderApp, parseNotification, broadcast, EVENTS } = require('../util');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
*
|
|
@@ -54,7 +54,7 @@ const sendToAppChannel = async ({
|
|
|
54
54
|
|
|
55
55
|
// parse sender
|
|
56
56
|
|
|
57
|
-
const appInfo = await
|
|
57
|
+
const appInfo = await ensureSenderApp({ sender, node, nodeInfo });
|
|
58
58
|
|
|
59
59
|
if (![appInfo.wallet.address, appInfo.permanentWallet.address].includes(channelInfo.appDid)) {
|
|
60
60
|
throw new Error('Cannot sent message to channel of other app');
|
|
@@ -8,7 +8,7 @@ const { getWalletDidFromUser } = require('@blocklet/sdk/lib/did');
|
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line global-require
|
|
10
10
|
const logger = require('@abtnode/logger')(`${require('../../../package.json').name}:notification`);
|
|
11
|
-
const {
|
|
11
|
+
const { ensureSenderApp, parseNotification, broadcast, EVENTS } = require('../util');
|
|
12
12
|
const states = require('../../state');
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -52,7 +52,7 @@ const sendToDid = async ({ sender, receiver: rawDid, notification, options, node
|
|
|
52
52
|
|
|
53
53
|
// parse sender
|
|
54
54
|
|
|
55
|
-
const senderInfo = await
|
|
55
|
+
const senderInfo = await ensureSenderApp({ sender, node, nodeInfo });
|
|
56
56
|
|
|
57
57
|
// parse notification
|
|
58
58
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { CHANNEL_TYPE, parseChannel, getRelayChannel } = require('@blocklet/meta/lib/channel');
|
|
2
|
-
const {
|
|
2
|
+
const { ensureSenderApp, broadcast, EVENTS } = require('../util');
|
|
3
3
|
|
|
4
4
|
// Only an application can send message to a relay channel
|
|
5
5
|
// But multiple clients can subscribe to the same relay channel
|
|
@@ -12,7 +12,7 @@ const sendToRelay = async ({ sender, channel, event = EVENTS.MESSAGE, data, node
|
|
|
12
12
|
const nodeInfo = await node.getNodeInfo();
|
|
13
13
|
|
|
14
14
|
// Sender is appDid of application
|
|
15
|
-
const appInfo = await
|
|
15
|
+
const appInfo = await ensureSenderApp({ sender, node, nodeInfo });
|
|
16
16
|
|
|
17
17
|
if (![appInfo.wallet.address, appInfo.permanentWallet.address].includes(channelInfo.appDid)) {
|
|
18
18
|
throw new Error('Cannot sent message to relay channel of other app');
|
package/api/socket/util.js
CHANGED
|
@@ -47,7 +47,7 @@ const broadcast = (...args) => {
|
|
|
47
47
|
});
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
const
|
|
50
|
+
const ensureSenderApp = async ({ sender, node, nodeInfo }) => {
|
|
51
51
|
let appInfo;
|
|
52
52
|
try {
|
|
53
53
|
appInfo = await getApplicationInfo({ node, nodeInfo, teamDid: sender.appDid });
|
|
@@ -77,7 +77,7 @@ const EVENTS = {
|
|
|
77
77
|
module.exports = {
|
|
78
78
|
parseNotification,
|
|
79
79
|
broadcast,
|
|
80
|
-
|
|
80
|
+
ensureSenderApp,
|
|
81
81
|
getTokenInfo,
|
|
82
82
|
EVENTS,
|
|
83
83
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
"main.css": "/.blocklet/proxy/blocklet-service/static/css/main.632501d5.css",
|
|
4
|
-
"main.js": "/.blocklet/proxy/blocklet-service/static/js/main.
|
|
5
|
-
"static/js/716.
|
|
4
|
+
"main.js": "/.blocklet/proxy/blocklet-service/static/js/main.00308947.js",
|
|
5
|
+
"static/js/716.bcea7c98.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/716.bcea7c98.chunk.js",
|
|
6
6
|
"static/js/359.c47779c2.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/359.c47779c2.chunk.js",
|
|
7
7
|
"static/js/255.279b1bca.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/255.279b1bca.chunk.js",
|
|
8
8
|
"static/js/371.ccef728f.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/371.ccef728f.chunk.js",
|
|
@@ -10,19 +10,19 @@
|
|
|
10
10
|
"static/js/460.97b02ba6.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/460.97b02ba6.chunk.js",
|
|
11
11
|
"static/js/868.9c03fa86.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/868.9c03fa86.chunk.js",
|
|
12
12
|
"static/js/547.f8830a9e.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/547.f8830a9e.chunk.js",
|
|
13
|
-
"static/js/343.
|
|
13
|
+
"static/js/343.f30fdb24.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/343.f30fdb24.chunk.js",
|
|
14
14
|
"static/js/682.c64ae291.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/682.c64ae291.chunk.js",
|
|
15
15
|
"static/js/711.6c22b7c7.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/711.6c22b7c7.chunk.js",
|
|
16
16
|
"static/js/437.d815f0c0.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/437.d815f0c0.chunk.js",
|
|
17
17
|
"static/js/690.e2a01dd2.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/690.e2a01dd2.chunk.js",
|
|
18
18
|
"static/js/42.a0526d16.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/42.a0526d16.chunk.js",
|
|
19
|
-
"static/js/648.
|
|
19
|
+
"static/js/648.5eec48ea.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/648.5eec48ea.chunk.js",
|
|
20
20
|
"static/js/162.58348adf.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/162.58348adf.chunk.js",
|
|
21
21
|
"static/js/610.40349d57.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/610.40349d57.chunk.js",
|
|
22
22
|
"static/css/61.03a48b17.chunk.css": "/.blocklet/proxy/blocklet-service/static/css/61.03a48b17.chunk.css",
|
|
23
|
-
"static/js/61.
|
|
23
|
+
"static/js/61.3c903dd8.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/61.3c903dd8.chunk.js",
|
|
24
24
|
"static/js/199.3d76c24b.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/199.3d76c24b.chunk.js",
|
|
25
|
-
"static/js/573.
|
|
25
|
+
"static/js/573.fc22f41e.chunk.js": "/.blocklet/proxy/blocklet-service/static/js/573.fc22f41e.chunk.js",
|
|
26
26
|
"static/media/ubuntu-mono-all-400-normal.woff": "/.blocklet/proxy/blocklet-service/static/media/ubuntu-mono-all-400-normal.c879328bc62e9c68268f.woff",
|
|
27
27
|
"static/media/lato-all-400-normal.woff": "/.blocklet/proxy/blocklet-service/static/media/lato-all-400-normal.3dc1eff492ab1f598560.woff",
|
|
28
28
|
"static/media/iconify.cjs": "/.blocklet/proxy/blocklet-service/static/media/iconify.32b54549e843e448ee9b.cjs",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"router-template-styles/styles.css": "/.blocklet/proxy/blocklet-service/router-template-styles/styles.css",
|
|
46
46
|
"index.html": "/.blocklet/proxy/blocklet-service/index.html",
|
|
47
47
|
"main.632501d5.css.map": "/.blocklet/proxy/blocklet-service/static/css/main.632501d5.css.map",
|
|
48
|
-
"main.
|
|
49
|
-
"716.
|
|
48
|
+
"main.00308947.js.map": "/.blocklet/proxy/blocklet-service/static/js/main.00308947.js.map",
|
|
49
|
+
"716.bcea7c98.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/716.bcea7c98.chunk.js.map",
|
|
50
50
|
"359.c47779c2.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/359.c47779c2.chunk.js.map",
|
|
51
51
|
"255.279b1bca.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/255.279b1bca.chunk.js.map",
|
|
52
52
|
"371.ccef728f.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/371.ccef728f.chunk.js.map",
|
|
@@ -54,22 +54,22 @@
|
|
|
54
54
|
"460.97b02ba6.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/460.97b02ba6.chunk.js.map",
|
|
55
55
|
"868.9c03fa86.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/868.9c03fa86.chunk.js.map",
|
|
56
56
|
"547.f8830a9e.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/547.f8830a9e.chunk.js.map",
|
|
57
|
-
"343.
|
|
57
|
+
"343.f30fdb24.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/343.f30fdb24.chunk.js.map",
|
|
58
58
|
"682.c64ae291.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/682.c64ae291.chunk.js.map",
|
|
59
59
|
"711.6c22b7c7.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/711.6c22b7c7.chunk.js.map",
|
|
60
60
|
"437.d815f0c0.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/437.d815f0c0.chunk.js.map",
|
|
61
61
|
"690.e2a01dd2.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/690.e2a01dd2.chunk.js.map",
|
|
62
62
|
"42.a0526d16.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/42.a0526d16.chunk.js.map",
|
|
63
|
-
"648.
|
|
63
|
+
"648.5eec48ea.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/648.5eec48ea.chunk.js.map",
|
|
64
64
|
"162.58348adf.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/162.58348adf.chunk.js.map",
|
|
65
65
|
"610.40349d57.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/610.40349d57.chunk.js.map",
|
|
66
66
|
"61.03a48b17.chunk.css.map": "/.blocklet/proxy/blocklet-service/static/css/61.03a48b17.chunk.css.map",
|
|
67
|
-
"61.
|
|
67
|
+
"61.3c903dd8.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/61.3c903dd8.chunk.js.map",
|
|
68
68
|
"199.3d76c24b.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/199.3d76c24b.chunk.js.map",
|
|
69
|
-
"573.
|
|
69
|
+
"573.fc22f41e.chunk.js.map": "/.blocklet/proxy/blocklet-service/static/js/573.fc22f41e.chunk.js.map"
|
|
70
70
|
},
|
|
71
71
|
"entrypoints": [
|
|
72
72
|
"static/css/main.632501d5.css",
|
|
73
|
-
"static/js/main.
|
|
73
|
+
"static/js/main.00308947.js"
|
|
74
74
|
]
|
|
75
75
|
}
|
package/build/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#000000"/><title>Blocklet Service</title><script src=".well-known/service/api/env"></script><script src="/__blocklet__.js"></script><script defer="defer" src="/.blocklet/proxy/blocklet-service/static/js/main.
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#000000"/><title>Blocklet Service</title><script src=".well-known/service/api/env"></script><script src="/__blocklet__.js"></script><script defer="defer" src="/.blocklet/proxy/blocklet-service/static/js/main.00308947.js"></script><link href="/.blocklet/proxy/blocklet-service/static/css/main.632501d5.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|