@ocap/asset 1.27.16 → 1.28.0

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/index.d.ts CHANGED
@@ -1,36 +1,38 @@
1
- import type { LiteralUnion, PartialDeep } from 'type-fest';
2
- import type { WalletObject } from '@ocap/wallet';
3
- import type { TAssetFactoryState, TCreateAssetTx } from '@ocap/types';
1
+ import { LiteralUnion, PartialDeep } from "type-fest";
2
+ import { WalletObject } from "@ocap/wallet";
3
+ import { TAssetFactoryState, TCreateAssetTx } from "@ocap/types";
4
+
5
+ //#region src/index.d.ts
4
6
  type $TSFixMe = any;
5
- export type TPickedFactoryState = PartialDeep<TAssetFactoryState>;
6
- export type TIssuer = {
7
- name: string;
8
- wallet: WalletObject;
7
+ type TPickedFactoryState = PartialDeep<TAssetFactoryState>;
8
+ type TIssuer = {
9
+ name: string;
10
+ wallet: WalletObject;
9
11
  };
10
- export type TIssuerInput = {
11
- id: string;
12
- pk: string;
13
- name: string;
12
+ type TIssuerInput = {
13
+ id: string;
14
+ pk: string;
15
+ name: string;
14
16
  };
15
- export type THook = {
16
- type: LiteralUnion<'contract' | 'url', string>;
17
- name: LiteralUnion<'mint' | 'postMint' | 'preMint', string>;
18
- hook: string;
17
+ type THook = {
18
+ type: LiteralUnion<'contract' | 'url', string>;
19
+ name: LiteralUnion<'mint' | 'postMint' | 'preMint', string>;
20
+ hook: string;
19
21
  };
20
- export type TInputMap = {
21
- [key: string]: string;
22
+ type TInputMap = {
23
+ [key: string]: string;
22
24
  };
23
- export type TMintResult = {
24
- address: string;
25
- asset: TCreateAssetTx;
25
+ type TMintResult = {
26
+ address: string;
27
+ asset: TCreateAssetTx;
26
28
  };
27
- export type TPreMintResult = TMintResult & {
28
- variables: TInputMap;
29
- issuer: TIssuerInput;
29
+ type TPreMintResult = TMintResult & {
30
+ variables: TInputMap;
31
+ issuer: TIssuerInput;
30
32
  };
31
- export declare const isValidNotation: (notation: string) => boolean;
32
- export declare const isValidHook: (hook: THook, quota?: $TSFixMe, throwOnError?: boolean) => boolean;
33
- export declare const isValidFactory: (props: any) => boolean;
33
+ declare const isValidNotation: (notation: string) => boolean;
34
+ declare const isValidHook: (hook: THook, quota?: $TSFixMe, throwOnError?: boolean) => boolean;
35
+ declare const isValidFactory: (props: any) => boolean;
34
36
  /**
35
37
  * Find credentialSubject path in the object
36
38
  * Because they need prerender
@@ -39,7 +41,7 @@ export declare const isValidFactory: (props: any) => boolean;
39
41
  * @param {string} keyword
40
42
  * @return {string} list of keys
41
43
  */
42
- export declare const findPrerenderKeys: (obj: $TSFixMe, keyword: string) => string[];
44
+ declare const findPrerenderKeys: (obj: $TSFixMe, keyword: string) => string[];
43
45
  /**
44
46
  * Mint from an asset factory, used on server side
45
47
  *
@@ -49,11 +51,16 @@ export declare const findPrerenderKeys: (obj: $TSFixMe, keyword: string) => stri
49
51
  * @param {string} params.owner owner did for the new asset
50
52
  * @param {object} params.issuer issuer object
51
53
  */
52
- export declare const mintFromFactory: ({ factory, inputs, owner, issuer, }: {
53
- factory: TPickedFactoryState;
54
- inputs: TInputMap;
55
- owner: string;
56
- issuer: TIssuerInput;
54
+ declare const mintFromFactory: ({
55
+ factory,
56
+ inputs,
57
+ owner,
58
+ issuer
59
+ }: {
60
+ factory: TPickedFactoryState;
61
+ inputs: TInputMap;
62
+ owner: string;
63
+ issuer: TIssuerInput;
57
64
  }) => TMintResult;
58
65
  /**
59
66
  * Simulate minting from an asset factory, used for client side
@@ -64,11 +71,17 @@ export declare const mintFromFactory: ({ factory, inputs, owner, issuer, }: {
64
71
  * @param {string} params.owner owner did for the new asset
65
72
  * @param {object} params.issuer factory issuer wallet and name
66
73
  */
67
- export declare const preMintFromFactory: ({ factory, inputs, owner, issuer, }: {
68
- factory?: TPickedFactoryState;
69
- inputs: TInputMap;
70
- owner?: string;
71
- issuer?: TIssuer;
74
+ declare const preMintFromFactory: ({
75
+ factory,
76
+ inputs,
77
+ owner,
78
+ issuer
79
+ }: {
80
+ factory?: TPickedFactoryState;
81
+ inputs: TInputMap;
82
+ owner?: string;
83
+ issuer?: TIssuer;
72
84
  }) => Promise<TPreMintResult>;
73
- export declare const formatFactoryState: (state: TAssetFactoryState) => TPickedFactoryState;
74
- export {};
85
+ declare const formatFactoryState: (state: TAssetFactoryState) => TPickedFactoryState;
86
+ //#endregion
87
+ export { THook, TInputMap, TIssuer, TIssuerInput, TMintResult, TPickedFactoryState, TPreMintResult, findPrerenderKeys, formatFactoryState, isValidFactory, isValidHook, isValidNotation, mintFromFactory, preMintFromFactory };
package/lib/index.js CHANGED
@@ -1,261 +1,262 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.formatFactoryState = exports.preMintFromFactory = exports.mintFromFactory = exports.findPrerenderKeys = exports.isValidFactory = exports.isValidHook = exports.isValidNotation = void 0;
7
- /* eslint-disable @typescript-eslint/ban-ts-comment */
8
- const get_1 = __importDefault(require("lodash/get"));
9
- const set_1 = __importDefault(require("lodash/set"));
10
- const uniq_1 = __importDefault(require("lodash/uniq"));
11
- const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
12
- const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
13
- const flat_1 = __importDefault(require("flat"));
14
- const mustache_1 = __importDefault(require("mustache"));
15
- const is_absolute_url_1 = __importDefault(require("is-absolute-url"));
16
- const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
17
- const did_1 = require("@arcblock/did");
18
- const vc_1 = require("@arcblock/vc");
19
- const validator_1 = require("@arcblock/validator");
20
- const did_util_1 = require("@arcblock/did-util");
21
- const mcrypto_1 = require("@ocap/mcrypto");
22
- const util_1 = require("@ocap/util");
23
- const contract_1 = require("@ocap/contract");
24
- const debug_1 = __importDefault(require("debug"));
25
- const debug = (0, debug_1.default)('@ocap/asset');
26
- const SUPPORTED_HOOK_NAMES = ['preMint', 'mint', 'postMint'];
27
- const SUPPORTED_HOOK_TYPES = ['contract', 'url'];
28
- const isValidNotation = (notation) => ['ctx', 'data', 'input'].includes(notation.split('.').shift());
29
- exports.isValidNotation = isValidNotation;
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.js');
2
+ let lodash_get = require("lodash/get");
3
+ lodash_get = require_rolldown_runtime.__toESM(lodash_get);
4
+ let lodash_set = require("lodash/set");
5
+ lodash_set = require_rolldown_runtime.__toESM(lodash_set);
6
+ let lodash_uniq = require("lodash/uniq");
7
+ lodash_uniq = require_rolldown_runtime.__toESM(lodash_uniq);
8
+ let lodash_uniqBy = require("lodash/uniqBy");
9
+ lodash_uniqBy = require_rolldown_runtime.__toESM(lodash_uniqBy);
10
+ let lodash_isEmpty = require("lodash/isEmpty");
11
+ lodash_isEmpty = require_rolldown_runtime.__toESM(lodash_isEmpty);
12
+ let flat = require("flat");
13
+ flat = require_rolldown_runtime.__toESM(flat);
14
+ let mustache = require("mustache");
15
+ mustache = require_rolldown_runtime.__toESM(mustache);
16
+ let is_absolute_url = require("is-absolute-url");
17
+ is_absolute_url = require_rolldown_runtime.__toESM(is_absolute_url);
18
+ let lodash_cloneDeep = require("lodash/cloneDeep");
19
+ lodash_cloneDeep = require_rolldown_runtime.__toESM(lodash_cloneDeep);
20
+ let _arcblock_did = require("@arcblock/did");
21
+ let _arcblock_vc = require("@arcblock/vc");
22
+ let _arcblock_validator = require("@arcblock/validator");
23
+ let _arcblock_did_util = require("@arcblock/did-util");
24
+ let _ocap_mcrypto = require("@ocap/mcrypto");
25
+ let _ocap_util = require("@ocap/util");
26
+ let _ocap_contract = require("@ocap/contract");
27
+ let debug = require("debug");
28
+ debug = require_rolldown_runtime.__toESM(debug);
29
+
30
+ //#region src/index.ts
31
+ const debug$1 = (0, debug.default)("@ocap/asset");
32
+ const SUPPORTED_HOOK_NAMES = [
33
+ "preMint",
34
+ "mint",
35
+ "postMint"
36
+ ];
37
+ const SUPPORTED_HOOK_TYPES = ["contract", "url"];
38
+ const isValidNotation = (notation) => [
39
+ "ctx",
40
+ "data",
41
+ "input"
42
+ ].includes(notation.split(".").shift());
30
43
  const isValidHook = (hook, quota, throwOnError = false) => {
31
- if (SUPPORTED_HOOK_TYPES.includes(hook.type) === false) {
32
- return false;
33
- }
34
- if (SUPPORTED_HOOK_NAMES.includes(hook.name) === false) {
35
- return false;
36
- }
37
- if (hook.type === 'url') {
38
- return (0, is_absolute_url_1.default)(hook.hook);
39
- }
40
- if (hook.type === 'contract') {
41
- try {
42
- const compiled = (0, contract_1.compile)(hook.hook);
43
- (0, contract_1.validate)(compiled, quota);
44
- return true;
45
- }
46
- catch (err) {
47
- if (process.env.NODE_ENV !== 'test') {
48
- console.error('invalid contract hook', err.message);
49
- }
50
- if (throwOnError) {
51
- throw new Error(`Factory hook ${hook.name} is invalid: ${err.message}`);
52
- }
53
- return false;
54
- }
55
- }
56
- return false;
44
+ if (SUPPORTED_HOOK_TYPES.includes(hook.type) === false) return false;
45
+ if (SUPPORTED_HOOK_NAMES.includes(hook.name) === false) return false;
46
+ if (hook.type === "url") return (0, is_absolute_url.default)(hook.hook);
47
+ if (hook.type === "contract") try {
48
+ (0, _ocap_contract.validate)((0, _ocap_contract.compile)(hook.hook), quota);
49
+ return true;
50
+ } catch (err) {
51
+ if (process.env.NODE_ENV !== "test") console.error("invalid contract hook", err.message);
52
+ if (throwOnError) throw new Error(`Factory hook ${hook.name} is invalid: ${err.message}`);
53
+ return false;
54
+ }
55
+ return false;
57
56
  };
58
- exports.isValidHook = isValidHook;
59
- // @link https://github.com/improbable-eng/ts-protoc-gen
60
57
  const isValidFactory = (props) => {
61
- if (!props) {
62
- throw new Error('Factory props should not be empty');
63
- }
64
- const { value, error } = validator_1.schemas.factorySchema.validate(props);
65
- if (error) {
66
- throw new Error(`Invalid factory: ${error.details.map((x) => x.message).join(', ')}`);
67
- }
68
- // input.tokens and input.assets should not be empty
69
- if (['tokens', 'assets'].every((x) => (0, isEmpty_1.default)(value.input[x])) && value.input.value <= 0) {
70
- throw new Error('Factory input should contain at least one token or asset');
71
- }
72
- if ((0, uniqBy_1.default)(value.input.tokens, 'address').length !== value.input.tokens.length) {
73
- throw new Error('Factory token input should not contains duplicate address');
74
- }
75
- if ((0, uniq_1.default)(value.input.assets).length !== value.input.assets.length) {
76
- throw new Error('Factory asset input should not contains duplicate address');
77
- }
78
- try {
79
- // should be a valid mustache template when serialized as json
80
- const template = JSON.stringify(value.output, null, 2);
81
- const result = mustache_1.default.parse(template);
82
- if (result.filter(([type]) => type === 'name').some(([, notation]) => (0, exports.isValidNotation)(notation) === false)) {
83
- throw new Error('Invalid tags found in the output template');
84
- }
85
- }
86
- catch (err) {
87
- throw new Error('Factory output should be a valid mustache template when serialized as json');
88
- }
89
- // validate hooks
90
- const quota = (0, contract_1.getQuota)(value.input);
91
- if (Array.isArray(value.hooks)) {
92
- const invalidHook = value.hooks.find((x) => (0, exports.isValidHook)(x, quota, true) === false);
93
- if (invalidHook) {
94
- throw new Error(`Factory hook ${invalidHook.name} is invalid`);
95
- }
96
- }
97
- // ensure input and hook are zero-sum for factories that consumes token
98
- if (value.settlement === 'instant') {
99
- if (quota.value <= 0 && Object.keys(quota.tokens).every((x) => quota[x] <= 0)) {
100
- return true;
101
- }
102
- if ((0, isEmpty_1.default)(value.hooks)) {
103
- throw new Error('Factory hooks should not be empty for instant settlement');
104
- }
105
- const mintHook = value.hooks.find((x) => x.name === 'mint');
106
- if (!mintHook) {
107
- throw new Error('Factory hook mint should not be empty for instant settlement that consumes token');
108
- }
109
- try {
110
- const compiled = (0, contract_1.compile)(mintHook.hook);
111
- (0, contract_1.validate)(compiled, quota, true);
112
- }
113
- catch (err) {
114
- throw new Error(`Factory hook mint is invalid: ${err.message}`);
115
- }
116
- }
117
- return true;
58
+ if (!props) throw new Error("Factory props should not be empty");
59
+ const { value, error } = _arcblock_validator.schemas.factorySchema.validate(props);
60
+ if (error) throw new Error(`Invalid factory: ${error.details.map((x) => x.message).join(", ")}`);
61
+ if (["tokens", "assets"].every((x) => (0, lodash_isEmpty.default)(value.input[x])) && value.input.value <= 0) throw new Error("Factory input should contain at least one token or asset");
62
+ if ((0, lodash_uniqBy.default)(value.input.tokens, "address").length !== value.input.tokens.length) throw new Error("Factory token input should not contains duplicate address");
63
+ if ((0, lodash_uniq.default)(value.input.assets).length !== value.input.assets.length) throw new Error("Factory asset input should not contains duplicate address");
64
+ try {
65
+ const template = JSON.stringify(value.output, null, 2);
66
+ if (mustache.default.parse(template).filter(([type]) => type === "name").some(([, notation]) => isValidNotation(notation) === false)) throw new Error("Invalid tags found in the output template");
67
+ } catch (err) {
68
+ throw new Error("Factory output should be a valid mustache template when serialized as json");
69
+ }
70
+ const quota = (0, _ocap_contract.getQuota)(value.input);
71
+ if (Array.isArray(value.hooks)) {
72
+ const invalidHook = value.hooks.find((x) => isValidHook(x, quota, true) === false);
73
+ if (invalidHook) throw new Error(`Factory hook ${invalidHook.name} is invalid`);
74
+ }
75
+ if (value.settlement === "instant") {
76
+ if (quota.value <= 0 && Object.keys(quota.tokens).every((x) => quota[x] <= 0)) return true;
77
+ if ((0, lodash_isEmpty.default)(value.hooks)) throw new Error("Factory hooks should not be empty for instant settlement");
78
+ const mintHook = value.hooks.find((x) => x.name === "mint");
79
+ if (!mintHook) throw new Error("Factory hook mint should not be empty for instant settlement that consumes token");
80
+ try {
81
+ (0, _ocap_contract.validate)((0, _ocap_contract.compile)(mintHook.hook), quota, true);
82
+ } catch (err) {
83
+ throw new Error(`Factory hook mint is invalid: ${err.message}`);
84
+ }
85
+ }
86
+ return true;
118
87
  };
119
- exports.isValidFactory = isValidFactory;
120
88
  /**
121
- * Find credentialSubject path in the object
122
- * Because they need prerender
123
- *
124
- * @param {object} obj
125
- * @param {string} keyword
126
- * @return {string} list of keys
127
- */
89
+ * Find credentialSubject path in the object
90
+ * Because they need prerender
91
+ *
92
+ * @param {object} obj
93
+ * @param {string} keyword
94
+ * @return {string} list of keys
95
+ */
128
96
  const findPrerenderKeys = (obj, keyword) => {
129
- const flatObj = (0, flat_1.default)(obj, { safe: true });
130
- const keys = Object.keys(flatObj)
131
- .map((x) => x.split('.'))
132
- .filter((x) => x.includes(keyword))
133
- .map((x) => x.slice(0, x.lastIndexOf(keyword) + 1))
134
- .sort((a, b) => b.length - a.length)
135
- .map((x) => x.join('.'));
136
- return (0, uniq_1.default)(keys);
97
+ const flatObj = (0, flat.default)(obj, { safe: true });
98
+ return (0, lodash_uniq.default)(Object.keys(flatObj).map((x) => x.split(".")).filter((x) => x.includes(keyword)).map((x) => x.slice(0, x.lastIndexOf(keyword) + 1)).sort((a, b) => b.length - a.length).map((x) => x.join(".")));
137
99
  };
138
- exports.findPrerenderKeys = findPrerenderKeys;
139
100
  /**
140
- * Mint from an asset factory, used on server side
141
- *
142
- * @param {object} params { factory, inputs, issuer }
143
- * @param {object} params.factory factory object
144
- * @param {object} params.inputs factory input variables
145
- * @param {string} params.owner owner did for the new asset
146
- * @param {object} params.issuer issuer object
147
- */
148
- const mintFromFactory = ({ factory, inputs, owner, issuer, }) => {
149
- const { output, address: factoryAddress, numMinted, data } = factory;
150
- debug('mintFromFactory.args', JSON.stringify({ output, factoryAddress, numMinted, inputs, owner, issuer, data }, null, 2));
151
- const asset = JSON.parse(mustache_1.default.render(JSON.stringify(output), {
152
- input: inputs,
153
- data: data.value || data,
154
- ctx: { factory: factoryAddress, id: numMinted + 1, owner, issuer },
155
- }));
156
- const address = (0, did_util_1.toAssetAddress)(asset);
157
- debug('mintFromFactory.result', JSON.stringify({ asset, address }, null, 2));
158
- return { asset, address };
101
+ * Mint from an asset factory, used on server side
102
+ *
103
+ * @param {object} params { factory, inputs, issuer }
104
+ * @param {object} params.factory factory object
105
+ * @param {object} params.inputs factory input variables
106
+ * @param {string} params.owner owner did for the new asset
107
+ * @param {object} params.issuer issuer object
108
+ */
109
+ const mintFromFactory = ({ factory, inputs, owner, issuer }) => {
110
+ const { output, address: factoryAddress, numMinted, data } = factory;
111
+ debug$1("mintFromFactory.args", JSON.stringify({
112
+ output,
113
+ factoryAddress,
114
+ numMinted,
115
+ inputs,
116
+ owner,
117
+ issuer,
118
+ data
119
+ }, null, 2));
120
+ const asset = JSON.parse(mustache.default.render(JSON.stringify(output), {
121
+ input: inputs,
122
+ data: data.value || data,
123
+ ctx: {
124
+ factory: factoryAddress,
125
+ id: numMinted + 1,
126
+ owner,
127
+ issuer
128
+ }
129
+ }));
130
+ const address = (0, _arcblock_did_util.toAssetAddress)(asset);
131
+ debug$1("mintFromFactory.result", JSON.stringify({
132
+ asset,
133
+ address
134
+ }, null, 2));
135
+ return {
136
+ asset,
137
+ address
138
+ };
159
139
  };
160
- exports.mintFromFactory = mintFromFactory;
161
140
  /**
162
- * Simulate minting from an asset factory, used for client side
163
- *
164
- * @param {object} params { factory, inputs, issuer }
165
- * @param {object} params.factory factory object
166
- * @param {object} params.inputs factory input variables
167
- * @param {string} params.owner owner did for the new asset
168
- * @param {object} params.issuer factory issuer wallet and name
169
- */
170
- const preMintFromFactory = async ({ factory, inputs, owner, issuer, }) => {
171
- if (Object.keys(inputs).some((x) => typeof inputs[x] !== 'string')) {
172
- throw new Error('Failed to mint asset from factory: input values must be strings');
173
- }
174
- let asset = null;
175
- const { output, numMinted, address: factoryAddress, data } = factory;
176
- const { wallet, name } = issuer;
177
- debug('preMintFromFactory.args', JSON.stringify({ output, factoryAddress, numMinted, inputs, owner, issuer, data }, null, 2));
178
- const extra = {};
179
- const issuerObject = { id: wallet.address, pk: (0, util_1.toBase58)(wallet.publicKey), name };
180
- const render = (templateObject) => JSON.parse(mustache_1.default.render(JSON.stringify(templateObject), {
181
- input: { ...inputs, ...extra },
182
- data: data.value || data,
183
- ctx: { factory: factoryAddress, id: numMinted + 1, owner, issuer: issuerObject },
184
- }));
185
- const template = (0, cloneDeep_1.default)(output);
186
- // prerender credentialSubjects if they exists
187
- // then populate their ids
188
- const prerenderKeys = (0, exports.findPrerenderKeys)(template, 'credentialSubject');
189
- if (prerenderKeys.length) {
190
- extra.issuanceDate = new Date().toISOString();
191
- for (const key of prerenderKeys) {
192
- const subjectTemplate = (0, get_1.default)(template, key);
193
- const subjectObject = Array.isArray(subjectTemplate)
194
- ? subjectTemplate.map((x) => render(x))
195
- : render(subjectTemplate);
196
- (0, set_1.default)(template, key, subjectObject);
197
- // calculate credential id from credentialSubject
198
- const vcRootPath = key.split('.').slice(0, -1).join('.');
199
- const vcIdPath = vcRootPath.split('.').concat(['id']).join('.');
200
- const typeInfo = (0, did_1.toTypeInfo)(issuerObject.id);
201
- const vcType = { ...typeInfo, role: mcrypto_1.types.RoleType.ROLE_VC };
202
- const vcId = (0, did_1.fromPublicKeyHash)(wallet.hash((0, vc_1.stableStringify)(subjectObject)), vcType);
203
- extra.id = vcId;
204
- extra.proofType = vc_1.proofTypes[typeInfo.pk];
205
- // technically we do not support nested vc when minting
206
- // But it is possible to support multiple credentialSubjects when minting
207
- (0, set_1.default)(template, vcIdPath, vcId);
208
- // Generate proof signatures
209
- if (!vc_1.proofTypes[typeInfo.pk]) {
210
- throw new Error('Unsupported signer type when create verifiable credential');
211
- }
212
- let vcObj = render((0, get_1.default)(template, vcRootPath));
213
- delete vcObj.proof;
214
- const vcStr = (0, vc_1.stableStringify)(vcObj);
215
- // eslint-disable-next-line no-await-in-loop
216
- const signature = (0, util_1.toBase64)(await wallet.sign(vcStr));
217
- vcObj.proof = {
218
- type: vc_1.proofTypes[typeInfo.pk],
219
- created: extra.issuanceDate,
220
- proofPurpose: 'assertionMethod',
221
- jws: signature,
222
- };
223
- extra.signature = signature;
224
- try {
225
- // Simulate minting from start, so that we can ensure the validity of minted asset
226
- asset = render((0, cloneDeep_1.default)(output));
227
- vcObj = (0, get_1.default)(asset, vcRootPath);
228
- debug('preMintFromFactory.result', JSON.stringify(asset, null, 2));
229
- // eslint-disable-next-line no-await-in-loop
230
- await (0, vc_1.verify)({ vc: vcObj, trustedIssuers: [issuerObject.id], ownerDid: owner, ignoreExpired: true });
231
- }
232
- catch (err) {
233
- console.error(err);
234
- throw new Error('Failed to mint asset from factory: invalid verifiable credential minted');
235
- }
236
- }
237
- }
238
- else {
239
- // populate other variables into the whole output
240
- asset = render(template);
241
- debug('preMintFromFactory.result', JSON.stringify(asset, null, 2));
242
- }
243
- // calculate address
244
- const address = (0, did_util_1.toAssetAddress)(asset);
245
- // return extra inputs
246
- return { address, issuer: issuerObject, variables: { ...inputs, ...extra }, asset };
141
+ * Simulate minting from an asset factory, used for client side
142
+ *
143
+ * @param {object} params { factory, inputs, issuer }
144
+ * @param {object} params.factory factory object
145
+ * @param {object} params.inputs factory input variables
146
+ * @param {string} params.owner owner did for the new asset
147
+ * @param {object} params.issuer factory issuer wallet and name
148
+ */
149
+ const preMintFromFactory = async ({ factory, inputs, owner, issuer }) => {
150
+ if (Object.keys(inputs).some((x) => typeof inputs[x] !== "string")) throw new Error("Failed to mint asset from factory: input values must be strings");
151
+ let asset = null;
152
+ const { output, numMinted, address: factoryAddress, data } = factory;
153
+ const { wallet, name } = issuer;
154
+ debug$1("preMintFromFactory.args", JSON.stringify({
155
+ output,
156
+ factoryAddress,
157
+ numMinted,
158
+ inputs,
159
+ owner,
160
+ issuer,
161
+ data
162
+ }, null, 2));
163
+ const extra = {};
164
+ const issuerObject = {
165
+ id: wallet.address,
166
+ pk: (0, _ocap_util.toBase58)(wallet.publicKey),
167
+ name
168
+ };
169
+ const render = (templateObject) => JSON.parse(mustache.default.render(JSON.stringify(templateObject), {
170
+ input: {
171
+ ...inputs,
172
+ ...extra
173
+ },
174
+ data: data.value || data,
175
+ ctx: {
176
+ factory: factoryAddress,
177
+ id: numMinted + 1,
178
+ owner,
179
+ issuer: issuerObject
180
+ }
181
+ }));
182
+ const template = (0, lodash_cloneDeep.default)(output);
183
+ const prerenderKeys = findPrerenderKeys(template, "credentialSubject");
184
+ if (prerenderKeys.length) {
185
+ extra.issuanceDate = (/* @__PURE__ */ new Date()).toISOString();
186
+ for (const key of prerenderKeys) {
187
+ const subjectTemplate = (0, lodash_get.default)(template, key);
188
+ const subjectObject = Array.isArray(subjectTemplate) ? subjectTemplate.map((x) => render(x)) : render(subjectTemplate);
189
+ (0, lodash_set.default)(template, key, subjectObject);
190
+ const vcRootPath = key.split(".").slice(0, -1).join(".");
191
+ const vcIdPath = vcRootPath.split(".").concat(["id"]).join(".");
192
+ const typeInfo = (0, _arcblock_did.toTypeInfo)(issuerObject.id);
193
+ const vcType = {
194
+ ...typeInfo,
195
+ role: _ocap_mcrypto.types.RoleType.ROLE_VC
196
+ };
197
+ const vcId = (0, _arcblock_did.fromPublicKeyHash)(wallet.hash((0, _arcblock_vc.stableStringify)(subjectObject)), vcType);
198
+ extra.id = vcId;
199
+ extra.proofType = _arcblock_vc.proofTypes[typeInfo.pk];
200
+ (0, lodash_set.default)(template, vcIdPath, vcId);
201
+ if (!_arcblock_vc.proofTypes[typeInfo.pk]) throw new Error("Unsupported signer type when create verifiable credential");
202
+ let vcObj = render((0, lodash_get.default)(template, vcRootPath));
203
+ delete vcObj.proof;
204
+ const vcStr = (0, _arcblock_vc.stableStringify)(vcObj);
205
+ const signature = (0, _ocap_util.toBase64)(await wallet.sign(vcStr));
206
+ vcObj.proof = {
207
+ type: _arcblock_vc.proofTypes[typeInfo.pk],
208
+ created: extra.issuanceDate,
209
+ proofPurpose: "assertionMethod",
210
+ jws: signature
211
+ };
212
+ extra.signature = signature;
213
+ try {
214
+ asset = render((0, lodash_cloneDeep.default)(output));
215
+ vcObj = (0, lodash_get.default)(asset, vcRootPath);
216
+ debug$1("preMintFromFactory.result", JSON.stringify(asset, null, 2));
217
+ await (0, _arcblock_vc.verify)({
218
+ vc: vcObj,
219
+ trustedIssuers: [issuerObject.id],
220
+ ownerDid: owner,
221
+ ignoreExpired: true
222
+ });
223
+ } catch (err) {
224
+ console.error(err);
225
+ throw new Error("Failed to mint asset from factory: invalid verifiable credential minted");
226
+ }
227
+ }
228
+ } else {
229
+ asset = render(template);
230
+ debug$1("preMintFromFactory.result", JSON.stringify(asset, null, 2));
231
+ }
232
+ return {
233
+ address: (0, _arcblock_did_util.toAssetAddress)(asset),
234
+ issuer: issuerObject,
235
+ variables: {
236
+ ...inputs,
237
+ ...extra
238
+ },
239
+ asset
240
+ };
247
241
  };
248
- exports.preMintFromFactory = preMintFromFactory;
249
242
  const formatFactoryState = (state) => {
250
- const { address, output, data, numMinted } = state;
251
- const outputX = (0, cloneDeep_1.default)(output);
252
- outputX.data.value = JSON.parse(outputX.data.value);
253
- outputX.data.type = outputX.data.typeUrl;
254
- return {
255
- address,
256
- output: outputX,
257
- data: data.value ? JSON.parse(data.value) : {},
258
- numMinted,
259
- };
243
+ const { address, output, data, numMinted } = state;
244
+ const outputX = (0, lodash_cloneDeep.default)(output);
245
+ outputX.data.value = JSON.parse(outputX.data.value);
246
+ outputX.data.type = outputX.data.typeUrl;
247
+ return {
248
+ address,
249
+ output: outputX,
250
+ data: data.value ? JSON.parse(data.value) : {},
251
+ numMinted
252
+ };
260
253
  };
254
+
255
+ //#endregion
256
+ exports.findPrerenderKeys = findPrerenderKeys;
261
257
  exports.formatFactoryState = formatFactoryState;
258
+ exports.isValidFactory = isValidFactory;
259
+ exports.isValidHook = isValidHook;
260
+ exports.isValidNotation = isValidNotation;
261
+ exports.mintFromFactory = mintFromFactory;
262
+ exports.preMintFromFactory = preMintFromFactory;
File without changes