@dcl/content-validator 7.2.0 → 7.3.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/README.md
CHANGED
|
@@ -132,7 +132,8 @@ The library supports two access validation strategies:
|
|
|
132
132
|
Direct blockchain queries for ownership verification:
|
|
133
133
|
|
|
134
134
|
```typescript
|
|
135
|
-
import { createOnChainAccessCheckValidateFns
|
|
135
|
+
import { createOnChainAccessCheckValidateFns } from '@dcl/content-validator/dist/validations/access/on-chain'
|
|
136
|
+
import { createOnChainClient } from '@dcl/content-validator/dist/validations/access/on-chain/client'
|
|
136
137
|
|
|
137
138
|
const validateFns = createOnChainAccessCheckValidateFns({
|
|
138
139
|
logs,
|
|
@@ -148,7 +149,8 @@ const validateFns = createOnChainAccessCheckValidateFns({
|
|
|
148
149
|
Uses The Graph for ownership queries (more efficient for bulk queries):
|
|
149
150
|
|
|
150
151
|
```typescript
|
|
151
|
-
import { createSubgraphAccessCheckValidateFns
|
|
152
|
+
import { createSubgraphAccessCheckValidateFns } from '@dcl/content-validator/dist/validations/access/subgraph'
|
|
153
|
+
import { createTheGraphClient } from '@dcl/content-validator/dist/validations/access/subgraph/the-graph-client'
|
|
152
154
|
|
|
153
155
|
const validateFns = createSubgraphAccessCheckValidateFns({
|
|
154
156
|
logs,
|
|
@@ -163,12 +165,12 @@ const validateFns = createSubgraphAccessCheckValidateFns({
|
|
|
163
165
|
|
|
164
166
|
### Development
|
|
165
167
|
|
|
166
|
-
Install dependencies and run tests:
|
|
168
|
+
Install dependencies and run tests from the monorepo root:
|
|
167
169
|
|
|
168
170
|
```bash
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
pnpm install
|
|
172
|
+
pnpm --filter @dcl/content-validator build
|
|
173
|
+
pnpm --filter @dcl/content-validator test
|
|
172
174
|
```
|
|
173
175
|
|
|
174
176
|
### Debugging Tests
|
|
@@ -3,6 +3,13 @@ import type { ValidationResponse } from '../../types';
|
|
|
3
3
|
/** Validate wearable representations are referencing valid content */
|
|
4
4
|
export declare function wearableRepresentationContentValidateFn(deployment: DeploymentToValidate): Promise<ValidationResponse>;
|
|
5
5
|
export declare function thirdPartyWearableMerkleProofContentValidateFn(deployment: DeploymentToValidate): Promise<ValidationResponse>;
|
|
6
|
+
/**
|
|
7
|
+
* Validate spring bones metadata when present on a wearable.
|
|
8
|
+
*
|
|
9
|
+
* Structural and per-parameter range checks are delegated to `SpringBonesData.validate`
|
|
10
|
+
* from `@dcl/schemas`. This function only enforces invariants that the schema cannot
|
|
11
|
+
* express on its own. */
|
|
12
|
+
export declare function springBonesMetadataValidateFn(deployment: DeploymentToValidate): Promise<ValidationResponse>;
|
|
6
13
|
/**
|
|
7
14
|
* Validate that given wearable deployment includes the thumbnail and doesn't exceed file sizes
|
|
8
15
|
* @public
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wearables.d.ts","sourceRoot":"","sources":["../../../src/validations/items/wearables.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErD,sEAAsE;AACtE,wBAAsB,uCAAuC,CAC3D,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED,wBAAsB,8CAA8C,CAClE,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAwC7B;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"wearables.d.ts","sourceRoot":"","sources":["../../../src/validations/items/wearables.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErD,sEAAsE;AACtE,wBAAsB,uCAAuC,CAC3D,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED,wBAAsB,8CAA8C,CAClE,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAwC7B;AAcD;;;;;yBAKyB;AACzB,wBAAsB,6BAA6B,CAAC,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA6CjH;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,4BAO9B,CAAA"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.wearableValidateFn = void 0;
|
|
4
4
|
exports.wearableRepresentationContentValidateFn = wearableRepresentationContentValidateFn;
|
|
5
5
|
exports.thirdPartyWearableMerkleProofContentValidateFn = thirdPartyWearableMerkleProofContentValidateFn;
|
|
6
|
+
exports.springBonesMetadataValidateFn = springBonesMetadataValidateFn;
|
|
6
7
|
const hashing_1 = require("@dcl/hashing");
|
|
7
8
|
const schemas_1 = require("@dcl/schemas");
|
|
8
9
|
const types_1 = require("../../types");
|
|
@@ -57,9 +58,58 @@ async function thirdPartyWearableMerkleProofContentValidateFn(deployment) {
|
|
|
57
58
|
}
|
|
58
59
|
return types_1.OK;
|
|
59
60
|
}
|
|
61
|
+
const SPRING_BONE_NAME_TOKEN = 'springbone';
|
|
62
|
+
function isSpringBoneName(name) {
|
|
63
|
+
return name.toLowerCase().includes(SPRING_BONE_NAME_TOKEN);
|
|
64
|
+
}
|
|
65
|
+
function formatErrorField(field) {
|
|
66
|
+
return field.length > 100
|
|
67
|
+
? JSON.stringify(field).slice(1, 100).concat('...')
|
|
68
|
+
: JSON.stringify(field).slice(1, field.length + 1);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate spring bones metadata when present on a wearable.
|
|
72
|
+
*
|
|
73
|
+
* Structural and per-parameter range checks are delegated to `SpringBonesData.validate`
|
|
74
|
+
* from `@dcl/schemas`. This function only enforces invariants that the schema cannot
|
|
75
|
+
* express on its own. */
|
|
76
|
+
async function springBonesMetadataValidateFn(deployment) {
|
|
77
|
+
const { entity } = deployment;
|
|
78
|
+
const wearableMetadata = entity.metadata;
|
|
79
|
+
// Spring bones are optional — skip validation if not present
|
|
80
|
+
const springBones = wearableMetadata?.data?.springBones;
|
|
81
|
+
if (!springBones) {
|
|
82
|
+
return types_1.OK;
|
|
83
|
+
}
|
|
84
|
+
const errors = [];
|
|
85
|
+
if (!schemas_1.SpringBonesData.validate(springBones)) {
|
|
86
|
+
const schemaErrors = (schemas_1.SpringBonesData.validate.errors ?? []).map((e) => `springBones${formatErrorField(e.instancePath)} ${e.message ?? 'is invalid'}`);
|
|
87
|
+
return (0, types_1.validationFailed)(...schemaErrors);
|
|
88
|
+
}
|
|
89
|
+
// Build the set of content hashes that current representations point to.
|
|
90
|
+
const representations = wearableMetadata.data?.representations ?? [];
|
|
91
|
+
const activeHashes = new Set();
|
|
92
|
+
for (const representation of representations) {
|
|
93
|
+
const contentEntry = entity.content?.find((c) => c.file === representation.mainFile);
|
|
94
|
+
if (contentEntry) {
|
|
95
|
+
activeHashes.add(contentEntry.hash);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const [modelHash, bones] of Object.entries(springBones.models)) {
|
|
99
|
+
if (!activeHashes.has(modelHash)) {
|
|
100
|
+
errors.push(`springBones.models key ${formatErrorField(modelHash)} does not match any current representation hash`);
|
|
101
|
+
}
|
|
102
|
+
for (const boneName of Object.keys(bones)) {
|
|
103
|
+
if (!isSpringBoneName(boneName)) {
|
|
104
|
+
errors.push(`Bone name ${formatErrorField(boneName)} in model ${formatErrorField(modelHash)} does not follow the spring bone naming convention`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return errors.length > 0 ? (0, types_1.validationFailed)(...errors) : types_1.OK;
|
|
109
|
+
}
|
|
60
110
|
/**
|
|
61
111
|
* Validate that given wearable deployment includes the thumbnail and doesn't exceed file sizes
|
|
62
112
|
* @public
|
|
63
113
|
*/
|
|
64
|
-
exports.wearableValidateFn = (0, validations_1.validateIfTypeMatches)(schemas_1.EntityType.WEARABLE, (0, validations_1.validateAll)(wearableRepresentationContentValidateFn, thirdPartyWearableMerkleProofContentValidateFn));
|
|
114
|
+
exports.wearableValidateFn = (0, validations_1.validateIfTypeMatches)(schemas_1.EntityType.WEARABLE, (0, validations_1.validateAll)(wearableRepresentationContentValidateFn, thirdPartyWearableMerkleProofContentValidateFn, springBonesMetadataValidateFn));
|
|
65
115
|
//# sourceMappingURL=wearables.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wearables.js","sourceRoot":"","sources":["../../../src/validations/items/wearables.ts"],"names":[],"mappings":";;;AASA,0FAiBC;AAED,wGA0CC;
|
|
1
|
+
{"version":3,"file":"wearables.js","sourceRoot":"","sources":["../../../src/validations/items/wearables.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/content-validator",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0",
|
|
4
4
|
"description": "Catalyst content validations",
|
|
5
5
|
"author": "Decentraland",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@dcl/block-indexer": "^1.1.2",
|
|
24
24
|
"@dcl/content-hash-tree": "^1.1.4",
|
|
25
|
-
"@dcl/schemas": "^26.
|
|
25
|
+
"@dcl/schemas": "^26.2.0",
|
|
26
26
|
"@well-known-components/interfaces": "^1.4.3",
|
|
27
27
|
"@well-known-components/thegraph-component": "^1.6.0",
|
|
28
28
|
"ms": "^2.1.3",
|
|
29
29
|
"p-queue": "^6.6.2",
|
|
30
|
-
"@dcl/
|
|
31
|
-
"@dcl/
|
|
30
|
+
"@dcl/urn-resolver": "1.0.2",
|
|
31
|
+
"@dcl/hashing": "1.1.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@dcl/eslint-config": "^2.4.3",
|