@ocap/asset 1.16.14 → 1.16.17
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 +54 -34
- package/lib/index.js +218 -268
- package/package.json +31 -33
package/lib/index.d.ts
CHANGED
@@ -1,40 +1,60 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
declare const
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
declare type $TSFixMe = any;
|
2
|
+
export declare const isValidHook: (hook: $TSFixMe, quota?: $TSFixMe, throwOnError?: boolean) => boolean;
|
3
|
+
export declare const isValidFactory: (props: $TSFixMe) => boolean;
|
4
|
+
/**
|
5
|
+
* Find credentialSubject path in the object
|
6
|
+
* Because they need prerender
|
7
|
+
*
|
8
|
+
* @param {object} obj
|
9
|
+
* @param {string} keyword
|
10
|
+
* @return {string} list of keys
|
11
|
+
*/
|
12
|
+
export declare const findPrerenderKeys: (obj: $TSFixMe, keyword: string) => string[];
|
13
|
+
/**
|
14
|
+
* Mint from an asset factory, used on server side
|
15
|
+
*
|
16
|
+
* @param {object} params { factory, inputs, issuer }
|
17
|
+
* @param {object} params.factory factory object
|
18
|
+
* @param {object} params.inputs factory input variables
|
19
|
+
* @param {string} params.owner owner did for the new asset
|
20
|
+
* @param {object} params.issuer issuer object
|
21
|
+
*/
|
22
|
+
export declare const mintFromFactory: ({ factory, inputs, owner, issuer, }: {
|
23
|
+
factory: $TSFixMe;
|
24
|
+
inputs: $TSFixMe;
|
8
25
|
owner: string;
|
9
|
-
issuer:
|
10
|
-
|
11
|
-
export interface T102 {
|
26
|
+
issuer: $TSFixMe;
|
27
|
+
}) => {
|
12
28
|
asset: any;
|
13
29
|
address: string;
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
30
|
+
};
|
31
|
+
/**
|
32
|
+
* Simulate minting from an asset factory, used for client side
|
33
|
+
*
|
34
|
+
* @param {object} params { factory, inputs, issuer }
|
35
|
+
* @param {object} params.factory factory object
|
36
|
+
* @param {object} params.inputs factory input variables
|
37
|
+
* @param {string} params.owner owner did for the new asset
|
38
|
+
* @param {object} params.issuer factory issuer wallet and name
|
39
|
+
*/
|
40
|
+
export declare const preMintFromFactory: ({ factory, inputs, owner, issuer, }: {
|
41
|
+
factory?: $TSFixMe;
|
42
|
+
inputs: $TSFixMe;
|
43
|
+
owner?: string;
|
44
|
+
issuer?: $TSFixMe;
|
45
|
+
}) => {
|
26
46
|
address: string;
|
27
|
-
issuer:
|
47
|
+
issuer: {
|
48
|
+
id: any;
|
49
|
+
pk: string;
|
50
|
+
name: any;
|
51
|
+
};
|
28
52
|
variables: any;
|
29
53
|
asset: any;
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
preMintFromFactory: (T104: _Lib.T101) => _Lib.T106;
|
38
|
-
}
|
39
|
-
}
|
40
|
-
export = _Lib;
|
54
|
+
};
|
55
|
+
export declare const formatFactoryState: (state: $TSFixMe) => {
|
56
|
+
address: any;
|
57
|
+
output: any;
|
58
|
+
data: any;
|
59
|
+
};
|
60
|
+
export {};
|
package/lib/index.js
CHANGED
@@ -1,143 +1,132 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
const
|
9
|
-
const
|
10
|
-
|
11
|
-
const
|
12
|
-
const
|
13
|
-
const
|
14
|
-
const
|
15
|
-
const
|
16
|
-
const
|
17
|
-
const
|
18
|
-
|
19
|
-
const
|
20
|
-
|
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 = 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 flat_1 = __importDefault(require("flat"));
|
13
|
+
const mustache_1 = __importDefault(require("mustache"));
|
14
|
+
const is_absolute_url_1 = __importDefault(require("is-absolute-url"));
|
15
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
16
|
+
const did_1 = require("@arcblock/did");
|
17
|
+
const vc_1 = require("@arcblock/vc");
|
18
|
+
const did_util_1 = require("@arcblock/did-util");
|
19
|
+
const mcrypto_1 = require("@ocap/mcrypto");
|
20
|
+
const util_1 = require("@ocap/util");
|
21
|
+
const contract_1 = require("@ocap/contract");
|
22
|
+
const debug_1 = __importDefault(require("debug"));
|
23
|
+
const lodash_1 = require("lodash");
|
24
|
+
const debug = (0, debug_1.default)('@ocap/asset');
|
21
25
|
const SUPPORTED_HOOK_NAMES = ['mint', 'postMint'];
|
22
26
|
const SUPPORTED_HOOK_TYPES = ['contract', 'url'];
|
23
|
-
|
24
27
|
const isValidHook = (hook, quota, throwOnError = false) => {
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}
|
31
|
-
|
32
|
-
if (hook.type === 'url') {
|
33
|
-
return isAbsoluteUrl(hook.hook);
|
34
|
-
}
|
35
|
-
|
36
|
-
if (hook.type === 'contract') {
|
37
|
-
try {
|
38
|
-
const compiled = compile(hook.hook);
|
39
|
-
validate(compiled, quota);
|
40
|
-
return true;
|
41
|
-
} catch (err) {
|
42
|
-
if (process.env.NODE_ENV !== 'test') {
|
43
|
-
console.error('invalid contract hook', err.message);
|
44
|
-
}
|
45
|
-
|
46
|
-
if (throwOnError) {
|
47
|
-
throw new Error(`Factory hook ${hook.name} is invalid: ${err.message}`);
|
48
|
-
}
|
49
|
-
|
50
|
-
return false;
|
28
|
+
if (SUPPORTED_HOOK_TYPES.includes(hook.type) === false) {
|
29
|
+
return false;
|
30
|
+
}
|
31
|
+
if (SUPPORTED_HOOK_NAMES.includes(hook.name) === false) {
|
32
|
+
return false;
|
51
33
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
34
|
+
if (hook.type === 'url') {
|
35
|
+
return (0, is_absolute_url_1.default)(hook.hook);
|
36
|
+
}
|
37
|
+
if (hook.type === 'contract') {
|
38
|
+
try {
|
39
|
+
const compiled = (0, contract_1.compile)(hook.hook);
|
40
|
+
(0, contract_1.validate)(compiled, quota);
|
41
|
+
return true;
|
42
|
+
}
|
43
|
+
catch (err) {
|
44
|
+
if (process.env.NODE_ENV !== 'test') {
|
45
|
+
console.error('invalid contract hook', err.message);
|
46
|
+
}
|
47
|
+
if (throwOnError) {
|
48
|
+
throw new Error(`Factory hook ${hook.name} is invalid: ${err.message}`);
|
49
|
+
}
|
50
|
+
return false;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
return false;
|
55
54
|
};
|
56
|
-
|
55
|
+
exports.isValidHook = isValidHook;
|
57
56
|
const isValidFactory = (props) => {
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
throw new Error(`Factory ${missingProp} prop should not be empty`);
|
66
|
-
}
|
67
|
-
|
68
|
-
if (['instant', 'periodic'].includes(props.settlement) === false) {
|
69
|
-
throw new Error('Factory settlement prop should only be instant or periodic');
|
70
|
-
}
|
71
|
-
|
72
|
-
// input.tokens and input.assets should not be empty
|
73
|
-
if (['value', 'tokens', 'assets'].every((x) => isEmpty(props.input[x]))) {
|
74
|
-
throw new Error('Factory input should contain at least one token or asset');
|
75
|
-
}
|
76
|
-
|
77
|
-
if (uniqBy(props.input.tokens, 'address').length !== props.input.tokens.length) {
|
78
|
-
throw new Error('Factory token input should not contains duplicate address');
|
79
|
-
}
|
80
|
-
|
81
|
-
if (uniq(props.input.assets).length !== props.input.assets.length) {
|
82
|
-
throw new Error('Factory asset input should not contains duplicate address');
|
83
|
-
}
|
84
|
-
|
85
|
-
for (const token of props.input.tokens) {
|
86
|
-
try {
|
87
|
-
// eslint-disable-next-line no-new
|
88
|
-
new BN(token.value);
|
89
|
-
} catch (err) {
|
90
|
-
throw new Error(`Factory token ${token.address} is invalid: token value is not valid big number`);
|
57
|
+
if (!props) {
|
58
|
+
throw new Error('Factory props should not be empty');
|
59
|
+
}
|
60
|
+
// required props
|
61
|
+
const missingProp = ['name', 'description', 'input', 'output', 'settlement'].find((x) => !props[x]);
|
62
|
+
if (missingProp) {
|
63
|
+
throw new Error(`Factory ${missingProp} prop should not be empty`);
|
91
64
|
}
|
92
|
-
|
93
|
-
|
94
|
-
// validate output
|
95
|
-
if (!props.output || typeof props.output !== 'object') {
|
96
|
-
throw new Error('Factory output should be an object');
|
97
|
-
}
|
98
|
-
try {
|
99
|
-
// should be a valid mustache template when serialized as json
|
100
|
-
const template = JSON.stringify(props.output);
|
101
|
-
mustache.parse(template);
|
102
|
-
} catch (err) {
|
103
|
-
throw new Error('Factory output should be a valid mustache template when serialized as json');
|
104
|
-
}
|
105
|
-
|
106
|
-
// validate hooks
|
107
|
-
const quota = getQuota(props.input);
|
108
|
-
if (Array.isArray(props.hooks)) {
|
109
|
-
const invalidHook = props.hooks.find((x) => isValidHook(x, quota, true) === false);
|
110
|
-
if (invalidHook) {
|
111
|
-
throw new Error(`Factory hook ${invalidHook.name} is invalid`);
|
65
|
+
if (['instant', 'periodic'].includes(props.settlement) === false) {
|
66
|
+
throw new Error('Factory settlement prop should only be instant or periodic');
|
112
67
|
}
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
if (props.settlement === 'instant') {
|
117
|
-
if (quota.value <= 0 && Object.keys(quota.tokens).every((x) => quota[x] <= 0)) {
|
118
|
-
return true;
|
68
|
+
// input.tokens and input.assets should not be empty
|
69
|
+
if (['value', 'tokens', 'assets'].every((x) => (0, lodash_1.isEmpty)(props.input[x]))) {
|
70
|
+
throw new Error('Factory input should contain at least one token or asset');
|
119
71
|
}
|
120
|
-
|
121
|
-
|
122
|
-
throw new Error('Factory hooks should not be empty for instant settlement');
|
72
|
+
if ((0, uniqBy_1.default)(props.input.tokens, 'address').length !== props.input.tokens.length) {
|
73
|
+
throw new Error('Factory token input should not contains duplicate address');
|
123
74
|
}
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
75
|
+
if ((0, uniq_1.default)(props.input.assets).length !== props.input.assets.length) {
|
76
|
+
throw new Error('Factory asset input should not contains duplicate address');
|
77
|
+
}
|
78
|
+
for (const token of props.input.tokens) {
|
79
|
+
try {
|
80
|
+
// eslint-disable-next-line no-new
|
81
|
+
new util_1.BN(token.value);
|
82
|
+
}
|
83
|
+
catch (err) {
|
84
|
+
throw new Error(`Factory token ${token.address} is invalid: token value is not valid big number`);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
// validate output
|
88
|
+
if (!props.output || typeof props.output !== 'object') {
|
89
|
+
throw new Error('Factory output should be an object');
|
128
90
|
}
|
129
|
-
|
130
91
|
try {
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
92
|
+
// should be a valid mustache template when serialized as json
|
93
|
+
const template = JSON.stringify(props.output);
|
94
|
+
mustache_1.default.parse(template);
|
95
|
+
}
|
96
|
+
catch (err) {
|
97
|
+
throw new Error('Factory output should be a valid mustache template when serialized as json');
|
98
|
+
}
|
99
|
+
// validate hooks
|
100
|
+
const quota = (0, contract_1.getQuota)(props.input);
|
101
|
+
if (Array.isArray(props.hooks)) {
|
102
|
+
const invalidHook = props.hooks.find((x) => (0, exports.isValidHook)(x, quota, true) === false);
|
103
|
+
if (invalidHook) {
|
104
|
+
throw new Error(`Factory hook ${invalidHook.name} is invalid`);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
// ensure input and hook are zero-sum for factories that consumes token
|
108
|
+
if (props.settlement === 'instant') {
|
109
|
+
if (quota.value <= 0 && Object.keys(quota.tokens).every((x) => quota[x] <= 0)) {
|
110
|
+
return true;
|
111
|
+
}
|
112
|
+
if ((0, lodash_1.isEmpty)(props.hooks)) {
|
113
|
+
throw new Error('Factory hooks should not be empty for instant settlement');
|
114
|
+
}
|
115
|
+
const mintHook = props.hooks.find((x) => x.name === 'mint');
|
116
|
+
if (!mintHook) {
|
117
|
+
throw new Error('Factory hook mint should not be empty for instant settlement that consumes token');
|
118
|
+
}
|
119
|
+
try {
|
120
|
+
const compiled = (0, contract_1.compile)(mintHook.hook);
|
121
|
+
(0, contract_1.validate)(compiled, quota, true);
|
122
|
+
}
|
123
|
+
catch (err) {
|
124
|
+
throw new Error(`Factory hook mint is invalid: ${err.message}`);
|
125
|
+
}
|
135
126
|
}
|
136
|
-
|
137
|
-
|
138
|
-
return true;
|
127
|
+
return true;
|
139
128
|
};
|
140
|
-
|
129
|
+
exports.isValidFactory = isValidFactory;
|
141
130
|
/**
|
142
131
|
* Find credentialSubject path in the object
|
143
132
|
* Because they need prerender
|
@@ -147,17 +136,16 @@ const isValidFactory = (props) => {
|
|
147
136
|
* @return {string} list of keys
|
148
137
|
*/
|
149
138
|
const findPrerenderKeys = (obj, keyword) => {
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
return uniq(keys);
|
139
|
+
const flatObj = (0, flat_1.default)(obj, { safe: true });
|
140
|
+
const keys = Object.keys(flatObj)
|
141
|
+
.map((x) => x.split('.'))
|
142
|
+
.filter((x) => x.includes(keyword))
|
143
|
+
.map((x) => x.slice(0, x.lastIndexOf(keyword) + 1))
|
144
|
+
.sort((a, b) => b.length - a.length)
|
145
|
+
.map((x) => x.join('.'));
|
146
|
+
return (0, uniq_1.default)(keys);
|
159
147
|
};
|
160
|
-
|
148
|
+
exports.findPrerenderKeys = findPrerenderKeys;
|
161
149
|
/**
|
162
150
|
* Mint from an asset factory, used on server side
|
163
151
|
*
|
@@ -167,25 +155,19 @@ const findPrerenderKeys = (obj, keyword) => {
|
|
167
155
|
* @param {string} params.owner owner did for the new asset
|
168
156
|
* @param {object} params.issuer issuer object
|
169
157
|
*/
|
170
|
-
const mintFromFactory = ({ factory, inputs, owner, issuer }) => {
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
})
|
182
|
-
);
|
183
|
-
|
184
|
-
debug('mintFromFactory.result', JSON.stringify(asset, null, 2));
|
185
|
-
const address = toAssetAddress(asset);
|
186
|
-
return { asset, address };
|
158
|
+
const mintFromFactory = ({ factory, inputs, owner, issuer, }) => {
|
159
|
+
const { output, address: factoryAddress, numMinted, data } = factory;
|
160
|
+
debug('mintFromFactory.args', JSON.stringify({ output, factoryAddress, numMinted, inputs, owner, issuer, data }, null, 2));
|
161
|
+
const asset = JSON.parse(mustache_1.default.render(JSON.stringify(output), {
|
162
|
+
input: inputs,
|
163
|
+
data: data.value || data,
|
164
|
+
ctx: { factory: factoryAddress, id: numMinted + 1, owner, issuer },
|
165
|
+
}));
|
166
|
+
debug('mintFromFactory.result', JSON.stringify(asset, null, 2));
|
167
|
+
const address = (0, did_util_1.toAssetAddress)(asset);
|
168
|
+
return { asset, address };
|
187
169
|
};
|
188
|
-
|
170
|
+
exports.mintFromFactory = mintFromFactory;
|
189
171
|
/**
|
190
172
|
* Simulate minting from an asset factory, used for client side
|
191
173
|
*
|
@@ -195,124 +177,92 @@ const mintFromFactory = ({ factory, inputs, owner, issuer }) => {
|
|
195
177
|
* @param {string} params.owner owner did for the new asset
|
196
178
|
* @param {object} params.issuer factory issuer wallet and name
|
197
179
|
*/
|
198
|
-
const preMintFromFactory = ({ factory, inputs, owner, issuer }) => {
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
);
|
211
|
-
|
212
|
-
const extra = {};
|
213
|
-
const issuerObject = { id: wallet.address, pk: toBase58(wallet.publicKey), name };
|
214
|
-
|
215
|
-
const render = (templateObject) =>
|
216
|
-
JSON.parse(
|
217
|
-
mustache.render(JSON.stringify(templateObject), {
|
218
|
-
input: { ...inputs, ...extra },
|
180
|
+
const preMintFromFactory = ({ factory, inputs, owner, issuer, }) => {
|
181
|
+
if (Object.keys(inputs).some((x) => typeof inputs[x] !== 'string')) {
|
182
|
+
throw new Error('Failed to mint asset from factory: input values must be strings');
|
183
|
+
}
|
184
|
+
let asset = null;
|
185
|
+
const { output, numMinted, address: factoryAddress, data } = factory;
|
186
|
+
const { wallet, name } = issuer;
|
187
|
+
debug('preMintFromFactory.args', JSON.stringify({ output, factoryAddress, numMinted, inputs, owner, issuer, data }, null, 2));
|
188
|
+
const extra = {};
|
189
|
+
const issuerObject = { id: wallet.address, pk: (0, util_1.toBase58)(wallet.publicKey), name };
|
190
|
+
const render = (templateObject) => JSON.parse(mustache_1.default.render(JSON.stringify(templateObject), {
|
191
|
+
input: Object.assign(Object.assign({}, inputs), extra),
|
219
192
|
data: data.value || data,
|
220
193
|
ctx: { factory: factoryAddress, id: numMinted + 1, owner, issuer: issuerObject },
|
221
|
-
|
222
|
-
);
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
194
|
+
}));
|
195
|
+
const template = (0, cloneDeep_1.default)(output);
|
196
|
+
// prerender credentialSubjects if they exists
|
197
|
+
// then populate their ids
|
198
|
+
const prerenderKeys = (0, exports.findPrerenderKeys)(template, 'credentialSubject');
|
199
|
+
if (prerenderKeys.length) {
|
200
|
+
extra.issuanceDate = new Date().toISOString();
|
201
|
+
for (const key of prerenderKeys) {
|
202
|
+
const subjectTemplate = (0, get_1.default)(template, key);
|
203
|
+
const subjectObject = Array.isArray(subjectTemplate)
|
204
|
+
? subjectTemplate.map((x) => render(x))
|
205
|
+
: render(subjectTemplate);
|
206
|
+
(0, set_1.default)(template, key, subjectObject);
|
207
|
+
// calculate credential id from credentialSubject
|
208
|
+
const vcRootPath = key.split('.').slice(0, -1).join('.');
|
209
|
+
const vcIdPath = vcRootPath.split('.').concat(['id']).join('.');
|
210
|
+
const typeInfo = (0, did_1.toTypeInfo)(issuerObject.id);
|
211
|
+
const vcType = Object.assign(Object.assign({}, typeInfo), { role: mcrypto_1.types.RoleType.ROLE_VC });
|
212
|
+
const vcId = (0, did_1.fromPublicKeyHash)(wallet.hash((0, vc_1.stableStringify)(subjectObject)), vcType);
|
213
|
+
extra.id = vcId;
|
214
|
+
extra.proofType = vc_1.proofTypes[typeInfo.pk];
|
215
|
+
// technically we do not support nested vc when minting
|
216
|
+
// But it is possible to support multiple credentialSubjects when minting
|
217
|
+
(0, set_1.default)(template, vcIdPath, vcId);
|
218
|
+
// Generate proof signatures
|
219
|
+
if (!vc_1.proofTypes[typeInfo.pk]) {
|
220
|
+
throw new Error('Unsupported signer type when create verifiable credential');
|
221
|
+
}
|
222
|
+
let vcObj = render((0, get_1.default)(template, vcRootPath));
|
223
|
+
delete vcObj.proof;
|
224
|
+
const vcStr = (0, vc_1.stableStringify)(vcObj);
|
225
|
+
const signature = (0, util_1.toBase64)(wallet.sign(vcStr));
|
226
|
+
vcObj.proof = {
|
227
|
+
type: vc_1.proofTypes[typeInfo.pk],
|
228
|
+
created: extra.issuanceDate,
|
229
|
+
proofPurpose: 'assertionMethod',
|
230
|
+
jws: signature,
|
231
|
+
};
|
232
|
+
extra.signature = signature;
|
233
|
+
try {
|
234
|
+
// Simulate minting from start, so that we can ensure the validity of minted asset
|
235
|
+
asset = render((0, cloneDeep_1.default)(output));
|
236
|
+
vcObj = (0, get_1.default)(asset, vcRootPath);
|
237
|
+
debug('preMintFromFactory.result', JSON.stringify(asset, null, 2));
|
238
|
+
(0, vc_1.verify)({ vc: vcObj, trustedIssuers: [issuerObject.id], ownerDid: owner, ignoreExpired: true });
|
239
|
+
}
|
240
|
+
catch (err) {
|
241
|
+
console.error(err);
|
242
|
+
throw new Error('Failed to mint asset from factory: invalid verifiable credential minted');
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
else {
|
247
|
+
// populate other variables into the whole output
|
248
|
+
asset = render(template);
|
277
249
|
debug('preMintFromFactory.result', JSON.stringify(asset, null, 2));
|
278
|
-
verify({ vc: vcObj, trustedIssuers: [issuerObject.id], ownerDid: owner, ignoreExpired: true });
|
279
|
-
} catch (err) {
|
280
|
-
console.error(err);
|
281
|
-
throw new Error('Failed to mint asset from factory: invalid verifiable credential minted');
|
282
|
-
}
|
283
250
|
}
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
}
|
289
|
-
|
290
|
-
// calculate address
|
291
|
-
const address = toAssetAddress(asset);
|
292
|
-
|
293
|
-
// return extra inputs
|
294
|
-
return { address, issuer: issuerObject, variables: { ...inputs, ...extra }, asset };
|
251
|
+
// calculate address
|
252
|
+
const address = (0, did_util_1.toAssetAddress)(asset);
|
253
|
+
// return extra inputs
|
254
|
+
return { address, issuer: issuerObject, variables: Object.assign(Object.assign({}, inputs), extra), asset };
|
295
255
|
};
|
296
|
-
|
256
|
+
exports.preMintFromFactory = preMintFromFactory;
|
297
257
|
const formatFactoryState = (state) => {
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
data: JSON.parse(data.value),
|
308
|
-
};
|
309
|
-
};
|
310
|
-
|
311
|
-
module.exports = {
|
312
|
-
isValidFactory,
|
313
|
-
isValidHook,
|
314
|
-
findPrerenderKeys,
|
315
|
-
mintFromFactory,
|
316
|
-
formatFactoryState,
|
317
|
-
preMintFromFactory,
|
258
|
+
const { address, output, data } = state;
|
259
|
+
const outputX = (0, cloneDeep_1.default)(output);
|
260
|
+
outputX.data.value = JSON.parse(outputX.data.value);
|
261
|
+
outputX.data.type = outputX.data.typeUrl;
|
262
|
+
return {
|
263
|
+
address,
|
264
|
+
output: outputX,
|
265
|
+
data: JSON.parse(data.value),
|
266
|
+
};
|
318
267
|
};
|
268
|
+
exports.formatFactoryState = formatFactoryState;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ocap/asset",
|
3
3
|
"description": "Utility to work with asset and factory on ArcBlock blockchain",
|
4
|
-
"version": "1.16.
|
4
|
+
"version": "1.16.17",
|
5
5
|
"author": {
|
6
6
|
"name": "wangshijun",
|
7
7
|
"email": "shijun@arcblock.io",
|
@@ -18,35 +18,33 @@
|
|
18
18
|
"wangshijun <shijun@arcblock.io> (https://github.com/wangshijun)"
|
19
19
|
],
|
20
20
|
"dependencies": {
|
21
|
-
"@arcblock/did": "1.16.
|
22
|
-
"@arcblock/did-util": "1.16.
|
23
|
-
"@arcblock/vc": "1.16.
|
24
|
-
"@ocap/contract": "1.16.
|
25
|
-
"@ocap/mcrypto": "1.16.
|
26
|
-
"@ocap/util": "1.16.
|
27
|
-
"@ocap/wallet": "1.16.
|
21
|
+
"@arcblock/did": "1.16.17",
|
22
|
+
"@arcblock/did-util": "1.16.17",
|
23
|
+
"@arcblock/vc": "1.16.17",
|
24
|
+
"@ocap/contract": "1.16.17",
|
25
|
+
"@ocap/mcrypto": "1.16.17",
|
26
|
+
"@ocap/util": "1.16.17",
|
27
|
+
"@ocap/wallet": "1.16.17",
|
28
28
|
"debug": "^4.3.3",
|
29
|
-
"
|
29
|
+
"express": "^4.17.3",
|
30
30
|
"flat": "^5.0.2",
|
31
31
|
"is-absolute-url": "^3.0.3",
|
32
32
|
"json-stable-stringify": "^1.0.1",
|
33
33
|
"lodash": "^4.17.21",
|
34
|
-
"mustache": "^4.1.0"
|
34
|
+
"mustache": "^4.1.0",
|
35
|
+
"prettier": "^2.3.2",
|
36
|
+
"web3-utils": "^1.5.2"
|
35
37
|
},
|
36
38
|
"devDependencies": {
|
37
|
-
"
|
38
|
-
"
|
39
|
-
"
|
40
|
-
|
41
|
-
|
42
|
-
"
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
"repository": "ArcBlock/asset-chain"
|
47
|
-
}
|
48
|
-
]
|
49
|
-
]
|
39
|
+
"@arcblock/eslint-config-ts": "0.2.2",
|
40
|
+
"@types/flat": "^5.0.2",
|
41
|
+
"@types/jest": "^28.1.0",
|
42
|
+
"@types/mustache": "^4.1.3",
|
43
|
+
"@types/node": "^17.0.38",
|
44
|
+
"eslint": "^8.17.0",
|
45
|
+
"jest": "^28.1.0",
|
46
|
+
"ts-jest": "^28.0.3",
|
47
|
+
"typescript": "^4.7.3"
|
50
48
|
},
|
51
49
|
"homepage": "https://github.com/ArcBlock/asset-chain/tree/master/core/asset",
|
52
50
|
"keywords": [
|
@@ -56,7 +54,8 @@
|
|
56
54
|
"nodejs"
|
57
55
|
],
|
58
56
|
"license": "Apache-2.0",
|
59
|
-
"main": "
|
57
|
+
"main": "lib/index.js",
|
58
|
+
"typings": "lib/index.d.ts",
|
60
59
|
"files": [
|
61
60
|
"lib"
|
62
61
|
],
|
@@ -65,15 +64,14 @@
|
|
65
64
|
"url": "https://github.com/ArcBlock/asset-chain/tree/master/core/asset"
|
66
65
|
},
|
67
66
|
"scripts": {
|
68
|
-
"lint": "eslint
|
69
|
-
"lint:fix": "
|
70
|
-
"docs": "yarn gen-dts && yarn gen-docs && yarn cleanup-docs && yarn format-docs",
|
71
|
-
"cleanup-docs": "node ../../scripts/cleanup-docs.js docs/README.md $npm_package_name",
|
72
|
-
"gen-dts": "j2d lib/index.js",
|
73
|
-
"gen-docs": "jsdoc2md lib/index.js > docs/README.md",
|
74
|
-
"format-docs": "remark . -o",
|
67
|
+
"lint": "eslint src tests",
|
68
|
+
"lint:fix": "npm run lint -- --fix",
|
75
69
|
"test": "jest --forceExit --detectOpenHandles",
|
76
|
-
"coverage": "yarn test -- --coverage"
|
70
|
+
"coverage": "yarn test -- --coverage",
|
71
|
+
"clean": "rm -fr lib",
|
72
|
+
"prebuild": "npm run clean",
|
73
|
+
"build": "tsc",
|
74
|
+
"build:watch": "npm run build -- -w"
|
77
75
|
},
|
78
|
-
"gitHead": "
|
76
|
+
"gitHead": "489ce5e03bce27ddcd535390228b11ab56e7a2e3"
|
79
77
|
}
|