phantasma-sdk-ts 0.2.0-rc.16 → 0.2.0-rc.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/dist/cjs/core/types/Carbon/Blockchain/Modules/Builders/MetadataHelper.js +212 -7
- package/dist/esm/core/types/Carbon/Blockchain/Modules/Builders/MetadataHelper.js +212 -7
- package/dist/types/core/types/Carbon/Blockchain/Modules/Builders/MetadataHelper.d.ts +10 -1
- package/dist/types/core/types/Carbon/Blockchain/Modules/Builders/MetadataHelper.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pushMetadataField = exports.findMetadataField = exports.standardMetadataFields = exports.nftDefaultMetadataFields = exports.seriesDefaultMetadataFields = exports.FieldType = exports.MetadataField = void 0;
|
|
4
|
+
const utils_1 = require("../../../../../utils");
|
|
5
|
+
const Bytes16_1 = require("../../../Bytes16");
|
|
6
|
+
const Bytes32_1 = require("../../../Bytes32");
|
|
7
|
+
const Bytes64_1 = require("../../../Bytes64");
|
|
4
8
|
const Vm_1 = require("../../Vm");
|
|
5
9
|
const StandardMeta_1 = require("../StandardMeta");
|
|
10
|
+
const INT64_MIN = -(1n << 63n);
|
|
11
|
+
const INT64_MAX = (1n << 63n) - 1n;
|
|
12
|
+
const UINT64_MAX = (1n << 64n) - 1n;
|
|
13
|
+
const INT256_MIN = -(1n << 255n);
|
|
14
|
+
const INT256_MAX = (1n << 255n) - 1n;
|
|
15
|
+
const UINT256_MAX = (1n << 256n) - 1n;
|
|
6
16
|
class MetadataField {
|
|
7
17
|
}
|
|
8
18
|
exports.MetadataField = MetadataField;
|
|
@@ -38,16 +48,211 @@ function pushMetadataField(fieldSchema, metadata, metadataFields) {
|
|
|
38
48
|
}
|
|
39
49
|
throw Error(`Metadata field '${fieldSchema.name.data}' is mandatory`);
|
|
40
50
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
const normalizedValue = normalizeMetadataValue(fieldSchema.schema, fieldSchema.name.data, found.value);
|
|
52
|
+
metadata.fields.push(Vm_1.VmNamedDynamicVariable.from(fieldSchema.name, fieldSchema.schema.type, normalizedValue));
|
|
53
|
+
}
|
|
54
|
+
exports.pushMetadataField = pushMetadataField;
|
|
55
|
+
function normalizeMetadataValue(schema, fieldName, value) {
|
|
56
|
+
if (value === null || value === undefined) {
|
|
57
|
+
throw Error(`Metadata field '${fieldName}' is mandatory`);
|
|
58
|
+
}
|
|
59
|
+
const isArray = (schema.type & Vm_1.VmType.Array) === Vm_1.VmType.Array;
|
|
60
|
+
const baseType = (isArray ? (schema.type & ~Vm_1.VmType.Array) : schema.type);
|
|
61
|
+
if (isArray) {
|
|
62
|
+
if (!Array.isArray(value)) {
|
|
63
|
+
throw Error(`Metadata field '${fieldName}' must be provided as an array`);
|
|
64
|
+
}
|
|
65
|
+
return normalizeArrayValue(baseType, fieldName, value, schema.structure);
|
|
66
|
+
}
|
|
67
|
+
return normalizeScalarValue(baseType, fieldName, value, schema.structure);
|
|
68
|
+
}
|
|
69
|
+
function normalizeScalarValue(type, fieldName, value, structSchema) {
|
|
70
|
+
switch (type) {
|
|
71
|
+
case Vm_1.VmType.String:
|
|
72
|
+
return ensureNonEmptyString(fieldName, value);
|
|
73
|
+
case Vm_1.VmType.Int8:
|
|
74
|
+
return ensureIntegerInRange(fieldName, value, -0x80, 0x7f, 0xff);
|
|
75
|
+
case Vm_1.VmType.Int16:
|
|
76
|
+
return ensureIntegerInRange(fieldName, value, -0x8000, 0x7fff, 0xffff);
|
|
77
|
+
case Vm_1.VmType.Int32:
|
|
78
|
+
return ensureIntegerInRange(fieldName, value, -0x80000000, 0x7fffffff, 0xffffffff);
|
|
79
|
+
case Vm_1.VmType.Int64:
|
|
80
|
+
return ensureBigInt(fieldName, value, INT64_MIN, INT64_MAX, 'Int64', UINT64_MAX);
|
|
81
|
+
case Vm_1.VmType.Int256:
|
|
82
|
+
return ensureBigInt(fieldName, value, INT256_MIN, INT256_MAX, 'Int256', UINT256_MAX);
|
|
83
|
+
case Vm_1.VmType.Bytes:
|
|
84
|
+
return ensureBytes(fieldName, value);
|
|
85
|
+
case Vm_1.VmType.Bytes16:
|
|
86
|
+
return ensureBytes16(fieldName, value);
|
|
87
|
+
case Vm_1.VmType.Bytes32:
|
|
88
|
+
return ensureBytes32(fieldName, value);
|
|
89
|
+
case Vm_1.VmType.Bytes64:
|
|
90
|
+
return ensureBytes64(fieldName, value);
|
|
91
|
+
case Vm_1.VmType.Struct:
|
|
92
|
+
return normalizeStructValue(fieldName, structSchema, value);
|
|
93
|
+
default:
|
|
94
|
+
throw Error(`Metadata field '${fieldName}' has unsupported type '${Vm_1.VmType[type] ?? type}'`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function normalizeArrayValue(type, fieldName, values, structSchema) {
|
|
98
|
+
const elementPath = (index) => `${fieldName}[${index}]`;
|
|
99
|
+
switch (type) {
|
|
100
|
+
case Vm_1.VmType.String:
|
|
101
|
+
return values.map((val, idx) => ensureNonEmptyString(elementPath(idx), val));
|
|
102
|
+
case Vm_1.VmType.Int8:
|
|
103
|
+
return Uint8Array.from(values.map((val, idx) => ensureIntegerInRange(elementPath(idx), val, -0x80, 0x7f, 0xff) & 0xff));
|
|
104
|
+
case Vm_1.VmType.Int16:
|
|
105
|
+
return values.map((val, idx) => ensureIntegerInRange(elementPath(idx), val, -0x8000, 0x7fff, 0xffff));
|
|
106
|
+
case Vm_1.VmType.Int32:
|
|
107
|
+
return values.map((val, idx) => ensureIntegerInRange(elementPath(idx), val, -0x80000000, 0x7fffffff, 0xffffffff));
|
|
108
|
+
case Vm_1.VmType.Int64:
|
|
109
|
+
return values.map((val, idx) => ensureBigInt(elementPath(idx), val, INT64_MIN, INT64_MAX, 'Int64', UINT64_MAX));
|
|
110
|
+
case Vm_1.VmType.Int256:
|
|
111
|
+
return values.map((val, idx) => ensureBigInt(elementPath(idx), val, INT256_MIN, INT256_MAX, 'Int256', UINT256_MAX));
|
|
112
|
+
case Vm_1.VmType.Bytes:
|
|
113
|
+
return values.map((val, idx) => ensureBytes(elementPath(idx), val));
|
|
114
|
+
case Vm_1.VmType.Bytes16:
|
|
115
|
+
return values.map((val, idx) => ensureBytes16(elementPath(idx), val));
|
|
116
|
+
case Vm_1.VmType.Bytes32:
|
|
117
|
+
return values.map((val, idx) => ensureBytes32(elementPath(idx), val));
|
|
118
|
+
case Vm_1.VmType.Bytes64:
|
|
119
|
+
return values.map((val, idx) => ensureBytes64(elementPath(idx), val));
|
|
120
|
+
case Vm_1.VmType.Struct: {
|
|
121
|
+
if (!structSchema) {
|
|
122
|
+
throw Error(`Metadata field '${fieldName}' is missing schema for struct elements`);
|
|
123
|
+
}
|
|
124
|
+
const sa = new Vm_1.VmStructArray();
|
|
125
|
+
sa.schema = structSchema;
|
|
126
|
+
sa.structs = values.map((val, idx) => normalizeStructValue(elementPath(idx), structSchema, val));
|
|
127
|
+
return sa;
|
|
44
128
|
}
|
|
45
|
-
|
|
46
|
-
throw Error(`Metadata field '${
|
|
129
|
+
default:
|
|
130
|
+
throw Error(`Metadata field '${fieldName}' with type '${Vm_1.VmType[type] ?? type}' does not support array values`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function normalizeStructValue(fieldName, structSchema, value) {
|
|
134
|
+
if (!structSchema) {
|
|
135
|
+
throw Error(`Metadata field '${fieldName}' is missing struct schema`);
|
|
136
|
+
}
|
|
137
|
+
const struct = new Vm_1.VmDynamicStruct();
|
|
138
|
+
struct.fields = [];
|
|
139
|
+
const providedFields = metadataStructInputToFields(fieldName, value);
|
|
140
|
+
structSchema.fields.forEach(childSchema => {
|
|
141
|
+
let childValue = providedFields.find(f => f.name === childSchema.name.data);
|
|
142
|
+
if (!childValue) {
|
|
143
|
+
childValue = providedFields.find(f => f.name.toLowerCase() === childSchema.name.data.toLowerCase());
|
|
144
|
+
if (childValue) {
|
|
145
|
+
throw Error(`Metadata field '${childSchema.name.data}' provided in incorrect case inside '${fieldName}': '${childValue.name}'`);
|
|
146
|
+
}
|
|
147
|
+
throw Error(`Metadata field '${fieldName}.${childSchema.name.data}' is mandatory`);
|
|
148
|
+
}
|
|
149
|
+
const normalized = normalizeMetadataValue(childSchema.schema, `${fieldName}.${childSchema.name.data}`, childValue.value);
|
|
150
|
+
struct.fields.push(Vm_1.VmNamedDynamicVariable.from(childSchema.name, childSchema.schema.type, normalized));
|
|
151
|
+
});
|
|
152
|
+
const allowedNames = new Set(structSchema.fields.map(f => f.name.data.toLowerCase()));
|
|
153
|
+
for (const provided of providedFields) {
|
|
154
|
+
if (!allowedNames.has(provided.name.toLowerCase())) {
|
|
155
|
+
throw Error(`Metadata field '${fieldName}' received unknown property '${provided.name}'`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return struct;
|
|
159
|
+
}
|
|
160
|
+
function metadataStructInputToFields(fieldName, value) {
|
|
161
|
+
if (Array.isArray(value)) {
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
if (value instanceof Uint8Array || typeof value !== "object") {
|
|
165
|
+
throw Error(`Metadata field '${fieldName}' must be provided as an object or array of fields`);
|
|
166
|
+
}
|
|
167
|
+
return Object.entries(value).map(([name, val]) => ({
|
|
168
|
+
name,
|
|
169
|
+
value: val
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
function ensureNonEmptyString(fieldName, value) {
|
|
173
|
+
if (typeof value !== "string") {
|
|
174
|
+
throw Error(`Metadata field '${fieldName}' must be a string`);
|
|
175
|
+
}
|
|
176
|
+
if (value.trim().length === 0) {
|
|
177
|
+
throw Error(`Metadata field '${fieldName}' is mandatory`);
|
|
178
|
+
}
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
function ensureIntegerInRange(fieldName, value, min, max, unsignedMax) {
|
|
182
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
183
|
+
const rangeText = unsignedMax !== undefined
|
|
184
|
+
? `an integer between ${min} and ${max} or between 0 and ${unsignedMax}`
|
|
185
|
+
: `an integer between ${min} and ${max}`;
|
|
186
|
+
throw Error(`Metadata field '${fieldName}' must be ${rangeText}`);
|
|
187
|
+
}
|
|
188
|
+
const fitsSigned = value >= min && value <= max;
|
|
189
|
+
const fitsUnsigned = unsignedMax !== undefined && value >= 0 && value <= unsignedMax;
|
|
190
|
+
if (!fitsSigned && !fitsUnsigned) {
|
|
191
|
+
const rangeText = unsignedMax !== undefined
|
|
192
|
+
? `between ${min} and ${max} or between 0 and ${unsignedMax}`
|
|
193
|
+
: `between ${min} and ${max}`;
|
|
194
|
+
throw Error(`Metadata field '${fieldName}' must be ${rangeText}`);
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
function ensureBigInt(fieldName, value, min, max, label, unsignedMax) {
|
|
199
|
+
let bigintValue;
|
|
200
|
+
if (typeof value === "bigint") {
|
|
201
|
+
bigintValue = value;
|
|
202
|
+
}
|
|
203
|
+
else if (typeof value === "number" && Number.isInteger(value)) {
|
|
204
|
+
if (!Number.isSafeInteger(value)) {
|
|
205
|
+
throw Error(`Metadata field '${fieldName}' must be provided as a bigint when it exceeds safe integer range`);
|
|
47
206
|
}
|
|
207
|
+
bigintValue = BigInt(value);
|
|
48
208
|
}
|
|
49
209
|
else {
|
|
50
|
-
|
|
210
|
+
throw Error(`Metadata field '${fieldName}' must be a bigint or a safe integer number`);
|
|
211
|
+
}
|
|
212
|
+
const hasSignedRange = min !== undefined && max !== undefined;
|
|
213
|
+
const fitsSigned = hasSignedRange ? bigintValue >= min && bigintValue <= max : false;
|
|
214
|
+
const hasUnsignedRange = unsignedMax !== undefined;
|
|
215
|
+
const fitsUnsigned = hasUnsignedRange ? bigintValue >= 0 && bigintValue <= unsignedMax : false;
|
|
216
|
+
if (!fitsSigned && !fitsUnsigned) {
|
|
217
|
+
const signedPart = hasSignedRange ? `between ${min.toString()} and ${max.toString()}` : null;
|
|
218
|
+
const unsignedPart = hasUnsignedRange ? `between 0 and ${unsignedMax.toString()}` : null;
|
|
219
|
+
const rangeText = [signedPart, unsignedPart].filter(Boolean).join(' or ');
|
|
220
|
+
const labelSuffix = label ? ` (${label})` : '';
|
|
221
|
+
throw Error(`Metadata field '${fieldName}' must be ${rangeText}${labelSuffix}`);
|
|
51
222
|
}
|
|
223
|
+
return bigintValue;
|
|
224
|
+
}
|
|
225
|
+
function ensureBytes(fieldName, value) {
|
|
226
|
+
if (value instanceof Uint8Array) {
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
if (typeof value === "string") {
|
|
230
|
+
const trimmed = value.trim();
|
|
231
|
+
if (trimmed.length === 0) {
|
|
232
|
+
throw Error(`Metadata field '${fieldName}' must be a byte array or hex string`);
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
return (0, utils_1.hexToBytes)(trimmed);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
throw Error(`Metadata field '${fieldName}' must be a byte array or hex string`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
throw Error(`Metadata field '${fieldName}' must be a byte array or hex string`);
|
|
242
|
+
}
|
|
243
|
+
function ensureFixedBytes(fieldName, value, expectedLength) {
|
|
244
|
+
const bytes = ensureBytes(fieldName, value);
|
|
245
|
+
if (bytes.length !== expectedLength) {
|
|
246
|
+
throw Error(`Metadata field '${fieldName}' must be exactly ${expectedLength} bytes`);
|
|
247
|
+
}
|
|
248
|
+
return bytes;
|
|
249
|
+
}
|
|
250
|
+
function ensureBytes16(fieldName, value) {
|
|
251
|
+
return new Bytes16_1.Bytes16(ensureFixedBytes(fieldName, value, 16));
|
|
252
|
+
}
|
|
253
|
+
function ensureBytes32(fieldName, value) {
|
|
254
|
+
return new Bytes32_1.Bytes32(ensureFixedBytes(fieldName, value, 32));
|
|
255
|
+
}
|
|
256
|
+
function ensureBytes64(fieldName, value) {
|
|
257
|
+
return new Bytes64_1.Bytes64(ensureFixedBytes(fieldName, value, 64));
|
|
52
258
|
}
|
|
53
|
-
exports.pushMetadataField = pushMetadataField;
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hexToBytes } from "../../../../../utils";
|
|
2
|
+
import { Bytes16 } from "../../../Bytes16";
|
|
3
|
+
import { Bytes32 } from "../../../Bytes32";
|
|
4
|
+
import { Bytes64 } from "../../../Bytes64";
|
|
5
|
+
import { VmDynamicStruct, VmNamedDynamicVariable, VmStructArray, VmType, } from "../../Vm";
|
|
2
6
|
import { StandardMeta } from "../StandardMeta";
|
|
7
|
+
const INT64_MIN = -(1n << 63n);
|
|
8
|
+
const INT64_MAX = (1n << 63n) - 1n;
|
|
9
|
+
const UINT64_MAX = (1n << 64n) - 1n;
|
|
10
|
+
const INT256_MIN = -(1n << 255n);
|
|
11
|
+
const INT256_MAX = (1n << 255n) - 1n;
|
|
12
|
+
const UINT256_MAX = (1n << 256n) - 1n;
|
|
3
13
|
export class MetadataField {
|
|
4
14
|
}
|
|
5
15
|
export class FieldType {
|
|
@@ -32,15 +42,210 @@ export function pushMetadataField(fieldSchema, metadata, metadataFields) {
|
|
|
32
42
|
}
|
|
33
43
|
throw Error(`Metadata field '${fieldSchema.name.data}' is mandatory`);
|
|
34
44
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
const normalizedValue = normalizeMetadataValue(fieldSchema.schema, fieldSchema.name.data, found.value);
|
|
46
|
+
metadata.fields.push(VmNamedDynamicVariable.from(fieldSchema.name, fieldSchema.schema.type, normalizedValue));
|
|
47
|
+
}
|
|
48
|
+
function normalizeMetadataValue(schema, fieldName, value) {
|
|
49
|
+
if (value === null || value === undefined) {
|
|
50
|
+
throw Error(`Metadata field '${fieldName}' is mandatory`);
|
|
51
|
+
}
|
|
52
|
+
const isArray = (schema.type & VmType.Array) === VmType.Array;
|
|
53
|
+
const baseType = (isArray ? (schema.type & ~VmType.Array) : schema.type);
|
|
54
|
+
if (isArray) {
|
|
55
|
+
if (!Array.isArray(value)) {
|
|
56
|
+
throw Error(`Metadata field '${fieldName}' must be provided as an array`);
|
|
57
|
+
}
|
|
58
|
+
return normalizeArrayValue(baseType, fieldName, value, schema.structure);
|
|
59
|
+
}
|
|
60
|
+
return normalizeScalarValue(baseType, fieldName, value, schema.structure);
|
|
61
|
+
}
|
|
62
|
+
function normalizeScalarValue(type, fieldName, value, structSchema) {
|
|
63
|
+
switch (type) {
|
|
64
|
+
case VmType.String:
|
|
65
|
+
return ensureNonEmptyString(fieldName, value);
|
|
66
|
+
case VmType.Int8:
|
|
67
|
+
return ensureIntegerInRange(fieldName, value, -0x80, 0x7f, 0xff);
|
|
68
|
+
case VmType.Int16:
|
|
69
|
+
return ensureIntegerInRange(fieldName, value, -0x8000, 0x7fff, 0xffff);
|
|
70
|
+
case VmType.Int32:
|
|
71
|
+
return ensureIntegerInRange(fieldName, value, -0x80000000, 0x7fffffff, 0xffffffff);
|
|
72
|
+
case VmType.Int64:
|
|
73
|
+
return ensureBigInt(fieldName, value, INT64_MIN, INT64_MAX, 'Int64', UINT64_MAX);
|
|
74
|
+
case VmType.Int256:
|
|
75
|
+
return ensureBigInt(fieldName, value, INT256_MIN, INT256_MAX, 'Int256', UINT256_MAX);
|
|
76
|
+
case VmType.Bytes:
|
|
77
|
+
return ensureBytes(fieldName, value);
|
|
78
|
+
case VmType.Bytes16:
|
|
79
|
+
return ensureBytes16(fieldName, value);
|
|
80
|
+
case VmType.Bytes32:
|
|
81
|
+
return ensureBytes32(fieldName, value);
|
|
82
|
+
case VmType.Bytes64:
|
|
83
|
+
return ensureBytes64(fieldName, value);
|
|
84
|
+
case VmType.Struct:
|
|
85
|
+
return normalizeStructValue(fieldName, structSchema, value);
|
|
86
|
+
default:
|
|
87
|
+
throw Error(`Metadata field '${fieldName}' has unsupported type '${VmType[type] ?? type}'`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function normalizeArrayValue(type, fieldName, values, structSchema) {
|
|
91
|
+
const elementPath = (index) => `${fieldName}[${index}]`;
|
|
92
|
+
switch (type) {
|
|
93
|
+
case VmType.String:
|
|
94
|
+
return values.map((val, idx) => ensureNonEmptyString(elementPath(idx), val));
|
|
95
|
+
case VmType.Int8:
|
|
96
|
+
return Uint8Array.from(values.map((val, idx) => ensureIntegerInRange(elementPath(idx), val, -0x80, 0x7f, 0xff) & 0xff));
|
|
97
|
+
case VmType.Int16:
|
|
98
|
+
return values.map((val, idx) => ensureIntegerInRange(elementPath(idx), val, -0x8000, 0x7fff, 0xffff));
|
|
99
|
+
case VmType.Int32:
|
|
100
|
+
return values.map((val, idx) => ensureIntegerInRange(elementPath(idx), val, -0x80000000, 0x7fffffff, 0xffffffff));
|
|
101
|
+
case VmType.Int64:
|
|
102
|
+
return values.map((val, idx) => ensureBigInt(elementPath(idx), val, INT64_MIN, INT64_MAX, 'Int64', UINT64_MAX));
|
|
103
|
+
case VmType.Int256:
|
|
104
|
+
return values.map((val, idx) => ensureBigInt(elementPath(idx), val, INT256_MIN, INT256_MAX, 'Int256', UINT256_MAX));
|
|
105
|
+
case VmType.Bytes:
|
|
106
|
+
return values.map((val, idx) => ensureBytes(elementPath(idx), val));
|
|
107
|
+
case VmType.Bytes16:
|
|
108
|
+
return values.map((val, idx) => ensureBytes16(elementPath(idx), val));
|
|
109
|
+
case VmType.Bytes32:
|
|
110
|
+
return values.map((val, idx) => ensureBytes32(elementPath(idx), val));
|
|
111
|
+
case VmType.Bytes64:
|
|
112
|
+
return values.map((val, idx) => ensureBytes64(elementPath(idx), val));
|
|
113
|
+
case VmType.Struct: {
|
|
114
|
+
if (!structSchema) {
|
|
115
|
+
throw Error(`Metadata field '${fieldName}' is missing schema for struct elements`);
|
|
116
|
+
}
|
|
117
|
+
const sa = new VmStructArray();
|
|
118
|
+
sa.schema = structSchema;
|
|
119
|
+
sa.structs = values.map((val, idx) => normalizeStructValue(elementPath(idx), structSchema, val));
|
|
120
|
+
return sa;
|
|
121
|
+
}
|
|
122
|
+
default:
|
|
123
|
+
throw Error(`Metadata field '${fieldName}' with type '${VmType[type] ?? type}' does not support array values`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function normalizeStructValue(fieldName, structSchema, value) {
|
|
127
|
+
if (!structSchema) {
|
|
128
|
+
throw Error(`Metadata field '${fieldName}' is missing struct schema`);
|
|
129
|
+
}
|
|
130
|
+
const struct = new VmDynamicStruct();
|
|
131
|
+
struct.fields = [];
|
|
132
|
+
const providedFields = metadataStructInputToFields(fieldName, value);
|
|
133
|
+
structSchema.fields.forEach(childSchema => {
|
|
134
|
+
let childValue = providedFields.find(f => f.name === childSchema.name.data);
|
|
135
|
+
if (!childValue) {
|
|
136
|
+
childValue = providedFields.find(f => f.name.toLowerCase() === childSchema.name.data.toLowerCase());
|
|
137
|
+
if (childValue) {
|
|
138
|
+
throw Error(`Metadata field '${childSchema.name.data}' provided in incorrect case inside '${fieldName}': '${childValue.name}'`);
|
|
139
|
+
}
|
|
140
|
+
throw Error(`Metadata field '${fieldName}.${childSchema.name.data}' is mandatory`);
|
|
141
|
+
}
|
|
142
|
+
const normalized = normalizeMetadataValue(childSchema.schema, `${fieldName}.${childSchema.name.data}`, childValue.value);
|
|
143
|
+
struct.fields.push(VmNamedDynamicVariable.from(childSchema.name, childSchema.schema.type, normalized));
|
|
144
|
+
});
|
|
145
|
+
const allowedNames = new Set(structSchema.fields.map(f => f.name.data.toLowerCase()));
|
|
146
|
+
for (const provided of providedFields) {
|
|
147
|
+
if (!allowedNames.has(provided.name.toLowerCase())) {
|
|
148
|
+
throw Error(`Metadata field '${fieldName}' received unknown property '${provided.name}'`);
|
|
38
149
|
}
|
|
39
|
-
|
|
40
|
-
|
|
150
|
+
}
|
|
151
|
+
return struct;
|
|
152
|
+
}
|
|
153
|
+
function metadataStructInputToFields(fieldName, value) {
|
|
154
|
+
if (Array.isArray(value)) {
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
157
|
+
if (value instanceof Uint8Array || typeof value !== "object") {
|
|
158
|
+
throw Error(`Metadata field '${fieldName}' must be provided as an object or array of fields`);
|
|
159
|
+
}
|
|
160
|
+
return Object.entries(value).map(([name, val]) => ({
|
|
161
|
+
name,
|
|
162
|
+
value: val
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
function ensureNonEmptyString(fieldName, value) {
|
|
166
|
+
if (typeof value !== "string") {
|
|
167
|
+
throw Error(`Metadata field '${fieldName}' must be a string`);
|
|
168
|
+
}
|
|
169
|
+
if (value.trim().length === 0) {
|
|
170
|
+
throw Error(`Metadata field '${fieldName}' is mandatory`);
|
|
171
|
+
}
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
function ensureIntegerInRange(fieldName, value, min, max, unsignedMax) {
|
|
175
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
176
|
+
const rangeText = unsignedMax !== undefined
|
|
177
|
+
? `an integer between ${min} and ${max} or between 0 and ${unsignedMax}`
|
|
178
|
+
: `an integer between ${min} and ${max}`;
|
|
179
|
+
throw Error(`Metadata field '${fieldName}' must be ${rangeText}`);
|
|
180
|
+
}
|
|
181
|
+
const fitsSigned = value >= min && value <= max;
|
|
182
|
+
const fitsUnsigned = unsignedMax !== undefined && value >= 0 && value <= unsignedMax;
|
|
183
|
+
if (!fitsSigned && !fitsUnsigned) {
|
|
184
|
+
const rangeText = unsignedMax !== undefined
|
|
185
|
+
? `between ${min} and ${max} or between 0 and ${unsignedMax}`
|
|
186
|
+
: `between ${min} and ${max}`;
|
|
187
|
+
throw Error(`Metadata field '${fieldName}' must be ${rangeText}`);
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
function ensureBigInt(fieldName, value, min, max, label, unsignedMax) {
|
|
192
|
+
let bigintValue;
|
|
193
|
+
if (typeof value === "bigint") {
|
|
194
|
+
bigintValue = value;
|
|
195
|
+
}
|
|
196
|
+
else if (typeof value === "number" && Number.isInteger(value)) {
|
|
197
|
+
if (!Number.isSafeInteger(value)) {
|
|
198
|
+
throw Error(`Metadata field '${fieldName}' must be provided as a bigint when it exceeds safe integer range`);
|
|
41
199
|
}
|
|
200
|
+
bigintValue = BigInt(value);
|
|
42
201
|
}
|
|
43
202
|
else {
|
|
44
|
-
|
|
203
|
+
throw Error(`Metadata field '${fieldName}' must be a bigint or a safe integer number`);
|
|
204
|
+
}
|
|
205
|
+
const hasSignedRange = min !== undefined && max !== undefined;
|
|
206
|
+
const fitsSigned = hasSignedRange ? bigintValue >= min && bigintValue <= max : false;
|
|
207
|
+
const hasUnsignedRange = unsignedMax !== undefined;
|
|
208
|
+
const fitsUnsigned = hasUnsignedRange ? bigintValue >= 0 && bigintValue <= unsignedMax : false;
|
|
209
|
+
if (!fitsSigned && !fitsUnsigned) {
|
|
210
|
+
const signedPart = hasSignedRange ? `between ${min.toString()} and ${max.toString()}` : null;
|
|
211
|
+
const unsignedPart = hasUnsignedRange ? `between 0 and ${unsignedMax.toString()}` : null;
|
|
212
|
+
const rangeText = [signedPart, unsignedPart].filter(Boolean).join(' or ');
|
|
213
|
+
const labelSuffix = label ? ` (${label})` : '';
|
|
214
|
+
throw Error(`Metadata field '${fieldName}' must be ${rangeText}${labelSuffix}`);
|
|
215
|
+
}
|
|
216
|
+
return bigintValue;
|
|
217
|
+
}
|
|
218
|
+
function ensureBytes(fieldName, value) {
|
|
219
|
+
if (value instanceof Uint8Array) {
|
|
220
|
+
return value;
|
|
45
221
|
}
|
|
222
|
+
if (typeof value === "string") {
|
|
223
|
+
const trimmed = value.trim();
|
|
224
|
+
if (trimmed.length === 0) {
|
|
225
|
+
throw Error(`Metadata field '${fieldName}' must be a byte array or hex string`);
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
return hexToBytes(trimmed);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
throw Error(`Metadata field '${fieldName}' must be a byte array or hex string`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
throw Error(`Metadata field '${fieldName}' must be a byte array or hex string`);
|
|
235
|
+
}
|
|
236
|
+
function ensureFixedBytes(fieldName, value, expectedLength) {
|
|
237
|
+
const bytes = ensureBytes(fieldName, value);
|
|
238
|
+
if (bytes.length !== expectedLength) {
|
|
239
|
+
throw Error(`Metadata field '${fieldName}' must be exactly ${expectedLength} bytes`);
|
|
240
|
+
}
|
|
241
|
+
return bytes;
|
|
242
|
+
}
|
|
243
|
+
function ensureBytes16(fieldName, value) {
|
|
244
|
+
return new Bytes16(ensureFixedBytes(fieldName, value, 16));
|
|
245
|
+
}
|
|
246
|
+
function ensureBytes32(fieldName, value) {
|
|
247
|
+
return new Bytes32(ensureFixedBytes(fieldName, value, 32));
|
|
248
|
+
}
|
|
249
|
+
function ensureBytes64(fieldName, value) {
|
|
250
|
+
return new Bytes64(ensureFixedBytes(fieldName, value, 64));
|
|
46
251
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VmDynamicStruct, VmNamedVariableSchema, VmType } from "../../Vm";
|
|
2
2
|
export declare class MetadataField {
|
|
3
3
|
name: string;
|
|
4
|
-
value:
|
|
4
|
+
value: MetadataValueInput;
|
|
5
5
|
}
|
|
6
6
|
export declare class FieldType {
|
|
7
7
|
name: string;
|
|
@@ -12,4 +12,13 @@ export declare const nftDefaultMetadataFields: readonly FieldType[];
|
|
|
12
12
|
export declare const standardMetadataFields: readonly FieldType[];
|
|
13
13
|
export declare function findMetadataField(fields: MetadataField[], name: string): MetadataField;
|
|
14
14
|
export declare function pushMetadataField(fieldSchema: VmNamedVariableSchema, metadata: VmDynamicStruct, metadataFields: MetadataField[]): void;
|
|
15
|
+
type MetadataPlainValue = string | number | bigint | Uint8Array;
|
|
16
|
+
interface MetadataStructRecord {
|
|
17
|
+
[key: string]: MetadataValueInput;
|
|
18
|
+
}
|
|
19
|
+
interface MetadataValueArray extends Array<MetadataValueInput> {
|
|
20
|
+
}
|
|
21
|
+
type MetadataStructInput = MetadataField[] | MetadataStructRecord;
|
|
22
|
+
export type MetadataValueInput = MetadataPlainValue | MetadataStructInput | MetadataValueArray;
|
|
23
|
+
export {};
|
|
15
24
|
//# sourceMappingURL=MetadataHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MetadataHelper.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/types/Carbon/Blockchain/Modules/Builders/MetadataHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MetadataHelper.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/types/Carbon/Blockchain/Modules/Builders/MetadataHelper.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,eAAe,EAEf,qBAAqB,EAGrB,MAAM,EAEP,MAAM,UAAU,CAAC;AAUlB,qBAAa,aAAa;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAED,qBAAa,SAAS;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,2BAA2B,EAAE,SAAS,SAAS,EAIlD,CAAC;AAEX,eAAO,MAAM,wBAAwB,EAAE,SAAS,SAAS,EAG/C,CAAC;AAEX,eAAO,MAAM,sBAAsB,EAAE,SAAS,SAAS,EAM7C,CAAC;AAEX,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAEtF;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,qBAAqB,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,IAAI,CAiBtI;AAED,KAAK,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAChE,UAAU,oBAAoB;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAC;CACnC;AACD,UAAU,kBAAmB,SAAQ,KAAK,CAAC,kBAAkB,CAAC;CAAG;AACjE,KAAK,mBAAmB,GAAG,aAAa,EAAE,GAAG,oBAAoB,CAAC;AAClE,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,mBAAmB,GAAG,kBAAkB,CAAC"}
|