@blocklet/meta 1.15.17 → 1.16.0-beta-8ee536d7

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.
Files changed (62) hide show
  1. package/lib/channel.d.ts +32 -0
  2. package/lib/channel.js +54 -0
  3. package/lib/constants.d.ts +2 -0
  4. package/lib/constants.js +5 -152
  5. package/lib/did.d.ts +3 -0
  6. package/lib/did.js +9 -9
  7. package/lib/engine.d.ts +7 -0
  8. package/lib/engine.js +21 -25
  9. package/lib/entry.d.ts +3 -0
  10. package/lib/entry.js +51 -64
  11. package/lib/extension.d.ts +14 -0
  12. package/lib/extension.js +82 -77
  13. package/lib/file.d.ts +23 -0
  14. package/lib/file.js +51 -36
  15. package/lib/fix.d.ts +36 -0
  16. package/lib/fix.js +231 -228
  17. package/lib/get-component-process-id.d.ts +5 -0
  18. package/lib/get-component-process-id.js +16 -0
  19. package/lib/has-reserved-key.d.ts +3 -0
  20. package/lib/has-reserved-key.js +15 -0
  21. package/lib/index.d.ts +86 -0
  22. package/lib/index.js +55 -34
  23. package/lib/info.d.ts +15 -0
  24. package/lib/info.js +70 -38
  25. package/lib/name.d.ts +15 -0
  26. package/lib/name.js +41 -8
  27. package/lib/nft-templates.d.ts +86 -0
  28. package/lib/nft-templates.js +52 -0
  29. package/lib/parse-navigation-from-blocklet.d.ts +92 -0
  30. package/lib/parse-navigation-from-blocklet.js +539 -0
  31. package/lib/parse-navigation.d.ts +3 -0
  32. package/lib/parse-navigation.js +197 -0
  33. package/lib/parse.d.ts +22 -0
  34. package/lib/parse.js +100 -89
  35. package/lib/payment/index.d.ts +254 -0
  36. package/lib/payment/index.js +14 -0
  37. package/lib/payment/v1.d.ts +185 -0
  38. package/lib/payment/v1.js +84 -0
  39. package/lib/payment/v2.d.ts +242 -0
  40. package/lib/payment/v2.js +576 -0
  41. package/lib/schema.d.ts +63 -0
  42. package/lib/schema.js +669 -283
  43. package/lib/service.d.ts +27 -0
  44. package/lib/service.js +71 -0
  45. package/lib/types/index.d.ts +1 -0
  46. package/lib/types/index.js +18 -0
  47. package/lib/types/schema.d.ts +284 -0
  48. package/lib/types/schema.js +3 -0
  49. package/lib/url-friendly.d.ts +6 -0
  50. package/lib/url-friendly.js +20 -0
  51. package/lib/util-meta.d.ts +42 -0
  52. package/lib/util-meta.js +146 -0
  53. package/lib/util.d.ts +201 -0
  54. package/lib/util.js +501 -82
  55. package/lib/validate.d.ts +13 -0
  56. package/lib/validate.js +37 -61
  57. package/lib/verify-multi-sig.d.ts +3 -0
  58. package/lib/verify-multi-sig.js +86 -59
  59. package/lib/wallet.d.ts +9 -0
  60. package/lib/wallet.js +19 -30
  61. package/package.json +59 -20
  62. package/lib/payment.js +0 -114
@@ -0,0 +1,576 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.version = exports.checkFreeBlocklet = exports.verifyNftFactory = exports.verifyPaymentIntegrity = exports.createNftFactoryItx = exports._test = void 0;
30
+ /* eslint-disable no-await-in-loop */
31
+ const crypto_1 = __importDefault(require("crypto"));
32
+ const debug_1 = __importDefault(require("debug"));
33
+ const url_join_1 = __importDefault(require("url-join"));
34
+ const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
35
+ const get_1 = __importDefault(require("lodash/get"));
36
+ const pick_1 = __importDefault(require("lodash/pick"));
37
+ const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
38
+ const axios_1 = __importDefault(require("@abtnode/util/lib/axios"));
39
+ const util_1 = require("@ocap/util");
40
+ const asset_1 = require("@ocap/asset");
41
+ const wallet_1 = require("@ocap/wallet");
42
+ const did_util_1 = require("@arcblock/did-util");
43
+ const did = __importStar(require("@arcblock/did"));
44
+ const constant_1 = __importDefault(require("@abtnode/constant"));
45
+ const nft_templates_1 = require("../nft-templates");
46
+ const validate_1 = require("../validate");
47
+ const util_2 = require("../util");
48
+ const util_meta_1 = require("../util-meta");
49
+ const debug = (0, debug_1.default)('@blocklet/meta:payment');
50
+ const { toTypeInfo } = did;
51
+ const { BLOCKLET_STORE_META_PATH } = constant_1.default;
52
+ const VERSION = '2.0.0';
53
+ exports.version = VERSION;
54
+ const ZeroBN = new util_1.BN(0);
55
+ const defaultDecimals = 1e6; // we only support 6 decimals on share ratio
56
+ const defaultDecimalsBN = new util_1.BN(defaultDecimals);
57
+ const getComponentConfig = (meta) => []
58
+ .concat(meta.components || meta.children)
59
+ .concat(meta.staticComponents)
60
+ .filter(Boolean);
61
+ const safeMul = (a, b) => Number((0, util_1.fromUnitToToken)((0, util_1.fromTokenToUnit)(a)
62
+ .mul(new util_1.BN(b * defaultDecimals))
63
+ .div(defaultDecimalsBN)));
64
+ const md5 = (str) => crypto_1.default.createHash('md5').update(str).digest('hex');
65
+ const getStoreInfo = async (url) => {
66
+ const storeMetaUrl = (0, url_join_1.default)(new URL(url).origin, BLOCKLET_STORE_META_PATH);
67
+ const { data: info } = await axios_1.default.get(storeMetaUrl, { timeout: 8000 });
68
+ return info;
69
+ };
70
+ /**
71
+ * @typedef {{
72
+ * meta: Object
73
+ * storeInfo: Object
74
+ * storeUrl: string
75
+ * children: Array<Component>
76
+ * }} Component
77
+ *
78
+ * @param {TBlockletMeta} inputMeta
79
+ * @param {{
80
+ * ancestors: Array<{TBlockletMeta}>
81
+ * bundles: {
82
+ * <bundleName>: <storeId>
83
+ * }
84
+ * }} context
85
+ *
86
+ * @returns {Array<Component>}
87
+ */
88
+ const innerGetComponents = async (inputMeta, context = {}) => {
89
+ // FIXME 是否需要验证: 在同一个链上; 重复的 component
90
+ const { ancestors = [], bundles = {} } = context;
91
+ // check ancestor length
92
+ if (ancestors.length > 40) {
93
+ throw new Error('The depth of component should not exceed 40');
94
+ }
95
+ const configs = getComponentConfig(inputMeta);
96
+ if (!configs || !configs.length) {
97
+ return [];
98
+ }
99
+ const children = [];
100
+ for (const config of configs) {
101
+ // get component meta
102
+ const urls = (0, util_meta_1.getSourceUrlsFromConfig)(config);
103
+ let meta;
104
+ let url;
105
+ try {
106
+ const res = await (0, util_meta_1.getBlockletMetaFromUrls)(urls, {
107
+ returnUrl: true,
108
+ validateFn: (m) => (0, validate_1.validateMeta)(m),
109
+ ensureTarball: false,
110
+ });
111
+ meta = res.meta;
112
+ url = res.url;
113
+ }
114
+ catch (err) {
115
+ throw new Error(`Failed get component meta: ${config.title || config.name}: ${err.message}`);
116
+ }
117
+ // check is component
118
+ if (!(0, util_2.isComponentBlocklet)(meta)) {
119
+ throw new Error(`The blocklet cannot be a component: ${meta.title}`);
120
+ }
121
+ // check circular dependencies
122
+ if (ancestors.map((x) => x.meta?.did).indexOf(meta.did) > -1) {
123
+ throw new Error('Blocklet components have circular dependencies');
124
+ }
125
+ // generate child
126
+ const child = {
127
+ meta,
128
+ };
129
+ // child store info
130
+ if (config.source.store) {
131
+ const storeInfo = await getStoreInfo(url);
132
+ // check uniq bundle did in different stores
133
+ if (!bundles[child.meta.did]) {
134
+ bundles[child.meta.did] = storeInfo.id;
135
+ }
136
+ else if (bundles[child.meta.did] !== storeInfo.id) {
137
+ throw new Error('Bundles with the same did cannot in different stores');
138
+ }
139
+ child.storeInfo = storeInfo;
140
+ child.storeUrl = new URL(url).origin;
141
+ }
142
+ // child children
143
+ child.children = await innerGetComponents(meta, {
144
+ ancestors: [...ancestors, { meta }],
145
+ bundles,
146
+ });
147
+ children.push(child);
148
+ }
149
+ return children;
150
+ };
151
+ /**
152
+ * @param {Array<Component>} components
153
+ * @param {Array<Store>} _stores
154
+ * @returns {Array<Store>}
155
+ */
156
+ const getStores = (components, _stores = []) => {
157
+ for (const { meta, storeInfo, storeUrl, children } of components) {
158
+ if (storeInfo && (!(0, util_2.isFreeBlocklet)(meta) || !(0, util_2.isFreeComponent)(meta))) {
159
+ const store = _stores.find((x) => x.id === storeInfo.id);
160
+ if (!store) {
161
+ _stores.push({
162
+ id: storeInfo.id,
163
+ pk: storeInfo.pk,
164
+ url: storeUrl,
165
+ components: [{ did: meta.did, version: meta.version }],
166
+ });
167
+ }
168
+ else if (!store.components.some((x) => x.did === meta.did && x.version === meta.version)) {
169
+ store.components.push({ did: meta.did, version: meta.version });
170
+ }
171
+ }
172
+ if (children && children.length > 0) {
173
+ getStores(children, _stores);
174
+ }
175
+ }
176
+ return _stores;
177
+ };
178
+ const getComponents = async (inputMeta) => {
179
+ const components = await innerGetComponents(inputMeta);
180
+ const stores = await getStores(components);
181
+ return { components, stores };
182
+ };
183
+ const getPriceTokens = async (meta, ocapClient) => {
184
+ const priceTokens = (0, cloneDeep_1.default)((0, get_1.default)(meta, 'payment.price', []));
185
+ for (const token of priceTokens) {
186
+ // eslint-disable-next-line no-await-in-loop
187
+ const { state } = await ocapClient.getTokenState({ address: token.address });
188
+ if (!state) {
189
+ throw new Error(`Token specified in blocklet meta was not found on chain: ${token.address}`);
190
+ }
191
+ token.decimal = state.decimal;
192
+ }
193
+ return priceTokens;
194
+ };
195
+ const getChildShare = (childMeta, parentPrice) => {
196
+ if (!childMeta?.payment?.componentPrice) {
197
+ return 0;
198
+ }
199
+ const priceList = childMeta.payment.componentPrice;
200
+ let price = 0;
201
+ for (const { type, value, parentPriceRange } of priceList) {
202
+ const isDefault = !parentPriceRange || !parentPriceRange.length;
203
+ const skip = isDefault && price !== 0;
204
+ const inRange = isDefault || (parentPriceRange && parentPrice >= parentPriceRange[0] && parentPrice <= parentPriceRange[1]);
205
+ if (!skip && inRange) {
206
+ if (type === 'fixed') {
207
+ price = value;
208
+ }
209
+ else if (type === 'percentage') {
210
+ price = safeMul(parentPrice, value);
211
+ }
212
+ }
213
+ }
214
+ return price;
215
+ };
216
+ /**
217
+ * @returns {Array<{
218
+ * tokenAddress: string
219
+ * accountAddress: string
220
+ * amount: BN
221
+ * }>}
222
+ */
223
+ const getTokenTransfers = ({ priceToken, shares = [], components = [], }) => {
224
+ // check share
225
+ const shareSum = shares.reduce((sum, x) => sum + x.value, 0);
226
+ if (shareSum > 1) {
227
+ throw new Error('payment.share invalid: share sum should not be greater than 1');
228
+ }
229
+ const { value: price } = priceToken;
230
+ let parentShareBN = (0, util_1.fromTokenToUnit)(price, priceToken.decimal);
231
+ const contracts = [];
232
+ for (const child of components) {
233
+ if (!(0, util_2.isFreeComponent)(child.meta)) {
234
+ // // check same token
235
+ const [token] = child.meta.payment.price || [];
236
+ if (token && token.address !== priceToken.address) {
237
+ throw new Error(`The token address of the component "${child.meta.title || child.meta.name}" is inconsistent with the blocklet. Component: ${priceToken.address}, Composite Blocklet: ${token.address}`);
238
+ }
239
+ const childShare = getChildShare(child.meta, price);
240
+ parentShareBN = parentShareBN.sub((0, util_1.fromTokenToUnit)(childShare, priceToken.decimal));
241
+ const componentContracts = getTokenTransfers({
242
+ priceToken: { ...priceToken, value: childShare },
243
+ shares: child.meta.payment.share,
244
+ components: child.children || [],
245
+ });
246
+ contracts.push(...componentContracts);
247
+ }
248
+ }
249
+ if (parentShareBN.lt(ZeroBN)) {
250
+ const needPrice = (0, util_1.fromUnitToToken)((0, util_1.fromTokenToUnit)(price, priceToken.decimal).sub(parentShareBN));
251
+ throw new Error(`Price for composite blocklet must be greater than ${needPrice} because paid components are included.`);
252
+ }
253
+ shares.forEach(({ name, address: accountAddress, value: ratio }) => {
254
+ contracts.push({
255
+ tokenAddress: priceToken.address,
256
+ accountName: name,
257
+ accountAddress,
258
+ amount: parentShareBN.mul(new util_1.BN(ratio * defaultDecimals)).div(defaultDecimalsBN),
259
+ });
260
+ });
261
+ const mergedContracts = [];
262
+ contracts.forEach((x) => {
263
+ const index = mergedContracts.findIndex((y) => y.tokenAddress === x.tokenAddress && y.accountAddress === x.accountAddress);
264
+ if (index > -1) {
265
+ mergedContracts[index].amount = mergedContracts[index].amount.add(x.amount);
266
+ }
267
+ else {
268
+ mergedContracts.push(x);
269
+ }
270
+ });
271
+ return mergedContracts;
272
+ };
273
+ const getContract = async ({ meta, priceTokens, components, }) => {
274
+ const shares = meta.payment.share || [];
275
+ const [priceToken] = priceTokens;
276
+ const contracts = getTokenTransfers({ priceToken, shares, components });
277
+ const code = contracts
278
+ .map((x) => `transferToken('${x.tokenAddress}','${x.accountAddress}','${x.amount.toString()}')`)
279
+ .join(';\n');
280
+ const shareList = contracts.map((x) => ({
281
+ ...x,
282
+ amount: (0, util_1.fromUnitToToken)(x.amount, priceToken.decimal),
283
+ }));
284
+ return {
285
+ code,
286
+ shares: shareList,
287
+ };
288
+ };
289
+ /**
290
+ * we need to ensure that blocklet purchase factory does not change across changes
291
+ *
292
+ * @typedef {{
293
+ * data: {
294
+ * type: 'json'
295
+ * value: {
296
+ * did: string
297
+ * url: string
298
+ * name: string
299
+ * version: string
300
+ * payment: {
301
+ * version: string
302
+ * }
303
+ * stores: Array<{
304
+ * signer: string
305
+ * pk: string
306
+ * signature: string
307
+ * components: Array<{did: string, version: string}>
308
+ * paymentIntegrity: string
309
+ * }>
310
+ * }
311
+ * }
312
+ * }} Itx
313
+ * @returns {Itx}
314
+ */
315
+ const innerCreateNftFactoryItx = ({ meta, issuers, serviceUrl, storeSignatures, factoryInput, contract, }) => {
316
+ const factoryOutput = (0, nft_templates_1.getBlockletPurchaseTemplate)(serviceUrl);
317
+ const itx = {
318
+ name: meta.title || meta.name,
319
+ description: `Purchase NFT factory for blocklet ${meta.name}`,
320
+ settlement: 'instant',
321
+ limit: 0,
322
+ trustedIssuers: issuers,
323
+ input: factoryInput,
324
+ output: {
325
+ issuer: '{{ctx.issuer.id}}',
326
+ parent: '{{ctx.factory}}',
327
+ moniker: 'BlockletPurchaseNFT',
328
+ readonly: true,
329
+ transferrable: false,
330
+ data: factoryOutput,
331
+ },
332
+ data: {
333
+ type: 'json',
334
+ value: {
335
+ did: meta.did,
336
+ url: (0, url_join_1.default)(serviceUrl, `/blocklet/${meta.did}`),
337
+ name: meta.name,
338
+ version: meta.version,
339
+ payment: {
340
+ version: VERSION,
341
+ },
342
+ stores: storeSignatures.map((x) => (0, pick_1.default)(x, ['signer', 'pk', 'signature', 'components', 'paymentIntegrity'])),
343
+ },
344
+ },
345
+ hooks: [
346
+ {
347
+ name: 'mint',
348
+ type: 'contract',
349
+ hook: contract,
350
+ },
351
+ ],
352
+ };
353
+ itx.address = (0, did_util_1.toFactoryAddress)(itx);
354
+ // @ts-expect-error FIXME: help wanted
355
+ (0, asset_1.isValidFactory)(itx, true);
356
+ return itx;
357
+ };
358
+ const getFactoryInput = (inputTokens, { formatToken = true } = {}) => {
359
+ const tokens = (0, cloneDeep_1.default)(inputTokens);
360
+ tokens.forEach((token) => {
361
+ if (formatToken) {
362
+ token.value = (0, util_1.fromTokenToUnit)(token.value, token.decimal).toString();
363
+ }
364
+ delete token.decimal;
365
+ });
366
+ return {
367
+ tokens,
368
+ assets: [],
369
+ variables: [],
370
+ };
371
+ };
372
+ const getPaymentIntegrity = async ({ contract, factoryInput, storeComponents, meta, client, storeId, }) => {
373
+ if (!contract && !factoryInput && !storeComponents) {
374
+ const priceTokens = await getPriceTokens(meta, client);
375
+ const { components, stores } = await getComponents(meta);
376
+ const store = stores.find((x) => x.id === storeId);
377
+ // eslint-disable-next-line no-param-reassign
378
+ contract = (await getContract({ meta, components, priceTokens })).code;
379
+ // eslint-disable-next-line no-param-reassign
380
+ factoryInput = await getFactoryInput(priceTokens);
381
+ // eslint-disable-next-line no-param-reassign
382
+ storeComponents = store?.components || [];
383
+ }
384
+ const paymentData = {
385
+ factoryInput,
386
+ contract,
387
+ components: storeComponents || [],
388
+ };
389
+ const integrity = md5((0, json_stable_stringify_1.default)(paymentData));
390
+ return integrity;
391
+ };
392
+ const getStoreSignatures = async ({ meta, stores, factoryInput, contract, }) => {
393
+ const storeSignatures = [];
394
+ for (const store of stores) {
395
+ const { id, url, pk, components: storeComponents } = store;
396
+ const paymentIntegrity = await getPaymentIntegrity({ factoryInput, contract, storeComponents });
397
+ /**
398
+ * protocol: /api/payment/signature
399
+ * method: POST
400
+ * body: { blockletMeta, paymentIntegrity, paymentVersion }
401
+ * return: { signer, pk, signature}
402
+ */
403
+ const { data: res } = await axios_1.default.post(`${url}/api/payment/signature`, {
404
+ blockletMeta: meta,
405
+ paymentIntegrity,
406
+ paymentVersion: VERSION,
407
+ }, { timeout: 20000 });
408
+ if (res.signer !== id) {
409
+ throw new Error('store signature: store id does not match');
410
+ }
411
+ if (res.pk !== pk) {
412
+ throw new Error('store signature: store pk does not match');
413
+ }
414
+ // verify sig
415
+ const type = toTypeInfo(id);
416
+ const wallet = (0, wallet_1.fromPublicKey)(pk, type);
417
+ const verifyRes = wallet.verify(paymentIntegrity, res.signature);
418
+ if (verifyRes !== true) {
419
+ throw new Error('verify store signature failed');
420
+ }
421
+ storeSignatures.push({
422
+ signer: res.signer,
423
+ pk: res.pk,
424
+ signature: res.signature,
425
+ components: storeComponents,
426
+ paymentIntegrity,
427
+ storeUrl: url,
428
+ });
429
+ }
430
+ return {
431
+ storeSignatures,
432
+ };
433
+ };
434
+ /**
435
+ * Used by CLI and Store to independent compute factory itx
436
+ *
437
+ * @param {{
438
+ * blockletMeta: TBlockletMeta,
439
+ * ocapClient: OcapClient,
440
+ * issuers: Array<string>,
441
+ * storeUrl: string,
442
+ * }}
443
+ * @returns {{
444
+ * itx: Itx
445
+ * store: Array<{id, url}>
446
+ * shares: Array<{
447
+ * accountName: string
448
+ * accountAddress: DID
449
+ * tokenAddress: DID
450
+ * amount: string|number,
451
+ * }>
452
+ * }}
453
+ */
454
+ const createNftFactoryItx = async ({ blockletMeta, ocapClient, issuers, storeUrl, }) => {
455
+ const priceTokens = await getPriceTokens(blockletMeta, ocapClient);
456
+ const { components, stores } = await getComponents(blockletMeta);
457
+ const factoryInput = getFactoryInput(priceTokens);
458
+ const { code: contract, shares } = await getContract({
459
+ meta: blockletMeta,
460
+ priceTokens,
461
+ components,
462
+ });
463
+ const { storeSignatures } = await getStoreSignatures({
464
+ meta: blockletMeta,
465
+ stores,
466
+ factoryInput,
467
+ contract,
468
+ });
469
+ return {
470
+ itx: innerCreateNftFactoryItx({
471
+ meta: blockletMeta,
472
+ issuers,
473
+ serviceUrl: storeUrl,
474
+ storeSignatures,
475
+ factoryInput,
476
+ contract,
477
+ }),
478
+ stores: storeSignatures.map((x) => ({ id: x.signer, url: x.storeUrl })),
479
+ shares,
480
+ };
481
+ };
482
+ exports.createNftFactoryItx = createNftFactoryItx;
483
+ /**
484
+ * Used by Store before generating payment signature
485
+ *
486
+ * @param {{
487
+ * integrity: string,
488
+ * blockletMeta: TBlockletMeta,
489
+ * ocapClient: OcapClient,
490
+ * storeId: string
491
+ * }}
492
+ * @returns {string} integrity
493
+ */
494
+ const verifyPaymentIntegrity = async ({ integrity: expected, blockletMeta, ocapClient, storeId, }) => {
495
+ const actual = await getPaymentIntegrity({ meta: blockletMeta, client: ocapClient, storeId });
496
+ if (actual !== expected) {
497
+ throw new Error('verify payment integrity failed');
498
+ }
499
+ return expected;
500
+ };
501
+ exports.verifyPaymentIntegrity = verifyPaymentIntegrity;
502
+ /**
503
+ * Used by Store before generating downloadToken
504
+ *
505
+ * @param {{
506
+ * {FactoryState} factoryState
507
+ * {Wallet} signerWallet
508
+ * }}
509
+ *
510
+ * @returns {{
511
+ * components: Array<{did: string, version: string}>
512
+ * }}
513
+ */
514
+ const verifyNftFactory = async ({ factoryState, signerWallet, }) => {
515
+ const data = JSON.parse(factoryState?.data?.value);
516
+ const stores = data?.stores || [];
517
+ const store = stores.find((x) => x.signer === signerWallet.address);
518
+ if (!store) {
519
+ throw new Error(`Signer does not found in factory. factory: ${factoryState.address}, signer: ${signerWallet.address}`);
520
+ }
521
+ const c = factoryState.hooks.find((x) => x.type === 'contract');
522
+ const { components } = store;
523
+ // Token 的字段和 factory 中的字段不一致
524
+ const factoryInput = getFactoryInput(factoryState.input.tokens.map((x) => (0, pick_1.default)(x, ['address', 'value'])), { formatToken: false });
525
+ const integrity = await getPaymentIntegrity({
526
+ contract: c.hook,
527
+ factoryInput,
528
+ storeComponents: components,
529
+ });
530
+ if (signerWallet.sign(integrity) !== store.signature) {
531
+ debug(store, factoryInput, integrity, components, c.hook);
532
+ throw new Error(`verify nft factory failed: ${factoryState.address}`);
533
+ }
534
+ return { components };
535
+ };
536
+ exports.verifyNftFactory = verifyNftFactory;
537
+ /**
538
+ * Check blocklet and all of components are free
539
+ * Throw Error if not free
540
+ *
541
+ * @param {TBlockletMeta} meta
542
+ */
543
+ const checkFreeBlocklet = async (blockletMeta) => {
544
+ if (!(0, util_2.isFreeBlocklet)(blockletMeta)) {
545
+ return Promise.reject(new Error('blocklet is not free'));
546
+ }
547
+ const { components } = await getComponents(blockletMeta);
548
+ const shouldAllComponentFree = (arr) => {
549
+ arr.forEach(({ meta, children }) => {
550
+ if (!(0, util_2.isFreeBlocklet)(meta) || !(0, util_2.isFreeComponent)(meta)) {
551
+ // throw new Error(`Found paid component "${meta.title || meta.name}" in free blocklet`);
552
+ throw new Error(`Paid component "${meta.title || meta.name}" found in free blocklet "${blockletMeta.title || blockletMeta.name}", which is forbidden`);
553
+ }
554
+ shouldAllComponentFree(children || []);
555
+ });
556
+ };
557
+ shouldAllComponentFree(components);
558
+ return true;
559
+ };
560
+ exports.checkFreeBlocklet = checkFreeBlocklet;
561
+ // eslint-disable-next-line @typescript-eslint/naming-convention
562
+ exports._test = {
563
+ getPriceTokens,
564
+ getFactoryInput,
565
+ getPaymentIntegrity,
566
+ getComponents,
567
+ getContract,
568
+ };
569
+ exports.default = {
570
+ createNftFactoryItx,
571
+ verifyPaymentIntegrity,
572
+ verifyNftFactory,
573
+ checkFreeBlocklet,
574
+ version: VERSION,
575
+ _test: exports._test,
576
+ };
@@ -0,0 +1,63 @@
1
+ import JOI from 'joi';
2
+ declare const titleSchema: JOI.StringSchema<string>;
3
+ declare const descriptionSchema: JOI.StringSchema<string>;
4
+ declare const logoSchema: JOI.StringSchema<string>;
5
+ declare const mountPointSchema: JOI.StringSchema<string>;
6
+ declare const updateMountPointSchema: JOI.StringSchema<string>;
7
+ declare const blockletNameSchema: JOI.StringSchema<string>;
8
+ declare const environmentNameSchema: JOI.StringSchema<string>;
9
+ declare const environmentSchema: JOI.ObjectSchema<any>;
10
+ declare const scriptsSchema: JOI.ObjectSchema<any>;
11
+ declare const serviceSchema: JOI.ObjectSchema<any>;
12
+ declare const endpointSchema: JOI.ObjectSchema<any>;
13
+ declare const cacheableSchema: JOI.StringSchema<string>;
14
+ declare const interfaceSchema: JOI.ObjectSchema<any>;
15
+ declare const engineSchema: JOI.ObjectSchema<any>;
16
+ declare const personSchema: JOI.ObjectSchema<any>;
17
+ declare const distSchema: JOI.ObjectSchema<any>;
18
+ declare const statsSchema: JOI.ObjectSchema<any>;
19
+ declare const componentSchema: JOI.ObjectSchema<any>;
20
+ declare const signatureSchema: JOI.ObjectSchema<any>;
21
+ declare const navigationItemSchema: JOI.ObjectSchema<any>;
22
+ declare const navigationSchema: JOI.ArraySchema<any[]>;
23
+ declare const themeSchema: JOI.ObjectSchema<any>;
24
+ declare const authConfigSchema: JOI.ObjectSchema<any>;
25
+ declare const blockletMetaSchema: JOI.ObjectSchema<any>;
26
+ declare const createBlockletSchema: (baseDir: string, { ensureMain, ensureFiles, ensureDist, ensureComponentStore, ensureName, skipValidateDidName, ...schemaOptions }?: {
27
+ ensureMain?: boolean;
28
+ ensureFiles?: boolean;
29
+ ensureDist?: boolean;
30
+ ensureComponentStore?: boolean;
31
+ ensureName?: boolean;
32
+ skipValidateDidName?: boolean;
33
+ }) => JOI.ObjectSchema;
34
+ export { blockletMetaSchema, blockletNameSchema, componentSchema, createBlockletSchema, descriptionSchema, distSchema, endpointSchema, engineSchema, environmentSchema, environmentNameSchema, interfaceSchema, logoSchema, mountPointSchema, updateMountPointSchema, navigationItemSchema, navigationSchema, personSchema, scriptsSchema, serviceSchema, signatureSchema, themeSchema, titleSchema, statsSchema, cacheableSchema, authConfigSchema, };
35
+ declare const _default: {
36
+ blockletNameSchema: JOI.StringSchema<string>;
37
+ componentSchema: JOI.ObjectSchema<any>;
38
+ endpointSchema: JOI.ObjectSchema<any>;
39
+ serviceSchema: JOI.ObjectSchema<any>;
40
+ createBlockletSchema: (baseDir: string, { ensureMain, ensureFiles, ensureDist, ensureComponentStore, ensureName, skipValidateDidName, ...schemaOptions }?: {
41
+ ensureMain?: boolean;
42
+ ensureFiles?: boolean;
43
+ ensureDist?: boolean;
44
+ ensureComponentStore?: boolean;
45
+ ensureName?: boolean;
46
+ skipValidateDidName?: boolean;
47
+ }) => JOI.ObjectSchema<any>;
48
+ interfaceSchema: JOI.ObjectSchema<any>;
49
+ environmentSchema: JOI.ObjectSchema<any>;
50
+ environmentNameSchema: JOI.StringSchema<string>;
51
+ scriptsSchema: JOI.ObjectSchema<any>;
52
+ personSchema: JOI.ObjectSchema<any>;
53
+ distSchema: JOI.ObjectSchema<any>;
54
+ titleSchema: JOI.StringSchema<string>;
55
+ descriptionSchema: JOI.StringSchema<string>;
56
+ logoSchema: JOI.StringSchema<string>;
57
+ navigationSchema: JOI.ArraySchema<any[]>;
58
+ themeSchema: JOI.ObjectSchema<any>;
59
+ mountPointSchema: JOI.StringSchema<string>;
60
+ updateMountPointSchema: JOI.StringSchema<string>;
61
+ authConfigSchema: JOI.ObjectSchema<any>;
62
+ };
63
+ export default _default;