@noosphere/registry 0.2.2-alpha.1 → 0.2.4-alpha.1
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/index.cjs +55 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +55 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -164,14 +164,68 @@ var RegistryManager = class {
|
|
|
164
164
|
Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {
|
|
165
165
|
this.deployments.set(chainId, metadata);
|
|
166
166
|
});
|
|
167
|
-
this.lastSync = Date.now();
|
|
168
167
|
console.log(`\u2713 Synced registry (version: ${registry.version})`);
|
|
168
|
+
await this.fetchNetworkFiles();
|
|
169
|
+
this.lastSync = Date.now();
|
|
169
170
|
await this.saveLocal();
|
|
170
171
|
} catch (error) {
|
|
171
172
|
console.error("Failed to sync remote registry:", error);
|
|
172
173
|
throw error;
|
|
173
174
|
}
|
|
174
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Parse remotePath to extract GitHub repo info.
|
|
178
|
+
* Supports raw.githubusercontent.com URLs.
|
|
179
|
+
* @returns owner, repo, branch tuple or null if URL doesn't match
|
|
180
|
+
*/
|
|
181
|
+
deriveGitHubInfo() {
|
|
182
|
+
const match = this.config.remotePath.match(
|
|
183
|
+
/raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)\//
|
|
184
|
+
);
|
|
185
|
+
return match ? { owner: match[1], repo: match[2], branch: match[3] } : null;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Fetch per-network registry files from the networks/ directory.
|
|
189
|
+
* Uses GitHub Contents API to discover files, then fetches each
|
|
190
|
+
* from raw.githubusercontent.com. Network files are authoritative
|
|
191
|
+
* and overwrite data from the root registry.json.
|
|
192
|
+
*/
|
|
193
|
+
async fetchNetworkFiles() {
|
|
194
|
+
const ghInfo = this.deriveGitHubInfo();
|
|
195
|
+
if (!ghInfo) return;
|
|
196
|
+
const contentsUrl = `https://api.github.com/repos/${ghInfo.owner}/${ghInfo.repo}/contents/networks?ref=${ghInfo.branch}`;
|
|
197
|
+
try {
|
|
198
|
+
const listResp = await (0, import_node_fetch.default)(contentsUrl, {
|
|
199
|
+
headers: {
|
|
200
|
+
"Accept": "application/vnd.github.v3+json",
|
|
201
|
+
"User-Agent": "noosphere-registry"
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (!listResp.ok) return;
|
|
205
|
+
const files = await listResp.json();
|
|
206
|
+
const networkFiles = files.filter((f) => f.name.endsWith(".json"));
|
|
207
|
+
for (const file of networkFiles) {
|
|
208
|
+
try {
|
|
209
|
+
const resp = await (0, import_node_fetch.default)(file.download_url);
|
|
210
|
+
if (!resp.ok) continue;
|
|
211
|
+
const networkRegistry = await resp.json();
|
|
212
|
+
Object.entries(networkRegistry.containers || {}).forEach(([id, metadata]) => {
|
|
213
|
+
this.containers.set(id, metadata);
|
|
214
|
+
});
|
|
215
|
+
Object.entries(networkRegistry.verifiers || {}).forEach(([id, metadata]) => {
|
|
216
|
+
this.verifiers.set(id, metadata);
|
|
217
|
+
});
|
|
218
|
+
Object.entries(networkRegistry.deployments || {}).forEach(([chainId2, metadata]) => {
|
|
219
|
+
this.deployments.set(chainId2, metadata);
|
|
220
|
+
});
|
|
221
|
+
const chainId = file.name.replace(".json", "");
|
|
222
|
+
console.log(` \u2713 Loaded network ${chainId}`);
|
|
223
|
+
} catch {
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
}
|
|
175
229
|
/**
|
|
176
230
|
* Get container by ID
|
|
177
231
|
*/
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/RegistryManager.ts"],"sourcesContent":["export { RegistryManager } from './RegistryManager';\nexport * from './types';\n","import fs from 'fs/promises';\nimport path from 'path';\nimport fetch from 'node-fetch';\nimport type { ContainerMetadata, DeploymentMetadata, VerifierMetadata, RegistryConfig, RegistryIndex } from './types';\n\nexport class RegistryManager {\n private containers = new Map<string, ContainerMetadata>();\n private verifiers = new Map<string, VerifierMetadata>();\n private deployments = new Map<string, DeploymentMetadata>();\n private config: Required<RegistryConfig>;\n private lastSync: number = 0;\n\n constructor(config: RegistryConfig = {}) {\n this.config = {\n localPath: config.localPath || path.join(process.cwd(), '.noosphere', 'registry.json'),\n remotePath:\n config.remotePath ||\n 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json',\n autoSync: config.autoSync ?? true,\n cacheTTL: config.cacheTTL || 3600000, // 1 hour default\n };\n }\n\n /**\n * Load registry from local and optionally sync from remote\n * Retries if 0 containers are loaded\n */\n async load(retryCount: number = 0): Promise<void> {\n const maxRetries = 3;\n const retryDelayMs = 5000;\n\n // Load local registry\n await this.loadLocal();\n\n // Sync from remote if enabled\n if (this.config.autoSync) {\n try {\n await this.sync();\n } catch (error) {\n console.warn('Failed to sync remote registry:', error);\n console.log('Continuing with local registry only');\n }\n }\n\n // Check if we have 0 containers and should retry (only when autoSync is enabled)\n if (this.config.autoSync && this.containers.size === 0 && retryCount < maxRetries) {\n console.warn(\n `⚠️ Loaded 0 containers, attempting recovery (attempt ${retryCount + 1}/${maxRetries})...`\n );\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, retryDelayMs));\n\n // Try force sync from remote\n try {\n await this.forceSync();\n } catch (error) {\n console.warn('Force sync failed:', error);\n }\n\n // If still 0, recurse with incremented retry count\n if (this.containers.size === 0) {\n return this.load(retryCount + 1);\n }\n }\n\n console.log(`✓ Loaded ${this.containers.size} containers, ${this.verifiers.size} verifiers, ${this.deployments.size} deployments`);\n }\n\n /**\n * Load local registry file\n */\n private async loadLocal(): Promise<void> {\n try {\n const data = await fs.readFile(this.config.localPath, 'utf-8');\n const registry: RegistryIndex = JSON.parse(data);\n\n // Load containers\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n\n // Load verifiers\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n\n // Load deployments\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n console.log(`✓ Loaded local registry from ${this.config.localPath}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n console.log('No local registry found, will create default');\n await this.createDefaultRegistry();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Sync registry from remote GitHub repository\n */\n async sync(): Promise<void> {\n const now = Date.now();\n\n // Check cache TTL\n if (now - this.lastSync < this.config.cacheTTL) {\n console.log('Registry cache is fresh, skipping sync');\n return;\n }\n\n await this.fetchRemote();\n }\n\n /**\n * Force sync from remote, bypassing cache TTL\n */\n async forceSync(): Promise<void> {\n console.log('Force syncing registry (bypassing cache)...');\n this.lastSync = 0; // Reset cache\n await this.fetchRemote();\n }\n\n /**\n * Reload registry completely (clear and reload from local + remote)\n */\n async reload(): Promise<void> {\n console.log('Reloading registry...');\n this.containers.clear();\n this.verifiers.clear();\n this.deployments.clear();\n this.lastSync = 0;\n await this.load();\n }\n\n /**\n * Fetch and merge remote registry\n */\n private async fetchRemote(): Promise<void> {\n console.log(`Syncing registry from ${this.config.remotePath}...`);\n\n try {\n const response = await fetch(this.config.remotePath);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const registry = (await response.json()) as RegistryIndex;\n\n // Merge remote registry (remote entries are added, local overrides are kept)\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n if (!this.containers.has(id)) {\n // Only add if not already in local registry (local takes precedence)\n this.containers.set(id, metadata);\n }\n });\n\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n if (!this.verifiers.has(id)) {\n this.verifiers.set(id, metadata);\n }\n });\n\n // Deployments: remote always wins (contract addresses are authoritative)\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n this.lastSync = Date.now();\n console.log(`✓ Synced registry (version: ${registry.version})`);\n\n // Persist synced registry to local file for faster subsequent loads\n await this.saveLocal();\n } catch (error) {\n console.error('Failed to sync remote registry:', error);\n throw error;\n }\n }\n\n /**\n * Get container by ID\n */\n getContainer(id: string): ContainerMetadata | undefined {\n return this.containers.get(id);\n }\n\n /**\n * Get all containers\n */\n listContainers(): ContainerMetadata[] {\n return Array.from(this.containers.values()).filter((c) => c.statusCode === 'ACTIVE');\n }\n\n /**\n * Search containers by name or tag\n */\n searchContainers(query: string): ContainerMetadata[] {\n const lowerQuery = query.toLowerCase();\n return this.listContainers().filter(\n (c) =>\n c.name.toLowerCase().includes(lowerQuery) ||\n c.description?.toLowerCase().includes(lowerQuery) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Get verifier by contract address\n */\n getVerifier(verifierAddress: string): VerifierMetadata | undefined {\n return this.verifiers.get(verifierAddress);\n }\n\n /**\n * Get verifier by ID\n */\n getVerifierById(id: string): VerifierMetadata | undefined {\n return Array.from(this.verifiers.values()).find((v) => v.id === id);\n }\n\n /**\n * Get all verifiers\n */\n listVerifiers(): VerifierMetadata[] {\n return Array.from(this.verifiers.values()).filter((v) => v.statusCode === 'ACTIVE');\n }\n\n /**\n * Get deployment by chain ID\n */\n getDeployment(chainId: string): DeploymentMetadata | undefined {\n return this.deployments.get(chainId);\n }\n\n /**\n * Get all active deployments\n */\n listDeployments(): DeploymentMetadata[] {\n return Array.from(this.deployments.values()).filter((d) => d.statusCode === 'ACTIVE');\n }\n\n /**\n * Add custom container to local registry\n */\n async addContainer(container: ContainerMetadata): Promise<void> {\n this.containers.set(container.id, container);\n await this.saveLocal();\n console.log(`✓ Added container: ${container.name} (${container.id})`);\n }\n\n /**\n * Add custom verifier to local registry\n */\n async addVerifier(verifier: VerifierMetadata): Promise<void> {\n this.verifiers.set(verifier.verifierAddress, verifier);\n await this.saveLocal();\n console.log(`✓ Added verifier: ${verifier.name} (${verifier.verifierAddress})`);\n }\n\n /**\n * Remove container from local registry\n */\n async removeContainer(id: string): Promise<void> {\n if (this.containers.delete(id)) {\n await this.saveLocal();\n console.log(`✓ Removed container: ${id}`);\n }\n }\n\n /**\n * Remove verifier from local registry\n */\n async removeVerifier(verifierAddress: string): Promise<void> {\n if (this.verifiers.delete(verifierAddress)) {\n await this.saveLocal();\n console.log(`✓ Removed verifier: ${verifierAddress}`);\n }\n }\n\n /**\n * Save local registry to disk\n */\n private async saveLocal(): Promise<void> {\n const registry: RegistryIndex = {\n containers: Object.fromEntries(this.containers),\n verifiers: Object.fromEntries(this.verifiers),\n deployments: Object.fromEntries(this.deployments),\n version: '1.0.0',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });\n await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));\n }\n\n /**\n * Create default registry with example entries\n */\n private async createDefaultRegistry(): Promise<void> {\n // Create empty registry - will be populated from remote sync\n // No default containers or verifiers\n await this.saveLocal();\n console.log('✓ Created empty local registry (will sync from remote)');\n }\n\n /**\n * Get registry statistics\n */\n getStats(): {\n totalContainers: number;\n activeContainers: number;\n totalVerifiers: number;\n activeVerifiers: number;\n totalDeployments: number;\n activeDeployments: number;\n lastSync: string;\n } {\n return {\n totalContainers: this.containers.size,\n activeContainers: this.listContainers().length,\n totalVerifiers: this.verifiers.size,\n activeVerifiers: this.listVerifiers().length,\n totalDeployments: this.deployments.size,\n activeDeployments: this.listDeployments().length,\n lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : 'Never',\n };\n }\n}\n"],"mappings":"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","names":["path","fs","fetch"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/RegistryManager.ts"],"sourcesContent":["export { RegistryManager } from './RegistryManager';\nexport * from './types';\n","import fs from 'fs/promises';\nimport path from 'path';\nimport fetch from 'node-fetch';\nimport type { ContainerMetadata, DeploymentMetadata, VerifierMetadata, RegistryConfig, RegistryIndex } from './types';\n\nexport class RegistryManager {\n private containers = new Map<string, ContainerMetadata>();\n private verifiers = new Map<string, VerifierMetadata>();\n private deployments = new Map<string, DeploymentMetadata>();\n private config: Required<RegistryConfig>;\n private lastSync: number = 0;\n\n constructor(config: RegistryConfig = {}) {\n this.config = {\n localPath: config.localPath || path.join(process.cwd(), '.noosphere', 'registry.json'),\n remotePath:\n config.remotePath ||\n 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json',\n autoSync: config.autoSync ?? true,\n cacheTTL: config.cacheTTL || 3600000, // 1 hour default\n };\n }\n\n /**\n * Load registry from local and optionally sync from remote\n * Retries if 0 containers are loaded\n */\n async load(retryCount: number = 0): Promise<void> {\n const maxRetries = 3;\n const retryDelayMs = 5000;\n\n // Load local registry\n await this.loadLocal();\n\n // Sync from remote if enabled\n if (this.config.autoSync) {\n try {\n await this.sync();\n } catch (error) {\n console.warn('Failed to sync remote registry:', error);\n console.log('Continuing with local registry only');\n }\n }\n\n // Check if we have 0 containers and should retry (only when autoSync is enabled)\n if (this.config.autoSync && this.containers.size === 0 && retryCount < maxRetries) {\n console.warn(\n `⚠️ Loaded 0 containers, attempting recovery (attempt ${retryCount + 1}/${maxRetries})...`\n );\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, retryDelayMs));\n\n // Try force sync from remote\n try {\n await this.forceSync();\n } catch (error) {\n console.warn('Force sync failed:', error);\n }\n\n // If still 0, recurse with incremented retry count\n if (this.containers.size === 0) {\n return this.load(retryCount + 1);\n }\n }\n\n console.log(`✓ Loaded ${this.containers.size} containers, ${this.verifiers.size} verifiers, ${this.deployments.size} deployments`);\n }\n\n /**\n * Load local registry file\n */\n private async loadLocal(): Promise<void> {\n try {\n const data = await fs.readFile(this.config.localPath, 'utf-8');\n const registry: RegistryIndex = JSON.parse(data);\n\n // Load containers\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n\n // Load verifiers\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n\n // Load deployments\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n console.log(`✓ Loaded local registry from ${this.config.localPath}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n console.log('No local registry found, will create default');\n await this.createDefaultRegistry();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Sync registry from remote GitHub repository\n */\n async sync(): Promise<void> {\n const now = Date.now();\n\n // Check cache TTL\n if (now - this.lastSync < this.config.cacheTTL) {\n console.log('Registry cache is fresh, skipping sync');\n return;\n }\n\n await this.fetchRemote();\n }\n\n /**\n * Force sync from remote, bypassing cache TTL\n */\n async forceSync(): Promise<void> {\n console.log('Force syncing registry (bypassing cache)...');\n this.lastSync = 0; // Reset cache\n await this.fetchRemote();\n }\n\n /**\n * Reload registry completely (clear and reload from local + remote)\n */\n async reload(): Promise<void> {\n console.log('Reloading registry...');\n this.containers.clear();\n this.verifiers.clear();\n this.deployments.clear();\n this.lastSync = 0;\n await this.load();\n }\n\n /**\n * Fetch and merge remote registry\n */\n private async fetchRemote(): Promise<void> {\n console.log(`Syncing registry from ${this.config.remotePath}...`);\n\n try {\n const response = await fetch(this.config.remotePath);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const registry = (await response.json()) as RegistryIndex;\n\n // Merge remote registry (remote entries are added, local overrides are kept)\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n if (!this.containers.has(id)) {\n // Only add if not already in local registry (local takes precedence)\n this.containers.set(id, metadata);\n }\n });\n\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n if (!this.verifiers.has(id)) {\n this.verifiers.set(id, metadata);\n }\n });\n\n // Deployments: remote always wins (contract addresses are authoritative)\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n console.log(`✓ Synced registry (version: ${registry.version})`);\n\n // Fetch per-network files (networks/{chainId}.json) — authoritative source\n await this.fetchNetworkFiles();\n\n this.lastSync = Date.now();\n\n // Persist synced registry to local file for faster subsequent loads\n await this.saveLocal();\n } catch (error) {\n console.error('Failed to sync remote registry:', error);\n throw error;\n }\n }\n\n /**\n * Parse remotePath to extract GitHub repo info.\n * Supports raw.githubusercontent.com URLs.\n * @returns owner, repo, branch tuple or null if URL doesn't match\n */\n private deriveGitHubInfo(): { owner: string; repo: string; branch: string } | null {\n const match = this.config.remotePath.match(\n /raw\\.githubusercontent\\.com\\/([^/]+)\\/([^/]+)\\/([^/]+)\\//\n );\n return match ? { owner: match[1], repo: match[2], branch: match[3] } : null;\n }\n\n /**\n * Fetch per-network registry files from the networks/ directory.\n * Uses GitHub Contents API to discover files, then fetches each\n * from raw.githubusercontent.com. Network files are authoritative\n * and overwrite data from the root registry.json.\n */\n private async fetchNetworkFiles(): Promise<void> {\n const ghInfo = this.deriveGitHubInfo();\n if (!ghInfo) return;\n\n const contentsUrl =\n `https://api.github.com/repos/${ghInfo.owner}/${ghInfo.repo}/contents/networks?ref=${ghInfo.branch}`;\n\n try {\n const listResp = await fetch(contentsUrl, {\n headers: {\n 'Accept': 'application/vnd.github.v3+json',\n 'User-Agent': 'noosphere-registry',\n },\n });\n if (!listResp.ok) return; // networks/ may not exist — not an error\n\n const files = (await listResp.json()) as Array<{ name: string; download_url: string }>;\n const networkFiles = files.filter(f => f.name.endsWith('.json'));\n\n for (const file of networkFiles) {\n try {\n const resp = await fetch(file.download_url);\n if (!resp.ok) continue;\n\n const networkRegistry = (await resp.json()) as RegistryIndex;\n\n // Network files are authoritative — overwrite existing entries\n Object.entries(networkRegistry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n Object.entries(networkRegistry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n Object.entries(networkRegistry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n const chainId = file.name.replace('.json', '');\n console.log(` ✓ Loaded network ${chainId}`);\n } catch {\n // Skip individual file errors\n }\n }\n } catch {\n // Network file discovery is optional — don't fail the main sync\n }\n }\n\n /**\n * Get container by ID\n */\n getContainer(id: string): ContainerMetadata | undefined {\n return this.containers.get(id);\n }\n\n /**\n * Get all containers\n */\n listContainers(): ContainerMetadata[] {\n return Array.from(this.containers.values()).filter((c) => c.statusCode === 'ACTIVE');\n }\n\n /**\n * Search containers by name or tag\n */\n searchContainers(query: string): ContainerMetadata[] {\n const lowerQuery = query.toLowerCase();\n return this.listContainers().filter(\n (c) =>\n c.name.toLowerCase().includes(lowerQuery) ||\n c.description?.toLowerCase().includes(lowerQuery) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Get verifier by contract address\n */\n getVerifier(verifierAddress: string): VerifierMetadata | undefined {\n return this.verifiers.get(verifierAddress);\n }\n\n /**\n * Get verifier by ID\n */\n getVerifierById(id: string): VerifierMetadata | undefined {\n return Array.from(this.verifiers.values()).find((v) => v.id === id);\n }\n\n /**\n * Get all verifiers\n */\n listVerifiers(): VerifierMetadata[] {\n return Array.from(this.verifiers.values()).filter((v) => v.statusCode === 'ACTIVE');\n }\n\n /**\n * Get deployment by chain ID\n */\n getDeployment(chainId: string): DeploymentMetadata | undefined {\n return this.deployments.get(chainId);\n }\n\n /**\n * Get all active deployments\n */\n listDeployments(): DeploymentMetadata[] {\n return Array.from(this.deployments.values()).filter((d) => d.statusCode === 'ACTIVE');\n }\n\n /**\n * Add custom container to local registry\n */\n async addContainer(container: ContainerMetadata): Promise<void> {\n this.containers.set(container.id, container);\n await this.saveLocal();\n console.log(`✓ Added container: ${container.name} (${container.id})`);\n }\n\n /**\n * Add custom verifier to local registry\n */\n async addVerifier(verifier: VerifierMetadata): Promise<void> {\n this.verifiers.set(verifier.verifierAddress, verifier);\n await this.saveLocal();\n console.log(`✓ Added verifier: ${verifier.name} (${verifier.verifierAddress})`);\n }\n\n /**\n * Remove container from local registry\n */\n async removeContainer(id: string): Promise<void> {\n if (this.containers.delete(id)) {\n await this.saveLocal();\n console.log(`✓ Removed container: ${id}`);\n }\n }\n\n /**\n * Remove verifier from local registry\n */\n async removeVerifier(verifierAddress: string): Promise<void> {\n if (this.verifiers.delete(verifierAddress)) {\n await this.saveLocal();\n console.log(`✓ Removed verifier: ${verifierAddress}`);\n }\n }\n\n /**\n * Save local registry to disk\n */\n private async saveLocal(): Promise<void> {\n const registry: RegistryIndex = {\n containers: Object.fromEntries(this.containers),\n verifiers: Object.fromEntries(this.verifiers),\n deployments: Object.fromEntries(this.deployments),\n version: '1.0.0',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });\n await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));\n }\n\n /**\n * Create default registry with example entries\n */\n private async createDefaultRegistry(): Promise<void> {\n // Create empty registry - will be populated from remote sync\n // No default containers or verifiers\n await this.saveLocal();\n console.log('✓ Created empty local registry (will sync from remote)');\n }\n\n /**\n * Get registry statistics\n */\n getStats(): {\n totalContainers: number;\n activeContainers: number;\n totalVerifiers: number;\n activeVerifiers: number;\n totalDeployments: number;\n activeDeployments: number;\n lastSync: string;\n } {\n return {\n totalContainers: this.containers.size,\n activeContainers: this.listContainers().length,\n totalVerifiers: this.verifiers.size,\n activeVerifiers: this.listVerifiers().length,\n totalDeployments: this.deployments.size,\n activeDeployments: this.listDeployments().length,\n lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : 'Never',\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sBAAe;AACf,kBAAiB;AACjB,wBAAkB;AAGX,IAAM,kBAAN,MAAsB;AAAA,EAO3B,YAAY,SAAyB,CAAC,GAAG;AANzC,SAAQ,aAAa,oBAAI,IAA+B;AACxD,SAAQ,YAAY,oBAAI,IAA8B;AACtD,SAAQ,cAAc,oBAAI,IAAgC;AAE1D,SAAQ,WAAmB;AAGzB,SAAK,SAAS;AAAA,MACZ,WAAW,OAAO,aAAa,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,cAAc,eAAe;AAAA,MACrF,YACE,OAAO,cACP;AAAA,MACF,UAAU,OAAO,YAAY;AAAA,MAC7B,UAAU,OAAO,YAAY;AAAA;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,aAAqB,GAAkB;AAChD,UAAM,aAAa;AACnB,UAAM,eAAe;AAGrB,UAAM,KAAK,UAAU;AAGrB,QAAI,KAAK,OAAO,UAAU;AACxB,UAAI;AACF,cAAM,KAAK,KAAK;AAAA,MAClB,SAAS,OAAO;AACd,gBAAQ,KAAK,mCAAmC,KAAK;AACrD,gBAAQ,IAAI,qCAAqC;AAAA,MACnD;AAAA,IACF;AAGA,QAAI,KAAK,OAAO,YAAY,KAAK,WAAW,SAAS,KAAK,aAAa,YAAY;AACjF,cAAQ;AAAA,QACN,mEAAyD,aAAa,CAAC,IAAI,UAAU;AAAA,MACvF;AAGA,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,YAAY,CAAC;AAGhE,UAAI;AACF,cAAM,KAAK,UAAU;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,KAAK,sBAAsB,KAAK;AAAA,MAC1C;AAGA,UAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,eAAO,KAAK,KAAK,aAAa,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,YAAQ,IAAI,iBAAY,KAAK,WAAW,IAAI,gBAAgB,KAAK,UAAU,IAAI,eAAe,KAAK,YAAY,IAAI,cAAc;AAAA,EACnI;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAA2B;AACvC,QAAI;AACF,YAAM,OAAO,MAAM,gBAAAC,QAAG,SAAS,KAAK,OAAO,WAAW,OAAO;AAC7D,YAAM,WAA0B,KAAK,MAAM,IAAI;AAG/C,aAAO,QAAQ,SAAS,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACpE,aAAK,WAAW,IAAI,IAAI,QAAQ;AAAA,MAClC,CAAC;AAGD,aAAO,QAAQ,SAAS,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACnE,aAAK,UAAU,IAAI,IAAI,QAAQ;AAAA,MACjC,CAAC;AAGD,aAAO,QAAQ,SAAS,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,SAAS,QAAQ,MAAM;AAC1E,aAAK,YAAY,IAAI,SAAS,QAAQ;AAAA,MACxC,CAAC;AAED,cAAQ,IAAI,qCAAgC,KAAK,OAAO,SAAS,EAAE;AAAA,IACrE,SAAS,OAAY;AACnB,UAAI,MAAM,SAAS,UAAU;AAC3B,gBAAQ,IAAI,8CAA8C;AAC1D,cAAM,KAAK,sBAAsB;AAAA,MACnC,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,MAAM,KAAK,WAAW,KAAK,OAAO,UAAU;AAC9C,cAAQ,IAAI,wCAAwC;AACpD;AAAA,IACF;AAEA,UAAM,KAAK,YAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA2B;AAC/B,YAAQ,IAAI,6CAA6C;AACzD,SAAK,WAAW;AAChB,UAAM,KAAK,YAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAwB;AAC5B,YAAQ,IAAI,uBAAuB;AACnC,SAAK,WAAW,MAAM;AACtB,SAAK,UAAU,MAAM;AACrB,SAAK,YAAY,MAAM;AACvB,SAAK,WAAW;AAChB,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAA6B;AACzC,YAAQ,IAAI,yBAAyB,KAAK,OAAO,UAAU,KAAK;AAEhE,QAAI;AACF,YAAM,WAAW,UAAM,kBAAAC,SAAM,KAAK,OAAO,UAAU;AACnD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,MACnE;AAEA,YAAM,WAAY,MAAM,SAAS,KAAK;AAGtC,aAAO,QAAQ,SAAS,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACpE,YAAI,CAAC,KAAK,WAAW,IAAI,EAAE,GAAG;AAE5B,eAAK,WAAW,IAAI,IAAI,QAAQ;AAAA,QAClC;AAAA,MACF,CAAC;AAED,aAAO,QAAQ,SAAS,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACnE,YAAI,CAAC,KAAK,UAAU,IAAI,EAAE,GAAG;AAC3B,eAAK,UAAU,IAAI,IAAI,QAAQ;AAAA,QACjC;AAAA,MACF,CAAC;AAGD,aAAO,QAAQ,SAAS,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,SAAS,QAAQ,MAAM;AAC1E,aAAK,YAAY,IAAI,SAAS,QAAQ;AAAA,MACxC,CAAC;AAED,cAAQ,IAAI,oCAA+B,SAAS,OAAO,GAAG;AAG9D,YAAM,KAAK,kBAAkB;AAE7B,WAAK,WAAW,KAAK,IAAI;AAGzB,YAAM,KAAK,UAAU;AAAA,IACvB,SAAS,OAAO;AACd,cAAQ,MAAM,mCAAmC,KAAK;AACtD,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAA2E;AACjF,UAAM,QAAQ,KAAK,OAAO,WAAW;AAAA,MACnC;AAAA,IACF;AACA,WAAO,QAAQ,EAAE,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,QAAQ,MAAM,CAAC,EAAE,IAAI;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oBAAmC;AAC/C,UAAM,SAAS,KAAK,iBAAiB;AACrC,QAAI,CAAC,OAAQ;AAEb,UAAM,cACJ,gCAAgC,OAAO,KAAK,IAAI,OAAO,IAAI,0BAA0B,OAAO,MAAM;AAEpG,QAAI;AACF,YAAM,WAAW,UAAM,kBAAAA,SAAM,aAAa;AAAA,QACxC,SAAS;AAAA,UACP,UAAU;AAAA,UACV,cAAc;AAAA,QAChB;AAAA,MACF,CAAC;AACD,UAAI,CAAC,SAAS,GAAI;AAElB,YAAM,QAAS,MAAM,SAAS,KAAK;AACnC,YAAM,eAAe,MAAM,OAAO,OAAK,EAAE,KAAK,SAAS,OAAO,CAAC;AAE/D,iBAAW,QAAQ,cAAc;AAC/B,YAAI;AACF,gBAAM,OAAO,UAAM,kBAAAA,SAAM,KAAK,YAAY;AAC1C,cAAI,CAAC,KAAK,GAAI;AAEd,gBAAM,kBAAmB,MAAM,KAAK,KAAK;AAGzC,iBAAO,QAAQ,gBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AAC3E,iBAAK,WAAW,IAAI,IAAI,QAAQ;AAAA,UAClC,CAAC;AACD,iBAAO,QAAQ,gBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AAC1E,iBAAK,UAAU,IAAI,IAAI,QAAQ;AAAA,UACjC,CAAC;AACD,iBAAO,QAAQ,gBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACC,UAAS,QAAQ,MAAM;AACjF,iBAAK,YAAY,IAAIA,UAAS,QAAQ;AAAA,UACxC,CAAC;AAED,gBAAM,UAAU,KAAK,KAAK,QAAQ,SAAS,EAAE;AAC7C,kBAAQ,IAAI,2BAAsB,OAAO,EAAE;AAAA,QAC7C,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,IAA2C;AACtD,WAAO,KAAK,WAAW,IAAI,EAAE;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAsC;AACpC,WAAO,MAAM,KAAK,KAAK,WAAW,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,OAAoC;AACnD,UAAM,aAAa,MAAM,YAAY;AACrC,WAAO,KAAK,eAAe,EAAE;AAAA,MAC3B,CAAC,MACC,EAAE,KAAK,YAAY,EAAE,SAAS,UAAU,KACxC,EAAE,aAAa,YAAY,EAAE,SAAS,UAAU,KAChD,EAAE,MAAM,KAAK,CAAC,QAAQ,IAAI,YAAY,EAAE,SAAS,UAAU,CAAC;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,iBAAuD;AACjE,WAAO,KAAK,UAAU,IAAI,eAAe;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,IAA0C;AACxD,WAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAoC;AAClC,WAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAiD;AAC7D,WAAO,KAAK,YAAY,IAAI,OAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwC;AACtC,WAAO,MAAM,KAAK,KAAK,YAAY,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,WAA6C;AAC9D,SAAK,WAAW,IAAI,UAAU,IAAI,SAAS;AAC3C,UAAM,KAAK,UAAU;AACrB,YAAQ,IAAI,2BAAsB,UAAU,IAAI,KAAK,UAAU,EAAE,GAAG;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,UAA2C;AAC3D,SAAK,UAAU,IAAI,SAAS,iBAAiB,QAAQ;AACrD,UAAM,KAAK,UAAU;AACrB,YAAQ,IAAI,0BAAqB,SAAS,IAAI,KAAK,SAAS,eAAe,GAAG;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,IAA2B;AAC/C,QAAI,KAAK,WAAW,OAAO,EAAE,GAAG;AAC9B,YAAM,KAAK,UAAU;AACrB,cAAQ,IAAI,6BAAwB,EAAE,EAAE;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,iBAAwC;AAC3D,QAAI,KAAK,UAAU,OAAO,eAAe,GAAG;AAC1C,YAAM,KAAK,UAAU;AACrB,cAAQ,IAAI,4BAAuB,eAAe,EAAE;AAAA,IACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAA2B;AACvC,UAAM,WAA0B;AAAA,MAC9B,YAAY,OAAO,YAAY,KAAK,UAAU;AAAA,MAC9C,WAAW,OAAO,YAAY,KAAK,SAAS;AAAA,MAC5C,aAAa,OAAO,YAAY,KAAK,WAAW;AAAA,MAChD,SAAS;AAAA,MACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAEA,UAAM,gBAAAF,QAAG,MAAM,YAAAD,QAAK,QAAQ,KAAK,OAAO,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,UAAM,gBAAAC,QAAG,UAAU,KAAK,OAAO,WAAW,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBAAuC;AAGnD,UAAM,KAAK,UAAU;AACrB,YAAQ,IAAI,6DAAwD;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,WAQE;AACA,WAAO;AAAA,MACL,iBAAiB,KAAK,WAAW;AAAA,MACjC,kBAAkB,KAAK,eAAe,EAAE;AAAA,MACxC,gBAAgB,KAAK,UAAU;AAAA,MAC/B,iBAAiB,KAAK,cAAc,EAAE;AAAA,MACtC,kBAAkB,KAAK,YAAY;AAAA,MACnC,mBAAmB,KAAK,gBAAgB,EAAE;AAAA,MAC1C,UAAU,KAAK,WAAW,IAAI,KAAK,KAAK,QAAQ,EAAE,YAAY,IAAI;AAAA,IACpE;AAAA,EACF;AACF;","names":["path","fs","fetch","chainId"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -22,6 +22,20 @@ interface ContainerMetadata {
|
|
|
22
22
|
updatedAt?: string;
|
|
23
23
|
description?: string;
|
|
24
24
|
tags?: string[];
|
|
25
|
+
inputSchema?: {
|
|
26
|
+
type: string;
|
|
27
|
+
required?: string[];
|
|
28
|
+
properties?: Record<string, {
|
|
29
|
+
type: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
default?: string;
|
|
32
|
+
examples?: string[];
|
|
33
|
+
properties?: Record<string, {
|
|
34
|
+
type: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
}>;
|
|
37
|
+
}>;
|
|
38
|
+
} | null;
|
|
25
39
|
}
|
|
26
40
|
interface ProofServiceConfig {
|
|
27
41
|
imageName: string;
|
|
@@ -114,6 +128,19 @@ declare class RegistryManager {
|
|
|
114
128
|
* Fetch and merge remote registry
|
|
115
129
|
*/
|
|
116
130
|
private fetchRemote;
|
|
131
|
+
/**
|
|
132
|
+
* Parse remotePath to extract GitHub repo info.
|
|
133
|
+
* Supports raw.githubusercontent.com URLs.
|
|
134
|
+
* @returns owner, repo, branch tuple or null if URL doesn't match
|
|
135
|
+
*/
|
|
136
|
+
private deriveGitHubInfo;
|
|
137
|
+
/**
|
|
138
|
+
* Fetch per-network registry files from the networks/ directory.
|
|
139
|
+
* Uses GitHub Contents API to discover files, then fetches each
|
|
140
|
+
* from raw.githubusercontent.com. Network files are authoritative
|
|
141
|
+
* and overwrite data from the root registry.json.
|
|
142
|
+
*/
|
|
143
|
+
private fetchNetworkFiles;
|
|
117
144
|
/**
|
|
118
145
|
* Get container by ID
|
|
119
146
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,20 @@ interface ContainerMetadata {
|
|
|
22
22
|
updatedAt?: string;
|
|
23
23
|
description?: string;
|
|
24
24
|
tags?: string[];
|
|
25
|
+
inputSchema?: {
|
|
26
|
+
type: string;
|
|
27
|
+
required?: string[];
|
|
28
|
+
properties?: Record<string, {
|
|
29
|
+
type: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
default?: string;
|
|
32
|
+
examples?: string[];
|
|
33
|
+
properties?: Record<string, {
|
|
34
|
+
type: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
}>;
|
|
37
|
+
}>;
|
|
38
|
+
} | null;
|
|
25
39
|
}
|
|
26
40
|
interface ProofServiceConfig {
|
|
27
41
|
imageName: string;
|
|
@@ -114,6 +128,19 @@ declare class RegistryManager {
|
|
|
114
128
|
* Fetch and merge remote registry
|
|
115
129
|
*/
|
|
116
130
|
private fetchRemote;
|
|
131
|
+
/**
|
|
132
|
+
* Parse remotePath to extract GitHub repo info.
|
|
133
|
+
* Supports raw.githubusercontent.com URLs.
|
|
134
|
+
* @returns owner, repo, branch tuple or null if URL doesn't match
|
|
135
|
+
*/
|
|
136
|
+
private deriveGitHubInfo;
|
|
137
|
+
/**
|
|
138
|
+
* Fetch per-network registry files from the networks/ directory.
|
|
139
|
+
* Uses GitHub Contents API to discover files, then fetches each
|
|
140
|
+
* from raw.githubusercontent.com. Network files are authoritative
|
|
141
|
+
* and overwrite data from the root registry.json.
|
|
142
|
+
*/
|
|
143
|
+
private fetchNetworkFiles;
|
|
117
144
|
/**
|
|
118
145
|
* Get container by ID
|
|
119
146
|
*/
|
package/dist/index.js
CHANGED
|
@@ -128,14 +128,68 @@ var RegistryManager = class {
|
|
|
128
128
|
Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {
|
|
129
129
|
this.deployments.set(chainId, metadata);
|
|
130
130
|
});
|
|
131
|
-
this.lastSync = Date.now();
|
|
132
131
|
console.log(`\u2713 Synced registry (version: ${registry.version})`);
|
|
132
|
+
await this.fetchNetworkFiles();
|
|
133
|
+
this.lastSync = Date.now();
|
|
133
134
|
await this.saveLocal();
|
|
134
135
|
} catch (error) {
|
|
135
136
|
console.error("Failed to sync remote registry:", error);
|
|
136
137
|
throw error;
|
|
137
138
|
}
|
|
138
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Parse remotePath to extract GitHub repo info.
|
|
142
|
+
* Supports raw.githubusercontent.com URLs.
|
|
143
|
+
* @returns owner, repo, branch tuple or null if URL doesn't match
|
|
144
|
+
*/
|
|
145
|
+
deriveGitHubInfo() {
|
|
146
|
+
const match = this.config.remotePath.match(
|
|
147
|
+
/raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)\//
|
|
148
|
+
);
|
|
149
|
+
return match ? { owner: match[1], repo: match[2], branch: match[3] } : null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Fetch per-network registry files from the networks/ directory.
|
|
153
|
+
* Uses GitHub Contents API to discover files, then fetches each
|
|
154
|
+
* from raw.githubusercontent.com. Network files are authoritative
|
|
155
|
+
* and overwrite data from the root registry.json.
|
|
156
|
+
*/
|
|
157
|
+
async fetchNetworkFiles() {
|
|
158
|
+
const ghInfo = this.deriveGitHubInfo();
|
|
159
|
+
if (!ghInfo) return;
|
|
160
|
+
const contentsUrl = `https://api.github.com/repos/${ghInfo.owner}/${ghInfo.repo}/contents/networks?ref=${ghInfo.branch}`;
|
|
161
|
+
try {
|
|
162
|
+
const listResp = await fetch(contentsUrl, {
|
|
163
|
+
headers: {
|
|
164
|
+
"Accept": "application/vnd.github.v3+json",
|
|
165
|
+
"User-Agent": "noosphere-registry"
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
if (!listResp.ok) return;
|
|
169
|
+
const files = await listResp.json();
|
|
170
|
+
const networkFiles = files.filter((f) => f.name.endsWith(".json"));
|
|
171
|
+
for (const file of networkFiles) {
|
|
172
|
+
try {
|
|
173
|
+
const resp = await fetch(file.download_url);
|
|
174
|
+
if (!resp.ok) continue;
|
|
175
|
+
const networkRegistry = await resp.json();
|
|
176
|
+
Object.entries(networkRegistry.containers || {}).forEach(([id, metadata]) => {
|
|
177
|
+
this.containers.set(id, metadata);
|
|
178
|
+
});
|
|
179
|
+
Object.entries(networkRegistry.verifiers || {}).forEach(([id, metadata]) => {
|
|
180
|
+
this.verifiers.set(id, metadata);
|
|
181
|
+
});
|
|
182
|
+
Object.entries(networkRegistry.deployments || {}).forEach(([chainId2, metadata]) => {
|
|
183
|
+
this.deployments.set(chainId2, metadata);
|
|
184
|
+
});
|
|
185
|
+
const chainId = file.name.replace(".json", "");
|
|
186
|
+
console.log(` \u2713 Loaded network ${chainId}`);
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
}
|
|
139
193
|
/**
|
|
140
194
|
* Get container by ID
|
|
141
195
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/RegistryManager.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\nimport fetch from 'node-fetch';\nimport type { ContainerMetadata, DeploymentMetadata, VerifierMetadata, RegistryConfig, RegistryIndex } from './types';\n\nexport class RegistryManager {\n private containers = new Map<string, ContainerMetadata>();\n private verifiers = new Map<string, VerifierMetadata>();\n private deployments = new Map<string, DeploymentMetadata>();\n private config: Required<RegistryConfig>;\n private lastSync: number = 0;\n\n constructor(config: RegistryConfig = {}) {\n this.config = {\n localPath: config.localPath || path.join(process.cwd(), '.noosphere', 'registry.json'),\n remotePath:\n config.remotePath ||\n 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json',\n autoSync: config.autoSync ?? true,\n cacheTTL: config.cacheTTL || 3600000, // 1 hour default\n };\n }\n\n /**\n * Load registry from local and optionally sync from remote\n * Retries if 0 containers are loaded\n */\n async load(retryCount: number = 0): Promise<void> {\n const maxRetries = 3;\n const retryDelayMs = 5000;\n\n // Load local registry\n await this.loadLocal();\n\n // Sync from remote if enabled\n if (this.config.autoSync) {\n try {\n await this.sync();\n } catch (error) {\n console.warn('Failed to sync remote registry:', error);\n console.log('Continuing with local registry only');\n }\n }\n\n // Check if we have 0 containers and should retry (only when autoSync is enabled)\n if (this.config.autoSync && this.containers.size === 0 && retryCount < maxRetries) {\n console.warn(\n `⚠️ Loaded 0 containers, attempting recovery (attempt ${retryCount + 1}/${maxRetries})...`\n );\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, retryDelayMs));\n\n // Try force sync from remote\n try {\n await this.forceSync();\n } catch (error) {\n console.warn('Force sync failed:', error);\n }\n\n // If still 0, recurse with incremented retry count\n if (this.containers.size === 0) {\n return this.load(retryCount + 1);\n }\n }\n\n console.log(`✓ Loaded ${this.containers.size} containers, ${this.verifiers.size} verifiers, ${this.deployments.size} deployments`);\n }\n\n /**\n * Load local registry file\n */\n private async loadLocal(): Promise<void> {\n try {\n const data = await fs.readFile(this.config.localPath, 'utf-8');\n const registry: RegistryIndex = JSON.parse(data);\n\n // Load containers\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n\n // Load verifiers\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n\n // Load deployments\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n console.log(`✓ Loaded local registry from ${this.config.localPath}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n console.log('No local registry found, will create default');\n await this.createDefaultRegistry();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Sync registry from remote GitHub repository\n */\n async sync(): Promise<void> {\n const now = Date.now();\n\n // Check cache TTL\n if (now - this.lastSync < this.config.cacheTTL) {\n console.log('Registry cache is fresh, skipping sync');\n return;\n }\n\n await this.fetchRemote();\n }\n\n /**\n * Force sync from remote, bypassing cache TTL\n */\n async forceSync(): Promise<void> {\n console.log('Force syncing registry (bypassing cache)...');\n this.lastSync = 0; // Reset cache\n await this.fetchRemote();\n }\n\n /**\n * Reload registry completely (clear and reload from local + remote)\n */\n async reload(): Promise<void> {\n console.log('Reloading registry...');\n this.containers.clear();\n this.verifiers.clear();\n this.deployments.clear();\n this.lastSync = 0;\n await this.load();\n }\n\n /**\n * Fetch and merge remote registry\n */\n private async fetchRemote(): Promise<void> {\n console.log(`Syncing registry from ${this.config.remotePath}...`);\n\n try {\n const response = await fetch(this.config.remotePath);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const registry = (await response.json()) as RegistryIndex;\n\n // Merge remote registry (remote entries are added, local overrides are kept)\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n if (!this.containers.has(id)) {\n // Only add if not already in local registry (local takes precedence)\n this.containers.set(id, metadata);\n }\n });\n\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n if (!this.verifiers.has(id)) {\n this.verifiers.set(id, metadata);\n }\n });\n\n // Deployments: remote always wins (contract addresses are authoritative)\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n this.lastSync = Date.now();\n console.log(`✓ Synced registry (version: ${registry.version})`);\n\n // Persist synced registry to local file for faster subsequent loads\n await this.saveLocal();\n } catch (error) {\n console.error('Failed to sync remote registry:', error);\n throw error;\n }\n }\n\n /**\n * Get container by ID\n */\n getContainer(id: string): ContainerMetadata | undefined {\n return this.containers.get(id);\n }\n\n /**\n * Get all containers\n */\n listContainers(): ContainerMetadata[] {\n return Array.from(this.containers.values()).filter((c) => c.statusCode === 'ACTIVE');\n }\n\n /**\n * Search containers by name or tag\n */\n searchContainers(query: string): ContainerMetadata[] {\n const lowerQuery = query.toLowerCase();\n return this.listContainers().filter(\n (c) =>\n c.name.toLowerCase().includes(lowerQuery) ||\n c.description?.toLowerCase().includes(lowerQuery) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Get verifier by contract address\n */\n getVerifier(verifierAddress: string): VerifierMetadata | undefined {\n return this.verifiers.get(verifierAddress);\n }\n\n /**\n * Get verifier by ID\n */\n getVerifierById(id: string): VerifierMetadata | undefined {\n return Array.from(this.verifiers.values()).find((v) => v.id === id);\n }\n\n /**\n * Get all verifiers\n */\n listVerifiers(): VerifierMetadata[] {\n return Array.from(this.verifiers.values()).filter((v) => v.statusCode === 'ACTIVE');\n }\n\n /**\n * Get deployment by chain ID\n */\n getDeployment(chainId: string): DeploymentMetadata | undefined {\n return this.deployments.get(chainId);\n }\n\n /**\n * Get all active deployments\n */\n listDeployments(): DeploymentMetadata[] {\n return Array.from(this.deployments.values()).filter((d) => d.statusCode === 'ACTIVE');\n }\n\n /**\n * Add custom container to local registry\n */\n async addContainer(container: ContainerMetadata): Promise<void> {\n this.containers.set(container.id, container);\n await this.saveLocal();\n console.log(`✓ Added container: ${container.name} (${container.id})`);\n }\n\n /**\n * Add custom verifier to local registry\n */\n async addVerifier(verifier: VerifierMetadata): Promise<void> {\n this.verifiers.set(verifier.verifierAddress, verifier);\n await this.saveLocal();\n console.log(`✓ Added verifier: ${verifier.name} (${verifier.verifierAddress})`);\n }\n\n /**\n * Remove container from local registry\n */\n async removeContainer(id: string): Promise<void> {\n if (this.containers.delete(id)) {\n await this.saveLocal();\n console.log(`✓ Removed container: ${id}`);\n }\n }\n\n /**\n * Remove verifier from local registry\n */\n async removeVerifier(verifierAddress: string): Promise<void> {\n if (this.verifiers.delete(verifierAddress)) {\n await this.saveLocal();\n console.log(`✓ Removed verifier: ${verifierAddress}`);\n }\n }\n\n /**\n * Save local registry to disk\n */\n private async saveLocal(): Promise<void> {\n const registry: RegistryIndex = {\n containers: Object.fromEntries(this.containers),\n verifiers: Object.fromEntries(this.verifiers),\n deployments: Object.fromEntries(this.deployments),\n version: '1.0.0',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });\n await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));\n }\n\n /**\n * Create default registry with example entries\n */\n private async createDefaultRegistry(): Promise<void> {\n // Create empty registry - will be populated from remote sync\n // No default containers or verifiers\n await this.saveLocal();\n console.log('✓ Created empty local registry (will sync from remote)');\n }\n\n /**\n * Get registry statistics\n */\n getStats(): {\n totalContainers: number;\n activeContainers: number;\n totalVerifiers: number;\n activeVerifiers: number;\n totalDeployments: number;\n activeDeployments: number;\n lastSync: string;\n } {\n return {\n totalContainers: this.containers.size,\n activeContainers: this.listContainers().length,\n totalVerifiers: this.verifiers.size,\n activeVerifiers: this.listVerifiers().length,\n totalDeployments: this.deployments.size,\n activeDeployments: this.listDeployments().length,\n lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : 'Never',\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/RegistryManager.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\nimport fetch from 'node-fetch';\nimport type { ContainerMetadata, DeploymentMetadata, VerifierMetadata, RegistryConfig, RegistryIndex } from './types';\n\nexport class RegistryManager {\n private containers = new Map<string, ContainerMetadata>();\n private verifiers = new Map<string, VerifierMetadata>();\n private deployments = new Map<string, DeploymentMetadata>();\n private config: Required<RegistryConfig>;\n private lastSync: number = 0;\n\n constructor(config: RegistryConfig = {}) {\n this.config = {\n localPath: config.localPath || path.join(process.cwd(), '.noosphere', 'registry.json'),\n remotePath:\n config.remotePath ||\n 'https://raw.githubusercontent.com/hpp-io/noosphere-registry/main/registry.json',\n autoSync: config.autoSync ?? true,\n cacheTTL: config.cacheTTL || 3600000, // 1 hour default\n };\n }\n\n /**\n * Load registry from local and optionally sync from remote\n * Retries if 0 containers are loaded\n */\n async load(retryCount: number = 0): Promise<void> {\n const maxRetries = 3;\n const retryDelayMs = 5000;\n\n // Load local registry\n await this.loadLocal();\n\n // Sync from remote if enabled\n if (this.config.autoSync) {\n try {\n await this.sync();\n } catch (error) {\n console.warn('Failed to sync remote registry:', error);\n console.log('Continuing with local registry only');\n }\n }\n\n // Check if we have 0 containers and should retry (only when autoSync is enabled)\n if (this.config.autoSync && this.containers.size === 0 && retryCount < maxRetries) {\n console.warn(\n `⚠️ Loaded 0 containers, attempting recovery (attempt ${retryCount + 1}/${maxRetries})...`\n );\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, retryDelayMs));\n\n // Try force sync from remote\n try {\n await this.forceSync();\n } catch (error) {\n console.warn('Force sync failed:', error);\n }\n\n // If still 0, recurse with incremented retry count\n if (this.containers.size === 0) {\n return this.load(retryCount + 1);\n }\n }\n\n console.log(`✓ Loaded ${this.containers.size} containers, ${this.verifiers.size} verifiers, ${this.deployments.size} deployments`);\n }\n\n /**\n * Load local registry file\n */\n private async loadLocal(): Promise<void> {\n try {\n const data = await fs.readFile(this.config.localPath, 'utf-8');\n const registry: RegistryIndex = JSON.parse(data);\n\n // Load containers\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n\n // Load verifiers\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n\n // Load deployments\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n console.log(`✓ Loaded local registry from ${this.config.localPath}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n console.log('No local registry found, will create default');\n await this.createDefaultRegistry();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Sync registry from remote GitHub repository\n */\n async sync(): Promise<void> {\n const now = Date.now();\n\n // Check cache TTL\n if (now - this.lastSync < this.config.cacheTTL) {\n console.log('Registry cache is fresh, skipping sync');\n return;\n }\n\n await this.fetchRemote();\n }\n\n /**\n * Force sync from remote, bypassing cache TTL\n */\n async forceSync(): Promise<void> {\n console.log('Force syncing registry (bypassing cache)...');\n this.lastSync = 0; // Reset cache\n await this.fetchRemote();\n }\n\n /**\n * Reload registry completely (clear and reload from local + remote)\n */\n async reload(): Promise<void> {\n console.log('Reloading registry...');\n this.containers.clear();\n this.verifiers.clear();\n this.deployments.clear();\n this.lastSync = 0;\n await this.load();\n }\n\n /**\n * Fetch and merge remote registry\n */\n private async fetchRemote(): Promise<void> {\n console.log(`Syncing registry from ${this.config.remotePath}...`);\n\n try {\n const response = await fetch(this.config.remotePath);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const registry = (await response.json()) as RegistryIndex;\n\n // Merge remote registry (remote entries are added, local overrides are kept)\n Object.entries(registry.containers || {}).forEach(([id, metadata]) => {\n if (!this.containers.has(id)) {\n // Only add if not already in local registry (local takes precedence)\n this.containers.set(id, metadata);\n }\n });\n\n Object.entries(registry.verifiers || {}).forEach(([id, metadata]) => {\n if (!this.verifiers.has(id)) {\n this.verifiers.set(id, metadata);\n }\n });\n\n // Deployments: remote always wins (contract addresses are authoritative)\n Object.entries(registry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n console.log(`✓ Synced registry (version: ${registry.version})`);\n\n // Fetch per-network files (networks/{chainId}.json) — authoritative source\n await this.fetchNetworkFiles();\n\n this.lastSync = Date.now();\n\n // Persist synced registry to local file for faster subsequent loads\n await this.saveLocal();\n } catch (error) {\n console.error('Failed to sync remote registry:', error);\n throw error;\n }\n }\n\n /**\n * Parse remotePath to extract GitHub repo info.\n * Supports raw.githubusercontent.com URLs.\n * @returns owner, repo, branch tuple or null if URL doesn't match\n */\n private deriveGitHubInfo(): { owner: string; repo: string; branch: string } | null {\n const match = this.config.remotePath.match(\n /raw\\.githubusercontent\\.com\\/([^/]+)\\/([^/]+)\\/([^/]+)\\//\n );\n return match ? { owner: match[1], repo: match[2], branch: match[3] } : null;\n }\n\n /**\n * Fetch per-network registry files from the networks/ directory.\n * Uses GitHub Contents API to discover files, then fetches each\n * from raw.githubusercontent.com. Network files are authoritative\n * and overwrite data from the root registry.json.\n */\n private async fetchNetworkFiles(): Promise<void> {\n const ghInfo = this.deriveGitHubInfo();\n if (!ghInfo) return;\n\n const contentsUrl =\n `https://api.github.com/repos/${ghInfo.owner}/${ghInfo.repo}/contents/networks?ref=${ghInfo.branch}`;\n\n try {\n const listResp = await fetch(contentsUrl, {\n headers: {\n 'Accept': 'application/vnd.github.v3+json',\n 'User-Agent': 'noosphere-registry',\n },\n });\n if (!listResp.ok) return; // networks/ may not exist — not an error\n\n const files = (await listResp.json()) as Array<{ name: string; download_url: string }>;\n const networkFiles = files.filter(f => f.name.endsWith('.json'));\n\n for (const file of networkFiles) {\n try {\n const resp = await fetch(file.download_url);\n if (!resp.ok) continue;\n\n const networkRegistry = (await resp.json()) as RegistryIndex;\n\n // Network files are authoritative — overwrite existing entries\n Object.entries(networkRegistry.containers || {}).forEach(([id, metadata]) => {\n this.containers.set(id, metadata);\n });\n Object.entries(networkRegistry.verifiers || {}).forEach(([id, metadata]) => {\n this.verifiers.set(id, metadata);\n });\n Object.entries(networkRegistry.deployments || {}).forEach(([chainId, metadata]) => {\n this.deployments.set(chainId, metadata);\n });\n\n const chainId = file.name.replace('.json', '');\n console.log(` ✓ Loaded network ${chainId}`);\n } catch {\n // Skip individual file errors\n }\n }\n } catch {\n // Network file discovery is optional — don't fail the main sync\n }\n }\n\n /**\n * Get container by ID\n */\n getContainer(id: string): ContainerMetadata | undefined {\n return this.containers.get(id);\n }\n\n /**\n * Get all containers\n */\n listContainers(): ContainerMetadata[] {\n return Array.from(this.containers.values()).filter((c) => c.statusCode === 'ACTIVE');\n }\n\n /**\n * Search containers by name or tag\n */\n searchContainers(query: string): ContainerMetadata[] {\n const lowerQuery = query.toLowerCase();\n return this.listContainers().filter(\n (c) =>\n c.name.toLowerCase().includes(lowerQuery) ||\n c.description?.toLowerCase().includes(lowerQuery) ||\n c.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery))\n );\n }\n\n /**\n * Get verifier by contract address\n */\n getVerifier(verifierAddress: string): VerifierMetadata | undefined {\n return this.verifiers.get(verifierAddress);\n }\n\n /**\n * Get verifier by ID\n */\n getVerifierById(id: string): VerifierMetadata | undefined {\n return Array.from(this.verifiers.values()).find((v) => v.id === id);\n }\n\n /**\n * Get all verifiers\n */\n listVerifiers(): VerifierMetadata[] {\n return Array.from(this.verifiers.values()).filter((v) => v.statusCode === 'ACTIVE');\n }\n\n /**\n * Get deployment by chain ID\n */\n getDeployment(chainId: string): DeploymentMetadata | undefined {\n return this.deployments.get(chainId);\n }\n\n /**\n * Get all active deployments\n */\n listDeployments(): DeploymentMetadata[] {\n return Array.from(this.deployments.values()).filter((d) => d.statusCode === 'ACTIVE');\n }\n\n /**\n * Add custom container to local registry\n */\n async addContainer(container: ContainerMetadata): Promise<void> {\n this.containers.set(container.id, container);\n await this.saveLocal();\n console.log(`✓ Added container: ${container.name} (${container.id})`);\n }\n\n /**\n * Add custom verifier to local registry\n */\n async addVerifier(verifier: VerifierMetadata): Promise<void> {\n this.verifiers.set(verifier.verifierAddress, verifier);\n await this.saveLocal();\n console.log(`✓ Added verifier: ${verifier.name} (${verifier.verifierAddress})`);\n }\n\n /**\n * Remove container from local registry\n */\n async removeContainer(id: string): Promise<void> {\n if (this.containers.delete(id)) {\n await this.saveLocal();\n console.log(`✓ Removed container: ${id}`);\n }\n }\n\n /**\n * Remove verifier from local registry\n */\n async removeVerifier(verifierAddress: string): Promise<void> {\n if (this.verifiers.delete(verifierAddress)) {\n await this.saveLocal();\n console.log(`✓ Removed verifier: ${verifierAddress}`);\n }\n }\n\n /**\n * Save local registry to disk\n */\n private async saveLocal(): Promise<void> {\n const registry: RegistryIndex = {\n containers: Object.fromEntries(this.containers),\n verifiers: Object.fromEntries(this.verifiers),\n deployments: Object.fromEntries(this.deployments),\n version: '1.0.0',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.mkdir(path.dirname(this.config.localPath), { recursive: true });\n await fs.writeFile(this.config.localPath, JSON.stringify(registry, null, 2));\n }\n\n /**\n * Create default registry with example entries\n */\n private async createDefaultRegistry(): Promise<void> {\n // Create empty registry - will be populated from remote sync\n // No default containers or verifiers\n await this.saveLocal();\n console.log('✓ Created empty local registry (will sync from remote)');\n }\n\n /**\n * Get registry statistics\n */\n getStats(): {\n totalContainers: number;\n activeContainers: number;\n totalVerifiers: number;\n activeVerifiers: number;\n totalDeployments: number;\n activeDeployments: number;\n lastSync: string;\n } {\n return {\n totalContainers: this.containers.size,\n activeContainers: this.listContainers().length,\n totalVerifiers: this.verifiers.size,\n activeVerifiers: this.listVerifiers().length,\n totalDeployments: this.deployments.size,\n activeDeployments: this.listDeployments().length,\n lastSync: this.lastSync ? new Date(this.lastSync).toISOString() : 'Never',\n };\n }\n}\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,WAAW;AAGX,IAAM,kBAAN,MAAsB;AAAA,EAO3B,YAAY,SAAyB,CAAC,GAAG;AANzC,SAAQ,aAAa,oBAAI,IAA+B;AACxD,SAAQ,YAAY,oBAAI,IAA8B;AACtD,SAAQ,cAAc,oBAAI,IAAgC;AAE1D,SAAQ,WAAmB;AAGzB,SAAK,SAAS;AAAA,MACZ,WAAW,OAAO,aAAa,KAAK,KAAK,QAAQ,IAAI,GAAG,cAAc,eAAe;AAAA,MACrF,YACE,OAAO,cACP;AAAA,MACF,UAAU,OAAO,YAAY;AAAA,MAC7B,UAAU,OAAO,YAAY;AAAA;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,aAAqB,GAAkB;AAChD,UAAM,aAAa;AACnB,UAAM,eAAe;AAGrB,UAAM,KAAK,UAAU;AAGrB,QAAI,KAAK,OAAO,UAAU;AACxB,UAAI;AACF,cAAM,KAAK,KAAK;AAAA,MAClB,SAAS,OAAO;AACd,gBAAQ,KAAK,mCAAmC,KAAK;AACrD,gBAAQ,IAAI,qCAAqC;AAAA,MACnD;AAAA,IACF;AAGA,QAAI,KAAK,OAAO,YAAY,KAAK,WAAW,SAAS,KAAK,aAAa,YAAY;AACjF,cAAQ;AAAA,QACN,mEAAyD,aAAa,CAAC,IAAI,UAAU;AAAA,MACvF;AAGA,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,YAAY,CAAC;AAGhE,UAAI;AACF,cAAM,KAAK,UAAU;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,KAAK,sBAAsB,KAAK;AAAA,MAC1C;AAGA,UAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,eAAO,KAAK,KAAK,aAAa,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,YAAQ,IAAI,iBAAY,KAAK,WAAW,IAAI,gBAAgB,KAAK,UAAU,IAAI,eAAe,KAAK,YAAY,IAAI,cAAc;AAAA,EACnI;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAA2B;AACvC,QAAI;AACF,YAAM,OAAO,MAAM,GAAG,SAAS,KAAK,OAAO,WAAW,OAAO;AAC7D,YAAM,WAA0B,KAAK,MAAM,IAAI;AAG/C,aAAO,QAAQ,SAAS,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACpE,aAAK,WAAW,IAAI,IAAI,QAAQ;AAAA,MAClC,CAAC;AAGD,aAAO,QAAQ,SAAS,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACnE,aAAK,UAAU,IAAI,IAAI,QAAQ;AAAA,MACjC,CAAC;AAGD,aAAO,QAAQ,SAAS,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,SAAS,QAAQ,MAAM;AAC1E,aAAK,YAAY,IAAI,SAAS,QAAQ;AAAA,MACxC,CAAC;AAED,cAAQ,IAAI,qCAAgC,KAAK,OAAO,SAAS,EAAE;AAAA,IACrE,SAAS,OAAY;AACnB,UAAI,MAAM,SAAS,UAAU;AAC3B,gBAAQ,IAAI,8CAA8C;AAC1D,cAAM,KAAK,sBAAsB;AAAA,MACnC,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,MAAM,KAAK,WAAW,KAAK,OAAO,UAAU;AAC9C,cAAQ,IAAI,wCAAwC;AACpD;AAAA,IACF;AAEA,UAAM,KAAK,YAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA2B;AAC/B,YAAQ,IAAI,6CAA6C;AACzD,SAAK,WAAW;AAChB,UAAM,KAAK,YAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAwB;AAC5B,YAAQ,IAAI,uBAAuB;AACnC,SAAK,WAAW,MAAM;AACtB,SAAK,UAAU,MAAM;AACrB,SAAK,YAAY,MAAM;AACvB,SAAK,WAAW;AAChB,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAA6B;AACzC,YAAQ,IAAI,yBAAyB,KAAK,OAAO,UAAU,KAAK;AAEhE,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,OAAO,UAAU;AACnD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,MACnE;AAEA,YAAM,WAAY,MAAM,SAAS,KAAK;AAGtC,aAAO,QAAQ,SAAS,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACpE,YAAI,CAAC,KAAK,WAAW,IAAI,EAAE,GAAG;AAE5B,eAAK,WAAW,IAAI,IAAI,QAAQ;AAAA,QAClC;AAAA,MACF,CAAC;AAED,aAAO,QAAQ,SAAS,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AACnE,YAAI,CAAC,KAAK,UAAU,IAAI,EAAE,GAAG;AAC3B,eAAK,UAAU,IAAI,IAAI,QAAQ;AAAA,QACjC;AAAA,MACF,CAAC;AAGD,aAAO,QAAQ,SAAS,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,SAAS,QAAQ,MAAM;AAC1E,aAAK,YAAY,IAAI,SAAS,QAAQ;AAAA,MACxC,CAAC;AAED,cAAQ,IAAI,oCAA+B,SAAS,OAAO,GAAG;AAG9D,YAAM,KAAK,kBAAkB;AAE7B,WAAK,WAAW,KAAK,IAAI;AAGzB,YAAM,KAAK,UAAU;AAAA,IACvB,SAAS,OAAO;AACd,cAAQ,MAAM,mCAAmC,KAAK;AACtD,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAA2E;AACjF,UAAM,QAAQ,KAAK,OAAO,WAAW;AAAA,MACnC;AAAA,IACF;AACA,WAAO,QAAQ,EAAE,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,QAAQ,MAAM,CAAC,EAAE,IAAI;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oBAAmC;AAC/C,UAAM,SAAS,KAAK,iBAAiB;AACrC,QAAI,CAAC,OAAQ;AAEb,UAAM,cACJ,gCAAgC,OAAO,KAAK,IAAI,OAAO,IAAI,0BAA0B,OAAO,MAAM;AAEpG,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,aAAa;AAAA,QACxC,SAAS;AAAA,UACP,UAAU;AAAA,UACV,cAAc;AAAA,QAChB;AAAA,MACF,CAAC;AACD,UAAI,CAAC,SAAS,GAAI;AAElB,YAAM,QAAS,MAAM,SAAS,KAAK;AACnC,YAAM,eAAe,MAAM,OAAO,OAAK,EAAE,KAAK,SAAS,OAAO,CAAC;AAE/D,iBAAW,QAAQ,cAAc;AAC/B,YAAI;AACF,gBAAM,OAAO,MAAM,MAAM,KAAK,YAAY;AAC1C,cAAI,CAAC,KAAK,GAAI;AAEd,gBAAM,kBAAmB,MAAM,KAAK,KAAK;AAGzC,iBAAO,QAAQ,gBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AAC3E,iBAAK,WAAW,IAAI,IAAI,QAAQ;AAAA,UAClC,CAAC;AACD,iBAAO,QAAQ,gBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM;AAC1E,iBAAK,UAAU,IAAI,IAAI,QAAQ;AAAA,UACjC,CAAC;AACD,iBAAO,QAAQ,gBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACA,UAAS,QAAQ,MAAM;AACjF,iBAAK,YAAY,IAAIA,UAAS,QAAQ;AAAA,UACxC,CAAC;AAED,gBAAM,UAAU,KAAK,KAAK,QAAQ,SAAS,EAAE;AAC7C,kBAAQ,IAAI,2BAAsB,OAAO,EAAE;AAAA,QAC7C,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,IAA2C;AACtD,WAAO,KAAK,WAAW,IAAI,EAAE;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAsC;AACpC,WAAO,MAAM,KAAK,KAAK,WAAW,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,OAAoC;AACnD,UAAM,aAAa,MAAM,YAAY;AACrC,WAAO,KAAK,eAAe,EAAE;AAAA,MAC3B,CAAC,MACC,EAAE,KAAK,YAAY,EAAE,SAAS,UAAU,KACxC,EAAE,aAAa,YAAY,EAAE,SAAS,UAAU,KAChD,EAAE,MAAM,KAAK,CAAC,QAAQ,IAAI,YAAY,EAAE,SAAS,UAAU,CAAC;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,iBAAuD;AACjE,WAAO,KAAK,UAAU,IAAI,eAAe;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,IAA0C;AACxD,WAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAoC;AAClC,WAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAiD;AAC7D,WAAO,KAAK,YAAY,IAAI,OAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwC;AACtC,WAAO,MAAM,KAAK,KAAK,YAAY,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,WAA6C;AAC9D,SAAK,WAAW,IAAI,UAAU,IAAI,SAAS;AAC3C,UAAM,KAAK,UAAU;AACrB,YAAQ,IAAI,2BAAsB,UAAU,IAAI,KAAK,UAAU,EAAE,GAAG;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,UAA2C;AAC3D,SAAK,UAAU,IAAI,SAAS,iBAAiB,QAAQ;AACrD,UAAM,KAAK,UAAU;AACrB,YAAQ,IAAI,0BAAqB,SAAS,IAAI,KAAK,SAAS,eAAe,GAAG;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,IAA2B;AAC/C,QAAI,KAAK,WAAW,OAAO,EAAE,GAAG;AAC9B,YAAM,KAAK,UAAU;AACrB,cAAQ,IAAI,6BAAwB,EAAE,EAAE;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,iBAAwC;AAC3D,QAAI,KAAK,UAAU,OAAO,eAAe,GAAG;AAC1C,YAAM,KAAK,UAAU;AACrB,cAAQ,IAAI,4BAAuB,eAAe,EAAE;AAAA,IACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAA2B;AACvC,UAAM,WAA0B;AAAA,MAC9B,YAAY,OAAO,YAAY,KAAK,UAAU;AAAA,MAC9C,WAAW,OAAO,YAAY,KAAK,SAAS;AAAA,MAC5C,aAAa,OAAO,YAAY,KAAK,WAAW;AAAA,MAChD,SAAS;AAAA,MACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAEA,UAAM,GAAG,MAAM,KAAK,QAAQ,KAAK,OAAO,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,UAAM,GAAG,UAAU,KAAK,OAAO,WAAW,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBAAuC;AAGnD,UAAM,KAAK,UAAU;AACrB,YAAQ,IAAI,6DAAwD;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,WAQE;AACA,WAAO;AAAA,MACL,iBAAiB,KAAK,WAAW;AAAA,MACjC,kBAAkB,KAAK,eAAe,EAAE;AAAA,MACxC,gBAAgB,KAAK,UAAU;AAAA,MAC/B,iBAAiB,KAAK,cAAc,EAAE;AAAA,MACtC,kBAAkB,KAAK,YAAY;AAAA,MACnC,mBAAmB,KAAK,gBAAgB,EAAE;AAAA,MAC1C,UAAU,KAAK,WAAW,IAAI,KAAK,KAAK,QAAQ,EAAE,YAAY,IAAI;AAAA,IACpE;AAAA,EACF;AACF;","names":["chainId"]}
|