@hashgraphonline/standards-sdk 0.0.183 → 0.0.184
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/hcs-12/builders/action-builder.d.ts +5 -0
- package/dist/cjs/hcs-12/builders/action-builder.d.ts.map +1 -1
- package/dist/cjs/hcs-12/registries/action-registry.d.ts +5 -0
- package/dist/cjs/hcs-12/registries/action-registry.d.ts.map +1 -1
- package/dist/cjs/hcs-12/rendering/resource-manager.d.ts.map +1 -1
- package/dist/cjs/hcs-12/security/hash-verifier.d.ts +13 -0
- package/dist/cjs/hcs-12/security/hash-verifier.d.ts.map +1 -1
- package/dist/cjs/hcs-12/security/signature-verifier.d.ts +5 -0
- package/dist/cjs/hcs-12/security/signature-verifier.d.ts.map +1 -1
- package/dist/cjs/hcs-12/validation/wasm-validator.d.ts +5 -0
- package/dist/cjs/hcs-12/validation/wasm-validator.d.ts.map +1 -1
- package/dist/cjs/{index-Bw4Oab1n.cjs → index-DH8JqKpL.cjs} +21 -21
- package/dist/cjs/{index-Bw4Oab1n.cjs.map → index-DH8JqKpL.cjs.map} +1 -1
- package/dist/cjs/{index-DNOBUKZd-Dr1ocWcA.cjs → index-DNOBUKZd-DP8GdiGA.cjs} +2 -2
- package/dist/cjs/{index-DNOBUKZd-Dr1ocWcA.cjs.map → index-DNOBUKZd-DP8GdiGA.cjs.map} +1 -1
- package/dist/cjs/standards-sdk.cjs +1 -1
- package/dist/cjs/{standards-sdk.es47-LpJXpYet-BnuWNzh2.cjs → standards-sdk.es47-LpJXpYet-BEh9hyjN.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es47-LpJXpYet-BnuWNzh2.cjs.map → standards-sdk.es47-LpJXpYet-BEh9hyjN.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es48-PT6ZHlCU-vjsmk9LW.cjs → standards-sdk.es48-PT6ZHlCU-AWU0EkFj.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es48-PT6ZHlCU-vjsmk9LW.cjs.map → standards-sdk.es48-PT6ZHlCU-AWU0EkFj.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es49-BoFc-ELK-FTU4u19G.cjs → standards-sdk.es49-BoFc-ELK-Bz7Gd2qu.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es49-BoFc-ELK-FTU4u19G.cjs.map → standards-sdk.es49-BoFc-ELK-Bz7Gd2qu.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es50-miBtNmtl-WpmGw_oZ.cjs → standards-sdk.es50-miBtNmtl-DcjyhGyg.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es50-miBtNmtl-WpmGw_oZ.cjs.map → standards-sdk.es50-miBtNmtl-DcjyhGyg.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es51-rS2UvvV5-BQccIjC7.cjs → standards-sdk.es51-rS2UvvV5-Bmyu85K4.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es51-rS2UvvV5-BQccIjC7.cjs.map → standards-sdk.es51-rS2UvvV5-Bmyu85K4.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es52-D-lvSMBY-dV3DzoSL.cjs → standards-sdk.es52-D-lvSMBY-t0dhVZEE.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es52-D-lvSMBY-dV3DzoSL.cjs.map → standards-sdk.es52-D-lvSMBY-t0dhVZEE.cjs.map} +1 -1
- package/dist/cjs/utils/crypto-abstraction.d.ts +89 -0
- package/dist/cjs/utils/crypto-abstraction.d.ts.map +1 -0
- package/dist/cjs/utils/crypto-env.d.ts +25 -0
- package/dist/cjs/utils/crypto-env.d.ts.map +1 -0
- package/dist/cjs/utils/hash-adapter.d.ts +46 -0
- package/dist/cjs/utils/hash-adapter.d.ts.map +1 -0
- package/dist/es/hcs-12/builders/action-builder.d.ts +5 -0
- package/dist/es/hcs-12/builders/action-builder.d.ts.map +1 -1
- package/dist/es/hcs-12/registries/action-registry.d.ts +5 -0
- package/dist/es/hcs-12/registries/action-registry.d.ts.map +1 -1
- package/dist/es/hcs-12/rendering/resource-manager.d.ts.map +1 -1
- package/dist/es/hcs-12/security/hash-verifier.d.ts +13 -0
- package/dist/es/hcs-12/security/hash-verifier.d.ts.map +1 -1
- package/dist/es/hcs-12/security/signature-verifier.d.ts +5 -0
- package/dist/es/hcs-12/security/signature-verifier.d.ts.map +1 -1
- package/dist/es/hcs-12/validation/wasm-validator.d.ts +5 -0
- package/dist/es/hcs-12/validation/wasm-validator.d.ts.map +1 -1
- package/dist/es/standards-sdk.es11.js +1 -1
- package/dist/es/standards-sdk.es12.js +1 -1
- package/dist/es/standards-sdk.es13.js +1 -1
- package/dist/es/standards-sdk.es18.js +1 -1
- package/dist/es/standards-sdk.es22.js +49 -6
- package/dist/es/standards-sdk.es22.js.map +1 -1
- package/dist/es/standards-sdk.es25.js +0 -1
- package/dist/es/standards-sdk.es25.js.map +1 -1
- package/dist/es/standards-sdk.es26.js +1 -2
- package/dist/es/standards-sdk.es26.js.map +1 -1
- package/dist/es/standards-sdk.es27.js +1 -1
- package/dist/es/standards-sdk.es28.js +1 -1
- package/dist/es/standards-sdk.es29.js +36 -10
- package/dist/es/standards-sdk.es29.js.map +1 -1
- package/dist/es/standards-sdk.es32.js +20 -4
- package/dist/es/standards-sdk.es32.js.map +1 -1
- package/dist/es/standards-sdk.es37.js +9 -0
- package/dist/es/standards-sdk.es37.js.map +1 -1
- package/dist/es/standards-sdk.es46.js +1 -1
- package/dist/es/standards-sdk.es52.js +1 -1
- package/dist/es/standards-sdk.es59.js +7 -7
- package/dist/es/standards-sdk.es64.js +1 -1
- package/dist/es/standards-sdk.es65.js +1 -1
- package/dist/es/standards-sdk.es66.js +2 -2
- package/dist/es/standards-sdk.es72.js +2 -410
- package/dist/es/standards-sdk.es72.js.map +1 -1
- package/dist/es/standards-sdk.es74.js +410 -2
- package/dist/es/standards-sdk.es74.js.map +1 -1
- package/dist/es/standards-sdk.es75.js +2 -2
- package/dist/es/standards-sdk.es75.js.map +1 -1
- package/dist/es/standards-sdk.es76.js +188 -156
- package/dist/es/standards-sdk.es76.js.map +1 -1
- package/dist/es/standards-sdk.es77.js +139 -289
- package/dist/es/standards-sdk.es77.js.map +1 -1
- package/dist/es/standards-sdk.es78.js +274 -298
- package/dist/es/standards-sdk.es78.js.map +1 -1
- package/dist/es/standards-sdk.es79.js +262 -369
- package/dist/es/standards-sdk.es79.js.map +1 -1
- package/dist/es/standards-sdk.es80.js +316 -194
- package/dist/es/standards-sdk.es80.js.map +1 -1
- package/dist/es/standards-sdk.es81.js +328 -303
- package/dist/es/standards-sdk.es81.js.map +1 -1
- package/dist/es/standards-sdk.es82.js +302 -72
- package/dist/es/standards-sdk.es82.js.map +1 -1
- package/dist/es/standards-sdk.es83.js +66 -194
- package/dist/es/standards-sdk.es83.js.map +1 -1
- package/dist/es/standards-sdk.es91.js +202 -0
- package/dist/es/standards-sdk.es91.js.map +1 -0
- package/dist/es/standards-sdk.es92.js +37 -0
- package/dist/es/standards-sdk.es92.js.map +1 -0
- package/dist/es/standards-sdk.es93.js +81 -0
- package/dist/es/standards-sdk.es93.js.map +1 -0
- package/dist/es/utils/crypto-abstraction.d.ts +89 -0
- package/dist/es/utils/crypto-abstraction.d.ts.map +1 -0
- package/dist/es/utils/crypto-env.d.ts +25 -0
- package/dist/es/utils/crypto-env.d.ts.map +1 -0
- package/dist/es/utils/hash-adapter.d.ts +46 -0
- package/dist/es/utils/hash-adapter.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BaseRegistry } from "./standards-sdk.es21.js";
|
|
2
2
|
import { RegistryType } from "./standards-sdk.es20.js";
|
|
3
3
|
import { validateWithSchema, hashLinksRegistrationSchema } from "./standards-sdk.es33.js";
|
|
4
|
-
import "crypto";
|
|
5
4
|
class HashLinksRegistry extends BaseRegistry {
|
|
6
5
|
constructor(networkType, logger, topicId, client) {
|
|
7
6
|
super(networkType, logger, RegistryType.HASHLINKS, topicId, client);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es25.js","sources":["../../src/hcs-12/registries/hashlinks-registry.ts"],"sourcesContent":["/**\n * HashLinks Registry for HCS-12\n *\n * Manages the global directory of HashLinks assemblies.\n * This registry provides discovery and cataloging of available HashLinks.\n */\n\nimport { ILogger } from '../../utils/logger';\nimport { BaseRegistry } from './base-registry';\nimport {\n RegistryType,\n HashLinksRegistration,\n AssemblyRegistryEntry,\n} from '../types';\nimport { hashLinksRegistrationSchema } from '../validation/schemas';\nimport { validateWithSchema } from '../validation';\nimport type { NetworkType } from '../../utils/types';\nimport type { HCS12Client } from '../sdk';\nimport type { HCS12BrowserClient } from '../browser';\n\n/**\n * Registry for managing HashLinks directory entries\n */\nexport class HashLinksRegistry extends BaseRegistry {\n constructor(\n networkType: NetworkType,\n logger: ILogger,\n topicId?: string,\n client?: HCS12Client | HCS12BrowserClient,\n ) {\n super(networkType, logger, RegistryType.HASHLINKS, topicId, client);\n }\n\n /**\n * Register a new HashLink in the global directory\n */\n async register(data: HashLinksRegistration): Promise<string> {\n this.validateRegistration(data);\n\n const id = `${this.topicId || 'local'}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n const entry: AssemblyRegistryEntry = {\n id,\n sequenceNumber: 0,\n timestamp: new Date().toISOString(),\n submitter:\n this.client && 'getHashConnect' in this.client\n ? 'browser'\n : this.client?.getOperatorAccountId() || 'local',\n data,\n };\n\n this.entries.set(id, entry);\n\n if (this.client && this.topicId) {\n try {\n const message = JSON.stringify(data);\n const result = await this.client.submitMessage(this.topicId, message);\n\n if (result.sequenceNumber) {\n entry.sequenceNumber = result.sequenceNumber;\n entry.id = result.sequenceNumber.toString();\n this.entries.delete(id);\n this.entries.set(entry.id, entry);\n }\n\n this.logger.info('HashLink submitted to HCS', {\n transactionId: result.transactionId,\n sequenceNumber: result.sequenceNumber,\n topicId: this.topicId,\n });\n\n return entry.id;\n } catch (error) {\n this.logger.error('Failed to submit HashLink to HCS', { error });\n\n this.entries.delete(id);\n throw error;\n }\n }\n\n this.logger.info('HashLink registered in directory', {\n id,\n name: data.name,\n assemblyTopicId: data.t_id,\n tags: data.tags,\n });\n\n return id;\n }\n\n /**\n * Search HashLinks by tags\n */\n async searchByTags(tags: string[]): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(hashLink => {\n if (!hashLink.tags || hashLink.tags.length === 0) {\n return false;\n }\n return tags.some(tag => hashLink.tags?.includes(tag));\n });\n }\n\n /**\n * Search HashLinks by name (partial match)\n */\n async searchByName(searchTerm: string): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n const lowerSearchTerm = searchTerm.toLowerCase();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(\n hashLink =>\n hashLink.name.toLowerCase().includes(lowerSearchTerm) ||\n (hashLink.description?.toLowerCase().includes(lowerSearchTerm) ??\n false),\n );\n }\n\n /**\n * Get featured HashLinks\n */\n async getFeatured(): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(hashLink => hashLink.featured === true);\n }\n\n /**\n * Get HashLinks by category\n */\n async getByCategory(category: string): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(hashLink => hashLink.category === category);\n }\n\n /**\n * Get all unique categories\n */\n async getCategories(): Promise<string[]> {\n const entries = await this.listEntries();\n const categories = new Set<string>();\n\n entries.forEach(entry => {\n const hashLink = entry.data as HashLinksRegistration;\n if (hashLink.category) {\n categories.add(hashLink.category);\n }\n });\n\n return Array.from(categories).sort();\n }\n\n /**\n * Get all unique tags\n */\n async getAllTags(): Promise<string[]> {\n const entries = await this.listEntries();\n const tags = new Set<string>();\n\n entries.forEach(entry => {\n const hashLink = entry.data as HashLinksRegistration;\n if (hashLink.tags) {\n hashLink.tags.forEach(tag => tags.add(tag));\n }\n });\n\n return Array.from(tags).sort();\n }\n\n /**\n * Validate HashLinks registration data\n */\n private validateRegistration(data: HashLinksRegistration): void {\n this.validateBaseRegistration(data);\n\n const validation = validateWithSchema(data, hashLinksRegistrationSchema);\n if (!validation.isValid) {\n throw new Error(\n `HashLinks validation failed: ${validation.errors.join(', ')}`,\n );\n }\n\n if (!data.t_id || !data.t_id.match(/^\\d+\\.\\d+\\.\\d+$/)) {\n throw new Error('Valid assembly topic ID (t_id) is required');\n }\n\n if (data.tags && data.tags.length > 10) {\n throw new Error('Maximum 10 tags allowed');\n }\n\n if (data.name.length > 100) {\n throw new Error('Name must be 100 characters or less');\n }\n\n if (data.description && data.description.length > 500) {\n throw new Error('Description must be 500 characters or less');\n }\n }\n\n /**\n * Get registry statistics with HashLinks-specific metrics\n */\n getStats(): {\n entryCount: number;\n lastSync?: string;\n topicId?: string;\n registryType: string;\n categories: number;\n totalTags: number;\n featuredCount: number;\n } {\n const baseStats = super.getStats();\n const entries = Array.from(this.entries.values());\n\n const categories = new Set<string>();\n const tags = new Set<string>();\n let featuredCount = 0;\n\n entries.forEach(entry => {\n const hashLink = entry.data as HashLinksRegistration;\n if (hashLink.category) {\n categories.add(hashLink.category);\n }\n if (hashLink.tags) {\n hashLink.tags.forEach(tag => tags.add(tag));\n }\n if (hashLink.featured) {\n featuredCount++;\n }\n });\n\n return {\n ...baseStats,\n categories: categories.size,\n totalTags: tags.size,\n featuredCount,\n };\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es25.js","sources":["../../src/hcs-12/registries/hashlinks-registry.ts"],"sourcesContent":["/**\n * HashLinks Registry for HCS-12\n *\n * Manages the global directory of HashLinks assemblies.\n * This registry provides discovery and cataloging of available HashLinks.\n */\n\nimport { ILogger } from '../../utils/logger';\nimport { BaseRegistry } from './base-registry';\nimport {\n RegistryType,\n HashLinksRegistration,\n AssemblyRegistryEntry,\n} from '../types';\nimport { hashLinksRegistrationSchema } from '../validation/schemas';\nimport { validateWithSchema } from '../validation';\nimport type { NetworkType } from '../../utils/types';\nimport type { HCS12Client } from '../sdk';\nimport type { HCS12BrowserClient } from '../browser';\n\n/**\n * Registry for managing HashLinks directory entries\n */\nexport class HashLinksRegistry extends BaseRegistry {\n constructor(\n networkType: NetworkType,\n logger: ILogger,\n topicId?: string,\n client?: HCS12Client | HCS12BrowserClient,\n ) {\n super(networkType, logger, RegistryType.HASHLINKS, topicId, client);\n }\n\n /**\n * Register a new HashLink in the global directory\n */\n async register(data: HashLinksRegistration): Promise<string> {\n this.validateRegistration(data);\n\n const id = `${this.topicId || 'local'}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n const entry: AssemblyRegistryEntry = {\n id,\n sequenceNumber: 0,\n timestamp: new Date().toISOString(),\n submitter:\n this.client && 'getHashConnect' in this.client\n ? 'browser'\n : this.client?.getOperatorAccountId() || 'local',\n data,\n };\n\n this.entries.set(id, entry);\n\n if (this.client && this.topicId) {\n try {\n const message = JSON.stringify(data);\n const result = await this.client.submitMessage(this.topicId, message);\n\n if (result.sequenceNumber) {\n entry.sequenceNumber = result.sequenceNumber;\n entry.id = result.sequenceNumber.toString();\n this.entries.delete(id);\n this.entries.set(entry.id, entry);\n }\n\n this.logger.info('HashLink submitted to HCS', {\n transactionId: result.transactionId,\n sequenceNumber: result.sequenceNumber,\n topicId: this.topicId,\n });\n\n return entry.id;\n } catch (error) {\n this.logger.error('Failed to submit HashLink to HCS', { error });\n\n this.entries.delete(id);\n throw error;\n }\n }\n\n this.logger.info('HashLink registered in directory', {\n id,\n name: data.name,\n assemblyTopicId: data.t_id,\n tags: data.tags,\n });\n\n return id;\n }\n\n /**\n * Search HashLinks by tags\n */\n async searchByTags(tags: string[]): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(hashLink => {\n if (!hashLink.tags || hashLink.tags.length === 0) {\n return false;\n }\n return tags.some(tag => hashLink.tags?.includes(tag));\n });\n }\n\n /**\n * Search HashLinks by name (partial match)\n */\n async searchByName(searchTerm: string): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n const lowerSearchTerm = searchTerm.toLowerCase();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(\n hashLink =>\n hashLink.name.toLowerCase().includes(lowerSearchTerm) ||\n (hashLink.description?.toLowerCase().includes(lowerSearchTerm) ??\n false),\n );\n }\n\n /**\n * Get featured HashLinks\n */\n async getFeatured(): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(hashLink => hashLink.featured === true);\n }\n\n /**\n * Get HashLinks by category\n */\n async getByCategory(category: string): Promise<HashLinksRegistration[]> {\n const entries = await this.listEntries();\n\n return entries\n .map(entry => entry.data as HashLinksRegistration)\n .filter(hashLink => hashLink.category === category);\n }\n\n /**\n * Get all unique categories\n */\n async getCategories(): Promise<string[]> {\n const entries = await this.listEntries();\n const categories = new Set<string>();\n\n entries.forEach(entry => {\n const hashLink = entry.data as HashLinksRegistration;\n if (hashLink.category) {\n categories.add(hashLink.category);\n }\n });\n\n return Array.from(categories).sort();\n }\n\n /**\n * Get all unique tags\n */\n async getAllTags(): Promise<string[]> {\n const entries = await this.listEntries();\n const tags = new Set<string>();\n\n entries.forEach(entry => {\n const hashLink = entry.data as HashLinksRegistration;\n if (hashLink.tags) {\n hashLink.tags.forEach(tag => tags.add(tag));\n }\n });\n\n return Array.from(tags).sort();\n }\n\n /**\n * Validate HashLinks registration data\n */\n private validateRegistration(data: HashLinksRegistration): void {\n this.validateBaseRegistration(data);\n\n const validation = validateWithSchema(data, hashLinksRegistrationSchema);\n if (!validation.isValid) {\n throw new Error(\n `HashLinks validation failed: ${validation.errors.join(', ')}`,\n );\n }\n\n if (!data.t_id || !data.t_id.match(/^\\d+\\.\\d+\\.\\d+$/)) {\n throw new Error('Valid assembly topic ID (t_id) is required');\n }\n\n if (data.tags && data.tags.length > 10) {\n throw new Error('Maximum 10 tags allowed');\n }\n\n if (data.name.length > 100) {\n throw new Error('Name must be 100 characters or less');\n }\n\n if (data.description && data.description.length > 500) {\n throw new Error('Description must be 500 characters or less');\n }\n }\n\n /**\n * Get registry statistics with HashLinks-specific metrics\n */\n getStats(): {\n entryCount: number;\n lastSync?: string;\n topicId?: string;\n registryType: string;\n categories: number;\n totalTags: number;\n featuredCount: number;\n } {\n const baseStats = super.getStats();\n const entries = Array.from(this.entries.values());\n\n const categories = new Set<string>();\n const tags = new Set<string>();\n let featuredCount = 0;\n\n entries.forEach(entry => {\n const hashLink = entry.data as HashLinksRegistration;\n if (hashLink.category) {\n categories.add(hashLink.category);\n }\n if (hashLink.tags) {\n hashLink.tags.forEach(tag => tags.add(tag));\n }\n if (hashLink.featured) {\n featuredCount++;\n }\n });\n\n return {\n ...baseStats,\n categories: categories.size,\n totalTags: tags.size,\n featuredCount,\n };\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -5,9 +5,8 @@ import "@hashgraph/proto";
|
|
|
5
5
|
import "buffer";
|
|
6
6
|
import "@hashgraph/sdk";
|
|
7
7
|
import "ethers";
|
|
8
|
-
import "./standards-sdk.
|
|
8
|
+
import "./standards-sdk.es74.js";
|
|
9
9
|
import "file-type";
|
|
10
|
-
import "crypto";
|
|
11
10
|
import "./standards-sdk.es33.js";
|
|
12
11
|
import "zod";
|
|
13
12
|
import { BlockLoader } from "./standards-sdk.es23.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es26.js","sources":["../../src/hcs-12/base-client.ts"],"sourcesContent":["import { ILogger, Logger, LogLevel } from '../utils/logger';\nimport { NetworkType } from '../utils/types';\nimport { HederaMirrorNode, MirrorNodeConfig } from '../services';\nimport { PrivateKey, PublicKey } from '@hashgraph/sdk';\nimport {\n ActionRegistry,\n BlockLoader,\n AssemblyRegistry,\n HashLinksRegistry,\n} from './registries';\nimport {\n ActionRegistration,\n BlockDefinition,\n AssemblyRegistration,\n HashLinksRegistration,\n RegistryType,\n AssemblyState,\n} from './types';\nimport { AssemblyEngine, Assembly } from './assembly';\n\n/**\n * Configuration for HCS-12 client\n */\nexport interface HCS12Config {\n /** The Hedera network to connect to */\n network: NetworkType;\n /** Custom logger instance (if not provided, one will be created) */\n logger?: ILogger;\n /** Log level for the client (ignored if logger is provided) */\n logLevel?: LogLevel;\n /** Whether to pretty print logs (ignored if logger is provided) */\n prettyPrint?: boolean;\n /** Custom mirror node configuration */\n mirrorNode?: MirrorNodeConfig;\n /** Whether to run logger in silent mode (ignored if logger is provided) */\n silent?: boolean;\n /** The key type to use for the operator */\n keyType?: 'ed25519' | 'ecdsa';\n}\n\n/**\n * Abstract base class for HCS-12 HashLinks clients\n */\nexport abstract class HCS12BaseClient {\n protected network: NetworkType;\n protected logger: ILogger;\n public mirrorNode: HederaMirrorNode;\n\n protected _actionRegistry?: ActionRegistry;\n protected _blockLoader?: BlockLoader;\n protected _assemblyRegistry?: AssemblyRegistry;\n protected _hashLinksRegistry?: HashLinksRegistry;\n protected _assemblyEngine?: AssemblyEngine;\n\n protected actionRegistryTopicId?: string;\n protected _assemblyRegistryTopicId?: string;\n protected _hashLinksRegistryTopicId?: string;\n\n constructor(config: HCS12Config) {\n this.network = config.network;\n\n this.logger =\n config.logger ||\n Logger.getInstance({\n level: config.logLevel || 'info',\n module: 'HCS12-BaseClient',\n prettyPrint: config.prettyPrint,\n silent: config.silent,\n });\n\n this.mirrorNode = new HederaMirrorNode(\n config.network,\n this.logger,\n config.mirrorNode,\n );\n }\n\n /**\n * Initialize registries with optional existing topic IDs\n */\n protected initializeRegistries(topicIds?: {\n action?: string;\n assembly?: string;\n hashlinks?: string;\n }): void {\n this.actionRegistryTopicId = topicIds?.action;\n this._assemblyRegistryTopicId = topicIds?.assembly;\n this._hashLinksRegistryTopicId = topicIds?.hashlinks;\n }\n\n /**\n * Create a new HCS topic for a registry\n */\n abstract createRegistryTopic(\n registryType: RegistryType,\n adminKey?: boolean | PublicKey,\n submitKey?: boolean | PublicKey,\n ): Promise<string>;\n\n /**\n * Submit a message to an HCS topic\n */\n abstract submitMessage(\n topicId: string,\n message: string,\n submitKey?: PrivateKey,\n ): Promise<{ transactionId: string; sequenceNumber?: number }>;\n\n /**\n * Register a new assembly in the assembly registry\n */\n async registerAssembly(\n registration: AssemblyRegistration,\n ): Promise<{ id: string; transactionId?: string }> {\n if (!this._assemblyRegistry) {\n throw new Error('Assembly registry not initialized');\n }\n\n const id = await this._assemblyRegistry.register(registration);\n return { id };\n }\n\n /**\n * Get action by hash\n */\n async getAction(hash: string): Promise<ActionRegistration | null> {\n if (!this._actionRegistry) {\n throw new Error('Action registry not initialized');\n }\n\n return this._actionRegistry.getAction(hash);\n }\n\n /**\n * Load block from HCS-1\n */\n async loadBlock(blockTopicId: string): Promise<{\n definition: BlockDefinition;\n template: string;\n }> {\n if (!this._blockLoader) {\n this._blockLoader = new BlockLoader(\n this.network,\n this.logger,\n this as any,\n );\n }\n\n return this._blockLoader.loadBlock(blockTopicId);\n }\n\n /**\n * Get assembly by name and version\n */\n async getAssembly(\n name: string,\n version: string,\n ): Promise<AssemblyState | null> {\n if (!this._assemblyRegistry) {\n throw new Error('Assembly registry not initialized');\n }\n\n const entries = await this._assemblyRegistry.listEntries();\n for (const entry of entries) {\n const state = await this._assemblyRegistry.getAssemblyState(entry.id);\n if (state && state.name === name && state.version === version) {\n return state;\n }\n }\n return null;\n }\n\n /**\n * Load and resolve a complete assembly by topic ID\n */\n async loadAssembly(topicId: string): Promise<Assembly> {\n if (this._actionRegistry) {\n this.logger.info('Syncing action registry before loading assembly');\n await this._actionRegistry.sync();\n }\n\n const assemblyRegistry = new AssemblyRegistry(\n this.network,\n this.logger,\n topicId,\n this as any,\n );\n\n await assemblyRegistry.sync();\n\n const assemblyEngine = new AssemblyEngine(\n this.logger,\n assemblyRegistry,\n this._actionRegistry!,\n this._blockLoader!,\n );\n\n return assemblyEngine.loadAndResolveAssembly(topicId);\n }\n\n /**\n * Get assembly state by topic ID (without resolving references)\n */\n async getAssemblyState(topicId: string): Promise<AssemblyState | null> {\n if (!this._assemblyRegistry) {\n throw new Error('Assembly registry not initialized');\n }\n return this._assemblyRegistry.getAssemblyState(topicId);\n }\n\n /**\n * Ensure assembly engine is initialized\n */\n protected ensureAssemblyEngine(): void {\n if (!this._assemblyEngine) {\n if (\n !this._actionRegistry ||\n !this._blockLoader ||\n !this._assemblyRegistry\n ) {\n throw new Error(\n 'Registries must be initialized before assembly engine',\n );\n }\n this._assemblyEngine = new AssemblyEngine(\n this.logger,\n this._assemblyRegistry,\n this._actionRegistry,\n this._blockLoader,\n );\n }\n }\n\n /**\n * Register a new HashLink in the global directory\n */\n async registerHashLink(\n registration: HashLinksRegistration,\n ): Promise<{ id: string; transactionId?: string }> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n const id = await this._hashLinksRegistry.register(registration);\n return { id };\n }\n\n /**\n * Search HashLinks by tags\n */\n async searchHashLinksByTags(\n tags: string[],\n ): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.searchByTags(tags);\n }\n\n /**\n * Search HashLinks by name\n */\n async searchHashLinksByName(\n searchTerm: string,\n ): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.searchByName(searchTerm);\n }\n\n /**\n * Get featured HashLinks\n */\n async getFeaturedHashLinks(): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.getFeatured();\n }\n\n /**\n * Get HashLinks by category\n */\n async getHashLinksByCategory(\n category: string,\n ): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.getByCategory(category);\n }\n\n /**\n * Sync all registries with the network\n */\n async syncRegistries(): Promise<void> {\n const promises: Promise<void>[] = [];\n\n if (this._actionRegistry) {\n promises.push(this._actionRegistry.sync());\n }\n if (this._assemblyRegistry) {\n promises.push(this._assemblyRegistry.sync());\n }\n if (this._hashLinksRegistry) {\n promises.push(this._hashLinksRegistry.sync());\n }\n\n await Promise.all(promises);\n }\n\n /**\n * Get registry topic IDs\n */\n getRegistryTopicIds(): {\n action?: string;\n assembly?: string;\n hashlinks?: string;\n } {\n return {\n action: this.actionRegistryTopicId,\n assembly: this._assemblyRegistryTopicId,\n hashlinks: this._hashLinksRegistryTopicId,\n };\n }\n\n /**\n * Clear all registry caches\n */\n clearCaches(): void {\n this._actionRegistry?.clearCache();\n this._blockLoader?.clearCache();\n this._assemblyRegistry?.clearCache();\n this._hashLinksRegistry?.clearCache();\n }\n\n /**\n * Get the action registry instance\n */\n get actionRegistry(): ActionRegistry | undefined {\n return this._actionRegistry;\n }\n\n /**\n * Get the block loader instance\n */\n get blockLoader(): BlockLoader | undefined {\n return this._blockLoader;\n }\n\n /**\n * Get the assembly registry instance\n */\n get assemblyRegistry(): AssemblyRegistry | undefined {\n return this._assemblyRegistry;\n }\n\n /**\n * Get the HashLinks registry instance\n */\n get hashLinksRegistry(): HashLinksRegistry | undefined {\n return this._hashLinksRegistry;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es26.js","sources":["../../src/hcs-12/base-client.ts"],"sourcesContent":["import { ILogger, Logger, LogLevel } from '../utils/logger';\nimport { NetworkType } from '../utils/types';\nimport { HederaMirrorNode, MirrorNodeConfig } from '../services';\nimport { PrivateKey, PublicKey } from '@hashgraph/sdk';\nimport {\n ActionRegistry,\n BlockLoader,\n AssemblyRegistry,\n HashLinksRegistry,\n} from './registries';\nimport {\n ActionRegistration,\n BlockDefinition,\n AssemblyRegistration,\n HashLinksRegistration,\n RegistryType,\n AssemblyState,\n} from './types';\nimport { AssemblyEngine, Assembly } from './assembly';\n\n/**\n * Configuration for HCS-12 client\n */\nexport interface HCS12Config {\n /** The Hedera network to connect to */\n network: NetworkType;\n /** Custom logger instance (if not provided, one will be created) */\n logger?: ILogger;\n /** Log level for the client (ignored if logger is provided) */\n logLevel?: LogLevel;\n /** Whether to pretty print logs (ignored if logger is provided) */\n prettyPrint?: boolean;\n /** Custom mirror node configuration */\n mirrorNode?: MirrorNodeConfig;\n /** Whether to run logger in silent mode (ignored if logger is provided) */\n silent?: boolean;\n /** The key type to use for the operator */\n keyType?: 'ed25519' | 'ecdsa';\n}\n\n/**\n * Abstract base class for HCS-12 HashLinks clients\n */\nexport abstract class HCS12BaseClient {\n protected network: NetworkType;\n protected logger: ILogger;\n public mirrorNode: HederaMirrorNode;\n\n protected _actionRegistry?: ActionRegistry;\n protected _blockLoader?: BlockLoader;\n protected _assemblyRegistry?: AssemblyRegistry;\n protected _hashLinksRegistry?: HashLinksRegistry;\n protected _assemblyEngine?: AssemblyEngine;\n\n protected actionRegistryTopicId?: string;\n protected _assemblyRegistryTopicId?: string;\n protected _hashLinksRegistryTopicId?: string;\n\n constructor(config: HCS12Config) {\n this.network = config.network;\n\n this.logger =\n config.logger ||\n Logger.getInstance({\n level: config.logLevel || 'info',\n module: 'HCS12-BaseClient',\n prettyPrint: config.prettyPrint,\n silent: config.silent,\n });\n\n this.mirrorNode = new HederaMirrorNode(\n config.network,\n this.logger,\n config.mirrorNode,\n );\n }\n\n /**\n * Initialize registries with optional existing topic IDs\n */\n protected initializeRegistries(topicIds?: {\n action?: string;\n assembly?: string;\n hashlinks?: string;\n }): void {\n this.actionRegistryTopicId = topicIds?.action;\n this._assemblyRegistryTopicId = topicIds?.assembly;\n this._hashLinksRegistryTopicId = topicIds?.hashlinks;\n }\n\n /**\n * Create a new HCS topic for a registry\n */\n abstract createRegistryTopic(\n registryType: RegistryType,\n adminKey?: boolean | PublicKey,\n submitKey?: boolean | PublicKey,\n ): Promise<string>;\n\n /**\n * Submit a message to an HCS topic\n */\n abstract submitMessage(\n topicId: string,\n message: string,\n submitKey?: PrivateKey,\n ): Promise<{ transactionId: string; sequenceNumber?: number }>;\n\n /**\n * Register a new assembly in the assembly registry\n */\n async registerAssembly(\n registration: AssemblyRegistration,\n ): Promise<{ id: string; transactionId?: string }> {\n if (!this._assemblyRegistry) {\n throw new Error('Assembly registry not initialized');\n }\n\n const id = await this._assemblyRegistry.register(registration);\n return { id };\n }\n\n /**\n * Get action by hash\n */\n async getAction(hash: string): Promise<ActionRegistration | null> {\n if (!this._actionRegistry) {\n throw new Error('Action registry not initialized');\n }\n\n return this._actionRegistry.getAction(hash);\n }\n\n /**\n * Load block from HCS-1\n */\n async loadBlock(blockTopicId: string): Promise<{\n definition: BlockDefinition;\n template: string;\n }> {\n if (!this._blockLoader) {\n this._blockLoader = new BlockLoader(\n this.network,\n this.logger,\n this as any,\n );\n }\n\n return this._blockLoader.loadBlock(blockTopicId);\n }\n\n /**\n * Get assembly by name and version\n */\n async getAssembly(\n name: string,\n version: string,\n ): Promise<AssemblyState | null> {\n if (!this._assemblyRegistry) {\n throw new Error('Assembly registry not initialized');\n }\n\n const entries = await this._assemblyRegistry.listEntries();\n for (const entry of entries) {\n const state = await this._assemblyRegistry.getAssemblyState(entry.id);\n if (state && state.name === name && state.version === version) {\n return state;\n }\n }\n return null;\n }\n\n /**\n * Load and resolve a complete assembly by topic ID\n */\n async loadAssembly(topicId: string): Promise<Assembly> {\n if (this._actionRegistry) {\n this.logger.info('Syncing action registry before loading assembly');\n await this._actionRegistry.sync();\n }\n\n const assemblyRegistry = new AssemblyRegistry(\n this.network,\n this.logger,\n topicId,\n this as any,\n );\n\n await assemblyRegistry.sync();\n\n const assemblyEngine = new AssemblyEngine(\n this.logger,\n assemblyRegistry,\n this._actionRegistry!,\n this._blockLoader!,\n );\n\n return assemblyEngine.loadAndResolveAssembly(topicId);\n }\n\n /**\n * Get assembly state by topic ID (without resolving references)\n */\n async getAssemblyState(topicId: string): Promise<AssemblyState | null> {\n if (!this._assemblyRegistry) {\n throw new Error('Assembly registry not initialized');\n }\n return this._assemblyRegistry.getAssemblyState(topicId);\n }\n\n /**\n * Ensure assembly engine is initialized\n */\n protected ensureAssemblyEngine(): void {\n if (!this._assemblyEngine) {\n if (\n !this._actionRegistry ||\n !this._blockLoader ||\n !this._assemblyRegistry\n ) {\n throw new Error(\n 'Registries must be initialized before assembly engine',\n );\n }\n this._assemblyEngine = new AssemblyEngine(\n this.logger,\n this._assemblyRegistry,\n this._actionRegistry,\n this._blockLoader,\n );\n }\n }\n\n /**\n * Register a new HashLink in the global directory\n */\n async registerHashLink(\n registration: HashLinksRegistration,\n ): Promise<{ id: string; transactionId?: string }> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n const id = await this._hashLinksRegistry.register(registration);\n return { id };\n }\n\n /**\n * Search HashLinks by tags\n */\n async searchHashLinksByTags(\n tags: string[],\n ): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.searchByTags(tags);\n }\n\n /**\n * Search HashLinks by name\n */\n async searchHashLinksByName(\n searchTerm: string,\n ): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.searchByName(searchTerm);\n }\n\n /**\n * Get featured HashLinks\n */\n async getFeaturedHashLinks(): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.getFeatured();\n }\n\n /**\n * Get HashLinks by category\n */\n async getHashLinksByCategory(\n category: string,\n ): Promise<HashLinksRegistration[]> {\n if (!this._hashLinksRegistry) {\n throw new Error('HashLinks registry not initialized');\n }\n\n return this._hashLinksRegistry.getByCategory(category);\n }\n\n /**\n * Sync all registries with the network\n */\n async syncRegistries(): Promise<void> {\n const promises: Promise<void>[] = [];\n\n if (this._actionRegistry) {\n promises.push(this._actionRegistry.sync());\n }\n if (this._assemblyRegistry) {\n promises.push(this._assemblyRegistry.sync());\n }\n if (this._hashLinksRegistry) {\n promises.push(this._hashLinksRegistry.sync());\n }\n\n await Promise.all(promises);\n }\n\n /**\n * Get registry topic IDs\n */\n getRegistryTopicIds(): {\n action?: string;\n assembly?: string;\n hashlinks?: string;\n } {\n return {\n action: this.actionRegistryTopicId,\n assembly: this._assemblyRegistryTopicId,\n hashlinks: this._hashLinksRegistryTopicId,\n };\n }\n\n /**\n * Clear all registry caches\n */\n clearCaches(): void {\n this._actionRegistry?.clearCache();\n this._blockLoader?.clearCache();\n this._assemblyRegistry?.clearCache();\n this._hashLinksRegistry?.clearCache();\n }\n\n /**\n * Get the action registry instance\n */\n get actionRegistry(): ActionRegistry | undefined {\n return this._actionRegistry;\n }\n\n /**\n * Get the block loader instance\n */\n get blockLoader(): BlockLoader | undefined {\n return this._blockLoader;\n }\n\n /**\n * Get the assembly registry instance\n */\n get assemblyRegistry(): AssemblyRegistry | undefined {\n return this._assemblyRegistry;\n }\n\n /**\n * Get the HashLinks registry instance\n */\n get hashLinksRegistry(): HashLinksRegistry | undefined {\n return this._hashLinksRegistry;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import "axios";
|
|
|
5
5
|
import "@hashgraph/proto";
|
|
6
6
|
import "buffer";
|
|
7
7
|
import "ethers";
|
|
8
|
-
import "./standards-sdk.
|
|
8
|
+
import "./standards-sdk.es74.js";
|
|
9
9
|
import { detectKeyTypeFromString } from "./standards-sdk.es62.js";
|
|
10
10
|
import { RegistryType } from "./standards-sdk.es20.js";
|
|
11
11
|
import { inscribe } from "./standards-sdk.es66.js";
|
|
@@ -6,7 +6,7 @@ import "./standards-sdk.es54.js";
|
|
|
6
6
|
import "@hashgraph/proto";
|
|
7
7
|
import "buffer";
|
|
8
8
|
import "ethers";
|
|
9
|
-
import "./standards-sdk.
|
|
9
|
+
import "./standards-sdk.es74.js";
|
|
10
10
|
import "file-type";
|
|
11
11
|
import { ActionRegistry } from "./standards-sdk.es22.js";
|
|
12
12
|
import { BlockLoader } from "./standards-sdk.es23.js";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCryptoAdapter } from "./standards-sdk.es91.js";
|
|
2
|
+
import { isSSREnvironment } from "./standards-sdk.es92.js";
|
|
2
3
|
class ActionBuilder {
|
|
3
4
|
constructor(logger) {
|
|
5
|
+
this.cryptoAdapter = getCryptoAdapter();
|
|
4
6
|
this.logger = logger;
|
|
5
7
|
this.registration = {
|
|
6
8
|
p: "hcs-12",
|
|
@@ -152,26 +154,50 @@ class ActionBuilder {
|
|
|
152
154
|
* Generate WASM hash from binary data
|
|
153
155
|
*/
|
|
154
156
|
async generateWasmHash(wasmData) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
157
|
+
if (isSSREnvironment()) {
|
|
158
|
+
return this.createSSRSafeHash(wasmData, "wasm");
|
|
159
|
+
}
|
|
160
|
+
const hasher = this.cryptoAdapter.createHash("sha256");
|
|
161
|
+
const result = hasher.update(Buffer.from(wasmData)).digest("hex");
|
|
162
|
+
const hash = result instanceof Promise ? await result : result;
|
|
163
|
+
return typeof hash === "string" ? hash : hash.toString("hex");
|
|
158
164
|
}
|
|
159
165
|
/**
|
|
160
166
|
* Generate INFO hash from module info
|
|
161
167
|
*/
|
|
162
168
|
async generateInfoHash(info) {
|
|
163
|
-
const hash = createHash("sha256");
|
|
164
169
|
const infoJson = JSON.stringify(info, Object.keys(info).sort());
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
if (isSSREnvironment()) {
|
|
171
|
+
return this.createSSRSafeHash(Buffer.from(infoJson), "info");
|
|
172
|
+
}
|
|
173
|
+
const hasher = this.cryptoAdapter.createHash("sha256");
|
|
174
|
+
const result = hasher.update(Buffer.from(infoJson)).digest("hex");
|
|
175
|
+
const hash = result instanceof Promise ? await result : result;
|
|
176
|
+
return typeof hash === "string" ? hash : hash.toString("hex");
|
|
167
177
|
}
|
|
168
178
|
/**
|
|
169
179
|
* Calculate hash for any data
|
|
170
180
|
*/
|
|
171
181
|
async calculateHash(data) {
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
182
|
+
const buffer = typeof data === "string" ? Buffer.from(data) : data instanceof Uint8Array ? Buffer.from(data) : data;
|
|
183
|
+
if (isSSREnvironment()) {
|
|
184
|
+
return this.createSSRSafeHash(buffer, "data");
|
|
185
|
+
}
|
|
186
|
+
const hasher = this.cryptoAdapter.createHash("sha256");
|
|
187
|
+
const result = hasher.update(buffer).digest("hex");
|
|
188
|
+
const hash = result instanceof Promise ? await result : result;
|
|
189
|
+
return typeof hash === "string" ? hash : hash.toString("hex");
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Create SSR-safe hash
|
|
193
|
+
*/
|
|
194
|
+
createSSRSafeHash(data, type) {
|
|
195
|
+
const buffer = data instanceof Uint8Array ? Buffer.from(data) : data;
|
|
196
|
+
let hash = 0;
|
|
197
|
+
for (let i = 0; i < Math.min(buffer.length, 256); i++) {
|
|
198
|
+
hash = (hash << 5) - hash + buffer[i] & 4294967295;
|
|
199
|
+
}
|
|
200
|
+
return `ssr-${type}-${buffer.length}-${Math.abs(hash).toString(16).padStart(8, "0")}`;
|
|
175
201
|
}
|
|
176
202
|
/**
|
|
177
203
|
* Create registration from WASM and INFO data
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es29.js","sources":["../../src/hcs-12/builders/action-builder.ts"],"sourcesContent":["/**\n * ActionBuilder utility for creating HCS-12 action registrations\n */\n\nimport { createHash } from 'crypto';\nimport { Logger } from '../../utils/logger';\nimport {\n ActionRegistration,\n SourceVerification,\n ValidationRule,\n ModuleInfo,\n} from '../types';\n\nexport interface BuildOptions {\n validate?: boolean;\n}\n\n/**\n * Builder for creating action registrations with validation\n */\nexport class ActionBuilder {\n private logger: Logger;\n private registration: Partial<ActionRegistration>;\n private alias?: string;\n\n constructor(logger: Logger) {\n this.logger = logger;\n this.registration = {\n p: 'hcs-12',\n op: 'register',\n };\n }\n\n /**\n * Set HCS-1 topic ID for WASM storage\n */\n setTopicId(topicId: string): ActionBuilder {\n if (!this.isValidTopicId(topicId)) {\n throw new Error('Invalid topic ID format');\n }\n this.registration.t_id = topicId;\n return this;\n }\n\n /**\n * Set alias for this action in the assembly\n */\n setAlias(alias: string): ActionBuilder {\n this.alias = alias;\n return this;\n }\n\n /**\n * Set INFO hash\n */\n setHash(hash: string): ActionBuilder {\n if (!this.isValidHash(hash)) {\n throw new Error('Invalid hash format');\n }\n this.registration.hash = hash;\n return this;\n }\n\n /**\n * Set WASM hash\n */\n setWasmHash(hash: string): ActionBuilder {\n if (!this.isValidHash(hash)) {\n throw new Error('Invalid hash format');\n }\n this.registration.wasm_hash = hash;\n return this;\n }\n\n /**\n * Set optional INFO topic ID\n */\n setInfoTopicId(topicId: string): ActionBuilder {\n if (!this.isValidTopicId(topicId)) {\n throw new Error('Invalid topic ID format');\n }\n this.registration.info_t_id = topicId;\n return this;\n }\n\n /**\n * Set JavaScript wrapper topic ID\n */\n setJsTopicId(topicId: string): ActionBuilder {\n if (!this.isValidTopicId(topicId)) {\n throw new Error('Invalid topic ID format');\n }\n this.registration.js_t_id = topicId;\n return this;\n }\n\n /**\n * Set JavaScript wrapper hash\n */\n setJsHash(hash: string): ActionBuilder {\n if (!this.isValidHash(hash)) {\n throw new Error('Invalid hash format');\n }\n this.registration.js_hash = hash;\n return this;\n }\n\n /**\n * Set interface version (wasm-bindgen version)\n */\n setInterfaceVersion(version: string): ActionBuilder {\n if (!this.isValidVersion(version)) {\n throw new Error('Invalid version format');\n }\n this.registration.interface_version = version;\n return this;\n }\n\n /**\n * Add validation rule for an action\n */\n addValidationRule(action: string, rule: ValidationRule): ActionBuilder {\n if (!this.registration.validation_rules) {\n this.registration.validation_rules = {};\n }\n this.registration.validation_rules[action] = rule;\n return this;\n }\n\n /**\n * Set source verification data\n */\n setSourceVerification(verification: SourceVerification): ActionBuilder {\n if (!this.isValidTopicId(verification.source_t_id)) {\n throw new Error('Invalid source topic ID');\n }\n if (!this.isValidHash(verification.source_hash)) {\n throw new Error('Invalid source hash');\n }\n if (verification.target !== 'wasm32-unknown-unknown') {\n throw new Error('Invalid compilation target');\n }\n this.registration.source_verification = verification;\n return this;\n }\n\n /**\n * Build the action registration\n */\n build(options: BuildOptions = { validate: true }): ActionRegistration {\n if (options.validate !== false) {\n this.validate();\n }\n\n return { ...this.registration } as ActionRegistration;\n }\n\n /**\n * Reset the builder\n */\n reset(): ActionBuilder {\n this.registration = {\n p: 'hcs-12',\n op: 'register',\n };\n this.alias = undefined;\n return this;\n }\n\n /**\n * Get the alias\n */\n getAlias(): string {\n if (!this.alias) {\n throw new Error('Action alias not set');\n }\n return this.alias;\n }\n\n /**\n * Get the topic ID\n */\n getTopicId(): string {\n if (!this.registration.t_id) {\n throw new Error('Action topic ID not set');\n }\n return this.registration.t_id;\n }\n\n /**\n * Generate WASM hash from binary data\n */\n async generateWasmHash(wasmData: Uint8Array): Promise<string> {\n const hash = createHash('sha256');\n hash.update(wasmData);\n return hash.digest('hex');\n }\n\n /**\n * Generate INFO hash from module info\n */\n async generateInfoHash(info: ModuleInfo): Promise<string> {\n const hash = createHash('sha256');\n const infoJson = JSON.stringify(info, Object.keys(info).sort());\n hash.update(infoJson);\n return hash.digest('hex');\n }\n\n /**\n * Calculate hash for any data\n */\n async calculateHash(data: Uint8Array | Buffer | string): Promise<string> {\n const hash = createHash('sha256');\n hash.update(data);\n return hash.digest('hex');\n }\n\n /**\n * Create registration from WASM and INFO data\n */\n async createFromWasmAndInfo(\n topicId: string,\n wasmData: Uint8Array,\n info: ModuleInfo,\n ): Promise<ActionRegistration> {\n const wasmHash = await this.generateWasmHash(wasmData);\n const infoHash = await this.generateInfoHash(info);\n\n const jsTopicId = this.registration.js_t_id;\n const jsHash = this.registration.js_hash;\n const interfaceVersion = this.registration.interface_version;\n\n this.reset().setTopicId(topicId).setHash(infoHash).setWasmHash(wasmHash);\n\n if (jsTopicId) this.setJsTopicId(jsTopicId);\n if (jsHash) this.setJsHash(jsHash);\n if (interfaceVersion) this.setInterfaceVersion(interfaceVersion);\n\n return this.build();\n }\n\n /**\n * Check if registration is complete\n */\n isComplete(registration: Partial<ActionRegistration>): boolean {\n return !!(\n registration.p === 'hcs-12' &&\n registration.op === 'register' &&\n registration.t_id &&\n registration.hash &&\n registration.wasm_hash\n );\n }\n\n /**\n * Validate the current registration\n */\n private validate(): void {\n if (!this.registration.t_id) {\n throw new Error('Topic ID is required');\n }\n if (!this.registration.hash) {\n throw new Error('INFO hash is required');\n }\n if (!this.registration.wasm_hash) {\n throw new Error('WASM hash is required');\n }\n }\n\n /**\n * Validate topic ID format\n */\n private isValidTopicId(topicId: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(topicId);\n }\n\n /**\n * Validate hash format\n */\n private isValidHash(hash: string): boolean {\n return /^[a-f0-9]{64}$/.test(hash);\n }\n\n /**\n * Validate semantic version format\n */\n private isValidVersion(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(version);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es29.js","sources":["../../src/hcs-12/builders/action-builder.ts"],"sourcesContent":["/**\n * ActionBuilder utility for creating HCS-12 action registrations\n */\n\nimport { Logger } from '../../utils/logger';\nimport { getCryptoAdapter } from '../../utils/crypto-abstraction';\nimport { isSSREnvironment } from '../../utils/crypto-env';\nimport {\n ActionRegistration,\n SourceVerification,\n ValidationRule,\n ModuleInfo,\n} from '../types';\n\nexport interface BuildOptions {\n validate?: boolean;\n}\n\n/**\n * Builder for creating action registrations with validation\n */\nexport class ActionBuilder {\n private logger: Logger;\n private registration: Partial<ActionRegistration>;\n private alias?: string;\n private cryptoAdapter = getCryptoAdapter();\n\n constructor(logger: Logger) {\n this.logger = logger;\n this.registration = {\n p: 'hcs-12',\n op: 'register',\n };\n }\n\n /**\n * Set HCS-1 topic ID for WASM storage\n */\n setTopicId(topicId: string): ActionBuilder {\n if (!this.isValidTopicId(topicId)) {\n throw new Error('Invalid topic ID format');\n }\n this.registration.t_id = topicId;\n return this;\n }\n\n /**\n * Set alias for this action in the assembly\n */\n setAlias(alias: string): ActionBuilder {\n this.alias = alias;\n return this;\n }\n\n /**\n * Set INFO hash\n */\n setHash(hash: string): ActionBuilder {\n if (!this.isValidHash(hash)) {\n throw new Error('Invalid hash format');\n }\n this.registration.hash = hash;\n return this;\n }\n\n /**\n * Set WASM hash\n */\n setWasmHash(hash: string): ActionBuilder {\n if (!this.isValidHash(hash)) {\n throw new Error('Invalid hash format');\n }\n this.registration.wasm_hash = hash;\n return this;\n }\n\n /**\n * Set optional INFO topic ID\n */\n setInfoTopicId(topicId: string): ActionBuilder {\n if (!this.isValidTopicId(topicId)) {\n throw new Error('Invalid topic ID format');\n }\n this.registration.info_t_id = topicId;\n return this;\n }\n\n /**\n * Set JavaScript wrapper topic ID\n */\n setJsTopicId(topicId: string): ActionBuilder {\n if (!this.isValidTopicId(topicId)) {\n throw new Error('Invalid topic ID format');\n }\n this.registration.js_t_id = topicId;\n return this;\n }\n\n /**\n * Set JavaScript wrapper hash\n */\n setJsHash(hash: string): ActionBuilder {\n if (!this.isValidHash(hash)) {\n throw new Error('Invalid hash format');\n }\n this.registration.js_hash = hash;\n return this;\n }\n\n /**\n * Set interface version (wasm-bindgen version)\n */\n setInterfaceVersion(version: string): ActionBuilder {\n if (!this.isValidVersion(version)) {\n throw new Error('Invalid version format');\n }\n this.registration.interface_version = version;\n return this;\n }\n\n /**\n * Add validation rule for an action\n */\n addValidationRule(action: string, rule: ValidationRule): ActionBuilder {\n if (!this.registration.validation_rules) {\n this.registration.validation_rules = {};\n }\n this.registration.validation_rules[action] = rule;\n return this;\n }\n\n /**\n * Set source verification data\n */\n setSourceVerification(verification: SourceVerification): ActionBuilder {\n if (!this.isValidTopicId(verification.source_t_id)) {\n throw new Error('Invalid source topic ID');\n }\n if (!this.isValidHash(verification.source_hash)) {\n throw new Error('Invalid source hash');\n }\n if (verification.target !== 'wasm32-unknown-unknown') {\n throw new Error('Invalid compilation target');\n }\n this.registration.source_verification = verification;\n return this;\n }\n\n /**\n * Build the action registration\n */\n build(options: BuildOptions = { validate: true }): ActionRegistration {\n if (options.validate !== false) {\n this.validate();\n }\n\n return { ...this.registration } as ActionRegistration;\n }\n\n /**\n * Reset the builder\n */\n reset(): ActionBuilder {\n this.registration = {\n p: 'hcs-12',\n op: 'register',\n };\n this.alias = undefined;\n return this;\n }\n\n /**\n * Get the alias\n */\n getAlias(): string {\n if (!this.alias) {\n throw new Error('Action alias not set');\n }\n return this.alias;\n }\n\n /**\n * Get the topic ID\n */\n getTopicId(): string {\n if (!this.registration.t_id) {\n throw new Error('Action topic ID not set');\n }\n return this.registration.t_id;\n }\n\n /**\n * Generate WASM hash from binary data\n */\n async generateWasmHash(wasmData: Uint8Array): Promise<string> {\n if (isSSREnvironment()) {\n return this.createSSRSafeHash(wasmData, 'wasm');\n }\n\n const hasher = this.cryptoAdapter.createHash('sha256');\n const result = hasher.update(Buffer.from(wasmData)).digest('hex');\n const hash = result instanceof Promise ? await result : result;\n return typeof hash === 'string' ? hash : hash.toString('hex');\n }\n\n /**\n * Generate INFO hash from module info\n */\n async generateInfoHash(info: ModuleInfo): Promise<string> {\n const infoJson = JSON.stringify(info, Object.keys(info).sort());\n \n if (isSSREnvironment()) {\n return this.createSSRSafeHash(Buffer.from(infoJson), 'info');\n }\n\n const hasher = this.cryptoAdapter.createHash('sha256');\n const result = hasher.update(Buffer.from(infoJson)).digest('hex');\n const hash = result instanceof Promise ? await result : result;\n return typeof hash === 'string' ? hash : hash.toString('hex');\n }\n\n /**\n * Calculate hash for any data\n */\n async calculateHash(data: Uint8Array | Buffer | string): Promise<string> {\n const buffer = typeof data === 'string' ? Buffer.from(data) : \n data instanceof Uint8Array ? Buffer.from(data) : data;\n \n if (isSSREnvironment()) {\n return this.createSSRSafeHash(buffer, 'data');\n }\n\n const hasher = this.cryptoAdapter.createHash('sha256');\n const result = hasher.update(buffer).digest('hex');\n const hash = result instanceof Promise ? await result : result;\n return typeof hash === 'string' ? hash : hash.toString('hex');\n }\n\n /**\n * Create SSR-safe hash\n */\n private createSSRSafeHash(data: Buffer | Uint8Array, type: string): string {\n const buffer = data instanceof Uint8Array ? Buffer.from(data) : data;\n let hash = 0;\n \n for (let i = 0; i < Math.min(buffer.length, 256); i++) {\n hash = ((hash << 5) - hash + buffer[i]) & 0xffffffff;\n }\n \n return `ssr-${type}-${buffer.length}-${Math.abs(hash).toString(16).padStart(8, '0')}`;\n }\n\n /**\n * Create registration from WASM and INFO data\n */\n async createFromWasmAndInfo(\n topicId: string,\n wasmData: Uint8Array,\n info: ModuleInfo,\n ): Promise<ActionRegistration> {\n const wasmHash = await this.generateWasmHash(wasmData);\n const infoHash = await this.generateInfoHash(info);\n\n const jsTopicId = this.registration.js_t_id;\n const jsHash = this.registration.js_hash;\n const interfaceVersion = this.registration.interface_version;\n\n this.reset().setTopicId(topicId).setHash(infoHash).setWasmHash(wasmHash);\n\n if (jsTopicId) this.setJsTopicId(jsTopicId);\n if (jsHash) this.setJsHash(jsHash);\n if (interfaceVersion) this.setInterfaceVersion(interfaceVersion);\n\n return this.build();\n }\n\n /**\n * Check if registration is complete\n */\n isComplete(registration: Partial<ActionRegistration>): boolean {\n return !!(\n registration.p === 'hcs-12' &&\n registration.op === 'register' &&\n registration.t_id &&\n registration.hash &&\n registration.wasm_hash\n );\n }\n\n /**\n * Validate the current registration\n */\n private validate(): void {\n if (!this.registration.t_id) {\n throw new Error('Topic ID is required');\n }\n if (!this.registration.hash) {\n throw new Error('INFO hash is required');\n }\n if (!this.registration.wasm_hash) {\n throw new Error('WASM hash is required');\n }\n }\n\n /**\n * Validate topic ID format\n */\n private isValidTopicId(topicId: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(topicId);\n }\n\n /**\n * Validate hash format\n */\n private isValidHash(hash: string): boolean {\n return /^[a-f0-9]{64}$/.test(hash);\n }\n\n /**\n * Validate semantic version format\n */\n private isValidVersion(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(version);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCryptoAdapter } from "./standards-sdk.es91.js";
|
|
2
|
+
import { isSSREnvironment } from "./standards-sdk.es92.js";
|
|
2
3
|
class WasmValidator {
|
|
3
4
|
constructor(logger) {
|
|
5
|
+
this.cryptoAdapter = getCryptoAdapter();
|
|
4
6
|
this.REQUIRED_EXPORTS = ["INFO", "POST", "GET"];
|
|
5
7
|
this.ALLOWED_IMPORTS = /* @__PURE__ */ new Set([
|
|
6
8
|
"env.console_log",
|
|
@@ -157,9 +159,23 @@ class WasmValidator {
|
|
|
157
159
|
* Calculate WASM hash
|
|
158
160
|
*/
|
|
159
161
|
async calculateHash(wasmData) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
if (isSSREnvironment()) {
|
|
163
|
+
return this.createSSRSafeHash(wasmData);
|
|
164
|
+
}
|
|
165
|
+
const hasher = this.cryptoAdapter.createHash("sha256");
|
|
166
|
+
const result = hasher.update(Buffer.from(wasmData)).digest("hex");
|
|
167
|
+
const hash = result instanceof Promise ? await result : result;
|
|
168
|
+
return typeof hash === "string" ? hash : hash.toString("hex");
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create SSR-safe hash for WASM data
|
|
172
|
+
*/
|
|
173
|
+
createSSRSafeHash(wasmData) {
|
|
174
|
+
let hash = 0;
|
|
175
|
+
for (let i = 0; i < Math.min(wasmData.length, 1024); i++) {
|
|
176
|
+
hash = (hash << 5) - hash + wasmData[i] & 4294967295;
|
|
177
|
+
}
|
|
178
|
+
return `ssr-wasm-${wasmData.length}-${Math.abs(hash).toString(16).padStart(8, "0")}`;
|
|
163
179
|
}
|
|
164
180
|
/**
|
|
165
181
|
* Validate WASM magic number
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es32.js","sources":["../../src/hcs-12/validation/wasm-validator.ts"],"sourcesContent":["/**\n * WASM Validator for HCS-12 HashLinks\n *\n * Validates WebAssembly modules for security, compatibility, and HashLink requirements.\n */\n\nimport { createHash } from 'crypto';\nimport { Logger } from '../../utils/logger';\nimport { ModuleInfo } from '../types';\n\nexport interface WasmValidationResult {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n version?: number;\n exports?: string[];\n imports?: ImportInfo[];\n memoryRequirements?: MemoryRequirements;\n exportSignatures?: Record<string, ExportSignature>;\n moduleInfo?: ModuleInfo;\n}\n\nexport interface ImportInfo {\n module: string;\n name: string;\n type: string;\n}\n\nexport interface MemoryRequirements {\n initial: number;\n maximum?: number;\n}\n\nexport interface ExportSignature {\n type: string;\n params: string[];\n results: string[];\n}\n\n/**\n * Validator for WASM modules\n */\nexport class WasmValidator {\n private logger: Logger;\n\n private readonly REQUIRED_EXPORTS = ['INFO', 'POST', 'GET'];\n\n private readonly ALLOWED_IMPORTS = new Set([\n 'env.console_log',\n 'env.get_network',\n 'env.submit_hcs_message',\n 'env.memory',\n ]);\n\n private readonly MAX_INITIAL_MEMORY = 256;\n\n private readonly WARN_MODULE_SIZE = 1 * 1024 * 1024;\n\n private readonly MAX_MODULE_SIZE = 5 * 1024 * 1024;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n /**\n * Validate a WASM module\n */\n async validate(wasmData: Uint8Array): Promise<WasmValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n const result: WasmValidationResult = {\n isValid: true,\n errors,\n warnings,\n };\n\n try {\n if (wasmData.length > this.WARN_MODULE_SIZE) {\n warnings.push(\n `Large module size: ${(wasmData.length / 1024 / 1024).toFixed(2)} MB`,\n );\n }\n if (wasmData.length > this.MAX_MODULE_SIZE) {\n errors.push('Module size exceeds maximum allowed');\n result.isValid = false;\n }\n\n if (!this.validateMagicNumber(wasmData)) {\n errors.push('Invalid WASM magic number');\n result.isValid = false;\n return result;\n }\n\n const version = this.getWasmVersion(wasmData);\n result.version = version;\n if (version !== 1) {\n errors.push(`Unsupported WASM version: ${version}`);\n result.isValid = false;\n return result;\n }\n\n const moduleInfo = await this.parseModule(wasmData);\n\n result.exports = moduleInfo.exports;\n for (const required of this.REQUIRED_EXPORTS) {\n if (!moduleInfo.exports.includes(required)) {\n errors.push(`Missing required export: ${required}`);\n result.isValid = false;\n }\n }\n\n result.imports = moduleInfo.imports;\n for (const imp of moduleInfo.imports) {\n const importName = `${imp.module}.${imp.name}`;\n if (!this.ALLOWED_IMPORTS.has(importName)) {\n errors.push(`Disallowed import: ${importName}`);\n result.isValid = false;\n }\n }\n\n if (moduleInfo.memory) {\n result.memoryRequirements = moduleInfo.memory;\n if (moduleInfo.memory.initial > this.MAX_INITIAL_MEMORY) {\n errors.push(\n `Excessive initial memory: ${moduleInfo.memory.initial} pages`,\n );\n result.isValid = false;\n }\n }\n\n if (moduleInfo.hasStartFunction) {\n warnings.push('Module has start function - may execute code on load');\n }\n\n if (moduleInfo.functionCount > 100) {\n warnings.push(`High function count: ${moduleInfo.functionCount}`);\n }\n\n if (this.hasSuspiciousPatterns(wasmData)) {\n warnings.push('Potentially unsafe operation detected');\n }\n\n result.exportSignatures = moduleInfo.exportSignatures;\n } catch (error) {\n this.logger.error('WASM validation failed', { error });\n errors.push(\n `Validation error: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n result.isValid = false;\n }\n\n return result;\n }\n\n /**\n * Validate INFO function return\n */\n async validateInfoFunction(\n infoFunc: () => Promise<string> | string,\n ): Promise<WasmValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n try {\n const infoStr = await infoFunc();\n const info = JSON.parse(infoStr);\n\n if (!info.name || !info.version || !info.hashlinks_version) {\n errors.push('INFO missing required fields');\n return {\n isValid: false,\n errors,\n warnings,\n };\n }\n\n return {\n isValid: true,\n errors,\n warnings,\n moduleInfo: info,\n };\n } catch (error) {\n errors.push('INFO function returned invalid JSON');\n return {\n isValid: false,\n errors,\n warnings,\n };\n }\n }\n\n /**\n * Validate action parameter schemas\n */\n async validateActionSchemas(moduleInfo: any): Promise<WasmValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (moduleInfo.validation_rules) {\n for (const [action, rule] of Object.entries(\n moduleInfo.validation_rules,\n )) {\n if (typeof rule !== 'object') {\n errors.push(`Invalid validation rule for action: ${action}`);\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Extract metadata from WASM\n */\n async extractMetadata(wasmData: Uint8Array): Promise<any> {\n return {\n size: wasmData.length,\n hash: await this.calculateHash(wasmData),\n producers: { language: ['Unknown'] },\n };\n }\n\n /**\n * Calculate WASM hash\n */\n async calculateHash(wasmData: Uint8Array): Promise<string> {\n const hash = createHash('sha256');\n hash.update(wasmData);\n return hash.digest('hex');\n }\n\n /**\n * Validate WASM magic number\n */\n private validateMagicNumber(data: Uint8Array): boolean {\n return (\n data.length >= 4 &&\n data[0] === 0x00 &&\n data[1] === 0x61 &&\n data[2] === 0x73 &&\n data[3] === 0x6d\n );\n }\n\n /**\n * Get WASM version\n */\n private getWasmVersion(data: Uint8Array): number {\n if (data.length < 8) return 0;\n return data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24);\n }\n\n /**\n * Parse WASM module (simplified for testing)\n */\n private async parseModule(data: Uint8Array): Promise<any> {\n const textData = data.slice(8);\n const dataStr = new TextDecoder('utf-8', { fatal: false }).decode(textData);\n\n const exports: string[] = [];\n if (dataStr.includes('INFO')) exports.push('INFO');\n if (dataStr.includes('POST')) exports.push('POST');\n if (dataStr.includes('GET')) exports.push('GET');\n\n if (exports.length === 0 && data.length > 8) {\n exports.push('INFO', 'POST', 'GET');\n }\n\n const imports: ImportInfo[] = [];\n const importParts = dataStr.split('import:');\n for (let i = 1; i < importParts.length; i++) {\n const part = importParts[i];\n const match = part.match(\n /^([a-zA-Z_]+[a-zA-Z0-9_]*)\\.([a-zA-Z_]+[a-zA-Z0-9_]*)/,\n );\n if (match) {\n imports.push({\n module: match[1],\n name: match[2],\n type: 'function',\n });\n }\n }\n\n let initial = 1;\n let maximum = 16;\n const memMatch = dataStr.match(/memory:(\\d+)(?:-(\\d+))?/);\n if (memMatch) {\n initial = parseInt(memMatch[1]);\n if (memMatch[2]) maximum = parseInt(memMatch[2]);\n }\n\n let functionCount = 10;\n const funcMatch = dataStr.match(/functions:(\\d+)/);\n if (funcMatch) {\n functionCount = parseInt(funcMatch[1]);\n }\n\n const hasStartFunction = dataStr.includes('start:true');\n\n return {\n exports,\n imports,\n memory: { initial, maximum },\n functionCount,\n hasStartFunction,\n exportSignatures: {\n INFO: { type: 'function', params: [], results: ['i32'] },\n POST: {\n type: 'function',\n params: ['i32', 'i32', 'i32', 'i32'],\n results: ['i32'],\n },\n GET: {\n type: 'function',\n params: ['i32', 'i32', 'i32'],\n results: ['i32'],\n },\n },\n };\n }\n\n /**\n * Check for suspicious patterns\n */\n private hasSuspiciousPatterns(data: Uint8Array): boolean {\n const dataStr = new TextDecoder('utf-8', { fatal: false }).decode(data);\n const suspiciousPatterns = ['eval', '__proto__', 'constructor'];\n\n return suspiciousPatterns.some(pattern => dataStr.includes(pattern));\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es32.js","sources":["../../src/hcs-12/validation/wasm-validator.ts"],"sourcesContent":["/**\n * WASM Validator for HCS-12 HashLinks\n *\n * Validates WebAssembly modules for security, compatibility, and HashLink requirements.\n */\n\nimport { Logger } from '../../utils/logger';\nimport { getCryptoAdapter } from '../../utils/crypto-abstraction';\nimport { isSSREnvironment } from '../../utils/crypto-env';\nimport { ModuleInfo } from '../types';\n\nexport interface WasmValidationResult {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n version?: number;\n exports?: string[];\n imports?: ImportInfo[];\n memoryRequirements?: MemoryRequirements;\n exportSignatures?: Record<string, ExportSignature>;\n moduleInfo?: ModuleInfo;\n}\n\nexport interface ImportInfo {\n module: string;\n name: string;\n type: string;\n}\n\nexport interface MemoryRequirements {\n initial: number;\n maximum?: number;\n}\n\nexport interface ExportSignature {\n type: string;\n params: string[];\n results: string[];\n}\n\n/**\n * Validator for WASM modules\n */\nexport class WasmValidator {\n private logger: Logger;\n private cryptoAdapter = getCryptoAdapter();\n\n private readonly REQUIRED_EXPORTS = ['INFO', 'POST', 'GET'];\n\n private readonly ALLOWED_IMPORTS = new Set([\n 'env.console_log',\n 'env.get_network',\n 'env.submit_hcs_message',\n 'env.memory',\n ]);\n\n private readonly MAX_INITIAL_MEMORY = 256;\n\n private readonly WARN_MODULE_SIZE = 1 * 1024 * 1024;\n\n private readonly MAX_MODULE_SIZE = 5 * 1024 * 1024;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n /**\n * Validate a WASM module\n */\n async validate(wasmData: Uint8Array): Promise<WasmValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n const result: WasmValidationResult = {\n isValid: true,\n errors,\n warnings,\n };\n\n try {\n if (wasmData.length > this.WARN_MODULE_SIZE) {\n warnings.push(\n `Large module size: ${(wasmData.length / 1024 / 1024).toFixed(2)} MB`,\n );\n }\n if (wasmData.length > this.MAX_MODULE_SIZE) {\n errors.push('Module size exceeds maximum allowed');\n result.isValid = false;\n }\n\n if (!this.validateMagicNumber(wasmData)) {\n errors.push('Invalid WASM magic number');\n result.isValid = false;\n return result;\n }\n\n const version = this.getWasmVersion(wasmData);\n result.version = version;\n if (version !== 1) {\n errors.push(`Unsupported WASM version: ${version}`);\n result.isValid = false;\n return result;\n }\n\n const moduleInfo = await this.parseModule(wasmData);\n\n result.exports = moduleInfo.exports;\n for (const required of this.REQUIRED_EXPORTS) {\n if (!moduleInfo.exports.includes(required)) {\n errors.push(`Missing required export: ${required}`);\n result.isValid = false;\n }\n }\n\n result.imports = moduleInfo.imports;\n for (const imp of moduleInfo.imports) {\n const importName = `${imp.module}.${imp.name}`;\n if (!this.ALLOWED_IMPORTS.has(importName)) {\n errors.push(`Disallowed import: ${importName}`);\n result.isValid = false;\n }\n }\n\n if (moduleInfo.memory) {\n result.memoryRequirements = moduleInfo.memory;\n if (moduleInfo.memory.initial > this.MAX_INITIAL_MEMORY) {\n errors.push(\n `Excessive initial memory: ${moduleInfo.memory.initial} pages`,\n );\n result.isValid = false;\n }\n }\n\n if (moduleInfo.hasStartFunction) {\n warnings.push('Module has start function - may execute code on load');\n }\n\n if (moduleInfo.functionCount > 100) {\n warnings.push(`High function count: ${moduleInfo.functionCount}`);\n }\n\n if (this.hasSuspiciousPatterns(wasmData)) {\n warnings.push('Potentially unsafe operation detected');\n }\n\n result.exportSignatures = moduleInfo.exportSignatures;\n } catch (error) {\n this.logger.error('WASM validation failed', { error });\n errors.push(\n `Validation error: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n result.isValid = false;\n }\n\n return result;\n }\n\n /**\n * Validate INFO function return\n */\n async validateInfoFunction(\n infoFunc: () => Promise<string> | string,\n ): Promise<WasmValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n try {\n const infoStr = await infoFunc();\n const info = JSON.parse(infoStr);\n\n if (!info.name || !info.version || !info.hashlinks_version) {\n errors.push('INFO missing required fields');\n return {\n isValid: false,\n errors,\n warnings,\n };\n }\n\n return {\n isValid: true,\n errors,\n warnings,\n moduleInfo: info,\n };\n } catch (error) {\n errors.push('INFO function returned invalid JSON');\n return {\n isValid: false,\n errors,\n warnings,\n };\n }\n }\n\n /**\n * Validate action parameter schemas\n */\n async validateActionSchemas(moduleInfo: any): Promise<WasmValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (moduleInfo.validation_rules) {\n for (const [action, rule] of Object.entries(\n moduleInfo.validation_rules,\n )) {\n if (typeof rule !== 'object') {\n errors.push(`Invalid validation rule for action: ${action}`);\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Extract metadata from WASM\n */\n async extractMetadata(wasmData: Uint8Array): Promise<any> {\n return {\n size: wasmData.length,\n hash: await this.calculateHash(wasmData),\n producers: { language: ['Unknown'] },\n };\n }\n\n /**\n * Calculate WASM hash\n */\n async calculateHash(wasmData: Uint8Array): Promise<string> {\n if (isSSREnvironment()) {\n return this.createSSRSafeHash(wasmData);\n }\n\n const hasher = this.cryptoAdapter.createHash('sha256');\n const result = hasher.update(Buffer.from(wasmData)).digest('hex');\n const hash = result instanceof Promise ? await result : result;\n return typeof hash === 'string' ? hash : hash.toString('hex');\n }\n\n /**\n * Create SSR-safe hash for WASM data\n */\n private createSSRSafeHash(wasmData: Uint8Array): string {\n let hash = 0;\n for (let i = 0; i < Math.min(wasmData.length, 1024); i++) {\n hash = ((hash << 5) - hash + wasmData[i]) & 0xffffffff;\n }\n return `ssr-wasm-${wasmData.length}-${Math.abs(hash).toString(16).padStart(8, '0')}`;\n }\n\n /**\n * Validate WASM magic number\n */\n private validateMagicNumber(data: Uint8Array): boolean {\n return (\n data.length >= 4 &&\n data[0] === 0x00 &&\n data[1] === 0x61 &&\n data[2] === 0x73 &&\n data[3] === 0x6d\n );\n }\n\n /**\n * Get WASM version\n */\n private getWasmVersion(data: Uint8Array): number {\n if (data.length < 8) return 0;\n return data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24);\n }\n\n /**\n * Parse WASM module (simplified for testing)\n */\n private async parseModule(data: Uint8Array): Promise<any> {\n const textData = data.slice(8);\n const dataStr = new TextDecoder('utf-8', { fatal: false }).decode(textData);\n\n const exports: string[] = [];\n if (dataStr.includes('INFO')) exports.push('INFO');\n if (dataStr.includes('POST')) exports.push('POST');\n if (dataStr.includes('GET')) exports.push('GET');\n\n if (exports.length === 0 && data.length > 8) {\n exports.push('INFO', 'POST', 'GET');\n }\n\n const imports: ImportInfo[] = [];\n const importParts = dataStr.split('import:');\n for (let i = 1; i < importParts.length; i++) {\n const part = importParts[i];\n const match = part.match(\n /^([a-zA-Z_]+[a-zA-Z0-9_]*)\\.([a-zA-Z_]+[a-zA-Z0-9_]*)/,\n );\n if (match) {\n imports.push({\n module: match[1],\n name: match[2],\n type: 'function',\n });\n }\n }\n\n let initial = 1;\n let maximum = 16;\n const memMatch = dataStr.match(/memory:(\\d+)(?:-(\\d+))?/);\n if (memMatch) {\n initial = parseInt(memMatch[1]);\n if (memMatch[2]) maximum = parseInt(memMatch[2]);\n }\n\n let functionCount = 10;\n const funcMatch = dataStr.match(/functions:(\\d+)/);\n if (funcMatch) {\n functionCount = parseInt(funcMatch[1]);\n }\n\n const hasStartFunction = dataStr.includes('start:true');\n\n return {\n exports,\n imports,\n memory: { initial, maximum },\n functionCount,\n hasStartFunction,\n exportSignatures: {\n INFO: { type: 'function', params: [], results: ['i32'] },\n POST: {\n type: 'function',\n params: ['i32', 'i32', 'i32', 'i32'],\n results: ['i32'],\n },\n GET: {\n type: 'function',\n params: ['i32', 'i32', 'i32'],\n results: ['i32'],\n },\n },\n };\n }\n\n /**\n * Check for suspicious patterns\n */\n private hasSuspiciousPatterns(data: Uint8Array): boolean {\n const dataStr = new TextDecoder('utf-8', { fatal: false }).decode(data);\n const suspiciousPatterns = ['eval', '__proto__', 'constructor'];\n\n return suspiciousPatterns.some(pattern => dataStr.includes(pattern));\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HCS } from "./standards-sdk.es2.js";
|
|
2
|
+
import { isSSREnvironment } from "./standards-sdk.es92.js";
|
|
2
3
|
class ResourceManager {
|
|
3
4
|
constructor(networkType, logger, hcs, options = {}) {
|
|
4
5
|
this.cache = /* @__PURE__ */ new Map();
|
|
@@ -172,6 +173,14 @@ class ResourceManager {
|
|
|
172
173
|
*/
|
|
173
174
|
async verifyIntegrity(content, expectedHash) {
|
|
174
175
|
try {
|
|
176
|
+
if (isSSREnvironment()) {
|
|
177
|
+
this.logger.warn("Integrity verification skipped in SSR environment");
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
if (typeof crypto === "undefined" || !crypto.subtle) {
|
|
181
|
+
this.logger.warn("WebCrypto not available, skipping integrity verification");
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
175
184
|
const buffer = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
176
185
|
const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
|
|
177
186
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es37.js","sources":["../../src/hcs-12/rendering/resource-manager.ts"],"sourcesContent":["/**\n * Resource Manager for HCS-12 HashLinks\n *\n * Manages loading and caching of resources (CSS, JS, images, templates)\n * from HCS-3 storage with integrity verification and security validation.\n */\n\nimport { Logger } from '../../utils/logger';\nimport { NetworkType } from '../../utils/types';\nimport { HCS } from '../../hcs-3/src';\n\nexport interface ResourceData {\n content: string | Uint8Array;\n contentType: string;\n size: number;\n hash?: string;\n}\n\nexport interface VerifiedResource {\n content: string | Uint8Array;\n verified: boolean;\n contentType: string;\n}\n\nexport interface ResourceDependency {\n topicId: string;\n type: 'css' | 'js' | 'template' | 'image';\n depends?: string[];\n}\n\nexport interface LoadedResource {\n topicId: string;\n content: string | Uint8Array;\n contentType: string;\n type: string;\n}\n\nexport interface CacheEntry {\n data: ResourceData;\n timestamp: number;\n size: number;\n}\n\nexport interface ResourceManagerOptions {\n cacheTTL?: number;\n maxCacheSize?: number;\n maxResourceSize?: number;\n}\n\n/**\n * Resource manager for efficient loading and caching of HCS-3 resources\n */\nexport class ResourceManager {\n private logger: Logger;\n private hcs: HCS;\n private cache: Map<string, CacheEntry> = new Map();\n private options: Required<ResourceManagerOptions>;\n private currentCacheSize: number = 0;\n\n private readonly supportedImageTypes = new Set([\n 'image/png',\n 'image/jpeg',\n 'image/jpg',\n 'image/gif',\n 'image/svg+xml',\n 'image/webp',\n ]);\n\n private readonly dangerousJSPatterns = [\n /eval\\s*\\(/g,\n /Function\\s*\\(/g,\n /setTimeout\\s*\\(\\s*[\"'].*[\"']/g,\n /setInterval\\s*\\(\\s*[\"'].*[\"']/g,\n /document\\.write/g,\n /innerHTML\\s*=/g,\n /outerHTML\\s*=/g,\n ];\n\n private readonly dangerousCSSPatterns = [\n /javascript\\s*:/gi,\n /@import.*url\\s*\\(\\s*[\"']?javascript:/gi,\n /expression\\s*\\(/gi,\n /behavior\\s*:/gi,\n ];\n\n constructor(\n networkType: NetworkType,\n logger: Logger,\n hcs?: HCS,\n options: ResourceManagerOptions = {},\n ) {\n this.logger = logger;\n this.hcs = hcs || new HCS();\n this.options = {\n cacheTTL: options.cacheTTL || 300000,\n maxCacheSize: options.maxCacheSize || 50 * 1024 * 1024,\n maxResourceSize: options.maxResourceSize || 5 * 1024 * 1024,\n };\n }\n\n /**\n * Load CSS resource from HCS-3\n */\n async loadCSS(topicId: string): Promise<string> {\n this.logger.debug('Loading CSS resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n if (resource.contentType !== 'text/css') {\n throw new Error(`Expected CSS resource, got ${resource.contentType}`);\n }\n\n const content = resource.content as string;\n const sanitized = this.sanitizeCSS(content);\n\n this.logger.debug('CSS resource loaded successfully', {\n topicId,\n size: content.length,\n sanitized: sanitized.length !== content.length,\n });\n\n return sanitized;\n } catch (error) {\n this.logger.error('Failed to load CSS resource', { topicId, error });\n throw new Error(\n `Failed to load CSS resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load JavaScript resource from HCS-3\n */\n async loadJS(topicId: string): Promise<string> {\n this.logger.debug('Loading JavaScript resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n if (\n !resource.contentType.includes('javascript') &&\n !resource.contentType.includes('ecmascript')\n ) {\n throw new Error(\n `Expected JavaScript resource, got ${resource.contentType}`,\n );\n }\n\n const content = resource.content as string;\n\n if (content.length > this.options.maxResourceSize) {\n throw new Error('JavaScript resource too large');\n }\n\n const sanitized = this.sanitizeJavaScript(content);\n\n this.logger.debug('JavaScript resource loaded successfully', {\n topicId,\n size: content.length,\n sanitized: sanitized.length !== content.length,\n });\n\n return sanitized;\n } catch (error) {\n this.logger.error('Failed to load JavaScript resource', {\n topicId,\n error,\n });\n throw new Error(\n `Failed to load JavaScript resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load image resource from HCS-3 as Blob\n */\n async loadImage(topicId: string): Promise<Blob> {\n this.logger.debug('Loading image resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n if (!this.supportedImageTypes.has(resource.contentType)) {\n throw new Error(`Unsupported image format: ${resource.contentType}`);\n }\n\n const content = resource.content as Uint8Array;\n const blob = new Blob([content], { type: resource.contentType });\n\n this.logger.debug('Image resource loaded successfully', {\n topicId,\n size: content.length,\n type: resource.contentType,\n });\n\n return blob;\n } catch (error) {\n this.logger.error('Failed to load image resource', { topicId, error });\n throw new Error(\n `Failed to load image resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load template resource from HCS-3\n */\n async loadTemplate(topicId: string): Promise<string> {\n this.logger.debug('Loading template resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n const content = resource.content as string;\n\n this.validateTemplateSyntax(content);\n\n const sanitized = this.sanitizeTemplate(content);\n\n this.logger.debug('Template resource loaded successfully', {\n topicId,\n size: content.length,\n });\n\n return sanitized;\n } catch (error) {\n this.logger.error('Failed to load template resource', { topicId, error });\n throw new Error(\n `Failed to load template resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load resource with integrity verification\n */\n async loadWithIntegrityCheck(\n topicId: string,\n expectedHash: string,\n ): Promise<VerifiedResource> {\n this.logger.debug('Loading resource with integrity check', {\n topicId,\n expectedHash,\n });\n\n try {\n const resource = await this.loadResource(topicId);\n\n const verified = await this.verifyIntegrity(\n resource.content,\n expectedHash,\n );\n\n if (!verified) {\n throw new Error('Resource integrity verification failed');\n }\n\n this.logger.debug('Resource integrity verified', { topicId });\n\n return {\n content: resource.content,\n verified,\n contentType: resource.contentType,\n };\n } catch (error) {\n this.logger.error('Resource integrity check failed', { topicId, error });\n throw error;\n }\n }\n\n /**\n * Verify content integrity using SHA-256 hash\n */\n private async verifyIntegrity(\n content: string | Uint8Array,\n expectedHash: string,\n ): Promise<boolean> {\n try {\n const buffer =\n typeof content === 'string'\n ? new TextEncoder().encode(content)\n : content;\n\n const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const actualHash = hashArray\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n\n return actualHash === expectedHash.toLowerCase();\n } catch (error) {\n this.logger.error('Error verifying integrity', { error });\n return false;\n }\n }\n\n /**\n * Load multiple dependencies in correct order\n */\n async loadDependencies(\n dependencies: ResourceDependency[],\n ): Promise<LoadedResource[]> {\n this.logger.debug('Loading dependencies', { count: dependencies.length });\n\n try {\n this.detectCircularDependencies(dependencies);\n\n const sorted = this.topologicalSort(dependencies);\n\n const results: LoadedResource[] = [];\n\n for (const dep of sorted) {\n let content: string | Uint8Array;\n\n switch (dep.type) {\n case 'css':\n content = await this.loadCSS(dep.topicId);\n break;\n case 'js':\n content = await this.loadJS(dep.topicId);\n break;\n case 'template':\n content = await this.loadTemplate(dep.topicId);\n break;\n case 'image':\n const blob = await this.loadImage(dep.topicId);\n content = new Uint8Array(await blob.arrayBuffer());\n break;\n default:\n throw new Error(`Unsupported dependency type: ${dep.type}`);\n }\n\n results.push({\n topicId: dep.topicId,\n content,\n contentType: this.getContentTypeForType(dep.type),\n type: dep.type,\n });\n }\n\n this.logger.debug('Dependencies loaded successfully', {\n count: results.length,\n });\n return results;\n } catch (error) {\n this.logger.error('Failed to load dependencies', { error });\n throw error;\n }\n }\n\n /**\n * Clear resource cache\n */\n clearCache(): void {\n this.cache.clear();\n this.currentCacheSize = 0;\n this.logger.debug('Resource cache cleared');\n }\n\n /**\n * Get current cache size for testing\n */\n getCacheSize(): number {\n return this.currentCacheSize;\n }\n\n /**\n * Load resource with caching\n */\n private async loadResource(topicId: string): Promise<ResourceData> {\n const cached = this.getFromCache(topicId);\n if (cached) {\n this.logger.debug('Resource loaded from cache', { topicId });\n return cached;\n }\n\n const blob = await this.hcs.retrieveHCS1Data(topicId);\n\n const contentType = blob.type || 'application/octet-stream';\n\n let content: string | Uint8Array;\n if (\n contentType.startsWith('text/') ||\n contentType.includes('javascript') ||\n contentType.includes('json')\n ) {\n content = await blob.text();\n } else {\n content = new Uint8Array(await blob.arrayBuffer());\n }\n\n const resource: ResourceData = {\n content,\n contentType,\n size: blob.size,\n };\n\n this.addToCache(topicId, resource);\n\n return resource;\n }\n\n /**\n * Get resource from cache if valid\n */\n private getFromCache(topicId: string): ResourceData | null {\n const entry = this.cache.get(topicId);\n if (!entry) return null;\n\n if (Date.now() - entry.timestamp > this.options.cacheTTL) {\n this.removeFromCache(topicId);\n return null;\n }\n\n return entry.data;\n }\n\n /**\n * Add resource to cache with size management\n */\n private addToCache(topicId: string, resource: ResourceData): void {\n const size =\n typeof resource.content === 'string'\n ? resource.content.length\n : resource.content.byteLength;\n\n if (size > this.options.maxCacheSize / 2) {\n this.logger.warn('Resource too large for cache', { topicId, size });\n return;\n }\n\n while (\n this.currentCacheSize + size > this.options.maxCacheSize &&\n this.cache.size > 0\n ) {\n this.evictOldestEntry();\n }\n\n const entry: CacheEntry = {\n data: resource,\n timestamp: Date.now(),\n size,\n };\n\n this.cache.set(topicId, entry);\n this.currentCacheSize += size;\n\n this.logger.debug('Resource added to cache', {\n topicId,\n size,\n totalCacheSize: this.currentCacheSize,\n });\n }\n\n /**\n * Remove resource from cache\n */\n private removeFromCache(topicId: string): void {\n const entry = this.cache.get(topicId);\n if (entry) {\n this.cache.delete(topicId);\n this.currentCacheSize -= entry.size;\n }\n }\n\n /**\n * Evict oldest cache entry\n */\n private evictOldestEntry(): void {\n let oldest: string | null = null;\n let oldestTime = Date.now();\n\n for (const [topicId, entry] of this.cache) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldest = topicId;\n }\n }\n\n if (oldest) {\n this.removeFromCache(oldest);\n this.logger.debug('Evicted oldest cache entry', { topicId: oldest });\n }\n }\n\n /**\n * Sanitize CSS content\n */\n private sanitizeCSS(css: string): string {\n let sanitized = css;\n\n for (const pattern of this.dangerousCSSPatterns) {\n sanitized = sanitized.replace(pattern, '');\n }\n\n return sanitized;\n }\n\n /**\n * Sanitize JavaScript content\n */\n private sanitizeJavaScript(js: string): string {\n let sanitized = js;\n\n for (const pattern of this.dangerousJSPatterns) {\n sanitized = sanitized.replace(pattern, '');\n }\n\n return sanitized;\n }\n\n /**\n * Sanitize template content\n */\n private sanitizeTemplate(template: string): string {\n return template\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/javascript\\s*:/gi, '');\n }\n\n /**\n * Validate template syntax\n */\n private validateTemplateSyntax(template: string): void {\n const openBraces = (template.match(/\\{\\{/g) || []).length;\n const closeBraces = (template.match(/\\}\\}/g) || []).length;\n\n if (openBraces !== closeBraces) {\n throw new Error('Invalid template syntax: unmatched braces');\n }\n\n const openBlocks = (template.match(/\\{\\{#\\w+/g) || []).length;\n const closeBlocks = (template.match(/\\{\\{\\/\\w+/g) || []).length;\n\n if (openBlocks !== closeBlocks) {\n throw new Error('Invalid template syntax: unclosed block helpers');\n }\n }\n\n /**\n * Detect circular dependencies\n */\n private detectCircularDependencies(dependencies: ResourceDependency[]): void {\n const dependencyMap = new Map<string, string[]>();\n\n for (const dep of dependencies) {\n dependencyMap.set(dep.topicId, dep.depends || []);\n }\n\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (topicId: string): void => {\n if (visiting.has(topicId)) {\n throw new Error('Circular dependency detected');\n }\n\n if (visited.has(topicId)) return;\n\n visiting.add(topicId);\n\n const deps = dependencyMap.get(topicId) || [];\n for (const dep of deps) {\n visit(dep);\n }\n\n visiting.delete(topicId);\n visited.add(topicId);\n };\n\n for (const dep of dependencies) {\n visit(dep.topicId);\n }\n }\n\n /**\n * Topological sort of dependencies\n */\n private topologicalSort(\n dependencies: ResourceDependency[],\n ): ResourceDependency[] {\n const dependencyMap = new Map<string, ResourceDependency>();\n const dependsMap = new Map<string, string[]>();\n\n for (const dep of dependencies) {\n dependencyMap.set(dep.topicId, dep);\n dependsMap.set(dep.topicId, dep.depends || []);\n }\n\n const sorted: ResourceDependency[] = [];\n const visited = new Set<string>();\n\n const visit = (topicId: string): void => {\n if (visited.has(topicId)) return;\n\n const deps = dependsMap.get(topicId) || [];\n for (const dep of deps) {\n visit(dep);\n }\n\n visited.add(topicId);\n const depObj = dependencyMap.get(topicId);\n if (depObj) {\n sorted.push(depObj);\n }\n };\n\n for (const dep of dependencies) {\n visit(dep.topicId);\n }\n\n return sorted;\n }\n\n /**\n * Get content type for dependency type\n */\n private getContentTypeForType(type: string): string {\n switch (type) {\n case 'css':\n return 'text/css';\n case 'js':\n return 'application/javascript';\n case 'template':\n return 'text/html';\n case 'image':\n return 'image/*';\n default:\n return 'application/octet-stream';\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es37.js","sources":["../../src/hcs-12/rendering/resource-manager.ts"],"sourcesContent":["/**\n * Resource Manager for HCS-12 HashLinks\n *\n * Manages loading and caching of resources (CSS, JS, images, templates)\n * from HCS-3 storage with integrity verification and security validation.\n */\n\nimport { Logger } from '../../utils/logger';\nimport { NetworkType } from '../../utils/types';\nimport { HCS } from '../../hcs-3/src';\nimport { isSSREnvironment } from '../../utils/crypto-env';\n\nexport interface ResourceData {\n content: string | Uint8Array;\n contentType: string;\n size: number;\n hash?: string;\n}\n\nexport interface VerifiedResource {\n content: string | Uint8Array;\n verified: boolean;\n contentType: string;\n}\n\nexport interface ResourceDependency {\n topicId: string;\n type: 'css' | 'js' | 'template' | 'image';\n depends?: string[];\n}\n\nexport interface LoadedResource {\n topicId: string;\n content: string | Uint8Array;\n contentType: string;\n type: string;\n}\n\nexport interface CacheEntry {\n data: ResourceData;\n timestamp: number;\n size: number;\n}\n\nexport interface ResourceManagerOptions {\n cacheTTL?: number;\n maxCacheSize?: number;\n maxResourceSize?: number;\n}\n\n/**\n * Resource manager for efficient loading and caching of HCS-3 resources\n */\nexport class ResourceManager {\n private logger: Logger;\n private hcs: HCS;\n private cache: Map<string, CacheEntry> = new Map();\n private options: Required<ResourceManagerOptions>;\n private currentCacheSize: number = 0;\n\n private readonly supportedImageTypes = new Set([\n 'image/png',\n 'image/jpeg',\n 'image/jpg',\n 'image/gif',\n 'image/svg+xml',\n 'image/webp',\n ]);\n\n private readonly dangerousJSPatterns = [\n /eval\\s*\\(/g,\n /Function\\s*\\(/g,\n /setTimeout\\s*\\(\\s*[\"'].*[\"']/g,\n /setInterval\\s*\\(\\s*[\"'].*[\"']/g,\n /document\\.write/g,\n /innerHTML\\s*=/g,\n /outerHTML\\s*=/g,\n ];\n\n private readonly dangerousCSSPatterns = [\n /javascript\\s*:/gi,\n /@import.*url\\s*\\(\\s*[\"']?javascript:/gi,\n /expression\\s*\\(/gi,\n /behavior\\s*:/gi,\n ];\n\n constructor(\n networkType: NetworkType,\n logger: Logger,\n hcs?: HCS,\n options: ResourceManagerOptions = {},\n ) {\n this.logger = logger;\n this.hcs = hcs || new HCS();\n this.options = {\n cacheTTL: options.cacheTTL || 300000,\n maxCacheSize: options.maxCacheSize || 50 * 1024 * 1024,\n maxResourceSize: options.maxResourceSize || 5 * 1024 * 1024,\n };\n }\n\n /**\n * Load CSS resource from HCS-3\n */\n async loadCSS(topicId: string): Promise<string> {\n this.logger.debug('Loading CSS resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n if (resource.contentType !== 'text/css') {\n throw new Error(`Expected CSS resource, got ${resource.contentType}`);\n }\n\n const content = resource.content as string;\n const sanitized = this.sanitizeCSS(content);\n\n this.logger.debug('CSS resource loaded successfully', {\n topicId,\n size: content.length,\n sanitized: sanitized.length !== content.length,\n });\n\n return sanitized;\n } catch (error) {\n this.logger.error('Failed to load CSS resource', { topicId, error });\n throw new Error(\n `Failed to load CSS resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load JavaScript resource from HCS-3\n */\n async loadJS(topicId: string): Promise<string> {\n this.logger.debug('Loading JavaScript resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n if (\n !resource.contentType.includes('javascript') &&\n !resource.contentType.includes('ecmascript')\n ) {\n throw new Error(\n `Expected JavaScript resource, got ${resource.contentType}`,\n );\n }\n\n const content = resource.content as string;\n\n if (content.length > this.options.maxResourceSize) {\n throw new Error('JavaScript resource too large');\n }\n\n const sanitized = this.sanitizeJavaScript(content);\n\n this.logger.debug('JavaScript resource loaded successfully', {\n topicId,\n size: content.length,\n sanitized: sanitized.length !== content.length,\n });\n\n return sanitized;\n } catch (error) {\n this.logger.error('Failed to load JavaScript resource', {\n topicId,\n error,\n });\n throw new Error(\n `Failed to load JavaScript resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load image resource from HCS-3 as Blob\n */\n async loadImage(topicId: string): Promise<Blob> {\n this.logger.debug('Loading image resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n if (!this.supportedImageTypes.has(resource.contentType)) {\n throw new Error(`Unsupported image format: ${resource.contentType}`);\n }\n\n const content = resource.content as Uint8Array;\n const blob = new Blob([content], { type: resource.contentType });\n\n this.logger.debug('Image resource loaded successfully', {\n topicId,\n size: content.length,\n type: resource.contentType,\n });\n\n return blob;\n } catch (error) {\n this.logger.error('Failed to load image resource', { topicId, error });\n throw new Error(\n `Failed to load image resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load template resource from HCS-3\n */\n async loadTemplate(topicId: string): Promise<string> {\n this.logger.debug('Loading template resource', { topicId });\n\n try {\n const resource = await this.loadResource(topicId);\n\n const content = resource.content as string;\n\n this.validateTemplateSyntax(content);\n\n const sanitized = this.sanitizeTemplate(content);\n\n this.logger.debug('Template resource loaded successfully', {\n topicId,\n size: content.length,\n });\n\n return sanitized;\n } catch (error) {\n this.logger.error('Failed to load template resource', { topicId, error });\n throw new Error(\n `Failed to load template resource: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n }\n\n /**\n * Load resource with integrity verification\n */\n async loadWithIntegrityCheck(\n topicId: string,\n expectedHash: string,\n ): Promise<VerifiedResource> {\n this.logger.debug('Loading resource with integrity check', {\n topicId,\n expectedHash,\n });\n\n try {\n const resource = await this.loadResource(topicId);\n\n const verified = await this.verifyIntegrity(\n resource.content,\n expectedHash,\n );\n\n if (!verified) {\n throw new Error('Resource integrity verification failed');\n }\n\n this.logger.debug('Resource integrity verified', { topicId });\n\n return {\n content: resource.content,\n verified,\n contentType: resource.contentType,\n };\n } catch (error) {\n this.logger.error('Resource integrity check failed', { topicId, error });\n throw error;\n }\n }\n\n /**\n * Verify content integrity using SHA-256 hash\n */\n private async verifyIntegrity(\n content: string | Uint8Array,\n expectedHash: string,\n ): Promise<boolean> {\n try {\n if (isSSREnvironment()) {\n this.logger.warn('Integrity verification skipped in SSR environment');\n return true;\n }\n\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n this.logger.warn('WebCrypto not available, skipping integrity verification');\n return true;\n }\n\n const buffer =\n typeof content === 'string'\n ? new TextEncoder().encode(content)\n : content;\n\n const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const actualHash = hashArray\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n\n return actualHash === expectedHash.toLowerCase();\n } catch (error) {\n this.logger.error('Error verifying integrity', { error });\n return false;\n }\n }\n\n /**\n * Load multiple dependencies in correct order\n */\n async loadDependencies(\n dependencies: ResourceDependency[],\n ): Promise<LoadedResource[]> {\n this.logger.debug('Loading dependencies', { count: dependencies.length });\n\n try {\n this.detectCircularDependencies(dependencies);\n\n const sorted = this.topologicalSort(dependencies);\n\n const results: LoadedResource[] = [];\n\n for (const dep of sorted) {\n let content: string | Uint8Array;\n\n switch (dep.type) {\n case 'css':\n content = await this.loadCSS(dep.topicId);\n break;\n case 'js':\n content = await this.loadJS(dep.topicId);\n break;\n case 'template':\n content = await this.loadTemplate(dep.topicId);\n break;\n case 'image':\n const blob = await this.loadImage(dep.topicId);\n content = new Uint8Array(await blob.arrayBuffer());\n break;\n default:\n throw new Error(`Unsupported dependency type: ${dep.type}`);\n }\n\n results.push({\n topicId: dep.topicId,\n content,\n contentType: this.getContentTypeForType(dep.type),\n type: dep.type,\n });\n }\n\n this.logger.debug('Dependencies loaded successfully', {\n count: results.length,\n });\n return results;\n } catch (error) {\n this.logger.error('Failed to load dependencies', { error });\n throw error;\n }\n }\n\n /**\n * Clear resource cache\n */\n clearCache(): void {\n this.cache.clear();\n this.currentCacheSize = 0;\n this.logger.debug('Resource cache cleared');\n }\n\n /**\n * Get current cache size for testing\n */\n getCacheSize(): number {\n return this.currentCacheSize;\n }\n\n /**\n * Load resource with caching\n */\n private async loadResource(topicId: string): Promise<ResourceData> {\n const cached = this.getFromCache(topicId);\n if (cached) {\n this.logger.debug('Resource loaded from cache', { topicId });\n return cached;\n }\n\n const blob = await this.hcs.retrieveHCS1Data(topicId);\n\n const contentType = blob.type || 'application/octet-stream';\n\n let content: string | Uint8Array;\n if (\n contentType.startsWith('text/') ||\n contentType.includes('javascript') ||\n contentType.includes('json')\n ) {\n content = await blob.text();\n } else {\n content = new Uint8Array(await blob.arrayBuffer());\n }\n\n const resource: ResourceData = {\n content,\n contentType,\n size: blob.size,\n };\n\n this.addToCache(topicId, resource);\n\n return resource;\n }\n\n /**\n * Get resource from cache if valid\n */\n private getFromCache(topicId: string): ResourceData | null {\n const entry = this.cache.get(topicId);\n if (!entry) return null;\n\n if (Date.now() - entry.timestamp > this.options.cacheTTL) {\n this.removeFromCache(topicId);\n return null;\n }\n\n return entry.data;\n }\n\n /**\n * Add resource to cache with size management\n */\n private addToCache(topicId: string, resource: ResourceData): void {\n const size =\n typeof resource.content === 'string'\n ? resource.content.length\n : resource.content.byteLength;\n\n if (size > this.options.maxCacheSize / 2) {\n this.logger.warn('Resource too large for cache', { topicId, size });\n return;\n }\n\n while (\n this.currentCacheSize + size > this.options.maxCacheSize &&\n this.cache.size > 0\n ) {\n this.evictOldestEntry();\n }\n\n const entry: CacheEntry = {\n data: resource,\n timestamp: Date.now(),\n size,\n };\n\n this.cache.set(topicId, entry);\n this.currentCacheSize += size;\n\n this.logger.debug('Resource added to cache', {\n topicId,\n size,\n totalCacheSize: this.currentCacheSize,\n });\n }\n\n /**\n * Remove resource from cache\n */\n private removeFromCache(topicId: string): void {\n const entry = this.cache.get(topicId);\n if (entry) {\n this.cache.delete(topicId);\n this.currentCacheSize -= entry.size;\n }\n }\n\n /**\n * Evict oldest cache entry\n */\n private evictOldestEntry(): void {\n let oldest: string | null = null;\n let oldestTime = Date.now();\n\n for (const [topicId, entry] of this.cache) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldest = topicId;\n }\n }\n\n if (oldest) {\n this.removeFromCache(oldest);\n this.logger.debug('Evicted oldest cache entry', { topicId: oldest });\n }\n }\n\n /**\n * Sanitize CSS content\n */\n private sanitizeCSS(css: string): string {\n let sanitized = css;\n\n for (const pattern of this.dangerousCSSPatterns) {\n sanitized = sanitized.replace(pattern, '');\n }\n\n return sanitized;\n }\n\n /**\n * Sanitize JavaScript content\n */\n private sanitizeJavaScript(js: string): string {\n let sanitized = js;\n\n for (const pattern of this.dangerousJSPatterns) {\n sanitized = sanitized.replace(pattern, '');\n }\n\n return sanitized;\n }\n\n /**\n * Sanitize template content\n */\n private sanitizeTemplate(template: string): string {\n return template\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/javascript\\s*:/gi, '');\n }\n\n /**\n * Validate template syntax\n */\n private validateTemplateSyntax(template: string): void {\n const openBraces = (template.match(/\\{\\{/g) || []).length;\n const closeBraces = (template.match(/\\}\\}/g) || []).length;\n\n if (openBraces !== closeBraces) {\n throw new Error('Invalid template syntax: unmatched braces');\n }\n\n const openBlocks = (template.match(/\\{\\{#\\w+/g) || []).length;\n const closeBlocks = (template.match(/\\{\\{\\/\\w+/g) || []).length;\n\n if (openBlocks !== closeBlocks) {\n throw new Error('Invalid template syntax: unclosed block helpers');\n }\n }\n\n /**\n * Detect circular dependencies\n */\n private detectCircularDependencies(dependencies: ResourceDependency[]): void {\n const dependencyMap = new Map<string, string[]>();\n\n for (const dep of dependencies) {\n dependencyMap.set(dep.topicId, dep.depends || []);\n }\n\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (topicId: string): void => {\n if (visiting.has(topicId)) {\n throw new Error('Circular dependency detected');\n }\n\n if (visited.has(topicId)) return;\n\n visiting.add(topicId);\n\n const deps = dependencyMap.get(topicId) || [];\n for (const dep of deps) {\n visit(dep);\n }\n\n visiting.delete(topicId);\n visited.add(topicId);\n };\n\n for (const dep of dependencies) {\n visit(dep.topicId);\n }\n }\n\n /**\n * Topological sort of dependencies\n */\n private topologicalSort(\n dependencies: ResourceDependency[],\n ): ResourceDependency[] {\n const dependencyMap = new Map<string, ResourceDependency>();\n const dependsMap = new Map<string, string[]>();\n\n for (const dep of dependencies) {\n dependencyMap.set(dep.topicId, dep);\n dependsMap.set(dep.topicId, dep.depends || []);\n }\n\n const sorted: ResourceDependency[] = [];\n const visited = new Set<string>();\n\n const visit = (topicId: string): void => {\n if (visited.has(topicId)) return;\n\n const deps = dependsMap.get(topicId) || [];\n for (const dep of deps) {\n visit(dep);\n }\n\n visited.add(topicId);\n const depObj = dependencyMap.get(topicId);\n if (depObj) {\n sorted.push(depObj);\n }\n };\n\n for (const dep of dependencies) {\n visit(dep.topicId);\n }\n\n return sorted;\n }\n\n /**\n * Get content type for dependency type\n */\n private getContentTypeForType(type: string): string {\n switch (type) {\n case 'css':\n return 'text/css';\n case 'js':\n return 'application/javascript';\n case 'template':\n return 'text/html';\n case 'image':\n return 'image/*';\n default:\n return 'application/octet-stream';\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TopicCreateTransaction, PublicKey, TopicMessageSubmitTransaction, TopicId } from "@hashgraph/sdk";
|
|
2
2
|
import { HCS2BaseClient } from "./standards-sdk.es47.js";
|
|
3
3
|
import { HCS2RegistryType, HCS2Operation } from "./standards-sdk.es44.js";
|
|
4
|
-
import { isBrowser } from "./standards-sdk.
|
|
4
|
+
import { isBrowser } from "./standards-sdk.es72.js";
|
|
5
5
|
import { KeyTypeDetector } from "./standards-sdk.es62.js";
|
|
6
6
|
class BrowserHCS2Client extends HCS2BaseClient {
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AccountId, Client, PrivateKey, TopicMessageSubmitTransaction, TopicId, Status, TopicCreateTransaction } from "@hashgraph/sdk";
|
|
2
2
|
import { HCS20BaseClient } from "./standards-sdk.es50.js";
|
|
3
3
|
import { PointsDeploymentError, PointsValidationError, PointsTransferError, PointsBurnError } from "./standards-sdk.es49.js";
|
|
4
|
-
import { sleep } from "./standards-sdk.
|
|
4
|
+
import { sleep } from "./standards-sdk.es75.js";
|
|
5
5
|
import { detectKeyTypeFromString } from "./standards-sdk.es62.js";
|
|
6
6
|
import { HCS2Client } from "./standards-sdk.es45.js";
|
|
7
7
|
class HCS20Client extends HCS20BaseClient {
|
|
@@ -5,14 +5,14 @@ import { ethers } from "ethers";
|
|
|
5
5
|
import { TransactionParsingError } from "./standards-sdk.es60.js";
|
|
6
6
|
import { resolveTransactionSummary } from "./standards-sdk.es61.js";
|
|
7
7
|
import { HTSParser } from "./standards-sdk.es64.js";
|
|
8
|
-
import { HCSParser } from "./standards-sdk.
|
|
9
|
-
import { FileParser } from "./standards-sdk.
|
|
10
|
-
import { CryptoParser } from "./standards-sdk.
|
|
11
|
-
import { SCSParser } from "./standards-sdk.
|
|
12
|
-
import { UtilParser } from "./standards-sdk.
|
|
8
|
+
import { HCSParser } from "./standards-sdk.es77.js";
|
|
9
|
+
import { FileParser } from "./standards-sdk.es78.js";
|
|
10
|
+
import { CryptoParser } from "./standards-sdk.es79.js";
|
|
11
|
+
import { SCSParser } from "./standards-sdk.es80.js";
|
|
12
|
+
import { UtilParser } from "./standards-sdk.es81.js";
|
|
13
13
|
import { ScheduleParser } from "./standards-sdk.es65.js";
|
|
14
|
-
import { transactionParserRegistry } from "./standards-sdk.
|
|
15
|
-
import { getTransactionTypeFromBody, getHumanReadableTransactionType } from "./standards-sdk.
|
|
14
|
+
import { transactionParserRegistry } from "./standards-sdk.es74.js";
|
|
15
|
+
import { getTransactionTypeFromBody, getHumanReadableTransactionType } from "./standards-sdk.es82.js";
|
|
16
16
|
class TransactionParser {
|
|
17
17
|
/**
|
|
18
18
|
* Parse transaction bytes in any supported format (base64 or hex, regular or scheduled)
|