@oma3/omatrust 0.1.0-alpha.11 → 0.1.0-alpha.12
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 +3 -0
- package/dist/app-registry/index.cjs +53 -0
- package/dist/app-registry/index.cjs.map +1 -1
- package/dist/app-registry/index.js +53 -0
- package/dist/app-registry/index.js.map +1 -1
- package/dist/identity/index.cjs +643 -164
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.d.cts +2 -2
- package/dist/identity/index.d.ts +2 -2
- package/dist/identity/index.js +616 -165
- package/dist/identity/index.js.map +1 -1
- package/dist/{index-QueRiudB.d.cts → index-B5OC9_8B.d.cts} +155 -4
- package/dist/index-Bu-xxcv9.d.ts +407 -0
- package/dist/{index-C2w5EvFH.d.ts → index-C6WNgPRx.d.ts} +155 -4
- package/dist/index-C7odEbp6.d.cts +407 -0
- package/dist/index.cjs +1000 -185
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +981 -185
- package/dist/index.js.map +1 -1
- package/dist/reputation/index.browser.cjs +153 -148
- package/dist/reputation/index.browser.cjs.map +1 -1
- package/dist/reputation/index.browser.js +153 -148
- package/dist/reputation/index.browser.js.map +1 -1
- package/dist/reputation/index.cjs +477 -140
- package/dist/reputation/index.cjs.map +1 -1
- package/dist/reputation/index.d.cts +2 -2
- package/dist/reputation/index.d.ts +2 -2
- package/dist/reputation/index.js +475 -141
- package/dist/reputation/index.js.map +1 -1
- package/dist/{types-dpYxRq8N.d.cts → types-Dn0OwaNj.d.cts} +37 -11
- package/dist/{types-dpYxRq8N.d.ts → types-Dn0OwaNj.d.ts} +37 -11
- package/dist/widgets/index.cjs.map +1 -1
- package/dist/widgets/index.d.cts +3 -0
- package/dist/widgets/index.d.ts +3 -0
- package/dist/widgets/index.js.map +1 -1
- package/package.json +4 -2
- package/dist/index-BOvk-7Ku.d.cts +0 -235
- package/dist/index-R78TpAhN.d.ts +0 -235
package/README.md
CHANGED
|
@@ -41,10 +41,13 @@ npm install @ethereum-attestation-service/eas-sdk
|
|
|
41
41
|
- DID address derivation
|
|
42
42
|
- CAIP-10 / CAIP-2 helpers
|
|
43
43
|
- JSON canonicalization helpers
|
|
44
|
+
- did:artifact construction and verification
|
|
45
|
+
- DID method migration (did:ethr → did:pkh, did:key → did:jwk)
|
|
44
46
|
- `@oma3/omatrust/reputation`
|
|
45
47
|
- attestation submit/delegated flows
|
|
46
48
|
- attestation query + verification
|
|
47
49
|
- proof creation/verification helpers
|
|
50
|
+
- schema-aware proof verification (linked identifier, key binding)
|
|
48
51
|
- controller witness client
|
|
49
52
|
- `@oma3/omatrust/app-registry`
|
|
50
53
|
- ERC-8004 helpers
|
|
@@ -165,7 +165,57 @@ var METADATA_KEY_VERSION_MINOR = "omat.versionMinor";
|
|
|
165
165
|
var METADATA_KEY_VERSION_PATCH = "omat.versionPatch";
|
|
166
166
|
var METADATA_KEY_TRAIT_HASHES = "omat.traitHashes";
|
|
167
167
|
var METADATA_KEY_METADATA_JSON = "omat.metadataJson";
|
|
168
|
+
var MAX_JSON_DEPTH = 32;
|
|
169
|
+
function assertDepthLimit(depth, context) {
|
|
170
|
+
if (depth > MAX_JSON_DEPTH) {
|
|
171
|
+
const msg = context ? `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH} at ${context}` : `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH}`;
|
|
172
|
+
throw new OmaTrustError("INVALID_INPUT", msg);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function assertJsonSafe(value, path = "$", depth = 0) {
|
|
176
|
+
assertDepthLimit(depth, path);
|
|
177
|
+
if (value === void 0) {
|
|
178
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: undefined`);
|
|
179
|
+
}
|
|
180
|
+
if (value === null) return;
|
|
181
|
+
switch (typeof value) {
|
|
182
|
+
case "string":
|
|
183
|
+
case "boolean":
|
|
184
|
+
return;
|
|
185
|
+
case "number":
|
|
186
|
+
if (!Number.isFinite(value)) {
|
|
187
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: ${value} (must be finite number)`);
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
case "bigint":
|
|
191
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: BigInt (use number or string)`);
|
|
192
|
+
case "function":
|
|
193
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: function`);
|
|
194
|
+
case "symbol":
|
|
195
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: Symbol`);
|
|
196
|
+
case "object":
|
|
197
|
+
if (value instanceof Date) {
|
|
198
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: Date (use ISO string or timestamp)`);
|
|
199
|
+
}
|
|
200
|
+
if (value instanceof RegExp) {
|
|
201
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: RegExp`);
|
|
202
|
+
}
|
|
203
|
+
if (Array.isArray(value)) {
|
|
204
|
+
for (let i = 0; i < value.length; i++) {
|
|
205
|
+
assertJsonSafe(value[i], `${path}[${i}]`, depth + 1);
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
for (const [key, val] of Object.entries(value)) {
|
|
210
|
+
assertJsonSafe(val, `${path}.${key}`, depth + 1);
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
default:
|
|
214
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: unknown type "${typeof value}"`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
168
217
|
function canonicalizeJson(obj) {
|
|
218
|
+
assertJsonSafe(obj);
|
|
169
219
|
const jcs = canonicalize__default.default(obj);
|
|
170
220
|
if (!jcs) {
|
|
171
221
|
throw new OmaTrustError("INVALID_INPUT", "Object cannot be canonicalized", { obj });
|
|
@@ -201,6 +251,9 @@ async function computeDataHashFromUrl(url, algorithm) {
|
|
|
201
251
|
if (!url || typeof url !== "string") {
|
|
202
252
|
throw new OmaTrustError("INVALID_INPUT", "url must be a non-empty string", { url });
|
|
203
253
|
}
|
|
254
|
+
if (algorithm !== "keccak256" && algorithm !== "sha256") {
|
|
255
|
+
throw new OmaTrustError("INVALID_INPUT", `Unsupported hash algorithm: "${algorithm}". Must be "keccak256" or "sha256".`, { algorithm });
|
|
256
|
+
}
|
|
204
257
|
const json = await fetchJson(url);
|
|
205
258
|
const jcsJson = canonicalizeJson(json);
|
|
206
259
|
return hashJcs(jcsJson, algorithm);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shared/errors.ts","../../src/shared/assert.ts","../../src/app-registry/traits.ts","../../src/app-registry/interfaces.ts","../../src/app-registry/status.ts","../../src/app-registry/version.ts","../../src/app-registry/metadata-keys.ts","../../src/identity/data.ts","../../src/app-registry/data-hash.ts"],"names":["id","canonicalize","toUtf8Bytes","keccak256","sha256"],"mappings":"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","file":"index.cjs","sourcesContent":["export class OmaTrustError extends Error {\n code: string;\n details?: unknown;\n\n constructor(code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"OmaTrustError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toOmaTrustError(\n code: string,\n message: string,\n details?: unknown\n): OmaTrustError {\n return new OmaTrustError(code, message, details);\n}\n","import { OmaTrustError } from \"./errors\";\n\nexport function assertString(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new OmaTrustError(code, `${name} must be a non-empty string`, { value });\n }\n}\n\nexport function assertNumber(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is number {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new OmaTrustError(code, `${name} must be a valid number`, { value });\n }\n}\n\nexport function assertObject(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new OmaTrustError(code, `${name} must be an object`, { value });\n }\n}\n\nexport function asError(err: unknown): Error {\n if (err instanceof Error) {\n return err;\n }\n return new Error(String(err));\n}\n","import { id } from \"ethers\";\nimport { assertString } from \"../shared/assert\";\n\ntype Hex = `0x${string}`;\n\nexport function hashTrait(trait: string): Hex {\n assertString(trait, \"trait\");\n return id(trait) as Hex;\n}\n\nexport function hashTraits(traits: string[]): Hex[] {\n if (!Array.isArray(traits)) {\n throw new TypeError(\"traits must be an array\");\n }\n return traits.map((trait) => hashTrait(trait));\n}\n","import type { InterfaceFlags, InterfaceType } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nconst BIT_HUMAN = 1;\nconst BIT_API = 2;\nconst BIT_CONTRACT = 4;\n\nexport function computeInterfacesBitmap(flags: InterfaceFlags): number {\n return (flags.human ? BIT_HUMAN : 0) +\n (flags.api ? BIT_API : 0) +\n (flags.smartContract ? BIT_CONTRACT : 0);\n}\n\nexport function parseBitmapToFlags(bitmap: number): InterfaceFlags {\n return {\n human: (bitmap & BIT_HUMAN) !== 0,\n api: (bitmap & BIT_API) !== 0,\n smartContract: (bitmap & BIT_CONTRACT) !== 0\n };\n}\n\nexport function hasInterface(bitmap: number, type: InterfaceType): boolean {\n switch (type) {\n case \"human\":\n return (bitmap & BIT_HUMAN) !== 0;\n case \"api\":\n return (bitmap & BIT_API) !== 0;\n case \"contract\":\n return (bitmap & BIT_CONTRACT) !== 0;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Unsupported interface type\", { type });\n }\n}\n\nexport function getInterfaceTypes(bitmap: number): InterfaceType[] {\n const results: InterfaceType[] = [];\n if (hasInterface(bitmap, \"human\")) {\n results.push(\"human\");\n }\n if (hasInterface(bitmap, \"api\")) {\n results.push(\"api\");\n }\n if (hasInterface(bitmap, \"contract\")) {\n results.push(\"contract\");\n }\n return results;\n}\n","import type { RegistryStatus } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function registryCodeToStatus(code: number): RegistryStatus {\n switch (code) {\n case 0:\n return \"Active\";\n case 1:\n return \"Deprecated\";\n case 2:\n return \"Replaced\";\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status code\", { code });\n }\n}\n\nexport function registryStatusToCode(status: RegistryStatus): number {\n switch (status) {\n case \"Active\":\n return 0;\n case \"Deprecated\":\n return 1;\n case \"Replaced\":\n return 2;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status\", { status });\n }\n}\n\nexport function isValidRegistryStatus(status: string): status is RegistryStatus {\n return status === \"Active\" || status === \"Deprecated\" || status === \"Replaced\";\n}\n","import type { Version } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function parseVersion(input: string): Version {\n const match = input.match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!match) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid semantic version\", { input });\n }\n\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3])\n };\n}\n\nexport function formatVersion(version: Version): string {\n return `${version.major}.${version.minor}.${version.patch}`;\n}\n\nexport function compareVersions(a: Version, b: Version): -1 | 0 | 1 {\n if (a.major !== b.major) {\n return a.major < b.major ? -1 : 1;\n }\n if (a.minor !== b.minor) {\n return a.minor < b.minor ? -1 : 1;\n }\n if (a.patch !== b.patch) {\n return a.patch < b.patch ? -1 : 1;\n }\n return 0;\n}\n\nexport function isVersionGreater(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 1;\n}\n\nexport function isVersionEqual(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 0;\n}\n\nexport function getLatestVersion(history: Version[]): Version {\n if (history.length === 0) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Version history cannot be empty\");\n }\n\n return history.reduce((current, candidate) => {\n return compareVersions(candidate, current) === 1 ? candidate : current;\n });\n}\n","export const METADATA_KEY_DID = \"omat.did\";\nexport const METADATA_KEY_DID_HASH = \"omat.didHash\";\nexport const METADATA_KEY_DATA_HASH = \"omat.dataHash\";\nexport const METADATA_KEY_DATA_HASH_ALGORITHM = \"omat.dataHashAlgorithm\";\nexport const METADATA_KEY_STATUS = \"omat.status\";\nexport const METADATA_KEY_INTERFACES = \"omat.interfaces\";\nexport const METADATA_KEY_FUNGIBLE_TOKEN_ID = \"omat.fungibleTokenId\";\nexport const METADATA_KEY_CONTRACT_ID = \"omat.contractId\";\nexport const METADATA_KEY_VERSION_MAJOR = \"omat.versionMajor\";\nexport const METADATA_KEY_VERSION_MINOR = \"omat.versionMinor\";\nexport const METADATA_KEY_VERSION_PATCH = \"omat.versionPatch\";\nexport const METADATA_KEY_TRAIT_HASHES = \"omat.traitHashes\";\nexport const METADATA_KEY_METADATA_JSON = \"omat.metadataJson\";\n","import canonicalize from \"canonicalize\";\nimport { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\n\nexport function canonicalizeJson(obj: unknown): string {\n const jcs = canonicalize(obj);\n if (!jcs) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Object cannot be canonicalized\", { obj });\n }\n return jcs;\n}\n\nexport function canonicalizeForHash(obj: unknown): { jcsJson: string; hash: Hex } {\n const jcsJson = canonicalizeJson(obj);\n return {\n jcsJson,\n hash: keccak256(toUtf8Bytes(jcsJson)) as Hex\n };\n}\n\nexport function hashCanonicalizedJson(obj: unknown, algorithm: \"keccak256\" | \"sha256\"): Hex {\n const jcs = canonicalizeJson(obj);\n const bytes = toUtf8Bytes(jcs);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n","import { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { canonicalizeJson } from \"../identity/data\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\nexport type DataHashAlgorithm = \"keccak256\" | \"sha256\";\n\nasync function fetchJson(url: string): Promise<unknown> {\n let response: Response;\n try {\n response = await fetch(url, { headers: { Accept: \"application/json\" } });\n } catch (err) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", { url, err });\n }\n\n if (!response.ok) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", {\n url,\n status: response.status\n });\n }\n\n try {\n return await response.json();\n } catch (err) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Response body is not valid JSON\", { url, err });\n }\n}\n\nfunction hashJcs(jcsJson: string, algorithm: DataHashAlgorithm): Hex {\n const bytes = toUtf8Bytes(jcsJson);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n\nexport async function computeDataHashFromUrl(\n url: string,\n algorithm: DataHashAlgorithm\n): Promise<Hex> {\n if (!url || typeof url !== \"string\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"url must be a non-empty string\", { url });\n }\n\n const json = await fetchJson(url);\n const jcsJson = canonicalizeJson(json);\n return hashJcs(jcsJson, algorithm);\n}\n\nexport async function verifyDataUrlHash(\n url: string,\n expectedHash: Hex,\n algorithm: DataHashAlgorithm\n): Promise<boolean> {\n const computedHash = await computeDataHashFromUrl(url, algorithm);\n return computedHash.toLowerCase() === expectedHash.toLowerCase();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/shared/errors.ts","../../src/shared/assert.ts","../../src/app-registry/traits.ts","../../src/app-registry/interfaces.ts","../../src/app-registry/status.ts","../../src/app-registry/version.ts","../../src/app-registry/metadata-keys.ts","../../src/identity/data.ts","../../src/app-registry/data-hash.ts"],"names":["id","canonicalize","toUtf8Bytes","keccak256","sha256"],"mappings":"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","file":"index.cjs","sourcesContent":["export class OmaTrustError extends Error {\n code: string;\n details?: unknown;\n\n constructor(code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"OmaTrustError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toOmaTrustError(\n code: string,\n message: string,\n details?: unknown\n): OmaTrustError {\n return new OmaTrustError(code, message, details);\n}\n","import { OmaTrustError } from \"./errors\";\n\nexport function assertString(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new OmaTrustError(code, `${name} must be a non-empty string`, { value });\n }\n}\n\nexport function assertNumber(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is number {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new OmaTrustError(code, `${name} must be a valid number`, { value });\n }\n}\n\nexport function assertObject(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new OmaTrustError(code, `${name} must be an object`, { value });\n }\n}\n\nexport function asError(err: unknown): Error {\n if (err instanceof Error) {\n return err;\n }\n return new Error(String(err));\n}\n","import { id } from \"ethers\";\nimport { assertString } from \"../shared/assert\";\n\ntype Hex = `0x${string}`;\n\nexport function hashTrait(trait: string): Hex {\n assertString(trait, \"trait\");\n return id(trait) as Hex;\n}\n\nexport function hashTraits(traits: string[]): Hex[] {\n if (!Array.isArray(traits)) {\n throw new TypeError(\"traits must be an array\");\n }\n return traits.map((trait) => hashTrait(trait));\n}\n","import type { InterfaceFlags, InterfaceType } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nconst BIT_HUMAN = 1;\nconst BIT_API = 2;\nconst BIT_CONTRACT = 4;\n\nexport function computeInterfacesBitmap(flags: InterfaceFlags): number {\n return (flags.human ? BIT_HUMAN : 0) +\n (flags.api ? BIT_API : 0) +\n (flags.smartContract ? BIT_CONTRACT : 0);\n}\n\nexport function parseBitmapToFlags(bitmap: number): InterfaceFlags {\n return {\n human: (bitmap & BIT_HUMAN) !== 0,\n api: (bitmap & BIT_API) !== 0,\n smartContract: (bitmap & BIT_CONTRACT) !== 0\n };\n}\n\nexport function hasInterface(bitmap: number, type: InterfaceType): boolean {\n switch (type) {\n case \"human\":\n return (bitmap & BIT_HUMAN) !== 0;\n case \"api\":\n return (bitmap & BIT_API) !== 0;\n case \"contract\":\n return (bitmap & BIT_CONTRACT) !== 0;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Unsupported interface type\", { type });\n }\n}\n\nexport function getInterfaceTypes(bitmap: number): InterfaceType[] {\n const results: InterfaceType[] = [];\n if (hasInterface(bitmap, \"human\")) {\n results.push(\"human\");\n }\n if (hasInterface(bitmap, \"api\")) {\n results.push(\"api\");\n }\n if (hasInterface(bitmap, \"contract\")) {\n results.push(\"contract\");\n }\n return results;\n}\n","import type { RegistryStatus } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function registryCodeToStatus(code: number): RegistryStatus {\n switch (code) {\n case 0:\n return \"Active\";\n case 1:\n return \"Deprecated\";\n case 2:\n return \"Replaced\";\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status code\", { code });\n }\n}\n\nexport function registryStatusToCode(status: RegistryStatus): number {\n switch (status) {\n case \"Active\":\n return 0;\n case \"Deprecated\":\n return 1;\n case \"Replaced\":\n return 2;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status\", { status });\n }\n}\n\nexport function isValidRegistryStatus(status: string): status is RegistryStatus {\n return status === \"Active\" || status === \"Deprecated\" || status === \"Replaced\";\n}\n","import type { Version } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function parseVersion(input: string): Version {\n const match = input.match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!match) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid semantic version\", { input });\n }\n\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3])\n };\n}\n\nexport function formatVersion(version: Version): string {\n return `${version.major}.${version.minor}.${version.patch}`;\n}\n\nexport function compareVersions(a: Version, b: Version): -1 | 0 | 1 {\n if (a.major !== b.major) {\n return a.major < b.major ? -1 : 1;\n }\n if (a.minor !== b.minor) {\n return a.minor < b.minor ? -1 : 1;\n }\n if (a.patch !== b.patch) {\n return a.patch < b.patch ? -1 : 1;\n }\n return 0;\n}\n\nexport function isVersionGreater(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 1;\n}\n\nexport function isVersionEqual(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 0;\n}\n\nexport function getLatestVersion(history: Version[]): Version {\n if (history.length === 0) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Version history cannot be empty\");\n }\n\n return history.reduce((current, candidate) => {\n return compareVersions(candidate, current) === 1 ? candidate : current;\n });\n}\n","export const METADATA_KEY_DID = \"omat.did\";\nexport const METADATA_KEY_DID_HASH = \"omat.didHash\";\nexport const METADATA_KEY_DATA_HASH = \"omat.dataHash\";\nexport const METADATA_KEY_DATA_HASH_ALGORITHM = \"omat.dataHashAlgorithm\";\nexport const METADATA_KEY_STATUS = \"omat.status\";\nexport const METADATA_KEY_INTERFACES = \"omat.interfaces\";\nexport const METADATA_KEY_FUNGIBLE_TOKEN_ID = \"omat.fungibleTokenId\";\nexport const METADATA_KEY_CONTRACT_ID = \"omat.contractId\";\nexport const METADATA_KEY_VERSION_MAJOR = \"omat.versionMajor\";\nexport const METADATA_KEY_VERSION_MINOR = \"omat.versionMinor\";\nexport const METADATA_KEY_VERSION_PATCH = \"omat.versionPatch\";\nexport const METADATA_KEY_TRAIT_HASHES = \"omat.traitHashes\";\nexport const METADATA_KEY_METADATA_JSON = \"omat.metadataJson\";\n","import canonicalize from \"canonicalize\";\nimport { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\n\nconst VALID_ALGORITHMS = new Set([\"keccak256\", \"sha256\"]);\n\n/** Maximum JSON nesting depth allowed. */\nconst MAX_JSON_DEPTH = 32;\n\nfunction assertDepthLimit(depth: number, context?: string): void {\n if (depth > MAX_JSON_DEPTH) {\n const msg = context\n ? `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH} at ${context}`\n : `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH}`;\n throw new OmaTrustError(\"INVALID_INPUT\", msg);\n }\n}\n\n/**\n * Parse JSON strictly, rejecting duplicate keys.\n * Standard JSON.parse() silently accepts duplicates (last-wins).\n * This function detects duplicates at any nesting depth and throws.\n */\nexport function parseJsonStrict(input: string): unknown {\n if (typeof input !== \"string\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Input must be a string\");\n }\n\n // First pass: detect duplicate keys by scanning object literals\n const seen = new Map<string, Set<string>>();\n let pathStack: string[] = [];\n let depth = 0;\n\n // Use a reviver to track keys at each depth\n const keyTracker = new Map<number, Set<string>>();\n\n // Parse with a reviver that tracks keys per object depth\n // JSON.parse calls the reviver bottom-up, so we use a different approach:\n // scan the raw string for duplicate keys using a state machine.\n const duplicateKeys = detectDuplicateKeys(input);\n if (duplicateKeys.length > 0) {\n throw new OmaTrustError(\n \"INVALID_INPUT\",\n `Duplicate JSON key${duplicateKeys.length > 1 ? \"s\" : \"\"} detected: ${duplicateKeys.map(k => `\"${k}\"`).join(\", \")}`,\n { duplicateKeys }\n );\n }\n\n try {\n return JSON.parse(input);\n } catch {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Input is not valid JSON\");\n }\n}\n\n/**\n * Detect duplicate keys in a JSON string.\n * Returns an array of key names that appear more than once in any single object.\n */\nfunction detectDuplicateKeys(input: string): string[] {\n const duplicates: string[] = [];\n // Stack of sets — each set tracks keys for the current object nesting level\n const objectKeyStack: Set<string>[] = [];\n let inString = false;\n let escaped = false;\n let currentKey = \"\";\n let collectingKey = false;\n let afterColon = false;\n let i = 0;\n\n while (i < input.length) {\n const ch = input[i];\n\n if (escaped) {\n if (collectingKey) currentKey += ch;\n escaped = false;\n i++;\n continue;\n }\n\n if (ch === \"\\\\\") {\n escaped = true;\n if (collectingKey) currentKey += ch;\n i++;\n continue;\n }\n\n if (ch === '\"') {\n if (!inString) {\n inString = true;\n // If we're in an object context and not after a colon, this is a key\n if (objectKeyStack.length > 0 && !afterColon) {\n collectingKey = true;\n currentKey = \"\";\n }\n } else {\n inString = false;\n if (collectingKey) {\n collectingKey = false;\n const keySet = objectKeyStack[objectKeyStack.length - 1];\n if (keySet.has(currentKey)) {\n if (!duplicates.includes(currentKey)) {\n duplicates.push(currentKey);\n }\n } else {\n keySet.add(currentKey);\n }\n }\n }\n i++;\n continue;\n }\n\n if (inString) {\n if (collectingKey) currentKey += ch;\n i++;\n continue;\n }\n\n // Outside string\n if (ch === \"{\") {\n objectKeyStack.push(new Set());\n assertDepthLimit(objectKeyStack.length);\n afterColon = false;\n } else if (ch === \"}\") {\n objectKeyStack.pop();\n afterColon = objectKeyStack.length > 0; // restore parent context\n } else if (ch === \"[\") {\n // Arrays don't have keys — push a sentinel\n objectKeyStack.push(new Set([\"__array__\"]));\n assertDepthLimit(objectKeyStack.length);\n afterColon = false;\n } else if (ch === \"]\") {\n objectKeyStack.pop();\n afterColon = objectKeyStack.length > 0;\n } else if (ch === \":\") {\n afterColon = true;\n } else if (ch === \",\") {\n afterColon = false;\n }\n\n i++;\n }\n\n return duplicates;\n}\n\n/**\n * Assert that a value is JSON-safe (representable in JSON without lossy conversion).\n * Rejects: undefined, NaN, Infinity, -Infinity, BigInt, functions, symbols, Date objects.\n * These values would be silently coerced or dropped by JSON.stringify / canonicalize.\n */\nexport function assertJsonSafe(value: unknown, path: string = \"$\", depth: number = 0): void {\n assertDepthLimit(depth, path);\n\n if (value === undefined) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: undefined`);\n }\n\n if (value === null) return;\n\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return;\n case \"number\":\n if (!Number.isFinite(value)) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: ${value} (must be finite number)`);\n }\n return;\n case \"bigint\":\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: BigInt (use number or string)`);\n case \"function\":\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: function`);\n case \"symbol\":\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: Symbol`);\n case \"object\":\n if (value instanceof Date) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: Date (use ISO string or timestamp)`);\n }\n if (value instanceof RegExp) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: RegExp`);\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n assertJsonSafe(value[i], `${path}[${i}]`, depth + 1);\n }\n return;\n }\n // Plain object\n for (const [key, val] of Object.entries(value)) {\n assertJsonSafe(val, `${path}.${key}`, depth + 1);\n }\n return;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: unknown type \"${typeof value}\"`);\n }\n}\n\nexport function canonicalizeJson(obj: unknown): string {\n assertJsonSafe(obj);\n const jcs = canonicalize(obj);\n if (!jcs) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Object cannot be canonicalized\", { obj });\n }\n return jcs;\n}\n\n/**\n * Canonicalize a JSON object (JCS / RFC 8785) and compute its keccak256 hash.\n * Returns both the canonical JCS string and the 0x-prefixed hash.\n */\nexport function canonicalizeAndKeccak256(obj: unknown): { jcsJson: string; hash: Hex } {\n const jcsJson = canonicalizeJson(obj);\n return {\n jcsJson,\n hash: keccak256(toUtf8Bytes(jcsJson)) as Hex\n };\n}\n\n/** @deprecated Use canonicalizeAndKeccak256 instead. */\nexport function canonicalizeForHash(obj: unknown): { jcsJson: string; hash: Hex } {\n return canonicalizeAndKeccak256(obj);\n}\n\nexport function hashCanonicalizedJson(obj: unknown, algorithm: \"keccak256\" | \"sha256\"): Hex {\n if (!VALID_ALGORITHMS.has(algorithm)) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Unsupported hash algorithm: \"${algorithm}\". Must be \"keccak256\" or \"sha256\".`, { algorithm });\n }\n const jcs = canonicalizeJson(obj);\n const bytes = toUtf8Bytes(jcs);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n","import { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { canonicalizeJson } from \"../identity/data\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\nexport type DataHashAlgorithm = \"keccak256\" | \"sha256\";\n\nasync function fetchJson(url: string): Promise<unknown> {\n let response: Response;\n try {\n response = await fetch(url, { headers: { Accept: \"application/json\" } });\n } catch (err) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", { url, err });\n }\n\n if (!response.ok) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", {\n url,\n status: response.status\n });\n }\n\n try {\n return await response.json();\n } catch (err) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Response body is not valid JSON\", { url, err });\n }\n}\n\nfunction hashJcs(jcsJson: string, algorithm: DataHashAlgorithm): Hex {\n const bytes = toUtf8Bytes(jcsJson);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n\nexport async function computeDataHashFromUrl(\n url: string,\n algorithm: DataHashAlgorithm\n): Promise<Hex> {\n if (!url || typeof url !== \"string\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"url must be a non-empty string\", { url });\n }\n\n if (algorithm !== \"keccak256\" && algorithm !== \"sha256\") {\n throw new OmaTrustError(\"INVALID_INPUT\", `Unsupported hash algorithm: \"${algorithm}\". Must be \"keccak256\" or \"sha256\".`, { algorithm });\n }\n\n const json = await fetchJson(url);\n const jcsJson = canonicalizeJson(json);\n return hashJcs(jcsJson, algorithm);\n}\n\nexport async function verifyDataUrlHash(\n url: string,\n expectedHash: Hex,\n algorithm: DataHashAlgorithm\n): Promise<boolean> {\n const computedHash = await computeDataHashFromUrl(url, algorithm);\n return computedHash.toLowerCase() === expectedHash.toLowerCase();\n}\n"]}
|
|
@@ -159,7 +159,57 @@ var METADATA_KEY_VERSION_MINOR = "omat.versionMinor";
|
|
|
159
159
|
var METADATA_KEY_VERSION_PATCH = "omat.versionPatch";
|
|
160
160
|
var METADATA_KEY_TRAIT_HASHES = "omat.traitHashes";
|
|
161
161
|
var METADATA_KEY_METADATA_JSON = "omat.metadataJson";
|
|
162
|
+
var MAX_JSON_DEPTH = 32;
|
|
163
|
+
function assertDepthLimit(depth, context) {
|
|
164
|
+
if (depth > MAX_JSON_DEPTH) {
|
|
165
|
+
const msg = context ? `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH} at ${context}` : `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH}`;
|
|
166
|
+
throw new OmaTrustError("INVALID_INPUT", msg);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function assertJsonSafe(value, path = "$", depth = 0) {
|
|
170
|
+
assertDepthLimit(depth, path);
|
|
171
|
+
if (value === void 0) {
|
|
172
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: undefined`);
|
|
173
|
+
}
|
|
174
|
+
if (value === null) return;
|
|
175
|
+
switch (typeof value) {
|
|
176
|
+
case "string":
|
|
177
|
+
case "boolean":
|
|
178
|
+
return;
|
|
179
|
+
case "number":
|
|
180
|
+
if (!Number.isFinite(value)) {
|
|
181
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: ${value} (must be finite number)`);
|
|
182
|
+
}
|
|
183
|
+
return;
|
|
184
|
+
case "bigint":
|
|
185
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: BigInt (use number or string)`);
|
|
186
|
+
case "function":
|
|
187
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: function`);
|
|
188
|
+
case "symbol":
|
|
189
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: Symbol`);
|
|
190
|
+
case "object":
|
|
191
|
+
if (value instanceof Date) {
|
|
192
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: Date (use ISO string or timestamp)`);
|
|
193
|
+
}
|
|
194
|
+
if (value instanceof RegExp) {
|
|
195
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: RegExp`);
|
|
196
|
+
}
|
|
197
|
+
if (Array.isArray(value)) {
|
|
198
|
+
for (let i = 0; i < value.length; i++) {
|
|
199
|
+
assertJsonSafe(value[i], `${path}[${i}]`, depth + 1);
|
|
200
|
+
}
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
for (const [key, val] of Object.entries(value)) {
|
|
204
|
+
assertJsonSafe(val, `${path}.${key}`, depth + 1);
|
|
205
|
+
}
|
|
206
|
+
return;
|
|
207
|
+
default:
|
|
208
|
+
throw new OmaTrustError("INVALID_INPUT", `Non-JSON-safe value at ${path}: unknown type "${typeof value}"`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
162
211
|
function canonicalizeJson(obj) {
|
|
212
|
+
assertJsonSafe(obj);
|
|
163
213
|
const jcs = canonicalize(obj);
|
|
164
214
|
if (!jcs) {
|
|
165
215
|
throw new OmaTrustError("INVALID_INPUT", "Object cannot be canonicalized", { obj });
|
|
@@ -195,6 +245,9 @@ async function computeDataHashFromUrl(url, algorithm) {
|
|
|
195
245
|
if (!url || typeof url !== "string") {
|
|
196
246
|
throw new OmaTrustError("INVALID_INPUT", "url must be a non-empty string", { url });
|
|
197
247
|
}
|
|
248
|
+
if (algorithm !== "keccak256" && algorithm !== "sha256") {
|
|
249
|
+
throw new OmaTrustError("INVALID_INPUT", `Unsupported hash algorithm: "${algorithm}". Must be "keccak256" or "sha256".`, { algorithm });
|
|
250
|
+
}
|
|
198
251
|
const json = await fetchJson(url);
|
|
199
252
|
const jcsJson = canonicalizeJson(json);
|
|
200
253
|
return hashJcs(jcsJson, algorithm);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shared/errors.ts","../../src/shared/assert.ts","../../src/app-registry/traits.ts","../../src/app-registry/interfaces.ts","../../src/app-registry/status.ts","../../src/app-registry/version.ts","../../src/app-registry/metadata-keys.ts","../../src/identity/data.ts","../../src/app-registry/data-hash.ts"],"names":["toUtf8Bytes","keccak256","sha256"],"mappings":"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","file":"index.js","sourcesContent":["export class OmaTrustError extends Error {\n code: string;\n details?: unknown;\n\n constructor(code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"OmaTrustError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toOmaTrustError(\n code: string,\n message: string,\n details?: unknown\n): OmaTrustError {\n return new OmaTrustError(code, message, details);\n}\n","import { OmaTrustError } from \"./errors\";\n\nexport function assertString(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new OmaTrustError(code, `${name} must be a non-empty string`, { value });\n }\n}\n\nexport function assertNumber(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is number {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new OmaTrustError(code, `${name} must be a valid number`, { value });\n }\n}\n\nexport function assertObject(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new OmaTrustError(code, `${name} must be an object`, { value });\n }\n}\n\nexport function asError(err: unknown): Error {\n if (err instanceof Error) {\n return err;\n }\n return new Error(String(err));\n}\n","import { id } from \"ethers\";\nimport { assertString } from \"../shared/assert\";\n\ntype Hex = `0x${string}`;\n\nexport function hashTrait(trait: string): Hex {\n assertString(trait, \"trait\");\n return id(trait) as Hex;\n}\n\nexport function hashTraits(traits: string[]): Hex[] {\n if (!Array.isArray(traits)) {\n throw new TypeError(\"traits must be an array\");\n }\n return traits.map((trait) => hashTrait(trait));\n}\n","import type { InterfaceFlags, InterfaceType } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nconst BIT_HUMAN = 1;\nconst BIT_API = 2;\nconst BIT_CONTRACT = 4;\n\nexport function computeInterfacesBitmap(flags: InterfaceFlags): number {\n return (flags.human ? BIT_HUMAN : 0) +\n (flags.api ? BIT_API : 0) +\n (flags.smartContract ? BIT_CONTRACT : 0);\n}\n\nexport function parseBitmapToFlags(bitmap: number): InterfaceFlags {\n return {\n human: (bitmap & BIT_HUMAN) !== 0,\n api: (bitmap & BIT_API) !== 0,\n smartContract: (bitmap & BIT_CONTRACT) !== 0\n };\n}\n\nexport function hasInterface(bitmap: number, type: InterfaceType): boolean {\n switch (type) {\n case \"human\":\n return (bitmap & BIT_HUMAN) !== 0;\n case \"api\":\n return (bitmap & BIT_API) !== 0;\n case \"contract\":\n return (bitmap & BIT_CONTRACT) !== 0;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Unsupported interface type\", { type });\n }\n}\n\nexport function getInterfaceTypes(bitmap: number): InterfaceType[] {\n const results: InterfaceType[] = [];\n if (hasInterface(bitmap, \"human\")) {\n results.push(\"human\");\n }\n if (hasInterface(bitmap, \"api\")) {\n results.push(\"api\");\n }\n if (hasInterface(bitmap, \"contract\")) {\n results.push(\"contract\");\n }\n return results;\n}\n","import type { RegistryStatus } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function registryCodeToStatus(code: number): RegistryStatus {\n switch (code) {\n case 0:\n return \"Active\";\n case 1:\n return \"Deprecated\";\n case 2:\n return \"Replaced\";\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status code\", { code });\n }\n}\n\nexport function registryStatusToCode(status: RegistryStatus): number {\n switch (status) {\n case \"Active\":\n return 0;\n case \"Deprecated\":\n return 1;\n case \"Replaced\":\n return 2;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status\", { status });\n }\n}\n\nexport function isValidRegistryStatus(status: string): status is RegistryStatus {\n return status === \"Active\" || status === \"Deprecated\" || status === \"Replaced\";\n}\n","import type { Version } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function parseVersion(input: string): Version {\n const match = input.match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!match) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid semantic version\", { input });\n }\n\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3])\n };\n}\n\nexport function formatVersion(version: Version): string {\n return `${version.major}.${version.minor}.${version.patch}`;\n}\n\nexport function compareVersions(a: Version, b: Version): -1 | 0 | 1 {\n if (a.major !== b.major) {\n return a.major < b.major ? -1 : 1;\n }\n if (a.minor !== b.minor) {\n return a.minor < b.minor ? -1 : 1;\n }\n if (a.patch !== b.patch) {\n return a.patch < b.patch ? -1 : 1;\n }\n return 0;\n}\n\nexport function isVersionGreater(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 1;\n}\n\nexport function isVersionEqual(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 0;\n}\n\nexport function getLatestVersion(history: Version[]): Version {\n if (history.length === 0) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Version history cannot be empty\");\n }\n\n return history.reduce((current, candidate) => {\n return compareVersions(candidate, current) === 1 ? candidate : current;\n });\n}\n","export const METADATA_KEY_DID = \"omat.did\";\nexport const METADATA_KEY_DID_HASH = \"omat.didHash\";\nexport const METADATA_KEY_DATA_HASH = \"omat.dataHash\";\nexport const METADATA_KEY_DATA_HASH_ALGORITHM = \"omat.dataHashAlgorithm\";\nexport const METADATA_KEY_STATUS = \"omat.status\";\nexport const METADATA_KEY_INTERFACES = \"omat.interfaces\";\nexport const METADATA_KEY_FUNGIBLE_TOKEN_ID = \"omat.fungibleTokenId\";\nexport const METADATA_KEY_CONTRACT_ID = \"omat.contractId\";\nexport const METADATA_KEY_VERSION_MAJOR = \"omat.versionMajor\";\nexport const METADATA_KEY_VERSION_MINOR = \"omat.versionMinor\";\nexport const METADATA_KEY_VERSION_PATCH = \"omat.versionPatch\";\nexport const METADATA_KEY_TRAIT_HASHES = \"omat.traitHashes\";\nexport const METADATA_KEY_METADATA_JSON = \"omat.metadataJson\";\n","import canonicalize from \"canonicalize\";\nimport { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\n\nexport function canonicalizeJson(obj: unknown): string {\n const jcs = canonicalize(obj);\n if (!jcs) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Object cannot be canonicalized\", { obj });\n }\n return jcs;\n}\n\nexport function canonicalizeForHash(obj: unknown): { jcsJson: string; hash: Hex } {\n const jcsJson = canonicalizeJson(obj);\n return {\n jcsJson,\n hash: keccak256(toUtf8Bytes(jcsJson)) as Hex\n };\n}\n\nexport function hashCanonicalizedJson(obj: unknown, algorithm: \"keccak256\" | \"sha256\"): Hex {\n const jcs = canonicalizeJson(obj);\n const bytes = toUtf8Bytes(jcs);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n","import { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { canonicalizeJson } from \"../identity/data\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\nexport type DataHashAlgorithm = \"keccak256\" | \"sha256\";\n\nasync function fetchJson(url: string): Promise<unknown> {\n let response: Response;\n try {\n response = await fetch(url, { headers: { Accept: \"application/json\" } });\n } catch (err) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", { url, err });\n }\n\n if (!response.ok) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", {\n url,\n status: response.status\n });\n }\n\n try {\n return await response.json();\n } catch (err) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Response body is not valid JSON\", { url, err });\n }\n}\n\nfunction hashJcs(jcsJson: string, algorithm: DataHashAlgorithm): Hex {\n const bytes = toUtf8Bytes(jcsJson);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n\nexport async function computeDataHashFromUrl(\n url: string,\n algorithm: DataHashAlgorithm\n): Promise<Hex> {\n if (!url || typeof url !== \"string\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"url must be a non-empty string\", { url });\n }\n\n const json = await fetchJson(url);\n const jcsJson = canonicalizeJson(json);\n return hashJcs(jcsJson, algorithm);\n}\n\nexport async function verifyDataUrlHash(\n url: string,\n expectedHash: Hex,\n algorithm: DataHashAlgorithm\n): Promise<boolean> {\n const computedHash = await computeDataHashFromUrl(url, algorithm);\n return computedHash.toLowerCase() === expectedHash.toLowerCase();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/shared/errors.ts","../../src/shared/assert.ts","../../src/app-registry/traits.ts","../../src/app-registry/interfaces.ts","../../src/app-registry/status.ts","../../src/app-registry/version.ts","../../src/app-registry/metadata-keys.ts","../../src/identity/data.ts","../../src/app-registry/data-hash.ts"],"names":["toUtf8Bytes","keccak256","sha256"],"mappings":"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","file":"index.js","sourcesContent":["export class OmaTrustError extends Error {\n code: string;\n details?: unknown;\n\n constructor(code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"OmaTrustError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toOmaTrustError(\n code: string,\n message: string,\n details?: unknown\n): OmaTrustError {\n return new OmaTrustError(code, message, details);\n}\n","import { OmaTrustError } from \"./errors\";\n\nexport function assertString(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new OmaTrustError(code, `${name} must be a non-empty string`, { value });\n }\n}\n\nexport function assertNumber(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is number {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new OmaTrustError(code, `${name} must be a valid number`, { value });\n }\n}\n\nexport function assertObject(value: unknown, name: string, code = \"INVALID_INPUT\"): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new OmaTrustError(code, `${name} must be an object`, { value });\n }\n}\n\nexport function asError(err: unknown): Error {\n if (err instanceof Error) {\n return err;\n }\n return new Error(String(err));\n}\n","import { id } from \"ethers\";\nimport { assertString } from \"../shared/assert\";\n\ntype Hex = `0x${string}`;\n\nexport function hashTrait(trait: string): Hex {\n assertString(trait, \"trait\");\n return id(trait) as Hex;\n}\n\nexport function hashTraits(traits: string[]): Hex[] {\n if (!Array.isArray(traits)) {\n throw new TypeError(\"traits must be an array\");\n }\n return traits.map((trait) => hashTrait(trait));\n}\n","import type { InterfaceFlags, InterfaceType } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nconst BIT_HUMAN = 1;\nconst BIT_API = 2;\nconst BIT_CONTRACT = 4;\n\nexport function computeInterfacesBitmap(flags: InterfaceFlags): number {\n return (flags.human ? BIT_HUMAN : 0) +\n (flags.api ? BIT_API : 0) +\n (flags.smartContract ? BIT_CONTRACT : 0);\n}\n\nexport function parseBitmapToFlags(bitmap: number): InterfaceFlags {\n return {\n human: (bitmap & BIT_HUMAN) !== 0,\n api: (bitmap & BIT_API) !== 0,\n smartContract: (bitmap & BIT_CONTRACT) !== 0\n };\n}\n\nexport function hasInterface(bitmap: number, type: InterfaceType): boolean {\n switch (type) {\n case \"human\":\n return (bitmap & BIT_HUMAN) !== 0;\n case \"api\":\n return (bitmap & BIT_API) !== 0;\n case \"contract\":\n return (bitmap & BIT_CONTRACT) !== 0;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Unsupported interface type\", { type });\n }\n}\n\nexport function getInterfaceTypes(bitmap: number): InterfaceType[] {\n const results: InterfaceType[] = [];\n if (hasInterface(bitmap, \"human\")) {\n results.push(\"human\");\n }\n if (hasInterface(bitmap, \"api\")) {\n results.push(\"api\");\n }\n if (hasInterface(bitmap, \"contract\")) {\n results.push(\"contract\");\n }\n return results;\n}\n","import type { RegistryStatus } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function registryCodeToStatus(code: number): RegistryStatus {\n switch (code) {\n case 0:\n return \"Active\";\n case 1:\n return \"Deprecated\";\n case 2:\n return \"Replaced\";\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status code\", { code });\n }\n}\n\nexport function registryStatusToCode(status: RegistryStatus): number {\n switch (status) {\n case \"Active\":\n return 0;\n case \"Deprecated\":\n return 1;\n case \"Replaced\":\n return 2;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid registry status\", { status });\n }\n}\n\nexport function isValidRegistryStatus(status: string): status is RegistryStatus {\n return status === \"Active\" || status === \"Deprecated\" || status === \"Replaced\";\n}\n","import type { Version } from \"./types\";\nimport { OmaTrustError } from \"../shared/errors\";\n\nexport function parseVersion(input: string): Version {\n const match = input.match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!match) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid semantic version\", { input });\n }\n\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3])\n };\n}\n\nexport function formatVersion(version: Version): string {\n return `${version.major}.${version.minor}.${version.patch}`;\n}\n\nexport function compareVersions(a: Version, b: Version): -1 | 0 | 1 {\n if (a.major !== b.major) {\n return a.major < b.major ? -1 : 1;\n }\n if (a.minor !== b.minor) {\n return a.minor < b.minor ? -1 : 1;\n }\n if (a.patch !== b.patch) {\n return a.patch < b.patch ? -1 : 1;\n }\n return 0;\n}\n\nexport function isVersionGreater(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 1;\n}\n\nexport function isVersionEqual(a: Version, b: Version): boolean {\n return compareVersions(a, b) === 0;\n}\n\nexport function getLatestVersion(history: Version[]): Version {\n if (history.length === 0) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Version history cannot be empty\");\n }\n\n return history.reduce((current, candidate) => {\n return compareVersions(candidate, current) === 1 ? candidate : current;\n });\n}\n","export const METADATA_KEY_DID = \"omat.did\";\nexport const METADATA_KEY_DID_HASH = \"omat.didHash\";\nexport const METADATA_KEY_DATA_HASH = \"omat.dataHash\";\nexport const METADATA_KEY_DATA_HASH_ALGORITHM = \"omat.dataHashAlgorithm\";\nexport const METADATA_KEY_STATUS = \"omat.status\";\nexport const METADATA_KEY_INTERFACES = \"omat.interfaces\";\nexport const METADATA_KEY_FUNGIBLE_TOKEN_ID = \"omat.fungibleTokenId\";\nexport const METADATA_KEY_CONTRACT_ID = \"omat.contractId\";\nexport const METADATA_KEY_VERSION_MAJOR = \"omat.versionMajor\";\nexport const METADATA_KEY_VERSION_MINOR = \"omat.versionMinor\";\nexport const METADATA_KEY_VERSION_PATCH = \"omat.versionPatch\";\nexport const METADATA_KEY_TRAIT_HASHES = \"omat.traitHashes\";\nexport const METADATA_KEY_METADATA_JSON = \"omat.metadataJson\";\n","import canonicalize from \"canonicalize\";\nimport { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\n\nconst VALID_ALGORITHMS = new Set([\"keccak256\", \"sha256\"]);\n\n/** Maximum JSON nesting depth allowed. */\nconst MAX_JSON_DEPTH = 32;\n\nfunction assertDepthLimit(depth: number, context?: string): void {\n if (depth > MAX_JSON_DEPTH) {\n const msg = context\n ? `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH} at ${context}`\n : `JSON nesting depth exceeds maximum of ${MAX_JSON_DEPTH}`;\n throw new OmaTrustError(\"INVALID_INPUT\", msg);\n }\n}\n\n/**\n * Parse JSON strictly, rejecting duplicate keys.\n * Standard JSON.parse() silently accepts duplicates (last-wins).\n * This function detects duplicates at any nesting depth and throws.\n */\nexport function parseJsonStrict(input: string): unknown {\n if (typeof input !== \"string\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Input must be a string\");\n }\n\n // First pass: detect duplicate keys by scanning object literals\n const seen = new Map<string, Set<string>>();\n let pathStack: string[] = [];\n let depth = 0;\n\n // Use a reviver to track keys at each depth\n const keyTracker = new Map<number, Set<string>>();\n\n // Parse with a reviver that tracks keys per object depth\n // JSON.parse calls the reviver bottom-up, so we use a different approach:\n // scan the raw string for duplicate keys using a state machine.\n const duplicateKeys = detectDuplicateKeys(input);\n if (duplicateKeys.length > 0) {\n throw new OmaTrustError(\n \"INVALID_INPUT\",\n `Duplicate JSON key${duplicateKeys.length > 1 ? \"s\" : \"\"} detected: ${duplicateKeys.map(k => `\"${k}\"`).join(\", \")}`,\n { duplicateKeys }\n );\n }\n\n try {\n return JSON.parse(input);\n } catch {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Input is not valid JSON\");\n }\n}\n\n/**\n * Detect duplicate keys in a JSON string.\n * Returns an array of key names that appear more than once in any single object.\n */\nfunction detectDuplicateKeys(input: string): string[] {\n const duplicates: string[] = [];\n // Stack of sets — each set tracks keys for the current object nesting level\n const objectKeyStack: Set<string>[] = [];\n let inString = false;\n let escaped = false;\n let currentKey = \"\";\n let collectingKey = false;\n let afterColon = false;\n let i = 0;\n\n while (i < input.length) {\n const ch = input[i];\n\n if (escaped) {\n if (collectingKey) currentKey += ch;\n escaped = false;\n i++;\n continue;\n }\n\n if (ch === \"\\\\\") {\n escaped = true;\n if (collectingKey) currentKey += ch;\n i++;\n continue;\n }\n\n if (ch === '\"') {\n if (!inString) {\n inString = true;\n // If we're in an object context and not after a colon, this is a key\n if (objectKeyStack.length > 0 && !afterColon) {\n collectingKey = true;\n currentKey = \"\";\n }\n } else {\n inString = false;\n if (collectingKey) {\n collectingKey = false;\n const keySet = objectKeyStack[objectKeyStack.length - 1];\n if (keySet.has(currentKey)) {\n if (!duplicates.includes(currentKey)) {\n duplicates.push(currentKey);\n }\n } else {\n keySet.add(currentKey);\n }\n }\n }\n i++;\n continue;\n }\n\n if (inString) {\n if (collectingKey) currentKey += ch;\n i++;\n continue;\n }\n\n // Outside string\n if (ch === \"{\") {\n objectKeyStack.push(new Set());\n assertDepthLimit(objectKeyStack.length);\n afterColon = false;\n } else if (ch === \"}\") {\n objectKeyStack.pop();\n afterColon = objectKeyStack.length > 0; // restore parent context\n } else if (ch === \"[\") {\n // Arrays don't have keys — push a sentinel\n objectKeyStack.push(new Set([\"__array__\"]));\n assertDepthLimit(objectKeyStack.length);\n afterColon = false;\n } else if (ch === \"]\") {\n objectKeyStack.pop();\n afterColon = objectKeyStack.length > 0;\n } else if (ch === \":\") {\n afterColon = true;\n } else if (ch === \",\") {\n afterColon = false;\n }\n\n i++;\n }\n\n return duplicates;\n}\n\n/**\n * Assert that a value is JSON-safe (representable in JSON without lossy conversion).\n * Rejects: undefined, NaN, Infinity, -Infinity, BigInt, functions, symbols, Date objects.\n * These values would be silently coerced or dropped by JSON.stringify / canonicalize.\n */\nexport function assertJsonSafe(value: unknown, path: string = \"$\", depth: number = 0): void {\n assertDepthLimit(depth, path);\n\n if (value === undefined) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: undefined`);\n }\n\n if (value === null) return;\n\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return;\n case \"number\":\n if (!Number.isFinite(value)) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: ${value} (must be finite number)`);\n }\n return;\n case \"bigint\":\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: BigInt (use number or string)`);\n case \"function\":\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: function`);\n case \"symbol\":\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: Symbol`);\n case \"object\":\n if (value instanceof Date) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: Date (use ISO string or timestamp)`);\n }\n if (value instanceof RegExp) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: RegExp`);\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n assertJsonSafe(value[i], `${path}[${i}]`, depth + 1);\n }\n return;\n }\n // Plain object\n for (const [key, val] of Object.entries(value)) {\n assertJsonSafe(val, `${path}.${key}`, depth + 1);\n }\n return;\n default:\n throw new OmaTrustError(\"INVALID_INPUT\", `Non-JSON-safe value at ${path}: unknown type \"${typeof value}\"`);\n }\n}\n\nexport function canonicalizeJson(obj: unknown): string {\n assertJsonSafe(obj);\n const jcs = canonicalize(obj);\n if (!jcs) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Object cannot be canonicalized\", { obj });\n }\n return jcs;\n}\n\n/**\n * Canonicalize a JSON object (JCS / RFC 8785) and compute its keccak256 hash.\n * Returns both the canonical JCS string and the 0x-prefixed hash.\n */\nexport function canonicalizeAndKeccak256(obj: unknown): { jcsJson: string; hash: Hex } {\n const jcsJson = canonicalizeJson(obj);\n return {\n jcsJson,\n hash: keccak256(toUtf8Bytes(jcsJson)) as Hex\n };\n}\n\n/** @deprecated Use canonicalizeAndKeccak256 instead. */\nexport function canonicalizeForHash(obj: unknown): { jcsJson: string; hash: Hex } {\n return canonicalizeAndKeccak256(obj);\n}\n\nexport function hashCanonicalizedJson(obj: unknown, algorithm: \"keccak256\" | \"sha256\"): Hex {\n if (!VALID_ALGORITHMS.has(algorithm)) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Unsupported hash algorithm: \"${algorithm}\". Must be \"keccak256\" or \"sha256\".`, { algorithm });\n }\n const jcs = canonicalizeJson(obj);\n const bytes = toUtf8Bytes(jcs);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n","import { keccak256, sha256, toUtf8Bytes } from \"ethers\";\nimport { canonicalizeJson } from \"../identity/data\";\nimport { OmaTrustError } from \"../shared/errors\";\n\ntype Hex = `0x${string}`;\nexport type DataHashAlgorithm = \"keccak256\" | \"sha256\";\n\nasync function fetchJson(url: string): Promise<unknown> {\n let response: Response;\n try {\n response = await fetch(url, { headers: { Accept: \"application/json\" } });\n } catch (err) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", { url, err });\n }\n\n if (!response.ok) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch data URL\", {\n url,\n status: response.status\n });\n }\n\n try {\n return await response.json();\n } catch (err) {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Response body is not valid JSON\", { url, err });\n }\n}\n\nfunction hashJcs(jcsJson: string, algorithm: DataHashAlgorithm): Hex {\n const bytes = toUtf8Bytes(jcsJson);\n return (algorithm === \"keccak256\" ? keccak256(bytes) : sha256(bytes)) as Hex;\n}\n\nexport async function computeDataHashFromUrl(\n url: string,\n algorithm: DataHashAlgorithm\n): Promise<Hex> {\n if (!url || typeof url !== \"string\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"url must be a non-empty string\", { url });\n }\n\n if (algorithm !== \"keccak256\" && algorithm !== \"sha256\") {\n throw new OmaTrustError(\"INVALID_INPUT\", `Unsupported hash algorithm: \"${algorithm}\". Must be \"keccak256\" or \"sha256\".`, { algorithm });\n }\n\n const json = await fetchJson(url);\n const jcsJson = canonicalizeJson(json);\n return hashJcs(jcsJson, algorithm);\n}\n\nexport async function verifyDataUrlHash(\n url: string,\n expectedHash: Hex,\n algorithm: DataHashAlgorithm\n): Promise<boolean> {\n const computedHash = await computeDataHashFromUrl(url, algorithm);\n return computedHash.toLowerCase() === expectedHash.toLowerCase();\n}\n"]}
|