@hauska-sdk/vda 0.1.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.
@@ -0,0 +1,203 @@
1
+ /**
2
+ * @hauska-sdk/vda
3
+ * VDA Metadata Validation
4
+ */
5
+ /**
6
+ * Valid asset types
7
+ */
8
+ export const VALID_ASSET_TYPES = [
9
+ "deed",
10
+ "blueprint",
11
+ "permit",
12
+ "contract",
13
+ "health-record",
14
+ "well-log",
15
+ "access-pass",
16
+ "invoice",
17
+ ];
18
+ /**
19
+ * Valid spoke types
20
+ */
21
+ export const VALID_SPOKE_TYPES = [
22
+ "real-estate",
23
+ "healthcare",
24
+ "oil-gas",
25
+ "architect",
26
+ "municipal",
27
+ ];
28
+ /**
29
+ * Valid permission types
30
+ */
31
+ export const VALID_PERMISSION_TYPES = [
32
+ "view",
33
+ "download",
34
+ "write",
35
+ "annotate",
36
+ ];
37
+ /**
38
+ * Validate VDA metadata
39
+ */
40
+ export function validateVDAMetadata(metadata) {
41
+ const errors = [];
42
+ // Validate assetId
43
+ if (!metadata.assetId) {
44
+ errors.push({
45
+ field: "assetId",
46
+ message: "Asset ID is required",
47
+ });
48
+ }
49
+ else if (typeof metadata.assetId !== "string" || metadata.assetId.trim() === "") {
50
+ errors.push({
51
+ field: "assetId",
52
+ message: "Asset ID must be a non-empty string",
53
+ });
54
+ }
55
+ // Validate assetType
56
+ if (!metadata.assetType) {
57
+ errors.push({
58
+ field: "assetType",
59
+ message: "Asset type is required",
60
+ });
61
+ }
62
+ else if (!VALID_ASSET_TYPES.includes(metadata.assetType)) {
63
+ errors.push({
64
+ field: "assetType",
65
+ message: `Invalid asset type. Must be one of: ${VALID_ASSET_TYPES.join(", ")}`,
66
+ });
67
+ }
68
+ // Validate universal metadata (at least one required)
69
+ const hasUniversalKey = metadata.address || metadata.legalDesc || metadata.patientId || metadata.api14;
70
+ if (!hasUniversalKey) {
71
+ errors.push({
72
+ field: "universalMetadata",
73
+ message: "At least one universal metadata key is required (address, legalDesc, patientId, or api14)",
74
+ });
75
+ }
76
+ // Validate ownerWallet
77
+ if (!metadata.ownerWallet) {
78
+ errors.push({
79
+ field: "ownerWallet",
80
+ message: "Owner wallet is required",
81
+ });
82
+ }
83
+ else if (!isValidEthereumAddress(metadata.ownerWallet)) {
84
+ errors.push({
85
+ field: "ownerWallet",
86
+ message: "Owner wallet must be a valid Ethereum address",
87
+ });
88
+ }
89
+ // Validate spoke
90
+ if (!metadata.spoke) {
91
+ errors.push({
92
+ field: "spoke",
93
+ message: "Spoke is required",
94
+ });
95
+ }
96
+ else if (!VALID_SPOKE_TYPES.includes(metadata.spoke)) {
97
+ errors.push({
98
+ field: "spoke",
99
+ message: `Invalid spoke. Must be one of: ${VALID_SPOKE_TYPES.join(", ")}`,
100
+ });
101
+ }
102
+ // Validate access pass fields (if assetType is access-pass)
103
+ if (metadata.assetType === "access-pass") {
104
+ if (!metadata.expiry) {
105
+ errors.push({
106
+ field: "expiry",
107
+ message: "Expiry is required for access pass VDAs",
108
+ });
109
+ }
110
+ else if (metadata.expiry <= Date.now()) {
111
+ errors.push({
112
+ field: "expiry",
113
+ message: "Expiry must be in the future",
114
+ });
115
+ }
116
+ if (!metadata.accessibleVDAs || metadata.accessibleVDAs.length === 0) {
117
+ errors.push({
118
+ field: "accessibleVDAs",
119
+ message: "Accessible VDAs array is required for access pass VDAs",
120
+ });
121
+ }
122
+ if (!metadata.permissions || metadata.permissions.length === 0) {
123
+ errors.push({
124
+ field: "permissions",
125
+ message: "Permissions array is required for access pass VDAs",
126
+ });
127
+ }
128
+ else {
129
+ // Validate each permission
130
+ for (const permission of metadata.permissions) {
131
+ if (!VALID_PERMISSION_TYPES.includes(permission)) {
132
+ errors.push({
133
+ field: "permissions",
134
+ message: `Invalid permission: ${permission}. Must be one of: ${VALID_PERMISSION_TYPES.join(", ")}`,
135
+ });
136
+ }
137
+ }
138
+ }
139
+ // Validate grantorWallet for access passes
140
+ if (!metadata.grantorWallet) {
141
+ errors.push({
142
+ field: "grantorWallet",
143
+ message: "Grantor wallet is required for access pass VDAs",
144
+ });
145
+ }
146
+ else if (!isValidEthereumAddress(metadata.grantorWallet)) {
147
+ errors.push({
148
+ field: "grantorWallet",
149
+ message: "Grantor wallet must be a valid Ethereum address",
150
+ });
151
+ }
152
+ }
153
+ // Validate timestamps
154
+ if (metadata.createdAt !== undefined && typeof metadata.createdAt !== "number") {
155
+ errors.push({
156
+ field: "createdAt",
157
+ message: "Created at must be a number (Unix timestamp)",
158
+ });
159
+ }
160
+ if (metadata.updatedAt !== undefined && typeof metadata.updatedAt !== "number") {
161
+ errors.push({
162
+ field: "updatedAt",
163
+ message: "Updated at must be a number (Unix timestamp)",
164
+ });
165
+ }
166
+ return {
167
+ valid: errors.length === 0,
168
+ errors,
169
+ };
170
+ }
171
+ /**
172
+ * Validate Ethereum address format
173
+ */
174
+ function isValidEthereumAddress(address) {
175
+ // Ethereum address: 0x followed by 40 hex characters
176
+ return /^0x[a-fA-F0-9]{40}$/.test(address);
177
+ }
178
+ /**
179
+ * Normalize address for search (basic normalization)
180
+ */
181
+ export function normalizeAddress(address) {
182
+ // Convert to lowercase and trim
183
+ return address.toLowerCase().trim();
184
+ }
185
+ /**
186
+ * Check if metadata has required universal key for spoke
187
+ */
188
+ export function hasRequiredUniversalKey(metadata, spoke) {
189
+ switch (spoke) {
190
+ case "real-estate":
191
+ return !!(metadata.address || metadata.legalDesc);
192
+ case "healthcare":
193
+ return !!metadata.patientId;
194
+ case "oil-gas":
195
+ return !!metadata.api14;
196
+ case "architect":
197
+ case "municipal":
198
+ return !!(metadata.address || metadata.legalDesc);
199
+ default:
200
+ return !!(metadata.address || metadata.legalDesc || metadata.patientId || metadata.api14);
201
+ }
202
+ }
203
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@hauska-sdk/vda",
3
+ "version": "0.1.0",
4
+ "description": "CNS Protocol VDA SDK - Verified Digital Assets management",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "clean": "rimraf dist",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest",
20
+ "test:coverage": "vitest run --coverage",
21
+ "type-check": "tsc --noEmit"
22
+ },
23
+ "dependencies": {
24
+ "@hauska-sdk/wallet": "^0.1.0"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.3.3",
28
+ "rimraf": "^5.0.5",
29
+ "vitest": "^4.0.18"
30
+ },
31
+ "keywords": [
32
+ "cns-protocol",
33
+ "vda",
34
+ "digital-assets",
35
+ "ownership",
36
+ "verified-digital-assets",
37
+ "metadata",
38
+ "access-control"
39
+ ],
40
+ "author": "Hauska SDK Team",
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/hauska-sdk/hauska-sdk.git",
45
+ "directory": "packages/vda"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/hauska-sdk/hauska-sdk/issues"
49
+ },
50
+ "homepage": "https://github.com/hauska-sdk/hauska-sdk#readme",
51
+ "engines": {
52
+ "node": ">=18.0.0",
53
+ "npm": ">=9.0.0"
54
+ },
55
+ "files": [
56
+ "dist",
57
+ "README.md",
58
+ "CHANGELOG.md"
59
+ ],
60
+ "scripts": {
61
+ "build": "tsc",
62
+ "clean": "rimraf dist",
63
+ "test": "vitest run",
64
+ "test:watch": "vitest",
65
+ "test:coverage": "vitest run --coverage",
66
+ "type-check": "tsc --noEmit",
67
+ "prepublishOnly": "npm run build"
68
+ },
69
+ "publishConfig": {
70
+ "access": "public",
71
+ "registry": "https://registry.npmjs.org"
72
+ }
73
+ }